<commit_before>export Prime, factors, num_of_divisors;

pure fn Prime() -> Prime {
    Prime { vec: ~[] }
}

struct Prime {
    priv mut vec: ~[u64],
}

impl Prime {
    priv pure fn is_coprime(num: u64) -> bool {
        for uint::range(0, self.vec.len()) |i| {
            let p = self.vec[i];
            if p * p > num  { return true; }
            if num % p == 0 { return false; }
        }
        return true;
    }

    priv fn grow_until(cond: fn() -> bool) {
        if cond() { return }

        let mut num = match vec::last_opt(self.vec) {
          None    => { self.vec =  ~[2]; return self.grow_until(cond); }
          Some(2) => { self.vec += ~[3]; return self.grow_until(cond); }
          Some(x) => { x + 2 }
        };

        while !cond() {
            if self.is_coprime(num) {
                self.vec += ~[num];
            }
            num += 2;
        }
    }

    fn get_at(idx: uint) -> u64 {
        self.grow_until(|| idx < self.vec.len());
        return self.vec[idx];
    }

    fn is_prime(num: u64) -> bool {
        if num < 2 { return false; }

        for self.each |p| {
            if p * p > num  { return true;  }
            if num % p == 0 { return false; }
        }
        unreachable();
    }

    fn each(f: fn(&&u64) -> bool) {
        let init_len = self.vec.len();
        for uint::range(0, init_len) |i| {
            let p = self.vec[i];
            if !f(p) { return; }
        }

        let mut idx = init_len;
        loop {
            if !f(self.get_at(idx)) { return; }
            idx += 1;
        }
    }
}

fn div_multi(&num: u64, f: u64) -> u64 {
    let mut exp = 0;
    while (num % f == 0) {
        exp += 1;
        num /= f;
    }
    return exp;
}

fn factors(num: u64, primes: &Prime, f: fn((u64, monoid::Sum<i64>)) -> bool) {
    let mut itr = num;
    for primes.each |p| {
        let exp = div_multi(itr, p);
        if exp > 0 {
            if !f((p, monoid::Sum(exp as i64))) { break; }
        }
        if itr == 1  { break; }
    };
}

fn num_of_divisors(num: u64, primes: &Prime) -> u64 {
    let mut prod = 1;
    for factors(num, primes) |f| {
        let (_base, exp) = f;
        prod *= (*exp + 1) as u64;
    }
    return prod;
}

// fn sum_of_divisors(num: u64, primes: Prime) -> u64 {

// }

#[cfg(test)]
mod tests {
    #[test]
    fn test_prime_opidx () {
        let table  = [  2,  3,  5,  7, 11, 13, 17, 19, 23, 29, 31, 37, 41 ];
        let ps = Prime();

        // Generated primes
        for table.eachi() |i, p| { assert ps.get_at(i) == p; }
        // Memoized primes
        for table.eachi() |i, p| { assert ps.get_at(i) == p; }
    }

    #[test]
    fn test_prime_each() {
        let table  = ~[  2,  3,  5,  7, 11, 13, 17, 19, 23, 29, 31, 37, 41 ];
        let table2 = ~[ 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 ];
        let ps = Prime();

        let mut v1 = ~[];
        for ps.each |p| {
            if p > table.last() { break; }
            v1 += [ p ];
        }
        assert table == v1;

        let mut v2 = ~[];
        for ps.each |p| {
            if p > table.last() { break; }
            v2 += [ p ];
        }
        assert table == v2;

        let mut v3 = ~[];
        for ps.each |p| {
            if p > table2.last() { break; }
            v3 += [ p ];
        }
        assert table + table2 == v3;
    }

    #[test]
    fn test_prime_is_prime() {
        let p = Prime();
        assert !p.is_prime(0);
        assert !p.is_prime(1);
        assert p.is_prime(2);
        assert p.is_prime(3);
        assert !p.is_prime(4);
        assert p.is_prime(5);
        assert !p.is_prime(6);
        assert p.is_prime(7);
        assert !p.is_prime(100);
    }
}
<commit_msg>Add euler::prime::sum_of_divisors()<commit_after>export Prime, factors, num_of_divisors, sum_of_divisors, sum_of_proper_divisors;

pure fn Prime() -> Prime {
    Prime { vec: ~[] }
}

struct Prime {
    priv mut vec: ~[u64],
}

impl Prime {
    priv pure fn is_coprime(num: u64) -> bool {
        for uint::range(0, self.vec.len()) |i| {
            let p = self.vec[i];
            if p * p > num  { return true; }
            if num % p == 0 { return false; }
        }
        return true;
    }

    priv fn grow_until(cond: fn() -> bool) {
        if cond() { return }

        let mut num = match vec::last_opt(self.vec) {
          None    => { self.vec =  ~[2]; return self.grow_until(cond); }
          Some(2) => { self.vec += ~[3]; return self.grow_until(cond); }
          Some(x) => { x + 2 }
        };

        while !cond() {
            if self.is_coprime(num) {
                self.vec += ~[num];
            }
            num += 2;
        }
    }

    fn get_at(idx: uint) -> u64 {
        self.grow_until(|| idx < self.vec.len());
        return self.vec[idx];
    }

    fn is_prime(num: u64) -> bool {
        if num < 2 { return false; }

        for self.each |p| {
            if p * p > num  { return true;  }
            if num % p == 0 { return false; }
        }
        unreachable();
    }

    fn each(f: fn(&&u64) -> bool) {
        let init_len = self.vec.len();
        for uint::range(0, init_len) |i| {
            let p = self.vec[i];
            if !f(p) { return; }
        }

        let mut idx = init_len;
        loop {
            if !f(self.get_at(idx)) { return; }
            idx += 1;
        }
    }
}

fn div_multi(&num: u64, f: u64) -> u64 {
    let mut exp = 0;
    while (num % f == 0) {
        exp += 1;
        num /= f;
    }
    return exp;
}

fn factors(num: u64, primes: &Prime, f: fn((u64, monoid::Sum<i64>)) -> bool) {
    if num == 0 { return; }
    let mut itr = num;
    for primes.each |p| {
        let exp = div_multi(itr, p);
        if exp > 0 {
            if !f((p, monoid::Sum(exp as i64))) { break; }
        }
        if itr == 1  { break; }
    };
}

fn num_of_divisors(num: u64, primes: &Prime) -> u64 {
    if num == 0 { return 0; }
    let mut prod = 1;
    for factors(num, primes) |f| {
        let (_base, exp) = f;
        prod *= (*exp + 1) as u64;
    }
    return prod;
}

fn sum_of_divisors(num: u64, primes: &Prime) -> u64 {
    if num == 0 { return 0; }
    let mut sum = 1;
    for factors(num, primes) |f| {
        let (base, monoid::Sum(exp)) = f;
        sum *= (int::pow(base as int, (exp + 1) as uint) as u64 - 1) / (base - 1);
    }
    return sum;
}

fn sum_of_proper_divisors(num: u64, primes: &Prime) -> u64 {
    sum_of_divisors(num, primes) - num
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_prime_opidx () {
        let table  = [  2,  3,  5,  7, 11, 13, 17, 19, 23, 29, 31, 37, 41 ];
        let ps = Prime();

        // Generated primes
        for table.eachi() |i, p| { assert ps.get_at(i) == p; }
        // Memoized primes
        for table.eachi() |i, p| { assert ps.get_at(i) == p; }
    }

    #[test]
    fn test_prime_each() {
        let table  = ~[  2,  3,  5,  7, 11, 13, 17, 19, 23, 29, 31, 37, 41 ];
        let table2 = ~[ 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 ];
        let ps = Prime();

        let mut v1 = ~[];
        for ps.each |p| {
            if p > table.last() { break; }
            v1 += [ p ];
        }
        assert table == v1;

        let mut v2 = ~[];
        for ps.each |p| {
            if p > table.last() { break; }
            v2 += [ p ];
        }
        assert table == v2;

        let mut v3 = ~[];
        for ps.each |p| {
            if p > table2.last() { break; }
            v3 += [ p ];
        }
        assert table + table2 == v3;
    }

    #[test]
    fn test_prime_is_prime() {
        let p = Prime();
        assert !p.is_prime(0);
        assert !p.is_prime(1);
        assert p.is_prime(2);
        assert p.is_prime(3);
        assert !p.is_prime(4);
        assert p.is_prime(5);
        assert !p.is_prime(6);
        assert p.is_prime(7);
        assert !p.is_prime(100);
    }
}
<|endoftext|>


<commit_before>// pest. The Elegant Parser
// Copyright (c) 2018 Dragoș Tiselice
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

#![feature(test)]

extern crate pest;
extern crate pest_grammars;
extern crate test;

use std::collections::HashMap;
use std::fs::File;
use std::io::Read;

use test::Bencher;

use pest::Parser;
use pest::iterators::Pair;
use pest::span::Span;

use pest_grammars::json::*;

enum Json<'i> {
    Null,
    Bool(bool),
    Number(f64),
    String(Span<'i>),
    Array(Vec<Json<'i>>),
    Object(HashMap<Span<'i>, Json<'i>>)
}

fn consume(pair: Pair<Rule>) -> Json {
    fn value(pair: Pair<Rule>) -> Json {
        let pair = pair.into_inner().next().unwrap();

        match pair.as_rule() {
            Rule::null => Json::Null,
            Rule::bool => match pair.as_str() {
                "false" => Json::Bool(false),
                "true" => Json::Bool(true),
                _ => unreachable!()
            },
            Rule::number => Json::Number(pair.as_str().parse().unwrap()),
            Rule::string => Json::String(pair.into_span()),
            Rule::array => Json::Array(pair.into_inner().map(value).collect()),
            Rule::object => {
                let pairs = pair.into_inner().map(|pos| {
                    let mut pair = pos.into_inner();

                    let key = pair.next().unwrap().into_span();
                    let value = value(pair.next().unwrap());

                    (key, value)
                });

                Json::Object(pairs.collect())
            }
            _ => unreachable!()
        }
    }

    value(pair)
}

#[bench]
fn data(b: &mut Bencher) {
    let mut file = File::open("benches/data.json").unwrap();
    let mut data = String::new();

    file.read_to_string(&mut data).unwrap();

    b.iter(|| {
        consume(
            JsonParser::parse(Rule::json, &data)
                .unwrap()
                .next()
                .unwrap()
        )
    });
}
<commit_msg>Fixed benchmark.<commit_after>// pest. The Elegant Parser
// Copyright (c) 2018 Dragoș Tiselice
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

#![feature(test)]

extern crate pest;
extern crate pest_grammars;
extern crate test;

use std::collections::HashMap;
use std::fs::File;
use std::io::Read;

use test::Bencher;

use pest::Parser;
use pest::iterators::Pair;
use pest::Span;

use pest_grammars::json::*;

enum Json<'i> {
    Null,
    Bool(bool),
    Number(f64),
    String(Span<'i>),
    Array(Vec<Json<'i>>),
    Object(HashMap<Span<'i>, Json<'i>>)
}

fn consume(pair: Pair<Rule>) -> Json {
    fn value(pair: Pair<Rule>) -> Json {
        let pair = pair.into_inner().next().unwrap();

        match pair.as_rule() {
            Rule::null => Json::Null,
            Rule::bool => match pair.as_str() {
                "false" => Json::Bool(false),
                "true" => Json::Bool(true),
                _ => unreachable!()
            },
            Rule::number => Json::Number(pair.as_str().parse().unwrap()),
            Rule::string => Json::String(pair.into_span()),
            Rule::array => Json::Array(pair.into_inner().map(value).collect()),
            Rule::object => {
                let pairs = pair.into_inner().map(|pos| {
                    let mut pair = pos.into_inner();

                    let key = pair.next().unwrap().into_span();
                    let value = value(pair.next().unwrap());

                    (key, value)
                });

                Json::Object(pairs.collect())
            }
            _ => unreachable!()
        }
    }

    value(pair)
}

#[bench]
fn data(b: &mut Bencher) {
    let mut file = File::open("benches/data.json").unwrap();
    let mut data = String::new();

    file.read_to_string(&mut data).unwrap();

    b.iter(|| {
        consume(
            JsonParser::parse(Rule::json, &data)
                .unwrap()
                .next()
                .unwrap()
        )
    });
}
<|endoftext|>


<commit_before>use std::fmt;
use std::any::Any;
use std::error::Error;

use mio::{self, EventLoop, Token, EventSet, Sender};
use mio::util::Slab;

use scope::scope;
use {Scope, Notify, Response, Machine};

pub enum Timeo {
    Fsm(Token),
}

pub struct Handler<Ctx, M>
    where M: Machine<Ctx>
{
    slab: Slab<M>,
    context: Ctx,
    channel: Sender<Notify>,
}

pub struct NoSlabSpace<S:Any+Sized>(pub S);

impl<C, M> Handler<C, M>
    where M: Machine<C>,
{
    pub fn new(context: C, eloop: &mut EventLoop<Handler<C, M>>)
        -> Handler<C, M>
    {
        // TODO(tailhook) create default config from the ulimit data instead
        // of using real defaults
        Handler {
            slab: Slab::new(4096),
            context: context,
            channel: eloop.channel(),
        }
    }
}

impl<C, M> Handler<C, M>
    where M: Machine<C>
{
    pub fn add_machine_with<F>(&mut self,
        eloop: &mut EventLoop<Self>, fun: F) -> Result<(), Box<Error>>
        where F: FnOnce(&mut Scope<C>) -> Result<M, Box<Error>>
    {
        let ref mut ctx = self.context;
        let ref mut chan = self.channel;
        let res = self.slab.insert_with(|token| {
            let ref mut scope = scope(token, ctx, chan, eloop);
            match fun(scope) {
                Ok(x) => x,
                Err(_) => {
                // TODO(tailhook) when Slab::insert_with_opt() lands, fix it
                    panic!("Unimplemented: Slab::insert_with_opt");
                }
            }
        });
        if res.is_some() {
            Ok(())
        } else {
            Err(Box::new(NoSlabSpace(())))
        }
    }

}

fn machine_loop<C, M, F>(handler: &mut Handler<C, M>,
    eloop: &mut EventLoop<Handler<C, M>>, token: Token, fun: F)
    where M: Machine<C>,
          F: FnOnce(M, &mut Scope<C>) -> Response<M, M::Seed>
{
    let mut creator = None;
    {
        let ref mut scope = scope(token, &mut handler.context,
            &mut handler.channel, eloop);
        handler.slab.replace_with(token, |m| {
            let res = fun(m, scope);
            creator = res.1;
            res.0
        }).ok();  // Spurious events are ok in mio
    }
    while let Some(new) = creator.take() {
        let mut new = Some(new);
        let res = handler.add_machine_with(eloop, |scope| {
            M::create(new.take().unwrap(), scope)
        });
        if let Err(mut err) = res {
            if let Some(new) = new.take() {
                err = Box::new(NoSlabSpace(new));
            }
            let ref mut scope = scope(token, &mut handler.context,
                &mut handler.channel, eloop);
            handler.slab.replace_with(token, |m| {
                m.spawn_error(scope, err)
            }).ok();
            break;
        } else {
            let ref mut scope = scope(token, &mut handler.context,
                &mut handler.channel, eloop);
            handler.slab.replace_with(token, |m| {
                let res = m.spawned(scope);
                creator = res.1;
                res.0
            }).ok();
        }
    }
}

impl<Ctx, M> mio::Handler for Handler<Ctx, M>
    where M: Machine<Ctx>
{
    type Message = Notify;
    type Timeout = Timeo;
    fn ready<'x>(&mut self, eloop: &'x mut EventLoop<Self>,
        token: Token, events: EventSet)
    {
        machine_loop(self, eloop, token, |m, scope| { m.ready(events, scope) })
    }

    fn notify(&mut self, eloop: &mut EventLoop<Self>, msg: Notify) {
        match msg {
            Notify::Fsm(token) => {
                machine_loop(self, eloop, token,
                    |m, scope| { m.wakeup(scope) })
            }
        }
    }

    fn timeout(&mut self, eloop: &mut EventLoop<Self>, timeo: Timeo) {
        match timeo {
            Timeo::Fsm(token) => {
                machine_loop(self, eloop, token,
                    |m, scope| { m.timeout(scope) })
            }
        }
    }
}

impl<S:Any+Sized> fmt::Debug for NoSlabSpace<S> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "NoSlabSpace(<hidden seed>)")
    }
}
impl<S:Any+Sized> fmt::Display for NoSlabSpace<S> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "no slab space available")
    }
}
impl<S:Any+Sized> Error for NoSlabSpace<S> {
    fn description(&self) -> &'static str {
        "no slab space available"
    }
    fn cause(&self) -> Option<&Error> {
        None
    }
}
<commit_msg>Add new_with_capacity constructor of handler<commit_after>use std::fmt;
use std::any::Any;
use std::error::Error;

use mio::{self, EventLoop, Token, EventSet, Sender};
use mio::util::Slab;

use scope::scope;
use {Scope, Notify, Response, Machine};

pub enum Timeo {
    Fsm(Token),
}

pub struct Handler<Ctx, M>
    where M: Machine<Ctx>
{
    slab: Slab<M>,
    context: Ctx,
    channel: Sender<Notify>,
}

pub struct NoSlabSpace<S:Any+Sized>(pub S);

impl<C, M> Handler<C, M>
    where M: Machine<C>,
{
    pub fn new_with_capacity(context: C, eloop: &mut EventLoop<Handler<C, M>>,
        capacity: usize)
        -> Handler<C, M>
    {
        Handler {
            slab: Slab::new(capacity),
            context: context,
            channel: eloop.channel(),
        }
    }
    pub fn new(context: C, eloop: &mut EventLoop<Handler<C, M>>)
        -> Handler<C, M>
    {
        // TODO(tailhook) create default config from the ulimit data instead
        // of using real defaults
        Handler {
            slab: Slab::new(4096),
            context: context,
            channel: eloop.channel(),
        }
    }
}

impl<C, M> Handler<C, M>
    where M: Machine<C>
{
    pub fn add_machine_with<F>(&mut self,
        eloop: &mut EventLoop<Self>, fun: F) -> Result<(), Box<Error>>
        where F: FnOnce(&mut Scope<C>) -> Result<M, Box<Error>>
    {
        let ref mut ctx = self.context;
        let ref mut chan = self.channel;
        let res = self.slab.insert_with(|token| {
            let ref mut scope = scope(token, ctx, chan, eloop);
            match fun(scope) {
                Ok(x) => x,
                Err(_) => {
                // TODO(tailhook) when Slab::insert_with_opt() lands, fix it
                    panic!("Unimplemented: Slab::insert_with_opt");
                }
            }
        });
        if res.is_some() {
            Ok(())
        } else {
            Err(Box::new(NoSlabSpace(())))
        }
    }

}

fn machine_loop<C, M, F>(handler: &mut Handler<C, M>,
    eloop: &mut EventLoop<Handler<C, M>>, token: Token, fun: F)
    where M: Machine<C>,
          F: FnOnce(M, &mut Scope<C>) -> Response<M, M::Seed>
{
    let mut creator = None;
    {
        let ref mut scope = scope(token, &mut handler.context,
            &mut handler.channel, eloop);
        handler.slab.replace_with(token, |m| {
            let res = fun(m, scope);
            creator = res.1;
            res.0
        }).ok();  // Spurious events are ok in mio
    }
    while let Some(new) = creator.take() {
        let mut new = Some(new);
        let res = handler.add_machine_with(eloop, |scope| {
            M::create(new.take().unwrap(), scope)
        });
        if let Err(mut err) = res {
            if let Some(new) = new.take() {
                err = Box::new(NoSlabSpace(new));
            }
            let ref mut scope = scope(token, &mut handler.context,
                &mut handler.channel, eloop);
            handler.slab.replace_with(token, |m| {
                m.spawn_error(scope, err)
            }).ok();
            break;
        } else {
            let ref mut scope = scope(token, &mut handler.context,
                &mut handler.channel, eloop);
            handler.slab.replace_with(token, |m| {
                let res = m.spawned(scope);
                creator = res.1;
                res.0
            }).ok();
        }
    }
}

impl<Ctx, M> mio::Handler for Handler<Ctx, M>
    where M: Machine<Ctx>
{
    type Message = Notify;
    type Timeout = Timeo;
    fn ready<'x>(&mut self, eloop: &'x mut EventLoop<Self>,
        token: Token, events: EventSet)
    {
        machine_loop(self, eloop, token, |m, scope| { m.ready(events, scope) })
    }

    fn notify(&mut self, eloop: &mut EventLoop<Self>, msg: Notify) {
        match msg {
            Notify::Fsm(token) => {
                machine_loop(self, eloop, token,
                    |m, scope| { m.wakeup(scope) })
            }
        }
    }

    fn timeout(&mut self, eloop: &mut EventLoop<Self>, timeo: Timeo) {
        match timeo {
            Timeo::Fsm(token) => {
                machine_loop(self, eloop, token,
                    |m, scope| { m.timeout(scope) })
            }
        }
    }
}

impl<S:Any+Sized> fmt::Debug for NoSlabSpace<S> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "NoSlabSpace(<hidden seed>)")
    }
}
impl<S:Any+Sized> fmt::Display for NoSlabSpace<S> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "no slab space available")
    }
}
impl<S:Any+Sized> Error for NoSlabSpace<S> {
    fn description(&self) -> &'static str {
        "no slab space available"
    }
    fn cause(&self) -> Option<&Error> {
        None
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::fmt::{self, Debug, Formatter};
use std::marker::PhantomData;
use std::ops::RangeFrom;
use {Command, Error, Record};

const ORIGIN: usize = 0;

/// A history of commands.
#[derive(Debug)]
pub struct History<R> {
    id: usize,
    parent: usize,
    next: RangeFrom<usize>,
    record: Record<R>,
    branches: HashMap<usize, Branch<R>>,
}

impl<R> History<R> {
    /// Returns a new history.
    #[inline]
    pub fn new(receiver: impl Into<R>) -> History<R> {
        History {
            id: ORIGIN,
            parent: ORIGIN,
            next: 1..,
            record: Record::new(receiver),
            branches: HashMap::new(),
        }
    }

    /// Pushes the command to the top of the history and executes its [`apply`] method.
    /// The command is merged with the previous top command if they have the same [`id`].
    ///
    /// # Errors
    /// If an error occur when executing [`apply`] the error is returned together with the command.
    ///
    /// [`apply`]: trait.Command.html#tymethod.apply
    /// [`id`]: trait.Command.html#method.id
    #[inline]
    pub fn apply(&mut self, cmd: impl Command<R> + 'static) -> Result<Option<usize>, Error<R>>
    where
        R: 'static,
    {
        let cursor = self.record.cursor();
        let commands = self.record.apply(cmd)?;
        let commands: Vec<_> = commands.collect();
        if !commands.is_empty() {
            let id = self.next.next().unwrap();
            self.branches.insert(
                id,
                Branch {
                    parent: self.id,
                    cursor,
                    commands,
                },
            );
            Ok(Some(id))
        } else {
            Ok(None)
        }
    }

    /// Calls the [`undo`] method for the active command and sets the previous one as the new active one.
    ///
    /// # Errors
    /// If an error occur when executing [`undo`] the error is returned together with the command.
    ///
    /// [`undo`]: trait.Command.html#tymethod.undo
    #[inline]
    #[must_use]
    pub fn undo(&mut self) -> Option<Result<(), Error<R>>> {
        self.record.undo()
    }

    /// Calls the [`redo`] method for the active command and sets the next one as the
    /// new active one.
    ///
    /// # Errors
    /// If an error occur when executing [`redo`] the error is returned together with the command.
    ///
    /// [`redo`]: trait.Command.html#method.redo
    #[inline]
    #[must_use]
    pub fn redo(&mut self) -> Option<Result<(), Error<R>>> {
        self.record.redo()
    }

    /// Jumps to the command in `branch` at `cursor`.
    #[inline]
    #[must_use]
    pub fn jump_to(&mut self, mut branch: usize, cursor: usize) -> Option<Result<(), Error<R>>>
    where
        R: 'static,
    {
        if self.id == branch {
            return self.record.set_cursor(cursor);
        }

        let mut dest = self.branches.remove(&branch)?;
        branch = dest.parent;
        let mut path = vec![dest];
        while branch != ORIGIN {
            dest = self.branches.remove(&branch).unwrap();
            path.push(dest);
        }

        if self.id != ORIGIN {
            let mut start = self.branches.remove(&self.parent).unwrap();
            branch = start.parent;
            let mut tmp = vec![start];
            while branch != ORIGIN {
                start = self.branches.remove(&branch).unwrap();
                tmp.push(start);
            }
            tmp.reverse();
            path.append(&mut tmp);
        }

        while let Some(branch) = path.pop() {
            // Walk the path from `start` to `dest`.
            if let Err(err) = self.record.set_cursor(branch.cursor).unwrap() {
                return Some(Err(err));
            }

            for cmd in branch.commands {
                if let Err(err) = self.apply(cmd) {
                    return Some(Err(err));
                }
            }
        }

        Some(Ok(()))
    }
}

impl<R: Default> Default for History<R> {
    #[inline]
    fn default() -> History<R> {
        History::new(R::default())
    }
}

impl<R> From<R> for History<R> {
    #[inline]
    fn from(receiver: R) -> Self {
        History::new(receiver)
    }
}

struct Branch<R> {
    parent: usize,
    cursor: usize,
    commands: Vec<Box<dyn Command<R> + 'static>>,
}

impl<R> Debug for Branch<R> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        f.debug_struct("Branch")
            .field("parent", &self.parent)
            .field("cursor", &self.cursor)
            .field("commands", &self.commands)
            .finish()
    }
}

/// Builder for a history.
#[derive(Debug)]
pub struct HistoryBuilder<R> {
    receiver: PhantomData<R>,
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::error::Error;

    #[derive(Debug)]
    struct Add(char);

    impl Command<String> for Add {
        fn apply(&mut self, receiver: &mut String) -> Result<(), Box<dyn Error>> {
            receiver.push(self.0);
            Ok(())
        }

        fn undo(&mut self, receiver: &mut String) -> Result<(), Box<dyn Error>> {
            self.0 = receiver.pop().ok_or("`receiver` is empty")?;
            Ok(())
        }
    }

    #[test]
    fn jump_to() {
        let mut history = History::default();
        history.apply(Add('a')).unwrap();
        history.apply(Add('b')).unwrap();
        history.apply(Add('c')).unwrap();
        history.apply(Add('d')).unwrap();
        history.apply(Add('e')).unwrap();

        history.undo().unwrap().unwrap();
        history.undo().unwrap().unwrap();

        let b = history.apply(Add('f')).unwrap().unwrap();
        history.apply(Add('g')).unwrap();

        history.jump_to(b, 5).unwrap().unwrap();
    }
}
<commit_msg>Add more comments to jump_to<commit_after>use std::collections::HashMap;
use std::fmt::{self, Debug, Formatter};
use std::marker::PhantomData;
use std::ops::RangeFrom;
use {Command, Error, Record};

const ORIGIN: usize = 0;

/// A history of commands.
#[derive(Debug)]
pub struct History<R> {
    id: usize,
    parent: usize,
    next: RangeFrom<usize>,
    record: Record<R>,
    branches: HashMap<usize, Branch<R>>,
}

impl<R> History<R> {
    /// Returns a new history.
    #[inline]
    pub fn new(receiver: impl Into<R>) -> History<R> {
        History {
            id: ORIGIN,
            parent: ORIGIN,
            next: 1..,
            record: Record::new(receiver),
            branches: HashMap::new(),
        }
    }

    /// Pushes the command to the top of the history and executes its [`apply`] method.
    /// The command is merged with the previous top command if they have the same [`id`].
    ///
    /// # Errors
    /// If an error occur when executing [`apply`] the error is returned together with the command.
    ///
    /// [`apply`]: trait.Command.html#tymethod.apply
    /// [`id`]: trait.Command.html#method.id
    #[inline]
    pub fn apply(&mut self, cmd: impl Command<R> + 'static) -> Result<Option<usize>, Error<R>>
    where
        R: 'static,
    {
        let cursor = self.record.cursor();
        let commands = self.record.apply(cmd)?;
        let commands: Vec<_> = commands.collect();
        if !commands.is_empty() {
            let id = self.next.next().unwrap();
            self.branches.insert(
                id,
                Branch {
                    parent: self.id,
                    cursor,
                    commands,
                },
            );
            Ok(Some(id))
        } else {
            Ok(None)
        }
    }

    /// Calls the [`undo`] method for the active command and sets the previous one as the new active one.
    ///
    /// # Errors
    /// If an error occur when executing [`undo`] the error is returned together with the command.
    ///
    /// [`undo`]: trait.Command.html#tymethod.undo
    #[inline]
    #[must_use]
    pub fn undo(&mut self) -> Option<Result<(), Error<R>>> {
        self.record.undo()
    }

    /// Calls the [`redo`] method for the active command and sets the next one as the
    /// new active one.
    ///
    /// # Errors
    /// If an error occur when executing [`redo`] the error is returned together with the command.
    ///
    /// [`redo`]: trait.Command.html#method.redo
    #[inline]
    #[must_use]
    pub fn redo(&mut self) -> Option<Result<(), Error<R>>> {
        self.record.redo()
    }

    /// Jumps to the command in `branch` at `cursor`.
    #[inline]
    #[must_use]
    pub fn jump_to(&mut self, mut branch: usize, cursor: usize) -> Option<Result<(), Error<R>>>
    where
        R: 'static,
    {
        if self.id == branch {
            return self.record.set_cursor(cursor);
        }

        // Find the path from `dest` to `ORIGIN`.
        let mut dest = self.branches.remove(&branch)?;
        branch = dest.parent;
        let mut path = vec![dest];
        while branch != ORIGIN {
            dest = self.branches.remove(&branch).unwrap();
            path.push(dest);
        }

        // Find the path from `start` to `ORIGIN`.
        if self.id != ORIGIN {
            let mut start = self.branches.remove(&self.parent).unwrap();
            branch = start.parent;
            let mut tmp = vec![start];
            while branch != ORIGIN {
                start = self.branches.remove(&branch).unwrap();
                tmp.push(start);
            }
            tmp.reverse();
            path.append(&mut tmp);
        }

        // Walk the path from `start` to `dest`.
        while let Some(dest) = path.pop() {
            // Move to `dest.cursor` either by undoing or redoing.
            if let Err(err) = self.record.set_cursor(dest.cursor).unwrap() {
                return Some(Err(err));
            }
            // Apply the commands in the branch and move older commands into their own branch.
            for cmd in dest.commands {
                if let Err(err) = self.apply(cmd) {
                    return Some(Err(err));
                }
            }
        }

        Some(Ok(()))
    }
}

impl<R: Default> Default for History<R> {
    #[inline]
    fn default() -> History<R> {
        History::new(R::default())
    }
}

impl<R> From<R> for History<R> {
    #[inline]
    fn from(receiver: R) -> Self {
        History::new(receiver)
    }
}

struct Branch<R> {
    parent: usize,
    cursor: usize,
    commands: Vec<Box<dyn Command<R> + 'static>>,
}

impl<R> Debug for Branch<R> {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        f.debug_struct("Branch")
            .field("parent", &self.parent)
            .field("cursor", &self.cursor)
            .field("commands", &self.commands)
            .finish()
    }
}

/// Builder for a history.
#[derive(Debug)]
pub struct HistoryBuilder<R> {
    receiver: PhantomData<R>,
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::error::Error;

    #[derive(Debug)]
    struct Add(char);

    impl Command<String> for Add {
        fn apply(&mut self, receiver: &mut String) -> Result<(), Box<dyn Error>> {
            receiver.push(self.0);
            Ok(())
        }

        fn undo(&mut self, receiver: &mut String) -> Result<(), Box<dyn Error>> {
            self.0 = receiver.pop().ok_or("`receiver` is empty")?;
            Ok(())
        }
    }

    #[test]
    fn jump_to() {
        let mut history = History::default();
        history.apply(Add('a')).unwrap();
        history.apply(Add('b')).unwrap();
        history.apply(Add('c')).unwrap();
        history.apply(Add('d')).unwrap();
        history.apply(Add('e')).unwrap();

        history.undo().unwrap().unwrap();
        history.undo().unwrap().unwrap();

        let b = history.apply(Add('f')).unwrap().unwrap();
        history.apply(Add('g')).unwrap();

        history.jump_to(b, 5).unwrap().unwrap();
    }
}
<|endoftext|>


<commit_before>//! Implements `Syscalls` for all types that implement `RawSyscalls`.

use crate::{
    allow_rw, exit_id, exit_on_drop, return_variant, share, subscribe, syscall_class, yield_id,
    AllowRw, CommandReturn, ErrorCode, RawSyscalls, Register, ReturnVariant, Subscribe, Syscalls,
    Upcall, YieldNoWaitReturn,
};

impl<S: RawSyscalls> Syscalls for S {
    // -------------------------------------------------------------------------
    // Yield
    // -------------------------------------------------------------------------

    fn yield_no_wait() -> YieldNoWaitReturn {
        let mut flag = core::mem::MaybeUninit::<YieldNoWaitReturn>::uninit();

        unsafe {
            // Flag can be uninitialized here because the kernel promises to
            // only write to it, not read from it. MaybeUninit guarantees that
            // it is safe to write a YieldNoWaitReturn into it.
            Self::yield2([yield_id::NO_WAIT.into(), flag.as_mut_ptr().into()]);

            // yield-no-wait guarantees it sets (initializes) flag before
            // returning.
            flag.assume_init()
        }
    }

    fn yield_wait() {
        // Safety: yield-wait does not return a value, which satisfies yield1's
        // requirement. The yield-wait system call cannot trigger undefined
        // behavior on its own in any other way.
        unsafe {
            Self::yield1([yield_id::WAIT.into()]);
        }
    }

    // -------------------------------------------------------------------------
    // Subscribe
    // -------------------------------------------------------------------------

    fn subscribe<
        'share,
        IDS: subscribe::SupportsId<DRIVER_NUM, SUBSCRIBE_NUM>,
        U: Upcall<IDS>,
        CONFIG: subscribe::Config,
        const DRIVER_NUM: u32,
        const SUBSCRIBE_NUM: u32,
    >(
        _subscribe: share::Handle<Subscribe<'share, Self, DRIVER_NUM, SUBSCRIBE_NUM>>,
        upcall: &'share U,
    ) -> Result<(), ErrorCode> {
        // The upcall function passed to the Tock kernel.
        //
        // Safety: data must be a reference to a valid instance of U.
        unsafe extern "C" fn kernel_upcall<S: Syscalls, IDS, U: Upcall<IDS>>(
            arg0: u32,
            arg1: u32,
            arg2: u32,
            data: Register,
        ) {
            let exit: exit_on_drop::ExitOnDrop<S> = Default::default();
            let upcall: *const U = data.into();
            unsafe { &*upcall }.upcall(arg0, arg1, arg2);
            core::mem::forget(exit);
        }

        // Inner function that does the majority of the work. This is not
        // monomorphized over DRIVER_NUM and SUBSCRIBE_NUM to keep code size
        // small.
        //
        // Safety: upcall_fcn must be kernel_upcall<S, IDS, U> and upcall_data
        // must be a reference to an instance of U that will remain valid as
        // long as the 'scope lifetime is alive. Can only be called if a
        // Subscribe<'scope, S, driver_num, subscribe_num> exists.
        unsafe fn inner<S: Syscalls, CONFIG: subscribe::Config>(
            driver_num: u32,
            subscribe_num: u32,
            upcall_fcn: Register,
            upcall_data: Register,
        ) -> Result<(), ErrorCode> {
            // Safety: syscall4's documentation indicates it can be used to call
            // Subscribe. These arguments follow TRD104. kernel_upcall has the
            // required signature. This function's preconditions mean that
            // upcall is a reference to an instance of U that will remain valid
            // until the 'scope lifetime is alive The existence of the
            // Subscribe<'scope, Self, DRIVER_NUM, SUBSCRIBE_NUM> guarantees
            // that if this Subscribe succeeds then the upcall will be cleaned
            // up before the 'scope lifetime ends, guaranteeing that upcall is
            // still alive when kernel_upcall is invoked.
            let [r0, r1, _, _] = unsafe {
                S::syscall4::<{ syscall_class::SUBSCRIBE }>([
                    driver_num.into(),
                    subscribe_num.into(),
                    upcall_fcn,
                    upcall_data,
                ])
            };

            let return_variant: ReturnVariant = r0.as_u32().into();
            // TRD 104 guarantees that Subscribe returns either Success with 2
            // U32 or Failure with 2 U32. We check the return variant by
            // comparing against Failure with 2 U32 for 2 reasons:
            //
            //   1. On RISC-V with compressed instructions, it generates smaller
            //      code. FAILURE_2_U32 has value 2, which can be loaded into a
            //      register with a single compressed instruction, whereas
            //      loading SUCCESS_2_U32 uses an uncompressed instruction.
            //   2. In the event the kernel malfuctions and returns a different
            //      return variant, the success path is actually safer than the
            //      failure path. The failure path assumes that r1 contains an
            //      ErrorCode, and produces UB if it has an out of range value.
            //      Incorrectly assuming the call succeeded will not generate
            //      unsoundness, and will likely lead to the application
            //      hanging.
            if return_variant == return_variant::FAILURE_2_U32 {
                // Safety: TRD 104 guarantees that if r0 is Failure with 2 U32,
                // then r1 will contain a valid error code. ErrorCode is
                // designed to be safely transmuted directly from a kernel error
                // code.
                return Err(unsafe { core::mem::transmute(r1.as_u32() as u16) });
            }

            // r0 indicates Success with 2 u32s. Confirm the null upcall was
            // returned, and it if wasn't then call the configured function.
            // We're relying on the optimizer to remove this branch if
            // returned_nonnull_upcall is a no-op.
            // Note: TRD 104 specifies that the null upcall has address 0,
            // not necessarily a null pointer.
            let returned_upcall: usize = r1.into();
            if returned_upcall != 0usize {
                CONFIG::returned_nonnull_upcall(driver_num, subscribe_num);
            }
            Ok(())
        }

        let upcall_fcn = (kernel_upcall::<S, IDS, U> as usize).into();
        let upcall_data = (upcall as *const U).into();
        // Safety: upcall's type guarantees it is a reference to a U that will
        // remain valid for at least the 'scope lifetime. _subscribe is a
        // reference to a Subscribe<'scope, Self, DRIVER_NUM, SUBSCRIBE_NUM>,
        // proving one exists. upcall_fcn and upcall_data are derived in ways
        // that satisfy inner's requirements.
        unsafe { inner::<Self, CONFIG>(DRIVER_NUM, SUBSCRIBE_NUM, upcall_fcn, upcall_data) }
    }

    fn unsubscribe(driver_num: u32, subscribe_num: u32) {
        unsafe {
            // syscall4's documentation indicates it can be used to call
            // Subscribe. The upcall pointer passed is the null upcall, which
            // cannot cause undefined behavior on its own.
            Self::syscall4::<{ syscall_class::SUBSCRIBE }>([
                driver_num.into(),
                subscribe_num.into(),
                0usize.into(),
                0usize.into(),
            ]);
        }
    }

    // -------------------------------------------------------------------------
    // Command
    // -------------------------------------------------------------------------

    fn command(driver_id: u32, command_id: u32, argument0: u32, argument1: u32) -> CommandReturn {
        unsafe {
            // syscall4's documentation indicates it can be used to call
            // Command. The Command system call cannot trigger undefined
            // behavior on its own.
            let [r0, r1, r2, r3] = Self::syscall4::<{ syscall_class::COMMAND }>([
                driver_id.into(),
                command_id.into(),
                argument0.into(),
                argument1.into(),
            ]);

            // Because r0 and r1 are returned directly from the kernel, we are
            // guaranteed that if r0 represents a failure variant then r1 is an
            // error code.
            CommandReturn::new(r0.as_u32().into(), r1.as_u32(), r2.as_u32(), r3.as_u32())
        }
    }

    // -------------------------------------------------------------------------
    // Read-Write Allow
    // -------------------------------------------------------------------------

    fn allow_rw<'share, CONFIG: allow_rw::Config, const DRIVER_NUM: u32, const BUFFER_NUM: u32>(
        _allow_rw: share::Handle<AllowRw<'share, Self, DRIVER_NUM, BUFFER_NUM>>,
        buffer: &'share mut [u8],
    ) -> Result<(), ErrorCode> {
        // Inner function that does the majority of the work. This is not
        // monomorphized over DRIVER_NUM and BUFFER_NUM to keep code size small.
        //
        // Safety: A share::Handle<AllowRw<'share, S, driver_num, buffer_num>>
        // must exist, and `buffer` must last for at least the 'share lifetime.
        unsafe fn inner<S: Syscalls, CONFIG: allow_rw::Config>(
            driver_num: u32,
            buffer_num: u32,
            buffer: &mut [u8],
        ) -> Result<(), ErrorCode> {
            // Safety: syscall4's documentation indicates it can be used to call
            // Read-Write Allow. These arguments follow TRD104.
            let [r0, r1, r2, _] = unsafe {
                S::syscall4::<{ syscall_class::ALLOW_RW }>([
                    driver_num.into(),
                    buffer_num.into(),
                    buffer.as_mut_ptr().into(),
                    buffer.len().into(),
                ])
            };

            let return_variant: ReturnVariant = r0.as_u32().into();
            // TRD 104 guarantees that Read-Write Allow returns either Success
            // with 2 U32 or Failure with 2 U32. We check the return variant by
            // comparing against Failure with 2 U32 for 2 reasons:
            //
            //   1. On RISC-V with compressed instructions, it generates smaller
            //      code. FAILURE_2_U32 has value 2, which can be loaded into a
            //      register with a single compressed instruction, whereas
            //      loading SUCCESS_2_U32 uses an uncompressed instruction.
            //   2. In the event the kernel malfuctions and returns a different
            //      return variant, the success path is actually safer than the
            //      failure path. The failure path assumes that r1 contains an
            //      ErrorCode, and produces UB if it has an out of range value.
            //      Incorrectly assuming the call succeeded will not generate
            //      unsoundness, and will likely lead to the application
            //      panicing.
            if return_variant == return_variant::FAILURE_2_U32 {
                // Safety: TRD 104 guarantees that if r0 is Failure with 2 U32,
                // then r1 will contain a valid error code. ErrorCode is
                // designed to be safely transmuted directly from a kernel error
                // code.
                return Err(unsafe { core::mem::transmute(r1.as_u32() as u16) });
            }

            // r0 indicates Success with 2 u32s. Confirm a zero buffer was
            // returned, and it if wasn't then call the configured function.
            // We're relying on the optimizer to remove this branch if
            // returned_nozero_buffer is a no-op.
            let returned_buffer: (usize, usize) = (r1.into(), r2.into());
            if returned_buffer != (0, 0) {
                CONFIG::returned_nonzero_buffer(driver_num, buffer_num);
            }
            Ok(())
        }

        // Safety: The presence of the share::Handle<AllowRw<'share, ...>>
        // guarantees that an AllowRw exists and will clean up this Allow ID
        // before the 'share lifetime ends.
        unsafe { inner::<Self, CONFIG>(DRIVER_NUM, BUFFER_NUM, buffer) }
    }

    fn unallow_rw(driver_num: u32, buffer_num: u32) {
        unsafe {
            // syscall4's documentation indicates it can be used to call
            // Read-Write Allow. The buffer passed has 0 length, which cannot
            // cause undefined behavior on its own.
            Self::syscall4::<{ syscall_class::ALLOW_RW }>([
                driver_num.into(),
                buffer_num.into(),
                0usize.into(),
                0usize.into(),
            ]);
        }
    }

    // -------------------------------------------------------------------------
    // Exit
    // -------------------------------------------------------------------------

    fn exit_terminate(exit_code: u32) -> ! {
        unsafe {
            // syscall2's documentation indicates it can be used to call Exit.
            // The exit system call cannot trigger undefined behavior on its
            // own.
            Self::syscall2::<{ syscall_class::EXIT }>([
                exit_id::TERMINATE.into(),
                exit_code.into(),
            ]);
            // TRD104 indicates that exit-terminate MUST always succeed and so
            // never return.
            core::hint::unreachable_unchecked()
        }
    }

    fn exit_restart(exit_code: u32) -> ! {
        unsafe {
            // syscall2's documentation indicates it can be used to call Exit.
            // The exit system call cannot trigger undefined behavior on its
            // own.
            Self::syscall2::<{ syscall_class::EXIT }>([exit_id::RESTART.into(), exit_code.into()]);
            // TRD104 indicates that exit-restart MUST always succeed and so
            // never return.
            core::hint::unreachable_unchecked()
        }
    }
}
<commit_msg>Mark the RW allow implementation with #'s so that git can better merge RO allow and RW allow.<commit_after>//! Implements `Syscalls` for all types that implement `RawSyscalls`.

use crate::{
    allow_rw, exit_id, exit_on_drop, return_variant, share, subscribe, syscall_class, yield_id,
    AllowRw, CommandReturn, ErrorCode, RawSyscalls, Register, ReturnVariant, Subscribe, Syscalls,
    Upcall, YieldNoWaitReturn,
};

impl<S: RawSyscalls> Syscalls for S {
    // -------------------------------------------------------------------------
    // Yield
    // -------------------------------------------------------------------------

    fn yield_no_wait() -> YieldNoWaitReturn {
        let mut flag = core::mem::MaybeUninit::<YieldNoWaitReturn>::uninit();

        unsafe {
            // Flag can be uninitialized here because the kernel promises to
            // only write to it, not read from it. MaybeUninit guarantees that
            // it is safe to write a YieldNoWaitReturn into it.
            Self::yield2([yield_id::NO_WAIT.into(), flag.as_mut_ptr().into()]);

            // yield-no-wait guarantees it sets (initializes) flag before
            // returning.
            flag.assume_init()
        }
    }

    fn yield_wait() {
        // Safety: yield-wait does not return a value, which satisfies yield1's
        // requirement. The yield-wait system call cannot trigger undefined
        // behavior on its own in any other way.
        unsafe {
            Self::yield1([yield_id::WAIT.into()]);
        }
    }

    // -------------------------------------------------------------------------
    // Subscribe
    // -------------------------------------------------------------------------

    fn subscribe<
        'share,
        IDS: subscribe::SupportsId<DRIVER_NUM, SUBSCRIBE_NUM>,
        U: Upcall<IDS>,
        CONFIG: subscribe::Config,
        const DRIVER_NUM: u32,
        const SUBSCRIBE_NUM: u32,
    >(
        _subscribe: share::Handle<Subscribe<'share, Self, DRIVER_NUM, SUBSCRIBE_NUM>>,
        upcall: &'share U,
    ) -> Result<(), ErrorCode> {
        // The upcall function passed to the Tock kernel.
        //
        // Safety: data must be a reference to a valid instance of U.
        unsafe extern "C" fn kernel_upcall<S: Syscalls, IDS, U: Upcall<IDS>>(
            arg0: u32,
            arg1: u32,
            arg2: u32,
            data: Register,
        ) {
            let exit: exit_on_drop::ExitOnDrop<S> = Default::default();
            let upcall: *const U = data.into();
            unsafe { &*upcall }.upcall(arg0, arg1, arg2);
            core::mem::forget(exit);
        }

        // Inner function that does the majority of the work. This is not
        // monomorphized over DRIVER_NUM and SUBSCRIBE_NUM to keep code size
        // small.
        //
        // Safety: upcall_fcn must be kernel_upcall<S, IDS, U> and upcall_data
        // must be a reference to an instance of U that will remain valid as
        // long as the 'scope lifetime is alive. Can only be called if a
        // Subscribe<'scope, S, driver_num, subscribe_num> exists.
        unsafe fn inner<S: Syscalls, CONFIG: subscribe::Config>(
            driver_num: u32,
            subscribe_num: u32,
            upcall_fcn: Register,
            upcall_data: Register,
        ) -> Result<(), ErrorCode> {
            // Safety: syscall4's documentation indicates it can be used to call
            // Subscribe. These arguments follow TRD104. kernel_upcall has the
            // required signature. This function's preconditions mean that
            // upcall is a reference to an instance of U that will remain valid
            // until the 'scope lifetime is alive The existence of the
            // Subscribe<'scope, Self, DRIVER_NUM, SUBSCRIBE_NUM> guarantees
            // that if this Subscribe succeeds then the upcall will be cleaned
            // up before the 'scope lifetime ends, guaranteeing that upcall is
            // still alive when kernel_upcall is invoked.
            let [r0, r1, _, _] = unsafe {
                S::syscall4::<{ syscall_class::SUBSCRIBE }>([
                    driver_num.into(),
                    subscribe_num.into(),
                    upcall_fcn,
                    upcall_data,
                ])
            };

            let return_variant: ReturnVariant = r0.as_u32().into();
            // TRD 104 guarantees that Subscribe returns either Success with 2
            // U32 or Failure with 2 U32. We check the return variant by
            // comparing against Failure with 2 U32 for 2 reasons:
            //
            //   1. On RISC-V with compressed instructions, it generates smaller
            //      code. FAILURE_2_U32 has value 2, which can be loaded into a
            //      register with a single compressed instruction, whereas
            //      loading SUCCESS_2_U32 uses an uncompressed instruction.
            //   2. In the event the kernel malfuctions and returns a different
            //      return variant, the success path is actually safer than the
            //      failure path. The failure path assumes that r1 contains an
            //      ErrorCode, and produces UB if it has an out of range value.
            //      Incorrectly assuming the call succeeded will not generate
            //      unsoundness, and will likely lead to the application
            //      hanging.
            if return_variant == return_variant::FAILURE_2_U32 {
                // Safety: TRD 104 guarantees that if r0 is Failure with 2 U32,
                // then r1 will contain a valid error code. ErrorCode is
                // designed to be safely transmuted directly from a kernel error
                // code.
                return Err(unsafe { core::mem::transmute(r1.as_u32() as u16) });
            }

            // r0 indicates Success with 2 u32s. Confirm the null upcall was
            // returned, and it if wasn't then call the configured function.
            // We're relying on the optimizer to remove this branch if
            // returned_nonnull_upcall is a no-op.
            // Note: TRD 104 specifies that the null upcall has address 0,
            // not necessarily a null pointer.
            let returned_upcall: usize = r1.into();
            if returned_upcall != 0usize {
                CONFIG::returned_nonnull_upcall(driver_num, subscribe_num);
            }
            Ok(())
        }

        let upcall_fcn = (kernel_upcall::<S, IDS, U> as usize).into();
        let upcall_data = (upcall as *const U).into();
        // Safety: upcall's type guarantees it is a reference to a U that will
        // remain valid for at least the 'scope lifetime. _subscribe is a
        // reference to a Subscribe<'scope, Self, DRIVER_NUM, SUBSCRIBE_NUM>,
        // proving one exists. upcall_fcn and upcall_data are derived in ways
        // that satisfy inner's requirements.
        unsafe { inner::<Self, CONFIG>(DRIVER_NUM, SUBSCRIBE_NUM, upcall_fcn, upcall_data) }
    }

    fn unsubscribe(driver_num: u32, subscribe_num: u32) {
        unsafe {
            // syscall4's documentation indicates it can be used to call
            // Subscribe. The upcall pointer passed is the null upcall, which
            // cannot cause undefined behavior on its own.
            Self::syscall4::<{ syscall_class::SUBSCRIBE }>([
                driver_num.into(),
                subscribe_num.into(),
                0usize.into(),
                0usize.into(),
            ]);
        }
    }

    // -------------------------------------------------------------------------
    // Command
    // -------------------------------------------------------------------------

    fn command(driver_id: u32, command_id: u32, argument0: u32, argument1: u32) -> CommandReturn {
        unsafe {
            // syscall4's documentation indicates it can be used to call
            // Command. The Command system call cannot trigger undefined
            // behavior on its own.
            let [r0, r1, r2, r3] = Self::syscall4::<{ syscall_class::COMMAND }>([
                driver_id.into(),
                command_id.into(),
                argument0.into(),
                argument1.into(),
            ]);

            // Because r0 and r1 are returned directly from the kernel, we are
            // guaranteed that if r0 represents a failure variant then r1 is an
            // error code.
            CommandReturn::new(r0.as_u32().into(), r1.as_u32(), r2.as_u32(), r3.as_u32())
        }
    }

#	// -------------------------------------------------------------------------
#	// Read-Write Allow
#	// -------------------------------------------------------------------------
#
#	fn allow_rw<'share, CONFIG: allow_rw::Config, const DRIVER_NUM: u32, const BUFFER_NUM: u32>(
#		_allow_rw: share::Handle<AllowRw<'share, Self, DRIVER_NUM, BUFFER_NUM>>,
#		buffer: &'share mut [u8],
#	) -> Result<(), ErrorCode> {
#		// Inner function that does the majority of the work. This is not
#		// monomorphized over DRIVER_NUM and BUFFER_NUM to keep code size small.
#		//
#		// Safety: A share::Handle<AllowRw<'share, S, driver_num, buffer_num>>
#		// must exist, and `buffer` must last for at least the 'share lifetime.
#		unsafe fn inner<S: Syscalls, CONFIG: allow_rw::Config>(
#			driver_num: u32,
#			buffer_num: u32,
#			buffer: &mut [u8],
#		) -> Result<(), ErrorCode> {
#			// Safety: syscall4's documentation indicates it can be used to call
#			// Read-Write Allow. These arguments follow TRD104.
#			let [r0, r1, r2, _] = unsafe {
#				S::syscall4::<{ syscall_class::ALLOW_RW }>([
#					driver_num.into(),
#					buffer_num.into(),
#					buffer.as_mut_ptr().into(),
#					buffer.len().into(),
#				])
#			};
#
#			let return_variant: ReturnVariant = r0.as_u32().into();
#			// TRD 104 guarantees that Read-Write Allow returns either Success
#			// with 2 U32 or Failure with 2 U32. We check the return variant by
#			// comparing against Failure with 2 U32 for 2 reasons:
#			//
#			//   1. On RISC-V with compressed instructions, it generates smaller
#			//      code. FAILURE_2_U32 has value 2, which can be loaded into a
#			//      register with a single compressed instruction, whereas
#			//      loading SUCCESS_2_U32 uses an uncompressed instruction.
#			//   2. In the event the kernel malfuctions and returns a different
#			//      return variant, the success path is actually safer than the
#			//      failure path. The failure path assumes that r1 contains an
#			//      ErrorCode, and produces UB if it has an out of range value.
#			//      Incorrectly assuming the call succeeded will not generate
#			//      unsoundness, and will likely lead to the application
#			//      panicing.
#			if return_variant == return_variant::FAILURE_2_U32 {
#				// Safety: TRD 104 guarantees that if r0 is Failure with 2 U32,
#				// then r1 will contain a valid error code. ErrorCode is
#				// designed to be safely transmuted directly from a kernel error
#				// code.
#				return Err(unsafe { core::mem::transmute(r1.as_u32() as u16) });
#			}
#
#			// r0 indicates Success with 2 u32s. Confirm a zero buffer was
#			// returned, and it if wasn't then call the configured function.
#			// We're relying on the optimizer to remove this branch if
#			// returned_nozero_buffer is a no-op.
#			let returned_buffer: (usize, usize) = (r1.into(), r2.into());
#			if returned_buffer != (0, 0) {
#				CONFIG::returned_nonzero_buffer(driver_num, buffer_num);
#			}
#			Ok(())
#		}
#
#		// Safety: The presence of the share::Handle<AllowRw<'share, ...>>
#		// guarantees that an AllowRw exists and will clean up this Allow ID
#		// before the 'share lifetime ends.
#		unsafe { inner::<Self, CONFIG>(DRIVER_NUM, BUFFER_NUM, buffer) }
#	}
#
#	fn unallow_rw(driver_num: u32, buffer_num: u32) {
#		unsafe {
#			// syscall4's documentation indicates it can be used to call
#			// Read-Write Allow. The buffer passed has 0 length, which cannot
#			// cause undefined behavior on its own.
#			Self::syscall4::<{ syscall_class::ALLOW_RW }>([
#				driver_num.into(),
#				buffer_num.into(),
#				0usize.into(),
#				0usize.into(),
#			]);
#		}
#	}

    // -------------------------------------------------------------------------
    // Exit
    // -------------------------------------------------------------------------

    fn exit_terminate(exit_code: u32) -> ! {
        unsafe {
            // syscall2's documentation indicates it can be used to call Exit.
            // The exit system call cannot trigger undefined behavior on its
            // own.
            Self::syscall2::<{ syscall_class::EXIT }>([
                exit_id::TERMINATE.into(),
                exit_code.into(),
            ]);
            // TRD104 indicates that exit-terminate MUST always succeed and so
            // never return.
            core::hint::unreachable_unchecked()
        }
    }

    fn exit_restart(exit_code: u32) -> ! {
        unsafe {
            // syscall2's documentation indicates it can be used to call Exit.
            // The exit system call cannot trigger undefined behavior on its
            // own.
            Self::syscall2::<{ syscall_class::EXIT }>([exit_id::RESTART.into(), exit_code.into()]);
            // TRD104 indicates that exit-restart MUST always succeed and so
            // never return.
            core::hint::unreachable_unchecked()
        }
    }
}
<|endoftext|>


<commit_before>#![no_main]

#[macro_use]
extern crate libfuzzer_sys;
extern crate wasmparser;

use wasmparser::WasmDecoder;

fuzz_target!(|data: &[u8]| {
    let mut parser = wasmparser::ValidatingParser::new(data);
    loop {
        match *parser.read() {
            wasmparser::ParserState::Error(..) | wasmparser::ParserState::EndWasm => break,
            _ => (),
        }
    }
});
<commit_msg>Fix compilation of fuzz_targets/validate.rs.<commit_after>#![no_main]

#[macro_use]
extern crate libfuzzer_sys;
extern crate wasmparser;

use wasmparser::WasmDecoder;

fuzz_target!(|data: &[u8]| {
    let mut parser = wasmparser::ValidatingParser::new(data, None);
    loop {
        match *parser.read() {
            wasmparser::ParserState::Error(..) | wasmparser::ParserState::EndWasm => break,
            _ => (),
        }
    }
});
<|endoftext|>


<commit_before>#![feature(proc_macro_hygiene, decl_macro)]

extern crate rocket_contrib;
extern crate serde;

#[macro_use]extern crate rocket;
#[macro_use]extern crate serde_derive;
#[macro_use]extern crate serde_json;

use std::sync::Mutex;
use std::collections::HashMap;

use rocket::State;
use rocket_contrib::json::{Json, JsonValue};

type ID = usize;

type MessageMap = Mutex<HashMap<ID, String>>;

#[derive(Serialize, Deserialize)]
struct Message {
    id: Option<ID>,
    contents: String
}

#[get("/<id>", format="json")]
fn get(id: ID, map: State<MessageMap>) -> Option<Json<Message>> {
    let hashmap = map.lock().unwrap();
    hashmap.get(&id).map(|contents| {
        Json(Message {
                id: Some(id),
                contents: contents.clone()
            })
    })
}

#[get("/")]
fn index() -> &'static str {
    return("Hello, world!");
}

#[catch(404)]
fn not_found() -> JsonValue {
    JsonValue(json!({
        "status": "error",
        "reason": "Resource was not found"
    }))
}

fn main () {
    rocket::ignite().mount("/", routes![index, get]).register(catchers![not_found]).manage(Mutex::new(HashMap::<ID, String>::new())).launch();
}
<commit_msg>Added other REST API functions<commit_after>#![feature(proc_macro_hygiene, decl_macro)]

extern crate rocket_contrib;
extern crate serde;

#[macro_use]extern crate rocket;
#[macro_use]extern crate serde_derive;
#[macro_use]extern crate serde_json;

use std::sync::Mutex;
use std::collections::HashMap;

use rocket::State;
use rocket_contrib::json::{Json, JsonValue};

type ID = usize;

type MessageMap = Mutex<HashMap<ID, String>>;

#[derive(Serialize, Deserialize)]
struct Message {
    id: Option<ID>,
    contents: String
}

#[get("/<id>", format="json")]
fn get(id: ID, map: State<MessageMap>) -> Option<Json<Message>> {
    let hashmap = map.lock().unwrap();
    hashmap.get(&id).map(|contents| {
        Json(Message {
                id: Some(id),
                contents: contents.clone()
            })
    })
}

#[get("/")]
fn index() -> &'static str {
    return("Hello, world!");
}

#[post("/<id>", format="json", data="<message>")]
fn new(id: ID, message: Json<Message>, map: State<MessageMap>) -> JsonValue{
    let mut hashmap = map.lock().expect("map lock.");
    if hashmap.contains_key(&id) {
        return(JsonValue(json!({
            "status": "error",
            "reason": "ID exists. Try put."})));
    } else  {
        hashmap.insert(id, message.0.contents);
        return(JsonValue(json!({"status": "ok"})));
    }
}

#[put("/<id>", format = "json", data="<message>")]
fn update(id: ID, message: Json<Message>, map: State<MessageMap>) -> Option<JsonValue> {
    let mut hashmap = map.lock().unwrap();
    if hashmap.contains_key(&id) {
        hashmap.insert(id, message.0.contents);
        return(Some(JsonValue(json!({"status" : "ok"}))));
    } else {
        return(None);
    }
}

#[catch(404)]
fn not_found() -> JsonValue {
    JsonValue(json!({
        "status": "error",
        "reason": "Resource was not found"
    }))
}

fn main () {
    rocket::ignite().mount("/", routes![index, get, new, update]).register(catchers![not_found]).manage(Mutex::new(HashMap::<ID, String>::new())).launch();
}
<|endoftext|>


<commit_before>use std::collections::{HashSet, HashMap, RingBuf, Deque};

use graph::{Graph, NodeIndex};
use tree::Tree;

/// Do a breadth-first traversal of the graph, returning the resulting breadth-
/// first tree (a tree on the connected component containing the start node)
///
/// Pseudocode:
///
///    BFS(G, v):
///        S = new queue
///        S.insert(v)
///        mark v as discovered
///        while S is not empty:
///            curr = S.pop()
///            for all nodes w reachable from curr
///                if w is not yet discovered
///                    S.insert(w)
///                    mark w as discovered
fn bf_trav<T, G: Graph<T>>(g: &G, start: NodeIndex) -> Tree<NodeIndex> {
    let mut tree = Tree::new();

    if g.num_nodes() == 0 {
        return tree;
    }

    let mut discovered = HashSet::new();
    let mut queue = RingBuf::new();

    queue.push_back((start, None));
    discovered.insert(start);
    loop {
        match queue.pop_front() {
            None => break,
            Some((ind, parent)) => {
                match parent {
                    None => tree.add_root(ind),
                    Some(p_ind) => tree.add_child(p_ind, ind),
                }

                for i in g.reachable(ind) {
                    if !discovered.contains(&i) {
                        queue.push_back((i, Some(ind)));
                        discovered.insert(i);
                    }
                }
            }
        }
    }
    return tree;
}

/// Do a depth-first traversal of the graph, returning the resulting depth-
/// first tree
///
/// Pseudocode:
///    DFS(G, v):
///        S = new stack
///        S.push(v)
///        while S is not empty:
///            curr = S.pop()
///            if curr is not yet visited:
///                add curr to visited
///                for all nodes w reachable from curr
///                    S.push(w)
fn df_trav<T, G: Graph<T>>(g: &G, start: NodeIndex) -> Tree<NodeIndex> {
    let mut tree = Tree::new();

    if g.num_nodes() == 0 {
        return tree;
    }

    let mut visited = HashSet::new();
    let mut stack = vec!();

    stack.push((start, None));
    loop {
        match stack.pop() {
            None => break,
            Some((ind, parent)) => {
                if !visited.contains(&ind) {
                    match parent {
                        None => tree.add_root(ind),
                        Some(p_ind) => tree.add_child(p_ind, ind),
                    }
                    visited.insert(ind);

                    for i in g.reachable(ind) {
                        stack.push((i, Some(ind)));
                    }
                }
            }
        }
    }
    return tree;
}
<commit_msg>Add an attempt at a method that will attempt to DF-traverse all components. Seems like a lot of unnecessary duplication.<commit_after>use std::collections::{HashSet, HashMap, RingBuf, Deque};

use graph::{Graph, NodeIndex};
use tree::Tree;

type Forest<T> = Vec<Tree<T>>;

/// Do a breadth-first traversal of the graph, returning the resulting breadth-
/// first tree (a tree on the connected component containing the start node)
///
/// Pseudocode:
///
///    BFS(G, v):
///        S = new queue
///        S.insert(v)
///        mark v as discovered
///        while S is not empty:
///            curr = S.pop()
///            for all nodes w reachable from curr
///                if w is not yet discovered
///                    S.insert(w)
///                    mark w as discovered
fn bf_trav<T, G: Graph<T>>(g: &G, start: NodeIndex) -> Tree<NodeIndex> {
    let mut tree = Tree::new();

    if g.num_nodes() == 0 {
        return tree;
    }

    let mut discovered = HashSet::new();
    let mut queue = RingBuf::new();

    queue.push_back((start, None));
    discovered.insert(start);
    loop {
        match queue.pop_front() {
            None => break,
            Some((ind, parent)) => {
                match parent {
                    None => tree.add_root(ind),
                    Some(p_ind) => tree.add_child(p_ind, ind),
                }

                for i in g.reachable(ind) {
                    if !discovered.contains(&i) {
                        queue.push_back((i, Some(ind)));
                        discovered.insert(i);
                    }
                }
            }
        }
    }
    return tree;
}

/// Do a depth-first traversal of the graph, returning the resulting depth-
/// first tree
///
/// Pseudocode:
///    DFS(G, v):
///        S = new stack
///        S.push(v)
///        while S is not empty:
///            curr = S.pop()
///            if curr is not yet visited:
///                add curr to visited
///                for all nodes w reachable from curr
///                    S.push(w)
fn df_trav<T, G: Graph<T>>(g: &G, start: NodeIndex) -> Tree<NodeIndex> {
    let mut tree = Tree::new();

    if g.num_nodes() == 0 {
        return tree;
    }

    let mut visited = HashSet::new();
    let mut stack = vec!();

    stack.push((start, None));
    loop {
        match stack.pop() {
            None => break,
            Some((ind, parent)) => {
                if !visited.contains(&ind) {
                    match parent {
                        None => tree.add_root(ind),
                        Some(p_ind) => tree.add_child(p_ind, ind),
                    }
                    visited.insert(ind);

                    for i in g.reachable(ind) {
                        stack.push((i, Some(ind)));
                    }
                }
            }
        }
    }
    return tree;
}

fn df_trav_all<T, G: Graph<T>>(g: &G, start: NodeIndex) -> Forest<NodeIndex> {
    let mut forest = vec!();
    let mut tree = Tree::new();

    if g.num_nodes() == 0 {
        return forest;
    }

    let mut unvisited: HashSet<NodeIndex> = g.node_indices().collect();
    let mut visited = HashSet::new();
    let mut stack = vec!();

    stack.push((start, None));
    loop {
        match stack.pop() {
            None => {
                if unvisited.is_empty() {
                    break;
                } else {
                    // we've exhausted the nodes reachable from our last start point
                    // so restart the traversal with an unvisited node
                    forest.push(tree);
                    tree = Tree::new();
                    let another = *unvisited.iter().next().unwrap();
                    stack.push((another, None));
                }
            }
            Some((ind, parent)) => {
                if !visited.contains(&ind) {
                    match parent {
                        None => tree.add_root(ind),
                        Some(p_ind) => tree.add_child(p_ind, ind),
                    }
                    visited.insert(ind);
                    unvisited.remove(&ind);

                    for i in g.reachable(ind) {
                        stack.push((i, Some(ind)));
                    }
                }
            }
        }
    }
    forest
}
<|endoftext|>


<commit_before>use super::RootMove;
use super::super::MAX_THREADS;
use super::root_moves_list::{RootMoveList,RawRootMoveList};

use std::heap::{Alloc, Layout, Heap};
use std::ptr::Unique;
use std::sync::Arc;
use std::sync::atomic::{Ordering,AtomicUsize,fence,compiler_fence};
use std::mem;

use std::iter::{Iterator,IntoIterator};

use pleco::Board;
use pleco::board::movegen::{MoveGen,Legal};
use pleco::core::mono_traits::AllGenType;

struct RawRmManager {
    pub rms: [RawRootMoveList; MAX_THREADS]
}

impl RawRmManager {
    pub fn new() -> Unique<RawRmManager> {
        unsafe {
            println!("Raw RMManager create: start");
            let ptr = Heap.alloc_zeroed(Layout::array::<RawRootMoveList>(MAX_THREADS).unwrap());
            println!("Raw RMManager create: created ptr");
            let new_ptr = match ptr {
                Ok(ptr) => ptr,
                Err(err) => Heap.oom(err),
            };
            println!("Raw RMManager create: created new_ptr");
            let raw = Unique::new(new_ptr as *mut RawRmManager).unwrap();
//            for x in 0..MAX_THREADS {
//                print!("Attempt {} :", x);
//                let mut list = mem::transmute::<*mut RawRmManager, *mut RawRootMoveList>(raw.as_ptr())
//                    .offset(x as isize);
//
//                let raw_list: &mut RawRootMoveList = (*raw.as_ptr()).rms.get_unchecked_mut(x);
//                print!(" raw_list ... ");
//                (*list).init();
//                raw_list.init();
//                println!("Made raw list");
//            }
//            println!("Raw RMManager create: Done!");
            raw
        }
    }
}

pub struct RmManager {
    threads: Arc<AtomicUsize>,
    moves: Unique<RawRmManager>,
    ref_count: Arc<AtomicUsize>
}

unsafe impl Send for RmManager {}

impl Clone for RmManager {
    fn clone(&self) -> Self {
        let ref_count: Arc<AtomicUsize> = self.ref_count.clone();
        ref_count.fetch_add(1, Ordering::SeqCst);
        RmManager {
            threads: self.threads.clone(),
            moves: self.moves.clone(),
            ref_count
        }
    }
}

impl RmManager {
    pub fn new() -> Self {
        println!("Creating RmManager");
        let mut rms = RmManager {
            threads: Arc::new(AtomicUsize::new(0)),
            moves: RawRmManager::new(),
            ref_count: Arc::new(AtomicUsize::new(1))
        };
        println!("Created RM Manager");
        for thread in 0..MAX_THREADS {
            unsafe {
                println!("Trying init raw list.... ");
                let mut rm = rms.get_list_unchecked(thread);
                print!(" pointer got ... ");
                rm.init();
                println!("Made raw list");
            }
        }
        rms
    }

    pub fn threads(&self) -> usize {
        self.threads.load(Ordering::Relaxed)
    }

    pub fn add_thread(&mut self) -> Option<RootMoveList> {
        if self.threads() >= MAX_THREADS {
            None
        } else {
            let thread_idx = self.threads.fetch_add(1, Ordering::SeqCst);
            unsafe {
                Some(self.get_list_unchecked(thread_idx))
            }
        }
    }

    pub fn get_list(&self, num: usize) -> Option<RootMoveList> {
        if num >= self.threads() {
            None
        } else {
            unsafe {
                Some(self.get_list_unchecked(num))
            }
        }
    }

    pub unsafe fn get_list_unchecked(&self, num: usize) -> RootMoveList {
        RootMoveList {
            moves: self.as_raw_ptr().offset(num as isize)
        }
    }

    pub unsafe fn replace_moves(&mut self, board: &Board) {
        let legal_moves = MoveGen::generate::<Legal, AllGenType>(&board);
        let mut first = self.as_ptr();
        first.replace(&legal_moves);
        let num = self.threads();
        for i in 1..num {
            self.get_list_unchecked(i).clone_from_other(&first);
        }
    }

    pub unsafe fn as_ptr(&self) -> RootMoveList {
        RootMoveList {
            moves: mem::transmute::<*mut RawRmManager, *mut RawRootMoveList>(self.moves.as_ptr())
        }
    }

    unsafe fn as_raw_ptr(&self) -> *mut RawRootMoveList {
        mem::transmute::<*mut RawRmManager, *mut RawRootMoveList>(self.moves.as_ptr())
    }

    pub fn wait_for_finish(&self) {
        unsafe {
            for i in 0..self.threads() {
                fence(Ordering::AcqRel);
                compiler_fence(Ordering::AcqRel);
                let root_moves = self.get_list_unchecked(i).moves;
                (*root_moves).finished.await(true);
            }
        }
    }
    pub fn wait_for_start(&self) {
        unsafe {
            let num_threads = self.threads();
            for i in 0..num_threads {
                fence(Ordering::AcqRel);
                compiler_fence(Ordering::AcqRel);
                let root_moves = self.get_list_unchecked(i).moves;
                (*root_moves).finished.await(false);
            }
        }
    }

    pub fn reset_depths(&self) {
        unsafe {
            for i in 0..self.threads() {
                self.get_list_unchecked(i).set_depth_completed(0);
            }
        }
    }

    pub fn thread_best_move_and_depth(&self, thread_id: usize) -> (RootMove, u16) {
        unsafe {
            let mut thread = self.get_list_unchecked(thread_id);
            (thread.first().clone(), thread.depth_completed())
        }

    }

    pub fn best_rootmove(&self, use_stdout: bool) -> RootMove {
        let (mut best_root_move, mut depth_reached): (RootMove, u16) = self.thread_best_move_and_depth(0);
        if use_stdout {
            println!("id: 0, value: {}, prev_value: {}, depth: {}, depth_comp: {}, mov: {}", best_root_move.score, best_root_move.prev_score, best_root_move.depth_reached,depth_reached, best_root_move.bit_move);
        }

        for x in 1..self.threads() {
            let (thread_move, thread_depth): (RootMove, u16)  = self.thread_best_move_and_depth(x);
            let depth_diff = thread_depth as i32 - depth_reached as i32;
            let value_diff = thread_move.score - best_root_move.score;
            if x != 0 {
                // If it has a bigger value and greater or equal depth
                if value_diff > 0 && depth_diff >= 0 {
                    best_root_move = thread_move;
                    depth_reached = thread_depth;
                }
            }

            if use_stdout {
                println!("id: {}, value: {}, prev_value: {}, depth: {}, depth_comp: {}, mov: {}",x, thread_move.score, thread_move.prev_score, thread_move.depth_reached,thread_depth, thread_move.bit_move);
            }
        }
        best_root_move
    }
}

pub struct RootMovesIter<'a> {
    root_moves: &'a RmManager,
    threads: usize,
    idx: usize,
}

impl<'a> Iterator for RootMovesIter<'a> {
    type Item = RootMoveList;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        if self.idx >= self.threads {
            None
        } else {
            unsafe {
                Some(self.root_moves.get_list_unchecked(self.idx))
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.threads - self.idx, Some(self.threads - self.idx))
    }
}

impl<'a> IntoIterator for &'a RmManager {
    type Item = RootMoveList;
    type IntoIter = RootMovesIter<'a>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        RootMovesIter {
            root_moves: &self,
            threads: self.threads(),
            idx: 0,
        }
    }
}

impl Drop for RmManager {
    fn drop(&mut self) {
        let num = self.ref_count.fetch_sub(1, Ordering::SeqCst);
        if num == 1 {
            unsafe {
                Heap.dealloc(self.as_raw_ptr() as *mut _,
                             Layout::array::<RawRootMoveList>(MAX_THREADS).unwrap());
            }
        }
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn rm_basic() {
        let mut rms = RmManager::new();
        assert_eq!(rms.threads(), 0);
        let moves_1 = rms.add_thread().unwrap();
        assert_eq!(rms.threads(), 1);
        assert_eq!(moves_1.len(), 0);
        let board = Board::default();
        unsafe {
            rms.replace_moves(&board);
            let moves_1_clone = rms.get_list_unchecked(0);
            assert_eq!(moves_1.len(), moves_1_clone.len());
            let moves_2 = rms.add_thread().unwrap();
            assert_eq!(rms.threads(), 2);
            rms.replace_moves(&board);
            let moves_2_clone = rms.get_list_unchecked(0);
            assert_eq!(moves_2.len(), moves_2_clone.len());
            assert_eq!(moves_1.len(), moves_2_clone.len());
        }
    }

    #[test]
    fn rm_cloning() {
        let mut rms = RmManager::new();
        let rmsc = rms.clone();
        rms.add_thread();
        rms.add_thread();
        assert_eq!(rms.threads(), rmsc.threads());
    }
}<commit_msg>More attempts2<commit_after>use super::RootMove;
use super::super::MAX_THREADS;
use super::root_moves_list::{RootMoveList,RawRootMoveList};

use std::heap::{Alloc, Layout, Heap};
use std::ptr::Unique;
use std::sync::Arc;
use std::sync::atomic::{Ordering,AtomicUsize,fence,compiler_fence};
use std::mem;

use std::iter::{Iterator,IntoIterator};

use pleco::Board;
use pleco::board::movegen::{MoveGen,Legal};
use pleco::core::mono_traits::AllGenType;

struct RawRmManager {
    pub rms: [RawRootMoveList; MAX_THREADS]
}

impl RawRmManager {
    pub fn new() -> Unique<RawRmManager> {
        unsafe {
            println!("Raw RMManager create: start");
            let ptr = Heap.alloc_zeroed(Layout::array::<RawRootMoveList>(MAX_THREADS).unwrap());
            println!("Raw RMManager create: created ptr");
            let new_ptr = match ptr {
                Ok(ptr) => ptr,
                Err(err) => Heap.oom(err),
            };
            println!("Raw RMManager create: created new_ptr");
            let raw = Unique::new(new_ptr as *mut RawRmManager).unwrap();
//            for x in 0..MAX_THREADS {
//                print!("Attempt {} :", x);
//                let mut list = mem::transmute::<*mut RawRmManager, *mut RawRootMoveList>(raw.as_ptr())
//                    .offset(x as isize);
//
//                let raw_list: &mut RawRootMoveList = (*raw.as_ptr()).rms.get_unchecked_mut(x);
//                print!(" raw_list ... ");
//                (*list).init();
//                raw_list.init();
//                println!("Made raw list");
//            }
//            println!("Raw RMManager create: Done!");
            raw
        }
    }
}

pub struct RmManager {
    threads: Arc<AtomicUsize>,
    moves: Unique<RawRmManager>,
    ref_count: Arc<AtomicUsize>
}

unsafe impl Send for RmManager {}

impl Clone for RmManager {
    fn clone(&self) -> Self {
        let ref_count: Arc<AtomicUsize> = self.ref_count.clone();
        ref_count.fetch_add(1, Ordering::SeqCst);
        RmManager {
            threads: self.threads.clone(),
            moves: self.moves.clone(),
            ref_count
        }
    }
}

impl RmManager {
    pub fn new() -> Self {
        println!("Creating RmManager");
        let mut rms = RmManager {
            threads: Arc::new(AtomicUsize::new(0)),
            moves: alloc_raw(),
            ref_count: Arc::new(AtomicUsize::new(1))
        };
        println!("Created RM Manager");
        for thread in 0..MAX_THREADS {
            unsafe {
                println!("Trying init raw list.... ");
                let mut rm = rms.get_list_unchecked(thread);
                print!(" pointer got ... ");
                rm.init();
                println!("Made raw list");
            }
        }
        rms
    }

    pub fn threads(&self) -> usize {
        self.threads.load(Ordering::Relaxed)
    }

    pub fn add_thread(&mut self) -> Option<RootMoveList> {
        if self.threads() >= MAX_THREADS {
            None
        } else {
            let thread_idx = self.threads.fetch_add(1, Ordering::SeqCst);
            unsafe {
                Some(self.get_list_unchecked(thread_idx))
            }
        }
    }

    pub fn get_list(&self, num: usize) -> Option<RootMoveList> {
        if num >= self.threads() {
            None
        } else {
            unsafe {
                Some(self.get_list_unchecked(num))
            }
        }
    }

    pub unsafe fn get_list_unchecked(&self, num: usize) -> RootMoveList {
        RootMoveList {
            moves: self.as_raw_ptr().offset(num as isize)
        }
    }

    pub unsafe fn replace_moves(&mut self, board: &Board) {
        let legal_moves = MoveGen::generate::<Legal, AllGenType>(&board);
        let mut first = self.as_ptr();
        first.replace(&legal_moves);
        let num = self.threads();
        for i in 1..num {
            self.get_list_unchecked(i).clone_from_other(&first);
        }
    }

    pub unsafe fn as_ptr(&self) -> RootMoveList {
        RootMoveList {
            moves: mem::transmute::<*mut RawRmManager, *mut RawRootMoveList>(self.moves.as_ptr())
        }
    }

    unsafe fn as_raw_ptr(&self) -> *mut RawRootMoveList {
        mem::transmute::<*mut RawRmManager, *mut RawRootMoveList>(self.moves.as_ptr())
    }

    pub fn wait_for_finish(&self) {
        unsafe {
            for i in 0..self.threads() {
                fence(Ordering::AcqRel);
                compiler_fence(Ordering::AcqRel);
                let root_moves = self.get_list_unchecked(i).moves;
                (*root_moves).finished.await(true);
            }
        }
    }
    pub fn wait_for_start(&self) {
        unsafe {
            let num_threads = self.threads();
            for i in 0..num_threads {
                fence(Ordering::AcqRel);
                compiler_fence(Ordering::AcqRel);
                let root_moves = self.get_list_unchecked(i).moves;
                (*root_moves).finished.await(false);
            }
        }
    }

    pub fn reset_depths(&self) {
        unsafe {
            for i in 0..self.threads() {
                self.get_list_unchecked(i).set_depth_completed(0);
            }
        }
    }

    pub fn thread_best_move_and_depth(&self, thread_id: usize) -> (RootMove, u16) {
        unsafe {
            let mut thread = self.get_list_unchecked(thread_id);
            (thread.first().clone(), thread.depth_completed())
        }

    }

    pub fn best_rootmove(&self, use_stdout: bool) -> RootMove {
        let (mut best_root_move, mut depth_reached): (RootMove, u16) = self.thread_best_move_and_depth(0);
        if use_stdout {
            println!("id: 0, value: {}, prev_value: {}, depth: {}, depth_comp: {}, mov: {}", best_root_move.score, best_root_move.prev_score, best_root_move.depth_reached,depth_reached, best_root_move.bit_move);
        }

        for x in 1..self.threads() {
            let (thread_move, thread_depth): (RootMove, u16)  = self.thread_best_move_and_depth(x);
            let depth_diff = thread_depth as i32 - depth_reached as i32;
            let value_diff = thread_move.score - best_root_move.score;
            if x != 0 {
                // If it has a bigger value and greater or equal depth
                if value_diff > 0 && depth_diff >= 0 {
                    best_root_move = thread_move;
                    depth_reached = thread_depth;
                }
            }

            if use_stdout {
                println!("id: {}, value: {}, prev_value: {}, depth: {}, depth_comp: {}, mov: {}",x, thread_move.score, thread_move.prev_score, thread_move.depth_reached,thread_depth, thread_move.bit_move);
            }
        }
        best_root_move
    }

}

pub struct RootMovesIter<'a> {
    root_moves: &'a RmManager,
    threads: usize,
    idx: usize,
}

impl<'a> Iterator for RootMovesIter<'a> {
    type Item = RootMoveList;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        if self.idx >= self.threads {
            None
        } else {
            unsafe {
                Some(self.root_moves.get_list_unchecked(self.idx))
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.threads - self.idx, Some(self.threads - self.idx))
    }
}

impl<'a> IntoIterator for &'a RmManager {
    type Item = RootMoveList;
    type IntoIter = RootMovesIter<'a>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        RootMovesIter {
            root_moves: &self,
            threads: self.threads(),
            idx: 0,
        }
    }
}

impl Drop for RmManager {
    fn drop(&mut self) {
        let num = self.ref_count.fetch_sub(1, Ordering::SeqCst);
        if num == 1 {
            unsafe {
                Heap.dealloc(self.as_raw_ptr() as *mut _,
                             Layout::array::<RawRootMoveList>(MAX_THREADS).unwrap());
            }
        }
    }
}

fn alloc_raw() -> Unique<RawRmManager> {
    unsafe {
        println!("Raw RMManager create: start");
        let ptr = Heap.alloc_zeroed(Layout::array::<RawRootMoveList>(MAX_THREADS).unwrap());
        println!("Raw RMManager create: created ptr");
        let new_ptr = match ptr {
            Ok(ptr) => ptr,
            Err(err) => Heap.oom(err),
        };
        println!("Raw RMManager create: created new_ptr");
        let raw = Unique::new(new_ptr as *mut RawRmManager).unwrap();
//            for x in 0..MAX_THREADS {
//                print!("Attempt {} :", x);
//                let mut list = mem::transmute::<*mut RawRmManager, *mut RawRootMoveList>(raw.as_ptr())
//                    .offset(x as isize);
//
//                let raw_list: &mut RawRootMoveList = (*raw.as_ptr()).rms.get_unchecked_mut(x);
//                print!(" raw_list ... ");
//                (*list).init();
//                raw_list.init();
//                println!("Made raw list");
//            }
//            println!("Raw RMManager create: Done!");
        raw
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn rm_basic() {
        let mut rms = RmManager::new();
        assert_eq!(rms.threads(), 0);
        let moves_1 = rms.add_thread().unwrap();
        assert_eq!(rms.threads(), 1);
        assert_eq!(moves_1.len(), 0);
        let board = Board::default();
        unsafe {
            rms.replace_moves(&board);
            let moves_1_clone = rms.get_list_unchecked(0);
            assert_eq!(moves_1.len(), moves_1_clone.len());
            let moves_2 = rms.add_thread().unwrap();
            assert_eq!(rms.threads(), 2);
            rms.replace_moves(&board);
            let moves_2_clone = rms.get_list_unchecked(0);
            assert_eq!(moves_2.len(), moves_2_clone.len());
            assert_eq!(moves_1.len(), moves_2_clone.len());
        }
    }

    #[test]
    fn rm_cloning() {
        let mut rms = RmManager::new();
        let rmsc = rms.clone();
        rms.add_thread();
        rms.add_thread();
        assert_eq!(rms.threads(), rmsc.threads());
    }
}<|endoftext|>


<commit_before>#[cfg(not(feature = "std"))]
fn main() {
    println!("You can't use gradients without the standard library");
}

#[cfg(feature = "std")]
fn main() {
    use palette::{FromColor, Gradient, IntoColor, Lch, LinSrgb, Srgb};

    use image::{GenericImage, GenericImageView, RgbImage};

    //A gradient of evenly spaced colors
    let grad1 = Gradient::new(vec![
        LinSrgb::new(1.0, 0.1, 0.1),
        LinSrgb::new(0.1, 0.1, 1.0),
        LinSrgb::new(0.1, 1.0, 0.1),
    ]);

    //The same colors as in grad1, but with the blue point shifted down
    let grad2 = Gradient::with_domain(vec![
        (0.0, LinSrgb::new(1.0, 0.1, 0.1)),
        (0.25, LinSrgb::new(0.1, 0.1, 1.0)),
        (1.0, LinSrgb::new(0.1, 1.0, 0.1)),
    ]);

    //The same colors and offsets as in grad1, but in a color space where the hue
    // is a component
    let grad3 = Gradient::new(vec![
        Lch::from_color(LinSrgb::new(1.0, 0.1, 0.1)),
        Lch::from_color(LinSrgb::new(0.1, 0.1, 1.0)),
        Lch::from_color(LinSrgb::new(0.1, 1.0, 0.1)),
    ]);

    //The same colors and and color space as in grad3, but with the blue point
    // shifted down
    let grad4 = Gradient::with_domain(vec![
        (0.0, Lch::from_color(LinSrgb::new(1.0, 0.1, 0.1))),
        (0.25, Lch::from_color(LinSrgb::new(0.1, 0.1, 1.0))),
        (1.0, Lch::from_color(LinSrgb::new(0.1, 1.0, 0.1))),
    ]);

    let mut image = RgbImage::new(256, 128);

    for (i, ((c1, c2), (c3, c4))) in grad1
        .take(256)
        .zip(grad2.take(256))
        .zip(grad3.take(256).zip(grad4.take(256)))
        .enumerate()
    {
        let c1 = Srgb::from_linear(c1).into_format().into();
        let c2 = Srgb::from_linear(c2).into_format().into();
        let c3 = Srgb::from_linear(c3.into_color()).into_format().into();
        let c4 = Srgb::from_linear(c4.into_color()).into_format().into();

        {
            let mut sub_image = image.sub_image(i as u32, 0, 1, 31);
            let (width, height) = sub_image.dimensions();
            for x in 0..width {
                for y in 0..height {
                    sub_image.put_pixel(x, y, image::Rgb(c1));
                }
            }
        }

        {
            let mut sub_image = image.sub_image(i as u32, 32, 1, 31);
            let (width, height) = sub_image.dimensions();
            for x in 0..width {
                for y in 0..height {
                    sub_image.put_pixel(x, y, image::Rgb(c2));
                }
            }
        }

        {
            let mut sub_image = image.sub_image(i as u32, 65, 1, 31);
            let (width, height) = sub_image.dimensions();
            for x in 0..width {
                for y in 0..height {
                    sub_image.put_pixel(x, y, image::Rgb(c3));
                }
            }
        }

        {
            let mut sub_image = image.sub_image(i as u32, 97, 1, 31);
            let (width, height) = sub_image.dimensions();
            for x in 0..width {
                for y in 0..height {
                    sub_image.put_pixel(x, y, image::Rgb(c4));
                }
            }
        }
    }

    let _ = std::fs::create_dir("example-data/output");
    match image.save("example-data/output/gradient.png") {
        Ok(()) => println!("see 'example-data/output/gradient.png' for the result"),
        Err(e) => println!("failed to write 'example-data/output/gradient.png': {}", e),
    }
}
<commit_msg>Fix typo<commit_after>#[cfg(not(feature = "std"))]
fn main() {
    println!("You can't use gradients without the standard library");
}

#[cfg(feature = "std")]
fn main() {
    use palette::{FromColor, Gradient, IntoColor, Lch, LinSrgb, Srgb};

    use image::{GenericImage, GenericImageView, RgbImage};

    //A gradient of evenly spaced colors
    let grad1 = Gradient::new(vec![
        LinSrgb::new(1.0, 0.1, 0.1),
        LinSrgb::new(0.1, 0.1, 1.0),
        LinSrgb::new(0.1, 1.0, 0.1),
    ]);

    //The same colors as in grad1, but with the blue point shifted down
    let grad2 = Gradient::with_domain(vec![
        (0.0, LinSrgb::new(1.0, 0.1, 0.1)),
        (0.25, LinSrgb::new(0.1, 0.1, 1.0)),
        (1.0, LinSrgb::new(0.1, 1.0, 0.1)),
    ]);

    //The same colors and offsets as in grad1, but in a color space where the hue
    // is a component
    let grad3 = Gradient::new(vec![
        Lch::from_color(LinSrgb::new(1.0, 0.1, 0.1)),
        Lch::from_color(LinSrgb::new(0.1, 0.1, 1.0)),
        Lch::from_color(LinSrgb::new(0.1, 1.0, 0.1)),
    ]);

    //The same colors and color space as in grad3, but with the blue point
    // shifted down
    let grad4 = Gradient::with_domain(vec![
        (0.0, Lch::from_color(LinSrgb::new(1.0, 0.1, 0.1))),
        (0.25, Lch::from_color(LinSrgb::new(0.1, 0.1, 1.0))),
        (1.0, Lch::from_color(LinSrgb::new(0.1, 1.0, 0.1))),
    ]);

    let mut image = RgbImage::new(256, 128);

    for (i, ((c1, c2), (c3, c4))) in grad1
        .take(256)
        .zip(grad2.take(256))
        .zip(grad3.take(256).zip(grad4.take(256)))
        .enumerate()
    {
        let c1 = Srgb::from_linear(c1).into_format().into();
        let c2 = Srgb::from_linear(c2).into_format().into();
        let c3 = Srgb::from_linear(c3.into_color()).into_format().into();
        let c4 = Srgb::from_linear(c4.into_color()).into_format().into();

        {
            let mut sub_image = image.sub_image(i as u32, 0, 1, 31);
            let (width, height) = sub_image.dimensions();
            for x in 0..width {
                for y in 0..height {
                    sub_image.put_pixel(x, y, image::Rgb(c1));
                }
            }
        }

        {
            let mut sub_image = image.sub_image(i as u32, 32, 1, 31);
            let (width, height) = sub_image.dimensions();
            for x in 0..width {
                for y in 0..height {
                    sub_image.put_pixel(x, y, image::Rgb(c2));
                }
            }
        }

        {
            let mut sub_image = image.sub_image(i as u32, 65, 1, 31);
            let (width, height) = sub_image.dimensions();
            for x in 0..width {
                for y in 0..height {
                    sub_image.put_pixel(x, y, image::Rgb(c3));
                }
            }
        }

        {
            let mut sub_image = image.sub_image(i as u32, 97, 1, 31);
            let (width, height) = sub_image.dimensions();
            for x in 0..width {
                for y in 0..height {
                    sub_image.put_pixel(x, y, image::Rgb(c4));
                }
            }
        }
    }

    let _ = std::fs::create_dir("example-data/output");
    match image.save("example-data/output/gradient.png") {
        Ok(()) => println!("see 'example-data/output/gradient.png' for the result"),
        Err(e) => println!("failed to write 'example-data/output/gradient.png': {}", e),
    }
}
<|endoftext|>