<commit_before>extern crate itertools;
extern crate rand;
extern crate rayon;

use self::itertools::Itertools;

use self::rand::Rng;

use super::train;
use super::train::Train;
use super::error::Error;
use super::common::{Node, Value};
use super::mutator::{Arc, Mutator};
use super::network::NetworkBuf;
use super::id_generator::IdGenerator;

pub struct Conf<'r, RngT: 'r + Rng> {
    pub train_conf: &'r train::Conf<'r>,
    pub rng: &'r mut RngT,
    pub node_id: &'r mut IdGenerator,
    pub population_size: usize,
    pub error: Value,
    pub iterations_count: usize,
}

pub trait Evolve {
    fn evolve<'r, RngT: 'r + Rng>(&self, conf: &'r mut Conf<'r, RngT>) -> Self;
}

impl Evolve for NetworkBuf {
    fn evolve<'r, RngT: 'r + Rng>(&self, conf: &'r mut Conf<'r, RngT>) -> Self {
        Mutator::from_network(&self.as_network()).evolve(conf).as_network_buf()
    }
}

impl Evolve for Mutator {
    fn evolve<'r, RngT: 'r + Rng>(&self, conf: &'r mut Conf<'r, RngT>) -> Self {
        Evolution::new(conf, self).perform()
    }
}

trait MutatorRandom {
    fn random_node<'r, RngT: 'r + Rng>(&self, rng: &mut RngT) -> Node;
    fn random_arc<'r, RngT: 'r + Rng>(&self, rng: &mut RngT) -> Arc;
}

impl MutatorRandom for Mutator {
    fn random_node<'r, RngT: 'r + Rng>(&self, rng: &mut RngT) -> Node {
        let nth = rng.gen_range(0, self.nodes().len());
        *self.nodes().nth(nth).unwrap()
    }

    fn random_arc<'r, RngT: 'r + Rng>(&self, rng: &mut RngT) -> Arc {
        let nth = rng.gen_range(0, self.arcs().len());
        self.arcs().nth(nth).unwrap().clone()
    }
}

struct Evolution<'c, 'f, RngT: 'c + Rng> {
    conf: &'c mut Conf<'c, RngT>,
    mutator: &'f Mutator,
    iterations_count: usize,
}

impl<'c, 'f, RngT: 'c + Rng> Evolution<'c, 'f, RngT> {
    pub fn new(conf: &'c mut Conf<'c, RngT>, mutator: &'f Mutator) -> Self {
        assert!(conf.population_size > 1);
        assert!(conf.population_size % 2 == 0);
        Evolution {conf: conf, mutator: mutator, iterations_count: 0}
    }

    pub fn perform(&mut self) -> Mutator {
        if !self.begin() {
            return self.mutator.clone();
        }
        let population = (0..self.conf.population_size)
            .map(|_| self.mutator.clone()).collect::<Vec<_>>();
        let evolved = self.evolve(population);
        self.select_one(evolved)
    }

    fn evolve(&mut self, mut population: Vec<Mutator>) -> Vec<Mutator> {
        loop {
            let mutated = self.mutate(population);
            self.iterations_count += 1;
            if self.terminate(&mutated[..]) {
                return mutated;
            }
            let propagated = self.propagate(mutated);
            population = self.select(propagated);
        }
    }

    fn mutate(&mut self, population: Vec<Mutator>) -> Vec<Mutator> {
        use self::rayon::prelude::{IntoParallelIterator, ParallelIterator, ExactParallelIterator};
        let ref mut node_id = self.conf.node_id;
        let ref mut rng = self.conf.rng;
        let ref train_conf = self.conf.train_conf;
        let mut result = Vec::new();
        population.into_iter()
            .map(|mut x| {
                for _ in 0..3 {
                    match rng.gen_range(0, 3) {
                        0 => {
                            let arc = x.random_arc(rng);
                            x.split(node_id, &arc);
                        },
                        1 => loop {
                            let src = x.random_node(rng);
                            let dst = x.random_node(rng);
                            if !x.graph().arcs().contains_key(&Arc(src, dst)) {
                                x.add_arc(src, dst, 1e-3);
                                break;
                            }
                        },
                        2 => {
                            let arc = x.random_arc(rng);
                            x.rm_arc(&arc);
                            x.rm_useless();
                        },
                        _ => (),
                    }
                }
                x
            })
            .collect::<Vec<_>>()
            .into_par_iter()
            .map(|x| {
                let mut network_buf = x.as_network_buf();
                network_buf.as_network_mut().train(train_conf);
                Mutator::from_network(&network_buf.as_network())
            })
            .collect_into(&mut result);
        result
    }

    fn begin(&self) -> bool {
        self.iterations_count < self.conf.iterations_count
        && self.mutator.as_network_buf().as_network().error(self.conf.train_conf.error_conf)
           > self.conf.error
    }

    fn terminate(&self, population: &[Mutator]) -> bool {
        use std::io::{Write, stderr};
        write!(&mut stderr(), "Evolve {}/{} iterations done\n",
               self.iterations_count, self.conf.iterations_count).unwrap();
        self.iterations_count >= self.conf.iterations_count
        || population.iter()
            .map(|x| x.as_network_buf().as_network().error(self.conf.train_conf.error_conf))
            .filter(|&x| x <= self.conf.error)
            .count() > 0
    }

    fn propagate(&mut self, population: Vec<Mutator>) -> Vec<Mutator> {
        let mut new = {
            let mut a = population.iter().collect::<Vec<_>>();
            let mut b = population.iter().collect::<Vec<_>>();
            self.conf.rng.shuffle(&mut a[..]);
            self.conf.rng.shuffle(&mut b[..]);
            a.iter().zip(b.iter()).map(|(l, r)| l.union(r)).collect::<Vec<_>>()
        };
        new.extend(population.into_iter());
        new
    }

    fn select(&self, population: Vec<Mutator>) -> Vec<Mutator> {
        population.into_iter()
            .map(|x| (x.as_network_buf().as_network().error(self.conf.train_conf.error_conf), x))
            .sorted_by(|l, r| l.0.partial_cmp(&r.0).unwrap())
            .into_iter()
            .take(self.conf.population_size)
            .map(|x| x.1)
            .collect()
    }

    fn select_one(&self, population: Vec<Mutator>) -> Mutator {
        population.into_iter()
            .map(|x| (x.as_network_buf().as_network().error(self.conf.train_conf.error_conf), x))
            .sorted_by(|l, r| l.0.partial_cmp(&r.0).unwrap())
            .into_iter()
            .nth(0)
            .unwrap().1
    }
}

#[test]
fn test_evolve_should_succeed() {
    extern crate rand;
    use std::collections::{BTreeSet, HashMap, HashSet};
    use self::rand::{XorShiftRng, SeedableRng};
    use neural_network::apply::{Conf as ApplyConf};
    use neural_network::error::{Conf as ErrorConf, Sample};
    use neural_network::train::{Conf as TrainConf};
    use neural_network::matrix::Matrix;
    use neural_network::network::Network;
    let mut weights_values = [
        0.0, 0.0, 0.0, 0.1, 0.1,
        0.0, 0.0, 0.0, 0.1, 0.1,
        0.0, 0.0, 0.0, 0.1, 0.1,
        0.0, 0.0, 0.0, 0.0, 0.0,
        0.0, 0.0, 0.0, 0.0, 0.0,
    ];
    let inputs = [0, 1, 2].iter().cloned().collect::<BTreeSet<usize>>();
    let outputs = [3, 4].iter().cloned().collect::<HashSet<usize>>();
    let weights = Matrix::new(5, &mut weights_values);
    let nodes = (0..5).map(|x| (x, Node(x))).collect::<HashMap<usize, Node>>();
    let network = Network {
        inputs: &inputs,
        outputs: &outputs,
        weights: weights,
        nodes: &nodes
    };
    let mutator = Mutator::from_network(&network);
    let apply_conf = ApplyConf {
        group_size: 1000,
        threshold: 1e-4,
    };
    let samples = [
        Sample {input: &[0.6, 0.7, 0.8], output: &[0.5, 0.4]},
        Sample {input: &[0.3, 0.4, 0.5], output: &[0.3, 0.4]},
    ];
    let error_conf = ErrorConf {
        apply_conf: &apply_conf,
        samples: &samples,
    };
    let train_conf = TrainConf {
        error_conf: &error_conf,
        max_function_calls_count: 111,
    };
    let mut rng = XorShiftRng::new_unseeded();
    rng.reseed([1, 1, 1, 1]);
    let mut node_id = IdGenerator::new(0);
    let mut conf = Conf {
        train_conf: &train_conf,
        rng: &mut rng,
        node_id: &mut node_id,
        population_size: 2,
        error: 1e-3,
        iterations_count: 2,
    };
    let evolved = mutator.evolve(&mut conf);
    let evolved_network_buf = evolved.as_network_buf();
    let evolved_network = evolved_network_buf.as_network();
    let result: &[f64] = evolved_network.weights.values();
    assert_eq!(result, &[
        0.0, 0.0, 0.0, 0.2683965623209851  , 0.17777079087862993   , 0.3539603853353258, 0.0,
        0.0, 0.0, 0.0, 0.0                 , 0.6691012007499241    , 0.0               , 0.5829220793286896,
        0.0, 0.0, 0.0, 0.47249060773832235 , 0.3731956371044444    , 0.0               , 0.0,
        0.0, 0.0, 0.0, 0.010525576601664234, 0.00012966522945039157, 0.0               , 0.0,
        0.0, 0.0, 0.0, 0.0                 , 0.02282920151502366   , 0.0               , 0.027966325746754388,
        0.0, 0.0, 0.0, 0.0                 , 0.3304639663408785    , 0.0               , 0.0,
        0.0, 0.0, 0.0, 0.5829220793286896  , 0.0                   , 0.0               , 0.0,
    ] as &[f64]);
}

#[test]
fn test_evolve_zero_iterations_should_do_nothing() {
    extern crate rand;
    use std::collections::{BTreeSet, HashMap, HashSet};
    use self::rand::{XorShiftRng, SeedableRng};
    use neural_network::apply::{Conf as ApplyConf};
    use neural_network::error::{Conf as ErrorConf, Sample};
    use neural_network::train::{Conf as TrainConf};
    use neural_network::matrix::Matrix;
    use neural_network::network::Network;
    let mut weights_values = [
        0.0, 0.0, 0.0, 0.1, 0.1,
        0.0, 0.0, 0.0, 0.1, 0.1,
        0.0, 0.0, 0.0, 0.1, 0.1,
        0.0, 0.0, 0.0, 0.0, 0.0,
        0.0, 0.0, 0.0, 0.0, 0.0,
    ];
    let inputs = [0, 1, 2].iter().cloned().collect::<BTreeSet<usize>>();
    let outputs = [3, 4].iter().cloned().collect::<HashSet<usize>>();
    let weights = Matrix::new(5, &mut weights_values);
    let nodes = (0..5).map(|x| (x, Node(x))).collect::<HashMap<usize, Node>>();
    let network = Network {
        inputs: &inputs,
        outputs: &outputs,
        weights: weights,
        nodes: &nodes
    };
    let mutator = Mutator::from_network(&network);
    let apply_conf = ApplyConf {
        group_size: 1000,
        threshold: 1e-4,
    };
    let samples = [
        Sample {input: &[0.6, 0.7, 0.8], output: &[0.5, 0.4]},
        Sample {input: &[0.3, 0.4, 0.5], output: &[0.3, 0.4]},
    ];
    let error_conf = ErrorConf {
        apply_conf: &apply_conf,
        samples: &samples,
    };
    let train_conf = TrainConf {
        error_conf: &error_conf,
        max_function_calls_count: 111,
    };
    let mut rng = XorShiftRng::new_unseeded();
    rng.reseed([1, 1, 1, 1]);
    let mut node_id = IdGenerator::new(0);
    let mut conf = Conf {
        train_conf: &train_conf,
        rng: &mut rng,
        node_id: &mut node_id,
        population_size: 2,
        error: 1e-3,
        iterations_count: 0,
    };
    let evolved = mutator.evolve(&mut conf);
    let evolved_network_buf = evolved.as_network_buf();
    let evolved_network = evolved_network_buf.as_network();
    let result: &[f64] = evolved_network.weights.values();
    assert_eq!(result, &[
        0.0, 0.0, 0.0, 0.1, 0.1,
        0.0, 0.0, 0.0, 0.1, 0.1,
        0.0, 0.0, 0.0, 0.1, 0.1,
        0.0, 0.0, 0.0, 0.0, 0.0,
        0.0, 0.0, 0.0, 0.0, 0.0,
    ] as &[f64]);
}
<commit_msg>Use error from train result<commit_after>extern crate itertools;
extern crate rand;
extern crate rayon;

use self::itertools::Itertools;

use self::rand::Rng;

use super::train;
use super::train::Train;
use super::error::Error;
use super::common::{Node, Value};
use super::mutator::{Arc, Mutator};
use super::network::NetworkBuf;
use super::id_generator::IdGenerator;

pub struct Conf<'r, RngT: 'r + Rng> {
    pub train_conf: &'r train::Conf<'r>,
    pub rng: &'r mut RngT,
    pub node_id: &'r mut IdGenerator,
    pub population_size: usize,
    pub error: Value,
    pub iterations_count: usize,
}

pub trait Evolve {
    fn evolve<'r, RngT: 'r + Rng>(&self, conf: &'r mut Conf<'r, RngT>) -> Self;
}

impl Evolve for NetworkBuf {
    fn evolve<'r, RngT: 'r + Rng>(&self, conf: &'r mut Conf<'r, RngT>) -> Self {
        Mutator::from_network(&self.as_network()).evolve(conf).as_network_buf()
    }
}

impl Evolve for Mutator {
    fn evolve<'r, RngT: 'r + Rng>(&self, conf: &'r mut Conf<'r, RngT>) -> Self {
        Evolution::new(conf, self).perform()
    }
}

trait MutatorRandom {
    fn random_node<'r, RngT: 'r + Rng>(&self, rng: &mut RngT) -> Node;
    fn random_arc<'r, RngT: 'r + Rng>(&self, rng: &mut RngT) -> Arc;
}

impl MutatorRandom for Mutator {
    fn random_node<'r, RngT: 'r + Rng>(&self, rng: &mut RngT) -> Node {
        let nth = rng.gen_range(0, self.nodes().len());
        *self.nodes().nth(nth).unwrap()
    }

    fn random_arc<'r, RngT: 'r + Rng>(&self, rng: &mut RngT) -> Arc {
        let nth = rng.gen_range(0, self.arcs().len());
        self.arcs().nth(nth).unwrap().clone()
    }
}

struct Mutation {
    mutator: Mutator,
    error: Value,
}

struct Evolution<'c, 'f, RngT: 'c + Rng> {
    conf: &'c mut Conf<'c, RngT>,
    mutator: &'f Mutator,
    iterations_count: usize,
}

impl<'c, 'f, RngT: 'c + Rng> Evolution<'c, 'f, RngT> {
    pub fn new(conf: &'c mut Conf<'c, RngT>, mutator: &'f Mutator) -> Self {
        assert!(conf.population_size > 1);
        assert!(conf.population_size % 2 == 0);
        Evolution {conf: conf, mutator: mutator, iterations_count: 0}
    }

    pub fn perform(&mut self) -> Mutator {
        if !self.begin() {
            return self.mutator.clone();
        }
        let error = self.mutator.as_network_buf().as_network().error(self.conf.train_conf.error_conf);
        let population = (0..self.conf.population_size)
            .map(|_| Mutation {mutator: self.mutator.clone(), error: error})
            .collect::<Vec<_>>();
        let evolved = self.evolve(population);
        self.select_one(evolved)
    }

    fn evolve(&mut self, mut population: Vec<Mutation>) -> Vec<Mutation> {
        loop {
            let mutated = self.mutate(population);
            self.iterations_count += 1;
            if self.terminate(&mutated) {
                return mutated;
            }
            let propagated = self.propagate(mutated);
            population = self.select(propagated);
        }
    }

    fn mutate(&mut self, population: Vec<Mutation>) -> Vec<Mutation> {
        use self::rayon::prelude::{IntoParallelIterator, ParallelIterator, ExactParallelIterator};
        let ref mut node_id = self.conf.node_id;
        let ref mut rng = self.conf.rng;
        let ref train_conf = self.conf.train_conf;
        let mut result = Vec::new();
        population.into_iter()
            .map(|x| x.mutator)
            .map(|mut x| {
                for _ in 0..3 {
                    match rng.gen_range(0, 3) {
                        0 => {
                            let arc = x.random_arc(rng);
                            x.split(node_id, &arc);
                        },
                        1 => loop {
                            let src = x.random_node(rng);
                            let dst = x.random_node(rng);
                            if !x.graph().arcs().contains_key(&Arc(src, dst)) {
                                x.add_arc(src, dst, 1e-3);
                                break;
                            }
                        },
                        2 => {
                            let arc = x.random_arc(rng);
                            x.rm_arc(&arc);
                            x.rm_useless();
                        },
                        _ => (),
                    }
                }
                x
            })
            .collect::<Vec<_>>()
            .into_par_iter()
            .map(|x| {
                let mut network_buf = x.as_network_buf();
                let error = network_buf.as_network_mut().train(train_conf);
                Mutation {
                    mutator: Mutator::from_network(&network_buf.as_network()),
                    error: error,
                }
            })
            .collect_into(&mut result);
        result
    }

    fn begin(&self) -> bool {
        self.iterations_count < self.conf.iterations_count
        && self.mutator.as_network_buf().as_network().error(self.conf.train_conf.error_conf)
           > self.conf.error
    }

    fn terminate(&self, population: &Vec<Mutation>) -> bool {
        use std::io::{Write, stderr};
        writeln!(stderr(), "Evolve {}/{} iterations done",
               self.iterations_count, self.conf.iterations_count).unwrap();
        self.iterations_count >= self.conf.iterations_count
        || population.iter()
            .filter(|x| x.error <= self.conf.error)
            .count() > 0
    }

    fn propagate(&mut self, population: Vec<Mutation>) -> Vec<Mutation> {
        let mut new = {
            let mut a = population.iter().collect::<Vec<_>>();
            let mut b = population.iter().collect::<Vec<_>>();
            self.conf.rng.shuffle(&mut a[..]);
            self.conf.rng.shuffle(&mut b[..]);
            a.iter()
                .zip(b.iter())
                .map(|(l, r)| {
                    let mutator = l.mutator.union(&r.mutator);
                    let error = mutator.as_network_buf().as_network().error(self.conf.train_conf.error_conf);
                    Mutation {mutator: mutator, error: error}
                })
                .collect::<Vec<_>>()
        };
        new.extend(population.into_iter());
        new
    }

    fn select(&self, population: Vec<Mutation>) -> Vec<Mutation> {
        population.into_iter()
            .sorted_by(|l, r| l.error.partial_cmp(&r.error).unwrap())
            .into_iter()
            .take(self.conf.population_size)
            .collect()
    }

    fn select_one(&self, population: Vec<Mutation>) -> Mutator {
        population.into_iter()
            .sorted_by(|l, r| l.error.partial_cmp(&r.error).unwrap())
            .into_iter()
            .nth(0).unwrap().mutator
    }
}

#[test]
fn test_evolve_should_succeed() {
    extern crate rand;
    use std::collections::{BTreeSet, HashMap, HashSet};
    use self::rand::{XorShiftRng, SeedableRng};
    use neural_network::apply::{Conf as ApplyConf};
    use neural_network::error::{Conf as ErrorConf, Sample};
    use neural_network::train::{Conf as TrainConf};
    use neural_network::matrix::Matrix;
    use neural_network::network::Network;
    let mut weights_values = [
        0.0, 0.0, 0.0, 0.1, 0.1,
        0.0, 0.0, 0.0, 0.1, 0.1,
        0.0, 0.0, 0.0, 0.1, 0.1,
        0.0, 0.0, 0.0, 0.0, 0.0,
        0.0, 0.0, 0.0, 0.0, 0.0,
    ];
    let inputs = [0, 1, 2].iter().cloned().collect::<BTreeSet<usize>>();
    let outputs = [3, 4].iter().cloned().collect::<HashSet<usize>>();
    let weights = Matrix::new(5, &mut weights_values);
    let nodes = (0..5).map(|x| (x, Node(x))).collect::<HashMap<usize, Node>>();
    let network = Network {
        inputs: &inputs,
        outputs: &outputs,
        weights: weights,
        nodes: &nodes
    };
    let mutator = Mutator::from_network(&network);
    let apply_conf = ApplyConf {
        group_size: 1000,
        threshold: 1e-4,
    };
    let samples = [
        Sample {input: &[0.6, 0.7, 0.8], output: &[0.5, 0.4]},
        Sample {input: &[0.3, 0.4, 0.5], output: &[0.3, 0.4]},
    ];
    let error_conf = ErrorConf {
        apply_conf: &apply_conf,
        samples: &samples,
    };
    let train_conf = TrainConf {
        error_conf: &error_conf,
        max_function_calls_count: 111,
    };
    let mut rng = XorShiftRng::new_unseeded();
    rng.reseed([1, 1, 1, 1]);
    let mut node_id = IdGenerator::new(0);
    let mut conf = Conf {
        train_conf: &train_conf,
        rng: &mut rng,
        node_id: &mut node_id,
        population_size: 2,
        error: 1e-3,
        iterations_count: 2,
    };
    let evolved = mutator.evolve(&mut conf);
    let evolved_network_buf = evolved.as_network_buf();
    let evolved_network = evolved_network_buf.as_network();
    let result: &[f64] = evolved_network.weights.values();
    assert_eq!(result, &[
        0.0, 0.0, 0.0, 0.2683965623209851  , 0.17777079087862993   , 0.3539603853353258, 0.0,
        0.0, 0.0, 0.0, 0.0                 , 0.6691012007499241    , 0.0               , 0.5829220793286896,
        0.0, 0.0, 0.0, 0.47249060773832235 , 0.3731956371044444    , 0.0               , 0.0,
        0.0, 0.0, 0.0, 0.010525576601664234, 0.00012966522945039157, 0.0               , 0.0,
        0.0, 0.0, 0.0, 0.0                 , 0.02282920151502366   , 0.0               , 0.027966325746754388,
        0.0, 0.0, 0.0, 0.0                 , 0.3304639663408785    , 0.0               , 0.0,
        0.0, 0.0, 0.0, 0.5829220793286896  , 0.0                   , 0.0               , 0.0,
    ] as &[f64]);
}

#[test]
fn test_evolve_zero_iterations_should_do_nothing() {
    extern crate rand;
    use std::collections::{BTreeSet, HashMap, HashSet};
    use self::rand::{XorShiftRng, SeedableRng};
    use neural_network::apply::{Conf as ApplyConf};
    use neural_network::error::{Conf as ErrorConf, Sample};
    use neural_network::train::{Conf as TrainConf};
    use neural_network::matrix::Matrix;
    use neural_network::network::Network;
    let mut weights_values = [
        0.0, 0.0, 0.0, 0.1, 0.1,
        0.0, 0.0, 0.0, 0.1, 0.1,
        0.0, 0.0, 0.0, 0.1, 0.1,
        0.0, 0.0, 0.0, 0.0, 0.0,
        0.0, 0.0, 0.0, 0.0, 0.0,
    ];
    let inputs = [0, 1, 2].iter().cloned().collect::<BTreeSet<usize>>();
    let outputs = [3, 4].iter().cloned().collect::<HashSet<usize>>();
    let weights = Matrix::new(5, &mut weights_values);
    let nodes = (0..5).map(|x| (x, Node(x))).collect::<HashMap<usize, Node>>();
    let network = Network {
        inputs: &inputs,
        outputs: &outputs,
        weights: weights,
        nodes: &nodes
    };
    let mutator = Mutator::from_network(&network);
    let apply_conf = ApplyConf {
        group_size: 1000,
        threshold: 1e-4,
    };
    let samples = [
        Sample {input: &[0.6, 0.7, 0.8], output: &[0.5, 0.4]},
        Sample {input: &[0.3, 0.4, 0.5], output: &[0.3, 0.4]},
    ];
    let error_conf = ErrorConf {
        apply_conf: &apply_conf,
        samples: &samples,
    };
    let train_conf = TrainConf {
        error_conf: &error_conf,
        max_function_calls_count: 111,
    };
    let mut rng = XorShiftRng::new_unseeded();
    rng.reseed([1, 1, 1, 1]);
    let mut node_id = IdGenerator::new(0);
    let mut conf = Conf {
        train_conf: &train_conf,
        rng: &mut rng,
        node_id: &mut node_id,
        population_size: 2,
        error: 1e-3,
        iterations_count: 0,
    };
    let evolved = mutator.evolve(&mut conf);
    let evolved_network_buf = evolved.as_network_buf();
    let evolved_network = evolved_network_buf.as_network();
    let result: &[f64] = evolved_network.weights.values();
    assert_eq!(result, &[
        0.0, 0.0, 0.0, 0.1, 0.1,
        0.0, 0.0, 0.0, 0.1, 0.1,
        0.0, 0.0, 0.0, 0.1, 0.1,
        0.0, 0.0, 0.0, 0.0, 0.0,
        0.0, 0.0, 0.0, 0.0, 0.0,
    ] as &[f64]);
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, Nick Stevens <nick@bitcurry.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/license/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Predicate
//!
//! This module contains the `Predicate` trait and a number of combinators for
//! the trait. See the crate docs, and the docs for `Predicate`, for full detail.

// primitive `Predicate` types
mod constant;
mod ord;
mod set;
pub use self::constant::{always, never, BooleanPredicate};
pub use self::ord::{eq, ne, lt, le, gt, ge, EqPredicate, OrdPredicate};
pub use self::set::{contains, ContainsPredicate, contains_ord, OrdContainsPredicate,
                    contains_hashable, HashableContainsPredicate};

// combinators
mod boolean;
pub use self::boolean::{AndPredicate, OrPredicate, NotPredicate};

/// Trait for generically evaluating a type against a dynamically created
/// predicate function.
///
/// The exact meaning of `eval` depends on the situation, but will usually
/// mean that the evaluated item is in some sort of pre-defined set.  This is
/// different from `Ord` and `Eq` in that an `item` will almost never be the
/// same type as the implementing `Predicate` type.
pub trait Predicate {
    /// The type that this `Predicate` will accept for evaluating.
    type Item;

    /// Execute this `Predicate` against `variable`, returning the resulting
    /// boolean.
    fn eval(&self, variable: &Self::Item) -> bool;

    /// Compute the logical AND of two `Predicate` results, returning the result.
    ///
    /// # Examples
    ///
    /// ```
    /// use predicates::predicate::*;
    ///
    /// let predicate_fn1 = always().and(always());
    /// let predicate_fn2 = always().and(never());
    /// assert_eq!(true, predicate_fn1.eval(&4));
    /// assert_eq!(false, predicate_fn2.eval(&4));
    fn and<B>(self, other: B) -> AndPredicate<Self, B>
        where B: Predicate<Item = Self::Item>,
              Self: Sized
    {
        AndPredicate::new(self, other)
    }

    /// Compute the logical OR of two `Predicate` results, returning the result.
    ///
    /// # Examples
    ///
    /// ```
    /// use predicates::predicate::*;
    ///
    /// let predicate_fn1 = always().or(always());
    /// let predicate_fn2 = always().or(never());
    /// let predicate_fn3 = never().or(never());
    /// assert_eq!(true, predicate_fn1.eval(&4));
    /// assert_eq!(true, predicate_fn2.eval(&4));
    /// assert_eq!(false, predicate_fn3.eval(&4));
    fn or<B>(self, other: B) -> OrPredicate<Self, B>
        where B: Predicate<Item = Self::Item>,
              Self: Sized
    {
        OrPredicate::new(self, other)
    }

    /// Compute the logical NOT of a `Predicate`, returning the result.
    ///
    /// # Examples
    ///
    /// ```
    /// use predicates::predicate::*;
    ///
    /// let predicate_fn1 = always().not();
    /// let predicate_fn2 = never().not();
    /// assert_eq!(false, predicate_fn1.eval(&4));
    /// assert_eq!(true, predicate_fn2.eval(&4));
    fn not(self) -> NotPredicate<Self>
        where Self: Sized
    {
        NotPredicate::new(self)
    }

    /// Convenience function that returns a trait object of this `Predicate`.
    ///
    /// # Examples
    ///
    /// ```
    /// use predicates::predicate::*;
    ///
    /// let predicates = vec![
    ///     always().boxed(),
    ///     never().boxed(),
    /// ];
    /// assert_eq!(true, predicates[0].eval(&4));
    /// assert_eq!(false, predicates[1].eval(&4));
    /// ```
    fn boxed(self) -> Box<Predicate<Item = Self::Item>>
        where Self: 'static + Sized
    {
        Box::new(self)
    }
}
<commit_msg>Allow `Predicate` Item type to be unsized<commit_after>// Copyright (c) 2017, Nick Stevens <nick@bitcurry.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/license/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Predicate
//!
//! This module contains the `Predicate` trait and a number of combinators for
//! the trait. See the crate docs, and the docs for `Predicate`, for full detail.

// primitive `Predicate` types
mod constant;
mod ord;
mod set;
pub use self::constant::{always, never, BooleanPredicate};
pub use self::ord::{eq, ne, lt, le, gt, ge, EqPredicate, OrdPredicate};
pub use self::set::{contains, ContainsPredicate, contains_ord, OrdContainsPredicate,
                    contains_hashable, HashableContainsPredicate};

// combinators
mod boolean;
pub use self::boolean::{AndPredicate, OrPredicate, NotPredicate};

/// Trait for generically evaluating a type against a dynamically created
/// predicate function.
///
/// The exact meaning of `eval` depends on the situation, but will usually
/// mean that the evaluated item is in some sort of pre-defined set.  This is
/// different from `Ord` and `Eq` in that an `item` will almost never be the
/// same type as the implementing `Predicate` type.
pub trait Predicate {
    /// The type that this `Predicate` will accept for evaluating.
    type Item: ?Sized;

    /// Execute this `Predicate` against `variable`, returning the resulting
    /// boolean.
    fn eval(&self, variable: &Self::Item) -> bool;

    /// Compute the logical AND of two `Predicate` results, returning the result.
    ///
    /// # Examples
    ///
    /// ```
    /// use predicates::predicate::*;
    ///
    /// let predicate_fn1 = always().and(always());
    /// let predicate_fn2 = always().and(never());
    /// assert_eq!(true, predicate_fn1.eval(&4));
    /// assert_eq!(false, predicate_fn2.eval(&4));
    fn and<B>(self, other: B) -> AndPredicate<Self, B>
        where B: Predicate<Item = Self::Item>,
              Self: Sized
    {
        AndPredicate::new(self, other)
    }

    /// Compute the logical OR of two `Predicate` results, returning the result.
    ///
    /// # Examples
    ///
    /// ```
    /// use predicates::predicate::*;
    ///
    /// let predicate_fn1 = always().or(always());
    /// let predicate_fn2 = always().or(never());
    /// let predicate_fn3 = never().or(never());
    /// assert_eq!(true, predicate_fn1.eval(&4));
    /// assert_eq!(true, predicate_fn2.eval(&4));
    /// assert_eq!(false, predicate_fn3.eval(&4));
    fn or<B>(self, other: B) -> OrPredicate<Self, B>
        where B: Predicate<Item = Self::Item>,
              Self: Sized
    {
        OrPredicate::new(self, other)
    }

    /// Compute the logical NOT of a `Predicate`, returning the result.
    ///
    /// # Examples
    ///
    /// ```
    /// use predicates::predicate::*;
    ///
    /// let predicate_fn1 = always().not();
    /// let predicate_fn2 = never().not();
    /// assert_eq!(false, predicate_fn1.eval(&4));
    /// assert_eq!(true, predicate_fn2.eval(&4));
    fn not(self) -> NotPredicate<Self>
        where Self: Sized
    {
        NotPredicate::new(self)
    }

    /// Convenience function that returns a trait object of this `Predicate`.
    ///
    /// # Examples
    ///
    /// ```
    /// use predicates::predicate::*;
    ///
    /// let predicates = vec![
    ///     always().boxed(),
    ///     never().boxed(),
    /// ];
    /// assert_eq!(true, predicates[0].eval(&4));
    /// assert_eq!(false, predicates[1].eval(&4));
    /// ```
    fn boxed(self) -> Box<Predicate<Item = Self::Item>>
        where Self: 'static + Sized
    {
        Box::new(self)
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

// Box-shadow, etc.
<% data.new_style_struct("Effects", inherited=False) %>

${helpers.predefined_type(
    "opacity",
    "Opacity",
    "1.0",
    animation_value_type="ComputedValue",
    flags="CREATES_STACKING_CONTEXT APPLIES_TO_PLACEHOLDER \
           CAN_ANIMATE_ON_COMPOSITOR",
    spec="https://drafts.csswg.org/css-color/#opacity",
    servo_restyle_damage = "reflow_out_of_flow",
)}

${helpers.predefined_type(
    "box-shadow",
    "BoxShadow",
    None,
    vector=True,
    animation_value_type="AnimatedBoxShadowList",
    vector_animation_type="with_zero",
    extra_prefixes="webkit",
    ignored_when_colors_disabled=True,
    flags="APPLIES_TO_FIRST_LETTER",
    spec="https://drafts.csswg.org/css-backgrounds/#box-shadow",
)}

${helpers.predefined_type(
    "clip",
    "ClipRectOrAuto",
    "computed::ClipRectOrAuto::auto()",
    animation_value_type="ComputedValue",
    boxed=True,
    allow_quirks=True,
    spec="https://drafts.fxtf.org/css-masking/#clip-property",
)}

${helpers.predefined_type(
    "filter",
    "Filter",
    None,
    vector=True,
    separator="Space",
    animation_value_type="AnimatedFilterList",
    vector_animation_type="with_zero",
    extra_prefixes="webkit",
    flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
    spec="https://drafts.fxtf.org/filters/#propdef-filter",
)}

${helpers.single_keyword(
    "mix-blend-mode",
    """normal multiply screen overlay darken lighten color-dodge
    color-burn hard-light soft-light difference exclusion hue
    saturation color luminosity""",
    gecko_constant_prefix="NS_STYLE_BLEND",
    animation_value_type="discrete",
    flags="CREATES_STACKING_CONTEXT",
    gecko_pref="layout.css.mix-blend-mode.enabled",
    spec="https://drafts.fxtf.org/compositing/#propdef-mix-blend-mode",
)}
<commit_msg>style: Drop layout.css.mix-blend-mode.enabled pref.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

// Box-shadow, etc.
<% data.new_style_struct("Effects", inherited=False) %>

${helpers.predefined_type(
    "opacity",
    "Opacity",
    "1.0",
    animation_value_type="ComputedValue",
    flags="CREATES_STACKING_CONTEXT APPLIES_TO_PLACEHOLDER \
           CAN_ANIMATE_ON_COMPOSITOR",
    spec="https://drafts.csswg.org/css-color/#opacity",
    servo_restyle_damage = "reflow_out_of_flow",
)}

${helpers.predefined_type(
    "box-shadow",
    "BoxShadow",
    None,
    vector=True,
    animation_value_type="AnimatedBoxShadowList",
    vector_animation_type="with_zero",
    extra_prefixes="webkit",
    ignored_when_colors_disabled=True,
    flags="APPLIES_TO_FIRST_LETTER",
    spec="https://drafts.csswg.org/css-backgrounds/#box-shadow",
)}

${helpers.predefined_type(
    "clip",
    "ClipRectOrAuto",
    "computed::ClipRectOrAuto::auto()",
    animation_value_type="ComputedValue",
    boxed=True,
    allow_quirks=True,
    spec="https://drafts.fxtf.org/css-masking/#clip-property",
)}

${helpers.predefined_type(
    "filter",
    "Filter",
    None,
    vector=True,
    separator="Space",
    animation_value_type="AnimatedFilterList",
    vector_animation_type="with_zero",
    extra_prefixes="webkit",
    flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
    spec="https://drafts.fxtf.org/filters/#propdef-filter",
)}

${helpers.single_keyword(
    "mix-blend-mode",
    """normal multiply screen overlay darken lighten color-dodge
    color-burn hard-light soft-light difference exclusion hue
    saturation color luminosity""",
    gecko_constant_prefix="NS_STYLE_BLEND",
    animation_value_type="discrete",
    flags="CREATES_STACKING_CONTEXT",
    spec="https://drafts.fxtf.org/compositing/#propdef-mix-blend-mode",
)}
<|endoftext|>


<commit_before>use board::sjadam_board::SjadamBoard;
use uci::UciBoard;
use board::sjadam_move::SjadamMove;
use search_algorithms::game_move::Move;
use search_algorithms::board::{GameResult, EvalBoard};
use tests::move_gen_tests;

#[test]
fn correct_move_gen_start_pos() {
    let start_board = SjadamBoard::start_board().clone();
    let moves = start_board.all_legal_moves();
    assert_eq!(moves.len(), 146, "Found {} moves: {:?}, expected 146",
               moves.len(), moves);
}

/// Tests whether a pawn is allowed to sjadam over an opponent pawn
#[test]
fn jump_over_opponent() {
    let board = SjadamBoard::from_fen("8/8/8/7p/7P/8/8/K1k5 w - - 1 1").unwrap();
    assert_eq!(board.game_result(), None);
    let moves = board.all_legal_moves();
    assert_eq!(board.all_legal_moves().len(), 5,
               "Expected 5 legal moves, found {} moves: {:?}\n{:?}",
               moves.len(), moves, board);
}

#[test]
fn no_stalemate_test() {
    let board = SjadamBoard::from_fen("8/8/8/5p1k/3p1Q2/3P2R1/P3p2P/4K3 b - - 2 39").unwrap();
    assert_eq!(board.game_result(), None);
    let moves = board.all_legal_moves();
    // The exact number may be wrong due to other bugs
    // So don't trust this test
    assert_eq!(board.all_legal_moves().len(), 13,
               "Expected 13 legal moves, found {} moves: {:?}\n{:?}",
               moves.len(), moves, board);
}

#[test]
fn can_take_king_while_checked() {
    let board = SjadamBoard::from_fen("r2q2n1/pp4pp/6k1/2Nb4/8/5P2/P1P1PK2/2B3q1 w - - 0 1").unwrap();
    // Black is really sjadammated, so this is also a possible outcome
    if board.game_result() != Some(GameResult::WhiteWin) {
        let moves = board.all_legal_moves();

        let correct_move = SjadamMove::from_alg("c5e5g6").unwrap();
        assert!(board.all_legal_moves().contains(&correct_move),
                "White couldn't take king on board:\n{:?}Moves: {:?}",
                board, moves);
    }
}

#[test]
fn sjadam_move_to_promote_pawn() {
    let board = SjadamBoard::from_fen("k7/5R2/5P2/8/8/8/8/7K w - - 0 1").unwrap();
    let moves = board.all_legal_moves();

    let correct_move = SjadamMove::from_alg("f6f8-").unwrap();
    assert!(board.all_legal_moves().contains(&correct_move),
            "White couldn't promote in sjadam on board:\n{:?}Moves: {:?}",
            board, moves);
}

#[test]
fn no_moves_on_back_rank() {
    let board = SjadamBoard::from_fen("8/K7/P7/8/8/8/8/7k w - - 0 1").unwrap();
    let moves = board.all_legal_moves();
    assert_eq!(moves.len(), 9, "Expected to find {} moves, found {}: {:?}", 9, moves.len(), moves);
}

#[test]
fn startpos_perf_test() {
    let mut board = SjadamBoard::start_board();
    for (n, &moves) in (1..4).zip([146, 21_469, 3_268_163].iter()) {
        assert_eq!(move_gen_tests::legal_moves_after_plies(&mut board, n), moves);
    }
}

#[test]
#[ignore]
fn startpos_perf_test_long() {
    let mut board = SjadamBoard::start_board();
    assert_eq!(move_gen_tests::legal_moves_after_plies(&mut board, 4), 500_951_687);
}

#[test]
fn castling_en_passant_perf_test() {
    let mut board = SjadamBoard::start_board();
    board.do_move(SjadamMove::from_alg("g1e3-").unwrap());
    board.do_move(SjadamMove::from_alg("g8e6-").unwrap());
    board.do_move(SjadamMove::from_alg("f1d3c4").unwrap());
    board.do_move(SjadamMove::from_alg("e8g8-").unwrap());
    board.do_move(SjadamMove::from_alg("-c2c3").unwrap());
    board.do_move(SjadamMove::from_alg("-d7d5").unwrap());
    board.do_move(SjadamMove::from_alg("c1a3-").unwrap());
    board.do_move(SjadamMove::from_alg("-b7b5").unwrap());
    for (n, &moves) in (1..4).zip([160, 26_959, 4_259_773].iter()) {
        let result = move_gen_tests::legal_moves_after_plies(&mut board, n);
        assert_eq!(result, moves,
                   "Expected {} moves, found {} on board:\n{:?}.", moves, result, board);
    }
}

#[test]
fn perf_test_3() {
    let mut board = SjadamBoard::from_fen("1nbqkb1r/pppppppp/4r3/8/8/4N3/PPPPPPPP/RNBQ1RK1 b k - 0 1").unwrap();
    for (n, &moves) in (1..4).zip([144, 22_645, 3_368_765].iter()) {
        let result = move_gen_tests::legal_moves_after_plies(&mut board, n);
        assert_eq!(result, moves,
                   "Expected {} moves, found {} on board:\n{:?}.", moves, result, board);
    }
}

#[test]
fn perf_test_4() {
    let mut board = SjadamBoard::from_fen("rnbqkbnr/pppppppp/8/8/8/5N2/PPPPPPPP/RNBQKB1R b KQkq - 1 1").unwrap();
    for (n, &moves) in (1..4).zip([144, 18_152, 2_750_259].iter()) {
        let result = move_gen_tests::legal_moves_after_plies(&mut board, n);
        assert_eq!(result, moves,
                   "Expected {} moves, found {} on board:\n{:?}.", moves, result, board);
    }
}

#[test]
fn perf_test_5() {
    let mut board = SjadamBoard::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 1 1").unwrap();
    for (n, &moves) in (1..4).zip([145, 25_359, 3_865_242].iter()) {
        let result = move_gen_tests::legal_moves_after_plies(&mut board, n);
        assert_eq!(result, moves,
                   "Expected {} moves, found {} on board:\n{:?}.", moves, result, board);
    }
}

#[test]
fn perf_test_6() {
    let mut board = SjadamBoard::from_fen("rnbqkbnr/pppppppp/8/8/2P5/8/PP1PPPPP/RNBQKBNR b KQkq - 0 1").unwrap();
    for (n, &moves) in (1..4).zip([140, 22_867, 3_417_912].iter()) {
        let result = move_gen_tests::legal_moves_after_plies(&mut board, n);
        assert_eq!(result, moves,
                   "Expected {} moves, found {} on board:\n{:?}.", moves, result, board);
    }
}
<commit_msg>Changed position of sjadam perf_test_6<commit_after>use board::sjadam_board::SjadamBoard;
use uci::UciBoard;
use board::sjadam_move::SjadamMove;
use search_algorithms::game_move::Move;
use search_algorithms::board::{GameResult, EvalBoard};
use tests::move_gen_tests;

#[test]
fn correct_move_gen_start_pos() {
    let start_board = SjadamBoard::start_board().clone();
    let moves = start_board.all_legal_moves();
    assert_eq!(moves.len(), 146, "Found {} moves: {:?}, expected 146",
               moves.len(), moves);
}

/// Tests whether a pawn is allowed to sjadam over an opponent pawn
#[test]
fn jump_over_opponent() {
    let board = SjadamBoard::from_fen("8/8/8/7p/7P/8/8/K1k5 w - - 1 1").unwrap();
    assert_eq!(board.game_result(), None);
    let moves = board.all_legal_moves();
    assert_eq!(board.all_legal_moves().len(), 5,
               "Expected 5 legal moves, found {} moves: {:?}\n{:?}",
               moves.len(), moves, board);
}

#[test]
fn no_stalemate_test() {
    let board = SjadamBoard::from_fen("8/8/8/5p1k/3p1Q2/3P2R1/P3p2P/4K3 b - - 2 39").unwrap();
    assert_eq!(board.game_result(), None);
    let moves = board.all_legal_moves();
    // The exact number may be wrong due to other bugs
    // So don't trust this test
    assert_eq!(board.all_legal_moves().len(), 13,
               "Expected 13 legal moves, found {} moves: {:?}\n{:?}",
               moves.len(), moves, board);
}

#[test]
fn can_take_king_while_checked() {
    let board = SjadamBoard::from_fen("r2q2n1/pp4pp/6k1/2Nb4/8/5P2/P1P1PK2/2B3q1 w - - 0 1").unwrap();
    // Black is really sjadammated, so this is also a possible outcome
    if board.game_result() != Some(GameResult::WhiteWin) {
        let moves = board.all_legal_moves();

        let correct_move = SjadamMove::from_alg("c5e5g6").unwrap();
        assert!(board.all_legal_moves().contains(&correct_move),
                "White couldn't take king on board:\n{:?}Moves: {:?}",
                board, moves);
    }
}

#[test]
fn sjadam_move_to_promote_pawn() {
    let board = SjadamBoard::from_fen("k7/5R2/5P2/8/8/8/8/7K w - - 0 1").unwrap();
    let moves = board.all_legal_moves();

    let correct_move = SjadamMove::from_alg("f6f8-").unwrap();
    assert!(board.all_legal_moves().contains(&correct_move),
            "White couldn't promote in sjadam on board:\n{:?}Moves: {:?}",
            board, moves);
}

#[test]
fn no_moves_on_back_rank() {
    let board = SjadamBoard::from_fen("8/K7/P7/8/8/8/8/7k w - - 0 1").unwrap();
    let moves = board.all_legal_moves();
    assert_eq!(moves.len(), 9, "Expected to find {} moves, found {}: {:?}", 9, moves.len(), moves);
}

#[test]
fn startpos_perf_test() {
    let mut board = SjadamBoard::start_board();
    for (n, &moves) in (1..4).zip([146, 21_469, 3_268_163].iter()) {
        assert_eq!(move_gen_tests::legal_moves_after_plies(&mut board, n), moves);
    }
}

#[test]
#[ignore]
fn startpos_perf_test_long() {
    let mut board = SjadamBoard::start_board();
    assert_eq!(move_gen_tests::legal_moves_after_plies(&mut board, 4), 500_951_687);
}

#[test]
fn castling_en_passant_perf_test() {
    let mut board = SjadamBoard::start_board();
    board.do_move(SjadamMove::from_alg("g1e3-").unwrap());
    board.do_move(SjadamMove::from_alg("g8e6-").unwrap());
    board.do_move(SjadamMove::from_alg("f1d3c4").unwrap());
    board.do_move(SjadamMove::from_alg("e8g8-").unwrap());
    board.do_move(SjadamMove::from_alg("-c2c3").unwrap());
    board.do_move(SjadamMove::from_alg("-d7d5").unwrap());
    board.do_move(SjadamMove::from_alg("c1a3-").unwrap());
    board.do_move(SjadamMove::from_alg("-b7b5").unwrap());
    for (n, &moves) in (1..4).zip([160, 26_959, 4_259_773].iter()) {
        let result = move_gen_tests::legal_moves_after_plies(&mut board, n);
        assert_eq!(result, moves,
                   "Expected {} moves, found {} on board:\n{:?}.", moves, result, board);
    }
}

#[test]
fn perf_test_3() {
    let mut board = SjadamBoard::from_fen("1nbqkb1r/pppppppp/4r3/8/8/4N3/PPPPPPPP/RNBQ1RK1 b k - 0 1").unwrap();
    for (n, &moves) in (1..4).zip([144, 22_645, 3_368_765].iter()) {
        let result = move_gen_tests::legal_moves_after_plies(&mut board, n);
        assert_eq!(result, moves,
                   "Expected {} moves, found {} on board:\n{:?}.", moves, result, board);
    }
}

#[test]
fn perf_test_4() {
    let mut board = SjadamBoard::from_fen("rnbqkbnr/pppppppp/8/8/8/5N2/PPPPPPPP/RNBQKB1R b KQkq - 1 1").unwrap();
    for (n, &moves) in (1..4).zip([144, 18_152, 2_750_259].iter()) {
        let result = move_gen_tests::legal_moves_after_plies(&mut board, n);
        assert_eq!(result, moves,
                   "Expected {} moves, found {} on board:\n{:?}.", moves, result, board);
    }
}

#[test]
fn perf_test_5() {
    let mut board = SjadamBoard::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 1 1").unwrap();
    for (n, &moves) in (1..4).zip([145, 25_359, 3_865_242].iter()) {
        let result = move_gen_tests::legal_moves_after_plies(&mut board, n);
        assert_eq!(result, moves,
                   "Expected {} moves, found {} on board:\n{:?}.", moves, result, board);
    }
}

#[test]
fn perf_test_6() {
    let mut board = SjadamBoard::from_fen("rnbqkbnr/pppppppp/8/8/2K5/8/PPPPPPPP/RNBQ1BNR b kq - 0 1").unwrap();
    for (n, &moves) in (1..4).zip([140, 24_826, 3_714_605].iter()) {
        let result = move_gen_tests::legal_moves_after_plies(&mut board, n);
        assert_eq!(result, moves,
                   "Expected {} moves, found {} on board:\n{:?}.", moves, result, board);
    }
}
<|endoftext|>


<commit_before>// Rust Bitcoin Library
// Written in 2014 by
//     Andrew Poelstra <apoelstra@wpsoftware.net>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # Floating-point decimal type
//!
//! `i64`-based floating-point decimal type designed to hold Bitcoin
//! amounts. For satoshi amounts (8 decimal places) the maximum
//! amounts that can be represented is ~92.25bn, well over the 21m
//! maximum number of bitcoin in existence. Be aware that some
//! altcoins with different granularity may require a wider type.
//!

use std::ops;

use serde::{ser, de};
use strason::Json;

/// A fixed-point decimal type
#[derive(Copy, Clone, Debug, Eq, Ord)]
pub struct Decimal {
    mantissa: i64,
    exponent: usize,
}

impl PartialEq<Decimal> for Decimal {
    fn eq(&self, other: &Decimal) -> bool {
        use std::cmp::max;
        let exp = max(self.exponent(), other.exponent());
        self.integer_value(exp) == other.integer_value(exp)
    }
}

impl PartialOrd<Decimal> for Decimal {
    fn partial_cmp(&self, other: &Decimal) -> Option<::std::cmp::Ordering> {
        use std::cmp::max;
        let exp = max(self.exponent(), other.exponent());
        self.integer_value(exp).partial_cmp(&other.integer_value(exp))
    }
}

impl ops::Add for Decimal {
    type Output = Decimal;

    #[inline]
    fn add(self, other: Decimal) -> Decimal {
        if self.exponent > other.exponent {
            Decimal {
                mantissa: other.mantissa * 10i64.pow((self.exponent - other.exponent) as u32) + self.mantissa,
                exponent: self.exponent
            }
        } else {
            Decimal {
                mantissa: self.mantissa * 10i64.pow((other.exponent - self.exponent) as u32) + other.mantissa,
                exponent: other.exponent
            }
        }
    }
}

impl ops::Neg for Decimal {
    type Output = Decimal;
    #[inline]
    fn neg(self) -> Decimal { Decimal { mantissa: -self.mantissa, exponent: self.exponent } }
}

impl ops::Sub for Decimal {
    type Output = Decimal;
    #[inline]
    fn sub(self, other: Decimal) -> Decimal { self + (-other) }
}

impl Decimal {
    /// Creates a new Decimal
    pub fn new(mantissa: i64, exponent: usize) -> Decimal {
        Decimal {
            mantissa: mantissa,
            exponent: exponent
        }
    }

    /// Returns the mantissa
    pub fn mantissa(&self) -> i64 { self.mantissa }
    /// Returns the exponent
    pub fn exponent(&self) -> usize { self.exponent }

    /// Get the decimal's value in an integer type, by multiplying
    /// by some power of ten to ensure the returned value is 10 **
    /// `exponent` types the actual value.
    pub fn integer_value(&self, exponent: usize) -> i64 {
        if exponent < self.exponent {
            self.mantissa / 10i64.pow((self.exponent - exponent) as u32)
        } else {
            self.mantissa * 10i64.pow((exponent - self.exponent) as u32)
        }
    }
}

impl ser::Serialize for Decimal {
    // Serialize through strason since it will not lose precision (when serializing
    // to strason itself, the value will be passed through; otherwise it will be
    // encoded as a string)
    fn serialize<S: ser::Serializer>(&self, s: &mut S) -> Result<(), S::Error> {
        let ten = 10i64.pow(self.exponent as u32);
        let int_part = self.mantissa / ten;
        let dec_part = (self.mantissa % ten).abs();
        println!("{}", format!("{}.{:02$}", int_part, dec_part, self.exponent));
        let json = Json::from_str(&format!("{}.{:02$}", int_part, dec_part, self.exponent)).unwrap();
        ser::Serialize::serialize(&json, s)
    }
}

impl de::Deserialize for Decimal {
    // Deserialize through strason for the same reason as in `Serialize`
    fn deserialize<D: de::Deserializer>(d: &mut D) -> Result<Decimal, D::Error> {
        let json: Json = try!(de::Deserialize::deserialize(d));
        match json.num() {
            Some(s) => {
                 // We know this will be a well-formed Json number, so we can
                 // be pretty lax about parsing
                 let mut negative = false;
                 let mut past_dec = false;
                 let mut exponent = 0;
                 let mut mantissa = 0i64;

                 for b in s.as_bytes() {
                     match *b {
                         b'-' => { negative = true; }
                         b'0'...b'9' => {
                             mantissa = 10 * mantissa + (b - b'0') as i64;
                             if past_dec { exponent += 1; }
                         }
                         b'.' => { past_dec = true; }
                         _ => { /* whitespace or something, just ignore it */ }
                     }
                 }
                 if negative { mantissa *= -1; }
                 Ok(Decimal {
                     mantissa: mantissa,
                     exponent: exponent,
                 })
            }
            None => Err(de::Error::syntax("expected decimal, got non-numeric"))
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use strason::Json;

    #[test]
    fn integer_value() {
        let d = Decimal::new(12345678, 4);
        assert_eq!(d.mantissa(), 12345678);
        assert_eq!(d.exponent(), 4);

        assert_eq!(d.integer_value(0), 1234);
        assert_eq!(d.integer_value(1), 12345);
        assert_eq!(d.integer_value(2), 123456);
        assert_eq!(d.integer_value(3), 1234567);
        assert_eq!(d.integer_value(4), 12345678);
        assert_eq!(d.integer_value(5), 123456780);
        assert_eq!(d.integer_value(6), 1234567800);
        assert_eq!(d.integer_value(7), 12345678000);
        assert_eq!(d.integer_value(8), 123456780000);
    }

    macro_rules! deserialize_round_trip(
        ($dec:expr, $s:expr) => ({
            let d = $dec;
            let encoded = Json::from_serialize(&d).unwrap();
            assert_eq!(encoded, Json::from_reader(&$s[..]).unwrap());
            assert_eq!(encoded.to_bytes(), &$s[..]);

            let decoded: Decimal = encoded.into_deserialize().unwrap();
            assert_eq!(decoded, d);
        })
    );

    #[test]
    fn deserialize() {
        deserialize_round_trip!(Decimal::new(0, 0), b"0.0");

        deserialize_round_trip!(Decimal::new(123456789001, 8), b"1234.56789001");
        deserialize_round_trip!(Decimal::new(-123456789001, 8), b"-1234.56789001");
        deserialize_round_trip!(Decimal::new(123456789001, 1), b"12345678900.1");
        deserialize_round_trip!(Decimal::new(-123456789001, 1), b"-12345678900.1");
        deserialize_round_trip!(Decimal::new(123456789001, 0), b"123456789001.0");
        deserialize_round_trip!(Decimal::new(-123456789001, 0), b"-123456789001.0");

        deserialize_round_trip!(Decimal::new(123400000001, 8), b"1234.00000001");
        deserialize_round_trip!(Decimal::new(-123400000001, 8), b"-1234.00000001");
    }

    #[test]
    fn equality() {
        let d1 = Decimal::new(1234, 8);
        let d2 = Decimal::new(12340, 9);
        let d3 = Decimal::new(12340, 8);
        assert_eq!(d1, d1);
        assert_eq!(d1, d2);
        assert!(d1 != d3);
        assert!(d2 != d3);

        assert!(d1 <= d1);
        assert!(d2 <= d2);
        assert!(d3 <= d3);
        assert!(d1 <= d2);
        assert!(d1 <= d3);
        assert!(d3 > d1);
        assert!(d3 > d2);
    }

    #[test]
    fn arithmetic() {
        let d1 = Decimal::new(5, 1);   //  0.5
        let d2 = Decimal::new(-2, 2);  // -0.02
        let d3 = Decimal::new(3, 0);   //  3.0

        assert_eq!(d1 + d2, Decimal::new(48, 2));
        assert_eq!(d1 - d2, Decimal::new(52, 2));
        assert_eq!(d1 + d3, Decimal::new(35, 1));
        assert_eq!(d1 - d3, Decimal::new(-25, 1));
        assert_eq!(d2 + d3, Decimal::new(298, 2));
        assert_eq!(d2 - d3, Decimal::new(-302, 2));
    }

    #[test]
    fn json_parse() {
        let json = Json::from_str("0.00980000").unwrap();
        assert_eq!(json.to_bytes(), b"0.00980000");
        let dec: Decimal = json.into_deserialize().unwrap();
        assert_eq!(dec, Decimal::new(980000, 8));

        let json = Json::from_str("0.00980").unwrap();
        assert_eq!(json.to_bytes(), b"0.00980");
        let dec: Decimal = json.into_deserialize().unwrap();
        assert_eq!(dec, Decimal::new(98000, 7));
    }
}

<commit_msg>Add Display impl for Decimal<commit_after>// Rust Bitcoin Library
// Written in 2014 by
//     Andrew Poelstra <apoelstra@wpsoftware.net>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # Floating-point decimal type
//!
//! `i64`-based floating-point decimal type designed to hold Bitcoin
//! amounts. For satoshi amounts (8 decimal places) the maximum
//! amounts that can be represented is ~92.25bn, well over the 21m
//! maximum number of bitcoin in existence. Be aware that some
//! altcoins with different granularity may require a wider type.
//!

use std::{fmt, ops};

use serde::{ser, de};
use strason::Json;

/// A fixed-point decimal type
#[derive(Copy, Clone, Debug, Eq, Ord)]
pub struct Decimal {
    mantissa: i64,
    exponent: usize,
}

impl PartialEq<Decimal> for Decimal {
    fn eq(&self, other: &Decimal) -> bool {
        use std::cmp::max;
        let exp = max(self.exponent(), other.exponent());
        self.integer_value(exp) == other.integer_value(exp)
    }
}

impl PartialOrd<Decimal> for Decimal {
    fn partial_cmp(&self, other: &Decimal) -> Option<::std::cmp::Ordering> {
        use std::cmp::max;
        let exp = max(self.exponent(), other.exponent());
        self.integer_value(exp).partial_cmp(&other.integer_value(exp))
    }
}

impl fmt::Display for Decimal {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let ten = 10i64.pow(self.exponent as u32);
        let int_part = self.mantissa / ten;
        let dec_part = (self.mantissa % ten).abs();
        write!(f, "{}.{:02$}", int_part, dec_part, self.exponent)
    }
}

impl ops::Add for Decimal {
    type Output = Decimal;

    #[inline]
    fn add(self, other: Decimal) -> Decimal {
        if self.exponent > other.exponent {
            Decimal {
                mantissa: other.mantissa * 10i64.pow((self.exponent - other.exponent) as u32) + self.mantissa,
                exponent: self.exponent
            }
        } else {
            Decimal {
                mantissa: self.mantissa * 10i64.pow((other.exponent - self.exponent) as u32) + other.mantissa,
                exponent: other.exponent
            }
        }
    }
}

impl ops::Neg for Decimal {
    type Output = Decimal;
    #[inline]
    fn neg(self) -> Decimal { Decimal { mantissa: -self.mantissa, exponent: self.exponent } }
}

impl ops::Sub for Decimal {
    type Output = Decimal;
    #[inline]
    fn sub(self, other: Decimal) -> Decimal { self + (-other) }
}

impl Decimal {
    /// Creates a new Decimal
    pub fn new(mantissa: i64, exponent: usize) -> Decimal {
        Decimal {
            mantissa: mantissa,
            exponent: exponent
        }
    }

    /// Returns the mantissa
    pub fn mantissa(&self) -> i64 { self.mantissa }
    /// Returns the exponent
    pub fn exponent(&self) -> usize { self.exponent }

    /// Get the decimal's value in an integer type, by multiplying
    /// by some power of ten to ensure the returned value is 10 **
    /// `exponent` types the actual value.
    pub fn integer_value(&self, exponent: usize) -> i64 {
        if exponent < self.exponent {
            self.mantissa / 10i64.pow((self.exponent - exponent) as u32)
        } else {
            self.mantissa * 10i64.pow((exponent - self.exponent) as u32)
        }
    }
}

impl ser::Serialize for Decimal {
    // Serialize through strason since it will not lose precision (when serializing
    // to strason itself, the value will be passed through; otherwise it will be
    // encoded as a string)
    fn serialize<S: ser::Serializer>(&self, s: &mut S) -> Result<(), S::Error> {
        let json = Json::from_str(&self.to_string()).unwrap();
        ser::Serialize::serialize(&json, s)
    }
}

impl de::Deserialize for Decimal {
    // Deserialize through strason for the same reason as in `Serialize`
    fn deserialize<D: de::Deserializer>(d: &mut D) -> Result<Decimal, D::Error> {
        let json: Json = try!(de::Deserialize::deserialize(d));
        match json.num() {
            Some(s) => {
                 // We know this will be a well-formed Json number, so we can
                 // be pretty lax about parsing
                 let mut negative = false;
                 let mut past_dec = false;
                 let mut exponent = 0;
                 let mut mantissa = 0i64;

                 for b in s.as_bytes() {
                     match *b {
                         b'-' => { negative = true; }
                         b'0'...b'9' => {
                             mantissa = 10 * mantissa + (b - b'0') as i64;
                             if past_dec { exponent += 1; }
                         }
                         b'.' => { past_dec = true; }
                         _ => { /* whitespace or something, just ignore it */ }
                     }
                 }
                 if negative { mantissa *= -1; }
                 Ok(Decimal {
                     mantissa: mantissa,
                     exponent: exponent,
                 })
            }
            None => Err(de::Error::syntax("expected decimal, got non-numeric"))
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use strason::Json;

    #[test]
    fn integer_value() {
        let d = Decimal::new(12345678, 4);
        assert_eq!(d.mantissa(), 12345678);
        assert_eq!(d.exponent(), 4);

        assert_eq!(d.integer_value(0), 1234);
        assert_eq!(d.integer_value(1), 12345);
        assert_eq!(d.integer_value(2), 123456);
        assert_eq!(d.integer_value(3), 1234567);
        assert_eq!(d.integer_value(4), 12345678);
        assert_eq!(d.integer_value(5), 123456780);
        assert_eq!(d.integer_value(6), 1234567800);
        assert_eq!(d.integer_value(7), 12345678000);
        assert_eq!(d.integer_value(8), 123456780000);
    }

    macro_rules! deserialize_round_trip(
        ($dec:expr, $s:expr) => ({
            let d = $dec;
            let encoded = Json::from_serialize(&d).unwrap();
            assert_eq!(encoded, Json::from_reader(&$s[..]).unwrap());
            assert_eq!(encoded.to_bytes(), &$s[..]);

            let decoded: Decimal = encoded.into_deserialize().unwrap();
            assert_eq!(decoded, d);
        })
    );

    #[test]
    fn deserialize() {
        deserialize_round_trip!(Decimal::new(0, 0), b"0.0");

        deserialize_round_trip!(Decimal::new(123456789001, 8), b"1234.56789001");
        deserialize_round_trip!(Decimal::new(-123456789001, 8), b"-1234.56789001");
        deserialize_round_trip!(Decimal::new(123456789001, 1), b"12345678900.1");
        deserialize_round_trip!(Decimal::new(-123456789001, 1), b"-12345678900.1");
        deserialize_round_trip!(Decimal::new(123456789001, 0), b"123456789001.0");
        deserialize_round_trip!(Decimal::new(-123456789001, 0), b"-123456789001.0");

        deserialize_round_trip!(Decimal::new(123400000001, 8), b"1234.00000001");
        deserialize_round_trip!(Decimal::new(-123400000001, 8), b"-1234.00000001");
    }

    #[test]
    fn equality() {
        let d1 = Decimal::new(1234, 8);
        let d2 = Decimal::new(12340, 9);
        let d3 = Decimal::new(12340, 8);
        assert_eq!(d1, d1);
        assert_eq!(d1, d2);
        assert!(d1 != d3);
        assert!(d2 != d3);

        assert!(d1 <= d1);
        assert!(d2 <= d2);
        assert!(d3 <= d3);
        assert!(d1 <= d2);
        assert!(d1 <= d3);
        assert!(d3 > d1);
        assert!(d3 > d2);
    }

    #[test]
    fn arithmetic() {
        let d1 = Decimal::new(5, 1);   //  0.5
        let d2 = Decimal::new(-2, 2);  // -0.02
        let d3 = Decimal::new(3, 0);   //  3.0

        assert_eq!(d1 + d2, Decimal::new(48, 2));
        assert_eq!(d1 - d2, Decimal::new(52, 2));
        assert_eq!(d1 + d3, Decimal::new(35, 1));
        assert_eq!(d1 - d3, Decimal::new(-25, 1));
        assert_eq!(d2 + d3, Decimal::new(298, 2));
        assert_eq!(d2 - d3, Decimal::new(-302, 2));
    }

    #[test]
    fn json_parse() {
        let json = Json::from_str("0.00980000").unwrap();
        assert_eq!(json.to_bytes(), b"0.00980000");
        let dec: Decimal = json.into_deserialize().unwrap();
        assert_eq!(dec, Decimal::new(980000, 8));

        let json = Json::from_str("0.00980").unwrap();
        assert_eq!(json.to_bytes(), b"0.00980");
        let dec: Decimal = json.into_deserialize().unwrap();
        assert_eq!(dec, Decimal::new(98000, 7));
    }
}

<|endoftext|>


<commit_before>//! Implementations of the Chalk `Cast` trait for our types.

use chalk_ir::{
    cast::{Cast, CastTo},
    interner::HasInterner,
};

use crate::{AliasEq, DomainGoal, GenericArg, GenericArgData, Interner, TraitRef, Ty, WhereClause};

macro_rules! has_interner {
    ($t:ty) => {
        impl HasInterner for $t {
            type Interner = crate::Interner;
        }
    };
}

has_interner!(WhereClause);
has_interner!(DomainGoal);
has_interner!(GenericArg);
has_interner!(Ty);

impl CastTo<WhereClause> for TraitRef {
    fn cast_to(self, _interner: &Interner) -> WhereClause {
        WhereClause::Implemented(self)
    }
}

impl CastTo<WhereClause> for AliasEq {
    fn cast_to(self, _interner: &Interner) -> WhereClause {
        WhereClause::AliasEq(self)
    }
}

impl CastTo<DomainGoal> for WhereClause {
    fn cast_to(self, _interner: &Interner) -> DomainGoal {
        DomainGoal::Holds(self)
    }
}

impl CastTo<GenericArg> for Ty {
    fn cast_to(self, interner: &Interner) -> GenericArg {
        GenericArg::new(interner, GenericArgData::Ty(self))
    }
}

macro_rules! transitive_impl {
    ($a:ty, $b:ty, $c:ty) => {
        impl CastTo<$c> for $a {
            fn cast_to(self, interner: &Interner) -> $c {
                self.cast::<$b>(interner).cast(interner)
            }
        }
    };
}

// In Chalk, these can be done as blanket impls, but that doesn't work here
// because of coherence

transitive_impl!(TraitRef, WhereClause, DomainGoal);
transitive_impl!(AliasEq, WhereClause, DomainGoal);

macro_rules! reflexive_impl {
    ($a:ty) => {
        impl CastTo<$a> for $a {
            fn cast_to(self, _interner: &Interner) -> $a {
                self
            }
        }
    };
}

reflexive_impl!(GenericArg);
<commit_msg>Remove obsolete Cast impls<commit_after>//! Implementations of the Chalk `Cast` trait for our types.

use chalk_ir::{
    cast::{Cast, CastTo},
    interner::HasInterner,
};

use crate::{AliasEq, DomainGoal, GenericArg, GenericArgData, Interner, TraitRef, Ty, WhereClause};

macro_rules! has_interner {
    ($t:ty) => {
        impl HasInterner for $t {
            type Interner = crate::Interner;
        }
    };
}

macro_rules! transitive_impl {
    ($a:ty, $b:ty, $c:ty) => {
        impl CastTo<$c> for $a {
            fn cast_to(self, interner: &Interner) -> $c {
                self.cast::<$b>(interner).cast(interner)
            }
        }
    };
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::io;
use std::io::ErrorKind::{WouldBlock, Interrupted};

use netbuf::Buf;
use time::SteadyTime;
use mio::{EventSet, PollOpt};

use super::StreamSocket as Socket;
use super::accept::Init;
use handler::{Registrator};
use {Async, EventMachine};

pub struct Timeout(pub SteadyTime);

struct Inner<S: Socket> {
    socket: S,
    inbuf: Buf,
    outbuf: Buf,
    writable: bool,
    readable: bool,
}

pub struct Stream<S: Socket, P: Protocol<C>, C>
    (Inner<S>, P, PhantomData<*mut C>);

pub struct Transport<'a> {
    inbuf: &'a mut Buf,
    outbuf: &'a mut Buf,
}

impl<S: Socket> Inner<S> {
    fn transport(&mut self) -> Transport {
        Transport {
            inbuf: &mut self.inbuf,
            outbuf: &mut self.outbuf,
        }
    }
}

impl<C, S: Socket, P: Protocol<C>> Init<S, C> for Stream<S, P, C> {
    fn accept(mut conn: S, context: &mut C) -> Option<Self>
    {
        let protocol = match Protocol::accepted(&mut conn, context) {
            Some(x) => x,
            None => return None
        };

        Some(Stream(Inner {
            socket: conn,
            inbuf: Buf::new(),
            outbuf: Buf::new(),
            readable: false,
            writable: true,   // Accepted socket is immediately writable
        }, protocol, PhantomData))
    }
}

impl<C, S: Socket, P: Protocol<C>> EventMachine<C> for Stream<S, P, C> {
    fn ready(self, evset: EventSet, context: &mut C)
        -> Async<Self, Option<Self>>
    {
        let Stream(mut stream, fsm, _) = self;
        let mut monad = Async::Continue(fsm, ());
        if evset.is_writable() && stream.outbuf.len() > 0 {
            stream.writable = true;
            while stream.outbuf.len() > 0 {
                match stream.outbuf.write_to(&mut stream.socket) {
                    Ok(0) => { // Connection closed
                        monad.done(|fsm| fsm.eof_received(context));
                        return Async::Stop;
                    }
                    Ok(_) => {
                        monad = async_try!(monad.and_then(|f| {
                            f.data_transferred(
                                &mut stream.transport(), context)
                        }));
                    }
                    Err(ref e) if e.kind() == WouldBlock => {
                        stream.writable = false;
                        break;
                    }
                    Err(ref e) if e.kind() == Interrupted =>  { continue; }
                    Err(e) => {
                        monad.done(|fsm| fsm.error_happened(e, context));
                        return Async::Stop;
                    }
                }
            }
        }
        if evset.is_readable() {
            stream.readable = true;
            loop {
                match stream.inbuf.read_from(&mut stream.socket) {
                    Ok(0) => { // Connection closed
                        monad.done(|fsm| fsm.eof_received(context));
                        return Async::Stop;
                    }
                    Ok(_) => {
                        monad = async_try!(monad.and_then(|f| {
                            f.data_received(
                                &mut stream.transport(), context)
                        }));
                    }
                    Err(ref e) if e.kind() == WouldBlock => {
                        stream.readable = false;
                        break;
                    }
                    Err(ref e) if e.kind() == Interrupted =>  { continue; }
                    Err(e) => {
                        monad.done(|fsm| fsm.error_happened(e, context));
                        return Async::Stop;
                    }
                }
            }
        }
        if stream.writable && stream.outbuf.len() > 0 {
            while stream.outbuf.len() > 0 {
                match stream.outbuf.write_to(&mut stream.socket) {
                    Ok(0) => { // Connection closed
                        monad.done(|fsm| fsm.eof_received(context));
                        return Async::Stop;
                    }
                    Ok(_) => {
                        monad = async_try!(monad.and_then(|f| {
                            f.data_transferred(
                                &mut stream.transport(), context)
                        }));
                    }
                    Err(ref e) if e.kind() == WouldBlock => {
                        stream.writable = false;
                        break;
                    }
                    Err(ref e) if e.kind() == Interrupted =>  { continue; }
                    Err(e) => {
                        monad.done(|fsm| fsm.error_happened(e, context));
                        return Async::Stop;
                    }
                }
            }
        }
        monad
        .map(|fsm| Stream(stream, fsm, PhantomData))
        .map_result(|()| None)
    }

    fn register(self, reg: &mut Registrator) -> Async<Self, ()> {
        reg.register(&self.0.socket, EventSet::all(), PollOpt::edge());
        Async::Continue(self, ())
    }

    fn timeout(self, context: &mut C) -> Async<Self, Option<Self>> {
        let Stream(stream, fsm, _) = self;
        async_try!(fsm.timeout(context))
        .map(|fsm| Stream(stream, fsm, PhantomData))
        .map_result(|()| None)
    }

    fn wakeup(self, context: &mut C) -> Async<Self, Option<Self>> {
        let Stream(stream, fsm, _) = self;
        async_try!(fsm.timeout(context))
        .map(|fsm| Stream(stream, fsm, PhantomData))
        .map_result(|()| None)
    }
}

pub trait Protocol<C>: Sized {
    fn accepted<S: Socket>(conn: &mut S, context: &mut C)
        -> Option<Self>;
    fn data_received(self, trans: &mut Transport, ctx: &mut C)
        -> Async<Self, ()>;
    fn data_transferred(self, _trans: &mut Transport, _ctx: &mut C)
        -> Async<Self, ()> {
        Async::Continue(self, ())
    }
    // TODO(tailhook) some error object should be here
    fn error_happened(self, _err: io::Error, _ctx: &mut C) {}
    fn eof_received(self, _ctx: &mut C) {}

    fn timeout(self, _context: &mut C) -> Async<Self, ()> {
        Async::Continue(self, ())
    }
    fn wakeup(self, _context: &mut C) -> Async<Self, ()> {
        Async::Continue(self, ())
    }
}

impl<'a> Transport<'a> {
    pub fn input<'x>(&'x mut self) -> &'x mut Buf {
        self.inbuf
    }
    pub fn output<'x>(&'x mut self) -> &'x mut Buf {
        self.outbuf
    }
}
<commit_msg>wakeup() incorrectly called timeout()<commit_after>use std::marker::PhantomData;
use std::io;
use std::io::ErrorKind::{WouldBlock, Interrupted};

use netbuf::Buf;
use time::SteadyTime;
use mio::{EventSet, PollOpt};

use super::StreamSocket as Socket;
use super::accept::Init;
use handler::{Registrator};
use {Async, EventMachine};

pub struct Timeout(pub SteadyTime);

struct Inner<S: Socket> {
    socket: S,
    inbuf: Buf,
    outbuf: Buf,
    writable: bool,
    readable: bool,
}

pub struct Stream<S: Socket, P: Protocol<C>, C>
    (Inner<S>, P, PhantomData<*mut C>);

pub struct Transport<'a> {
    inbuf: &'a mut Buf,
    outbuf: &'a mut Buf,
}

impl<S: Socket> Inner<S> {
    fn transport(&mut self) -> Transport {
        Transport {
            inbuf: &mut self.inbuf,
            outbuf: &mut self.outbuf,
        }
    }
}

impl<C, S: Socket, P: Protocol<C>> Init<S, C> for Stream<S, P, C> {
    fn accept(mut conn: S, context: &mut C) -> Option<Self>
    {
        let protocol = match Protocol::accepted(&mut conn, context) {
            Some(x) => x,
            None => return None
        };

        Some(Stream(Inner {
            socket: conn,
            inbuf: Buf::new(),
            outbuf: Buf::new(),
            readable: false,
            writable: true,   // Accepted socket is immediately writable
        }, protocol, PhantomData))
    }
}

impl<C, S: Socket, P: Protocol<C>> EventMachine<C> for Stream<S, P, C> {
    fn ready(self, evset: EventSet, context: &mut C)
        -> Async<Self, Option<Self>>
    {
        let Stream(mut stream, fsm, _) = self;
        let mut monad = Async::Continue(fsm, ());
        if evset.is_writable() && stream.outbuf.len() > 0 {
            stream.writable = true;
            while stream.outbuf.len() > 0 {
                match stream.outbuf.write_to(&mut stream.socket) {
                    Ok(0) => { // Connection closed
                        monad.done(|fsm| fsm.eof_received(context));
                        return Async::Stop;
                    }
                    Ok(_) => {
                        monad = async_try!(monad.and_then(|f| {
                            f.data_transferred(
                                &mut stream.transport(), context)
                        }));
                    }
                    Err(ref e) if e.kind() == WouldBlock => {
                        stream.writable = false;
                        break;
                    }
                    Err(ref e) if e.kind() == Interrupted =>  { continue; }
                    Err(e) => {
                        monad.done(|fsm| fsm.error_happened(e, context));
                        return Async::Stop;
                    }
                }
            }
        }
        if evset.is_readable() {
            stream.readable = true;
            loop {
                match stream.inbuf.read_from(&mut stream.socket) {
                    Ok(0) => { // Connection closed
                        monad.done(|fsm| fsm.eof_received(context));
                        return Async::Stop;
                    }
                    Ok(_) => {
                        monad = async_try!(monad.and_then(|f| {
                            f.data_received(
                                &mut stream.transport(), context)
                        }));
                    }
                    Err(ref e) if e.kind() == WouldBlock => {
                        stream.readable = false;
                        break;
                    }
                    Err(ref e) if e.kind() == Interrupted =>  { continue; }
                    Err(e) => {
                        monad.done(|fsm| fsm.error_happened(e, context));
                        return Async::Stop;
                    }
                }
            }
        }
        if stream.writable && stream.outbuf.len() > 0 {
            while stream.outbuf.len() > 0 {
                match stream.outbuf.write_to(&mut stream.socket) {
                    Ok(0) => { // Connection closed
                        monad.done(|fsm| fsm.eof_received(context));
                        return Async::Stop;
                    }
                    Ok(_) => {
                        monad = async_try!(monad.and_then(|f| {
                            f.data_transferred(
                                &mut stream.transport(), context)
                        }));
                    }
                    Err(ref e) if e.kind() == WouldBlock => {
                        stream.writable = false;
                        break;
                    }
                    Err(ref e) if e.kind() == Interrupted =>  { continue; }
                    Err(e) => {
                        monad.done(|fsm| fsm.error_happened(e, context));
                        return Async::Stop;
                    }
                }
            }
        }
        monad
        .map(|fsm| Stream(stream, fsm, PhantomData))
        .map_result(|()| None)
    }

    fn register(self, reg: &mut Registrator) -> Async<Self, ()> {
        reg.register(&self.0.socket, EventSet::all(), PollOpt::edge());
        Async::Continue(self, ())
    }

    fn timeout(self, context: &mut C) -> Async<Self, Option<Self>> {
        let Stream(stream, fsm, _) = self;
        async_try!(fsm.timeout(context))
        .map(|fsm| Stream(stream, fsm, PhantomData))
        .map_result(|()| None)
    }

    fn wakeup(self, context: &mut C) -> Async<Self, Option<Self>> {
        let Stream(stream, fsm, _) = self;
        async_try!(fsm.wakeup(context))
        .map(|fsm| Stream(stream, fsm, PhantomData))
        .map_result(|()| None)
    }
}

pub trait Protocol<C>: Sized {
    fn accepted<S: Socket>(conn: &mut S, context: &mut C)
        -> Option<Self>;
    fn data_received(self, trans: &mut Transport, ctx: &mut C)
        -> Async<Self, ()>;
    fn data_transferred(self, _trans: &mut Transport, _ctx: &mut C)
        -> Async<Self, ()> {
        Async::Continue(self, ())
    }
    // TODO(tailhook) some error object should be here
    fn error_happened(self, _err: io::Error, _ctx: &mut C) {}
    fn eof_received(self, _ctx: &mut C) {}

    fn timeout(self, _context: &mut C) -> Async<Self, ()> {
        Async::Continue(self, ())
    }
    fn wakeup(self, _context: &mut C) -> Async<Self, ()> {
        Async::Continue(self, ())
    }
}

impl<'a> Transport<'a> {
    pub fn input<'x>(&'x mut self) -> &'x mut Buf {
        self.inbuf
    }
    pub fn output<'x>(&'x mut self) -> &'x mut Buf {
        self.outbuf
    }
}
<|endoftext|>