<commit_before>extern crate conv;
extern crate rand;

use self::conv::prelude::*;
use neat::gene::Gene as Gene;
use neat::mutation::Mutation as Mutation;

#[derive(Debug, Clone)]
pub struct Genome{
    genes: Vec<Gene>,
    last_neuron_id: usize
}

const COMPATIBILITY_THRESHOLD: f64 = 1f64;
//const MUTATE_ADD_NEURON_PROBABILITY: f64 = 0.33f64;
const MUTATE_CONNECTION_WEIGHT: f64 = 0.33f64;
const MUTATE_ADD_CONNECTION: f64 = 0.33f64;

impl Genome{

    pub fn new() -> Genome {
        Genome {
            genes: vec![],
            last_neuron_id: 0 //we need 1 neuron to start to mutate
        }
    }

    pub fn mutate(&mut self) {
        let random = rand::random::<f64>();
        if random > MUTATE_ADD_CONNECTION + MUTATE_CONNECTION_WEIGHT && self.genes.len() > 0 {
            self.mutate_add_neuron();
        } else if random > MUTATE_ADD_CONNECTION && self.genes.len() > 0 {
            self.mutate_connection_weight();
        } else {
            self.mutate_add_connection();
        }
    }

    pub fn mate(&self, other: &Genome) -> Genome{
        if self.genes.len() > other.genes.len() {
            self.mate_genes(other)
        }else{
            other.mate_genes(self)
        }
    }

    fn mate_genes(&self, other: &Genome) -> Genome{
        let mut genome = Genome::new();
        for gene in &self.genes {
            genome.genes.push({
                if rand::random::<f64>() > 0.5f64 {
                    match other.genes.binary_search(&gene) {
                        Ok(position) => other.genes[position].clone(),
                        Err(_) => gene.clone()
                    }
                } else {
                    gene.clone()
                }
            });
        }
        genome
    }

    pub fn get_genes<'a>(&'a self)-> &'a Vec<Gene>{
        &self.genes
    }

    // only allow connected nodes
    pub fn inject_gene(&mut self, in_neuron_id: usize, out_neuron_id: usize, weight: f64) {
        let max_neuron_id = self.last_neuron_id + 1;

        if in_neuron_id == out_neuron_id && in_neuron_id > max_neuron_id {
            panic!("Try to create a gene neuron unconnected, max neuron id {}, {} -> {}", max_neuron_id, in_neuron_id, out_neuron_id);
        }

        assert!(in_neuron_id <= max_neuron_id, format!("in_neuron_id {} is greater than max allowed id {}", in_neuron_id, max_neuron_id));
        assert!(out_neuron_id <= max_neuron_id, format!("out_neuron_id {} is greater than max allowed id {}", out_neuron_id, max_neuron_id));

        if in_neuron_id > self.last_neuron_id {
            self.last_neuron_id = in_neuron_id;
        }
        if out_neuron_id > self.last_neuron_id {
            self.last_neuron_id = out_neuron_id;
        }
        self.create_gene(in_neuron_id, out_neuron_id, weight)
    }

    pub fn len(&self) -> usize{
        self.last_neuron_id + 1 //first neuron id is 0
    }

    fn create_gene(&mut self, in_neuron_id: usize, out_neuron_id: usize, weight: f64) {
        let gene = Gene {
            in_neuron_id: in_neuron_id,
            out_neuron_id: out_neuron_id,
            weight: weight,
            ..Default::default()
        };
        self.genes.push(gene);
    }

    fn mutate_add_connection(&mut self) {
        let mut rng = rand::thread_rng();
        let connections = {
            if self.last_neuron_id == 0 {
                vec![0, 0]
            } else {
                rand::sample(&mut rng, 0..self.last_neuron_id + 1, 2)
            }
        };
        self.add_connection(connections[0], connections[1]);
    }

    fn mutate_connection_weight(&mut self) {
        let mut rng = rand::thread_rng();
        let selected_gene = rand::sample(&mut rng, 0..self.genes.len(), 1)[0];
        let gene = &mut self.genes[selected_gene];
        Mutation::connection_weight(gene);
    }

    fn mutate_add_neuron(&mut self) {
        let (gene1, gene2) = {
            let mut rng = rand::thread_rng();
            let selected_gene = rand::sample(&mut rng, 0..self.genes.len(), 1)[0];
            let gene = &mut self.genes[selected_gene];
            self.last_neuron_id += 1;
            Mutation::add_neuron(gene, self.last_neuron_id)
        };
        self.genes.push(gene1);
        self.genes.push(gene2);
    }

    fn add_connection(&mut self, in_neuron_id: usize, out_neuron_id: usize) {
        let gene = Mutation::add_connection(in_neuron_id, out_neuron_id);
        self.genes.push(gene);
    }

    pub fn is_same_specie(&self, other: &Genome) -> bool{
        self.compatibility_distance(other) < COMPATIBILITY_THRESHOLD
    }

    pub fn total_weights(&self) -> f64{
        let mut total = 0f64;
        for gene in &self.genes {
            total += gene.weight;
        }
        total
    }

    pub fn total_genes(&self) -> usize{
        self.genes.len()
    }

    //http://nn.cs.utexas.edu/downloads/papers/stanley.ec02.pdf - Pag. 110
    //I have consider disjoint and excess genes as the same
    fn compatibility_distance(&self, other: &Genome) -> f64 {
        //TODO: optimize this method
        let c2 = 0.5f64;
        let c3 = 0.5f64;

        //Number of excess
        let n1 = self.genes.len().value_as::<f64>().unwrap();
        let n2 = other.genes.len().value_as::<f64>().unwrap();
        let n = n1.max(n2);

        if n == 0f64 {
            return 0f64; //no genes in any genome, the genomes are equal
        }

        let matching_genes  = self.genes.iter().filter(|i1_gene| other.genes.contains(i1_gene)).collect::<Vec<&Gene>>();

        let n3 = matching_genes.len().value_as::<f64>().unwrap();

        //Disjoint genes
        let d = n1 + n2 - (2f64 * n3);

        //average weight differences of matching genes
        let w1 = matching_genes.iter().fold(0f64, |acc, &m_gene| acc + (m_gene.weight + other.genes.get(other.genes.binary_search(m_gene).unwrap()).unwrap().weight)).abs();

        let w = w1 / n3;

        //compatibility distance
        let delta = (c2 * d / n) + c3 * w;
        delta
    }
}

#[cfg(test)]
mod tests {
    use neat::*;

    #[test]
    fn mutation_connection_weight(){
        let mut genome = Genome::new();
        genome.create_gene(1, 1, 1f64);
        let orig_gene = genome.genes[0].clone();
        genome.mutate_connection_weight();

        assert!(genome.genes[0].weight != orig_gene.weight);
    }

    #[test]
    fn mutation_add_connection(){
        let mut genome = Genome::new();
        genome.add_connection(1, 2);

        assert!(genome.genes[0].in_neuron_id == 1);
        assert!(genome.genes[0].out_neuron_id == 2);
    }

    #[test]
    fn mutation_add_neuron(){
        let mut genome = Genome::new();
        genome.mutate_add_connection();
        genome.mutate_add_neuron();
        assert!(!genome.genes[0].enabled);
        assert!(genome.genes[1].in_neuron_id == genome.genes[0].in_neuron_id);
        assert!(genome.genes[1].out_neuron_id == 1);
        assert!(genome.genes[2].in_neuron_id == 1);
        assert!(genome.genes[2].out_neuron_id == genome.genes[0].out_neuron_id);
    }

    #[test]
    #[should_panic(expected = "Try to create a gene neuron unconnected, max neuron id 1, 2 -> 2")]
    fn try_to_inject_a_unconnected_neuron_gene_should_panic(){
        let mut genome1 = Genome::new();
        genome1.inject_gene(2, 2, 0.5f64);
    }

    #[test]
    fn two_genomes_without_differences_should_be_in_same_specie(){
        let mut genome1 = Genome::new();
        genome1.create_gene(1, 1, 1f64);
        genome1.create_gene(1, 2, 1f64);
        let mut genome2 = Genome::new();
        genome2.create_gene(1, 1, 0f64);
        genome2.create_gene(1, 2, 0f64);
        genome2.create_gene(1, 3, 0f64);
        assert!(genome1.is_same_specie(&genome2));
    }

    #[test]
    fn two_genomes_with_enought_difference_should_be_in_different_species(){
        let mut genome1 = Genome::new();
        genome1.create_gene(1, 1, 1f64);
        genome1.create_gene(1, 2, 1f64);
        let mut genome2 = Genome::new();
        genome2.create_gene(1, 3, 1f64);
        genome2.create_gene(1, 4, 1f64);
        assert!(!genome1.is_same_specie(&genome2));
    }
}
<commit_msg>Disallow duplicate genes<commit_after>extern crate conv;
extern crate rand;

use self::conv::prelude::*;
use neat::gene::Gene as Gene;
use neat::mutation::Mutation as Mutation;

#[derive(Debug, Clone)]
pub struct Genome{
    genes: Vec<Gene>,
    last_neuron_id: usize
}

const COMPATIBILITY_THRESHOLD: f64 = 1f64;
//const MUTATE_ADD_NEURON_PROBABILITY: f64 = 0.33f64;
const MUTATE_CONNECTION_WEIGHT: f64 = 0.33f64;
const MUTATE_ADD_CONNECTION: f64 = 0.33f64;

impl Genome{

    pub fn new() -> Genome {
        Genome {
            genes: vec![],
            last_neuron_id: 0 //we need 1 neuron to start to mutate
        }
    }

    pub fn mutate(&mut self) {
        let random = rand::random::<f64>();
        if random > MUTATE_ADD_CONNECTION + MUTATE_CONNECTION_WEIGHT && self.genes.len() > 0 {
            self.mutate_add_neuron();
        } else if random > MUTATE_ADD_CONNECTION && self.genes.len() > 0 {
            self.mutate_connection_weight();
        } else {
            self.mutate_add_connection();
        }
    }

    pub fn mate(&self, other: &Genome) -> Genome{
        if self.genes.len() > other.genes.len() {
            self.mate_genes(other)
        }else{
            other.mate_genes(self)
        }
    }

    fn mate_genes(&self, other: &Genome) -> Genome{
        let mut genome = Genome::new();
        for gene in &self.genes {
            genome.add_gene({
                if rand::random::<f64>() > 0.5f64 {
                    match other.genes.binary_search(&gene) {
                        Ok(position) => other.genes[position].clone(),
                        Err(_) => gene.clone()
                    }
                } else {
                    gene.clone()
                }
            });
        }
        genome
    }

    pub fn get_genes<'a>(&'a self)-> &'a Vec<Gene>{
        &self.genes
    }

    // only allow connected nodes
    pub fn inject_gene(&mut self, in_neuron_id: usize, out_neuron_id: usize, weight: f64) {
        let max_neuron_id = self.last_neuron_id + 1;

        if in_neuron_id == out_neuron_id && in_neuron_id > max_neuron_id {
            panic!("Try to create a gene neuron unconnected, max neuron id {}, {} -> {}", max_neuron_id, in_neuron_id, out_neuron_id);
        }

        assert!(in_neuron_id <= max_neuron_id, format!("in_neuron_id {} is greater than max allowed id {}", in_neuron_id, max_neuron_id));
        assert!(out_neuron_id <= max_neuron_id, format!("out_neuron_id {} is greater than max allowed id {}", out_neuron_id, max_neuron_id));

        if in_neuron_id > self.last_neuron_id {
            self.last_neuron_id = in_neuron_id;
        }
        if out_neuron_id > self.last_neuron_id {
            self.last_neuron_id = out_neuron_id;
        }
        self.create_gene(in_neuron_id, out_neuron_id, weight)
    }

    pub fn len(&self) -> usize{
        self.last_neuron_id + 1 //first neuron id is 0
    }

    fn create_gene(&mut self, in_neuron_id: usize, out_neuron_id: usize, weight: f64) {
        let gene = Gene {
            in_neuron_id: in_neuron_id,
            out_neuron_id: out_neuron_id,
            weight: weight,
            ..Default::default()
        };
        self.add_gene(gene);
    }

    fn mutate_add_connection(&mut self) {
        let mut rng = rand::thread_rng();
        let neuron_ids_to_connect = {
            if self.last_neuron_id == 0 {
                vec![0, 0]
            } else {
                rand::sample(&mut rng, 0..self.last_neuron_id + 1, 2)
            }
        };
        self.add_connection(neuron_ids_to_connect[0], neuron_ids_to_connect[1]);
    }

    fn mutate_connection_weight(&mut self) {
        let mut rng = rand::thread_rng();
        let selected_gene = rand::sample(&mut rng, 0..self.genes.len(), 1)[0];
        let gene = &mut self.genes[selected_gene];
        Mutation::connection_weight(gene);
    }

    fn mutate_add_neuron(&mut self) {
        let (gene1, gene2) = {
            let mut rng = rand::thread_rng();
            let selected_gene = rand::sample(&mut rng, 0..self.genes.len(), 1)[0];
            let gene = &mut self.genes[selected_gene];
            self.last_neuron_id += 1;
            Mutation::add_neuron(gene, self.last_neuron_id)
        };
        self.add_gene(gene1);
        self.add_gene(gene2);
    }

    fn add_connection(&mut self, in_neuron_id: usize, out_neuron_id: usize) {
        let gene = Mutation::add_connection(in_neuron_id, out_neuron_id);
        self.add_gene(gene);
    }

    fn add_gene(&mut self, gene: Gene){
        if !self.genes.contains(&gene) {
            self.genes.push(gene);
        }
    }

    pub fn is_same_specie(&self, other: &Genome) -> bool{
        self.compatibility_distance(other) < COMPATIBILITY_THRESHOLD
    }

    pub fn total_weights(&self) -> f64{
        let mut total = 0f64;
        for gene in &self.genes {
            total += gene.weight;
        }
        total
    }

    pub fn total_genes(&self) -> usize{
        self.genes.len()
    }

    //http://nn.cs.utexas.edu/downloads/papers/stanley.ec02.pdf - Pag. 110
    //I have consider disjoint and excess genes as the same
    fn compatibility_distance(&self, other: &Genome) -> f64 {
        //TODO: optimize this method
        let c2 = 0.5f64;
        let c3 = 0.5f64;

        //Number of excess
        let n1 = self.genes.len().value_as::<f64>().unwrap();
        let n2 = other.genes.len().value_as::<f64>().unwrap();
        let n = n1.max(n2);

        if n == 0f64 {
            return 0f64; //no genes in any genome, the genomes are equal
        }

        let matching_genes  = self.genes.iter().filter(|i1_gene| other.genes.contains(i1_gene)).collect::<Vec<&Gene>>();

        let n3 = matching_genes.len().value_as::<f64>().unwrap();

        //Disjoint genes
        let d = n1 + n2 - (2f64 * n3);

        //average weight differences of matching genes
        let w1 = matching_genes.iter().fold(0f64, |acc, &m_gene| acc + (m_gene.weight + other.genes.get(other.genes.binary_search(m_gene).unwrap()).unwrap().weight)).abs();

        let w = w1 / n3;

        //compatibility distance
        let delta = (c2 * d / n) + c3 * w;
        delta
    }
}

#[cfg(test)]
mod tests {
    use neat::*;

    #[test]
    fn mutation_connection_weight(){
        let mut genome = Genome::new();
        genome.create_gene(1, 1, 1f64);
        let orig_gene = genome.genes[0].clone();
        genome.mutate_connection_weight();

        assert!(genome.genes[0].weight != orig_gene.weight);
    }

    #[test]
    fn mutation_add_connection(){
        let mut genome = Genome::new();
        genome.add_connection(1, 2);

        assert!(genome.genes[0].in_neuron_id == 1);
        assert!(genome.genes[0].out_neuron_id == 2);
    }

    #[test]
    fn mutation_add_neuron(){
        let mut genome = Genome::new();
        genome.mutate_add_connection();
        genome.mutate_add_neuron();
        assert!(!genome.genes[0].enabled);
        assert!(genome.genes[1].in_neuron_id == genome.genes[0].in_neuron_id);
        assert!(genome.genes[1].out_neuron_id == 1);
        assert!(genome.genes[2].in_neuron_id == 1);
        assert!(genome.genes[2].out_neuron_id == genome.genes[0].out_neuron_id);
    }

    #[test]
    #[should_panic(expected = "Try to create a gene neuron unconnected, max neuron id 1, 2 -> 2")]
    fn try_to_inject_a_unconnected_neuron_gene_should_panic(){
        let mut genome1 = Genome::new();
        genome1.inject_gene(2, 2, 0.5f64);
    }

    #[test]
    fn two_genomes_without_differences_should_be_in_same_specie(){
        let mut genome1 = Genome::new();
        genome1.create_gene(1, 1, 1f64);
        genome1.create_gene(1, 2, 1f64);
        let mut genome2 = Genome::new();
        genome2.create_gene(1, 1, 0f64);
        genome2.create_gene(1, 2, 0f64);
        genome2.create_gene(1, 3, 0f64);
        assert!(genome1.is_same_specie(&genome2));
    }

    #[test]
    fn two_genomes_with_enought_difference_should_be_in_different_species(){
        let mut genome1 = Genome::new();
        genome1.create_gene(1, 1, 1f64);
        genome1.create_gene(1, 2, 1f64);
        let mut genome2 = Genome::new();
        genome2.create_gene(1, 3, 1f64);
        genome2.create_gene(1, 4, 1f64);
        assert!(!genome1.is_same_specie(&genome2));
    }

    #[test]
    fn already_existing_gene_should_be_not_duplicated(){
        let mut genome1 = Genome::new();
        genome1.create_gene(0, 0, 1f64);
        genome1.add_connection(0, 0);
        assert!(genome1.genes.len() == 1);
        assert!(genome1.get_genes()[0].weight == 1f64);
    }
}
<|endoftext|>


<commit_before>#![crate_name = "uu_nproc"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Michael Gehring <mg@ebfe.org>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;
extern crate num_cpus;

#[cfg(not(windows))]
extern crate libc;

#[macro_use]
extern crate uucore;

use std::io::Write;
use std::env;

#[cfg(target_os = "linux")]
pub const _SC_NPROCESSORS_CONF: libc::c_int = 83;
#[cfg(target_os = "macos")]
pub const _SC_NPROCESSORS_CONF: libc::c_int = libc::_SC_NPROCESSORS_CONF;
#[cfg(target_os = "freebsd")]
pub const _SC_NPROCESSORS_CONF: libc::c_int = 57;
#[cfg(target_os = "netbsd")]
pub const _SC_NPROCESSORS_CONF: libc::c_int = 1001;

static NAME: &'static str = "nproc";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = getopts::Options::new();

    opts.optflag("", "all", "print the number of cores available to the system");
    opts.optopt("", "ignore", "ignore up to N cores", "N");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(err) => {
            show_error!("{}", err);
            return 1;
        }
    };

    if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
        return 0;
    }

    if matches.opt_present("help") {
        let msg = format!("{0} {1}

Usage:
  {0} [OPTIONS]...

Print the number of cores available to the current process.", NAME, VERSION);

        print!("{}", opts.usage(&msg));
        return 0;
    }

    let mut ignore = match matches.opt_str("ignore") {
        Some(numstr) => match numstr.parse() {
            Ok(num) => num,
            Err(e) => {
                show_error!("\"{}\" is not a valid number: {}", numstr, e);
                return 1;
            }
        },
        None => 0
    };

    if !matches.opt_present("all") {
        ignore += match env::var("OMP_NUM_THREADS") {
            Ok(threadstr) => match threadstr.parse() {
                Ok(num) => num,
                Err(_)=> 0
            },
            Err(_) => 0
        };
    }

    let mut cores = if matches.opt_present("all") {
        if cfg!(target_os = "linux") || cfg!(target_os = "macos") || cfg!(target_os = "freebsd") || cfg!(target_os = "netbsd") {
            let nprocs = unsafe { libc::sysconf(_SC_NPROCESSORS_CONF) };
            if nprocs == 1 {
                // In some situation, /proc and /sys are not mounted, and sysconf returns 1.
                // However, we want to guarantee that `nproc --all` >= `nproc`.
                num_cpus::get()
            } else {
                if nprocs > 0 { nprocs as usize } else { 1 }
            }
        } else {
            // Other platform(e.g., windows), num_cpus::get() directly.
            num_cpus::get()
        }
    } else {
        num_cpus::get()
    };

    if cores <= ignore {
        cores = 1;
    } else {
        cores -= ignore;
    }
    println!("{}", cores);
    0
}
<commit_msg>nproc: fix conditional compilation<commit_after>#![crate_name = "uu_nproc"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Michael Gehring <mg@ebfe.org>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;
extern crate num_cpus;

#[cfg(unix)]
extern crate libc;

#[macro_use]
extern crate uucore;

use std::io::Write;
use std::env;

#[cfg(target_os = "linux")]
pub const _SC_NPROCESSORS_CONF: libc::c_int = 83;
#[cfg(target_os = "macos")]
pub const _SC_NPROCESSORS_CONF: libc::c_int = libc::_SC_NPROCESSORS_CONF;
#[cfg(target_os = "freebsd")]
pub const _SC_NPROCESSORS_CONF: libc::c_int = 57;
#[cfg(target_os = "netbsd")]
pub const _SC_NPROCESSORS_CONF: libc::c_int = 1001;

static NAME: &'static str = "nproc";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = getopts::Options::new();

    opts.optflag("", "all", "print the number of cores available to the system");
    opts.optopt("", "ignore", "ignore up to N cores", "N");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(err) => {
            show_error!("{}", err);
            return 1;
        }
    };

    if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
        return 0;
    }

    if matches.opt_present("help") {
        let msg = format!("{0} {1}

Usage:
  {0} [OPTIONS]...

Print the number of cores available to the current process.", NAME, VERSION);

        print!("{}", opts.usage(&msg));
        return 0;
    }

    let mut ignore = match matches.opt_str("ignore") {
        Some(numstr) => match numstr.parse() {
            Ok(num) => num,
            Err(e) => {
                show_error!("\"{}\" is not a valid number: {}", numstr, e);
                return 1;
            }
        },
        None => 0
    };

    if !matches.opt_present("all") {
        ignore += match env::var("OMP_NUM_THREADS") {
            Ok(threadstr) => match threadstr.parse() {
                Ok(num) => num,
                Err(_)=> 0
            },
            Err(_) => 0
        };
    }

    let mut cores = if matches.opt_present("all") {
        num_cpus_all()
    } else {
        num_cpus::get()
    };

    if cores <= ignore {
        cores = 1;
    } else {
        cores -= ignore;
    }
    println!("{}", cores);
    0
}

#[cfg(any(target_os = "linux",
          target_os = "macos",
          target_os = "freebsd",
          target_os = "netbsd"))]
fn num_cpus_all() -> usize {
    let nprocs = unsafe { libc::sysconf(_SC_NPROCESSORS_CONF) };
    if nprocs == 1 {
        // In some situation, /proc and /sys are not mounted, and sysconf returns 1.
        // However, we want to guarantee that `nproc --all` >= `nproc`.
        num_cpus::get()
    } else {
        if nprocs > 0 { nprocs as usize } else { 1 }
    }
}

// Other platform(e.g., windows), num_cpus::get() directly.
#[cfg(not(any(target_os = "linux",
              target_os = "macos",
              target_os = "freebsd",
              target_os = "netbsd")))]
fn num_cpus_all() -> usize {
    num_cpus::get()
}
<|endoftext|>


<commit_before>use failure::Error;
use regex::Captures;

use crate::captures::CapturesExt;
use crate::details::Details;
use crate::pool::Popularity;

pub(crate) fn na_handler(
    popularity: &mut Popularity,
    sink: &mut Vec<Details>,
    captures: Captures,
) -> Result<(), Error> {
    let point = usize::from_str_radix(captures.name_ok("point")?, 16)?;
    let alias = captures.name_ok("alias")?;
    let r#type = captures.name_ok("type")?;

    if r#type == "correction" {
        if let Some(old) = sink[point].nacorr.as_deref() {
            eprintln!("Warning: sink[{}].nacorr being overwritten from “{}” to “{}”", point, old, alias);
        }
        sink[point].nacorr = Some(popularity.vote(alias));
    }
    if r#type == "control" {
        if let Some(old) = sink[point].nacont.as_deref() {
            eprintln!("Warning: sink[{}].nacont being overwritten from “{}” to “{}”", point, old, alias);
        }
        sink[point].nacont = Some(popularity.vote(alias));
    }
    if r#type == "alternate" {
        if let Some(old) = sink[point].naalte.as_deref() {
            eprintln!("Warning: sink[{}].naalte being overwritten from “{}” to “{}”", point, old, alias);
        }
        sink[point].naalte = Some(popularity.vote(alias));
    }
    if r#type == "figment" {
        if let Some(old) = sink[point].nafigm.as_deref() {
            eprintln!("Warning: sink[{}].nafigm being overwritten from “{}” to “{}”", point, old, alias);
        }
        sink[point].nafigm = Some(popularity.vote(alias));
    }
    if r#type == "abbreviation" {
        if let Some(old) = sink[point].naabbr.as_deref() {
            eprintln!("Warning: sink[{}].naabbr being overwritten from “{}” to “{}”", point, old, alias);
        }
        sink[point].naabbr = Some(popularity.vote(alias));
    }

    Ok(())
}
<commit_msg>data: tweak format of alias warnings<commit_after>use failure::Error;
use regex::Captures;

use crate::captures::CapturesExt;
use crate::details::Details;
use crate::pool::Popularity;

pub(crate) fn na_handler(
    popularity: &mut Popularity,
    sink: &mut Vec<Details>,
    captures: Captures,
) -> Result<(), Error> {
    let point = usize::from_str_radix(captures.name_ok("point")?, 16)?;
    let alias = captures.name_ok("alias")?;
    let r#type = captures.name_ok("type")?;

    if r#type == "correction" {
        if let Some(old) = sink[point].nacorr.as_deref() {
            eprintln!("Warning: sink[U+{:04X}].nacorr being overwritten from “{}” to “{}”", point, old, alias);
        }
        sink[point].nacorr = Some(popularity.vote(alias));
    }
    if r#type == "control" {
        if let Some(old) = sink[point].nacont.as_deref() {
            eprintln!("Warning: sink[U+{:04X}].nacont being overwritten from “{}” to “{}”", point, old, alias);
        }
        sink[point].nacont = Some(popularity.vote(alias));
    }
    if r#type == "alternate" {
        if let Some(old) = sink[point].naalte.as_deref() {
            eprintln!("Warning: sink[U+{:04X}].naalte being overwritten from “{}” to “{}”", point, old, alias);
        }
        sink[point].naalte = Some(popularity.vote(alias));
    }
    if r#type == "figment" {
        if let Some(old) = sink[point].nafigm.as_deref() {
            eprintln!("Warning: sink[U+{:04X}].nafigm being overwritten from “{}” to “{}”", point, old, alias);
        }
        sink[point].nafigm = Some(popularity.vote(alias));
    }
    if r#type == "abbreviation" {
        if let Some(old) = sink[point].naabbr.as_deref() {
            eprintln!("Warning: sink[U+{:04X}].naabbr being overwritten from “{}” to “{}”", point, old, alias);
        }
        sink[point].naabbr = Some(popularity.vote(alias));
    }

    Ok(())
}
<|endoftext|>


<commit_before>//! Encoding of PPM Images
use std::io;
use std::io::Write;

use super::{PNMHeader, PNMSubtype};

enum HeaderStrategy {
    Dynamic,
    Subtype(PNMSubtype),
    Chosen(PNMHeader),
}

pub struct PNMEncoder<'a> {
    writer: &'a mut Write,
    header: HeaderStrategy,
}

impl<'a> PNMEncoder<'a> {
    /// Create new PNMEncoder from the `writer`.
    ///
    /// The encoded images will have some `pnm` format. If more control over the image type is
    /// required, use either one of `with_subtype` or `with_header`. For more information on the
    /// behaviour, see `with_dynamic_header`.
    pub fn new(writer: &'a mut Write) -> Self {
        PNMEncoder {
            writer,
            header: HeaderStrategy::Dynamic,
        }
    }

    /// Encode a specific pnm subtype image.
    ///
    /// The magic number and encoding type will be chosen as provided while the rest of the header
    /// data will be generated dynamically. Trying to encode incompatible images (e.g. encoding an
    /// RGB image as Graymap) will result in an error.
    ///
    /// This will overwrite the effect of earlier calls to `with_header` and `with_dynamic_header`.
    pub fn with_subtype(self, subtype: PNMSubtype) -> Self {
        PNMEncoder {
            writer: self.writer,
            header: HeaderStrategy::Subtype(subtype),
        }
    }

    /// Enforce the use of a chosen header.
    ///
    /// While this option gives the most control over the actual written data, the encoding process
    /// will error in case the header data and image parameters do not agree. It is the users
    /// obligation to ensure that the width and height are set accordingly, for example.
    ///
    /// Choose this option if you want a lossless decoding/encoding round trip.
    ///
    /// This will overwrite the effect of earlier calls to `with_subtype` and `with_dynamic_header`.
    pub fn with_header(self, header: PNMHeader) -> Self {
        PNMEncoder {
            writer: self.writer,
            header: HeaderStrategy::Chosen(header)
        }
    }

    /// Create the header dynamically for each image.
    ///
    /// This is the default option upon creation of the encoder. With this, most images should be
    /// encodable but the specific format chosen is out of the users control. The pnm subtype is
    /// chosen arbitrarily by the library.
    ///
    /// This will overwrite the effect of earlier calls to `with_subtype` and `with_header`.
    pub fn with_dynamic_header(self) -> Self {
        PNMEncoder {
            writer: self.writer,
            header: HeaderStrategy::Dynamic,
        }
    }
}
<commit_msg>Add Encoder for u8 pixel values<commit_after>//! Encoding of PPM Images
use std::io;
use std::io::Write;

use color::{ColorType, num_components};
use super::{HeaderRecord, PNMHeader, PNMSubtype, SampleEncoding};
use super::{ArbitraryHeader, ArbitraryTuplType, BitmapHeader, GraymapHeader, PixmapHeader};

enum HeaderStrategy {
    Dynamic,
    Subtype(PNMSubtype),
    Chosen(PNMHeader),
}

pub struct PNMEncoder<'a> {
    writer: &'a mut Write,
    header: HeaderStrategy,
}

enum TupleEncoding {
    PbmBits {
        width: u32,
        height: u32,
    },
    U8 {
        encoding: SampleEncoding,
        width: u32,
        height: u32,
        components: u32,
    },
}

impl<'a> PNMEncoder<'a> {
    /// Create new PNMEncoder from the `writer`.
    ///
    /// The encoded images will have some `pnm` format. If more control over the image type is
    /// required, use either one of `with_subtype` or `with_header`. For more information on the
    /// behaviour, see `with_dynamic_header`.
    pub fn new(writer: &'a mut Write) -> Self {
        PNMEncoder {
            writer,
            header: HeaderStrategy::Dynamic,
        }
    }

    /// Encode a specific pnm subtype image.
    ///
    /// The magic number and encoding type will be chosen as provided while the rest of the header
    /// data will be generated dynamically. Trying to encode incompatible images (e.g. encoding an
    /// RGB image as Graymap) will result in an error.
    ///
    /// This will overwrite the effect of earlier calls to `with_header` and `with_dynamic_header`.
    pub fn with_subtype(self, subtype: PNMSubtype) -> Self {
        PNMEncoder {
            writer: self.writer,
            header: HeaderStrategy::Subtype(subtype),
        }
    }

    /// Enforce the use of a chosen header.
    ///
    /// While this option gives the most control over the actual written data, the encoding process
    /// will error in case the header data and image parameters do not agree. It is the users
    /// obligation to ensure that the width and height are set accordingly, for example.
    ///
    /// Choose this option if you want a lossless decoding/encoding round trip.
    ///
    /// This will overwrite the effect of earlier calls to `with_subtype` and `with_dynamic_header`.
    pub fn with_header(self, header: PNMHeader) -> Self {
        PNMEncoder {
            writer: self.writer,
            header: HeaderStrategy::Chosen(header)
        }
    }

    /// Create the header dynamically for each image.
    ///
    /// This is the default option upon creation of the encoder. With this, most images should be
    /// encodable but the specific format chosen is out of the users control. The pnm subtype is
    /// chosen arbitrarily by the library.
    ///
    /// This will overwrite the effect of earlier calls to `with_subtype` and `with_header`.
    pub fn with_dynamic_header(self) -> Self {
        PNMEncoder {
            writer: self.writer,
            header: HeaderStrategy::Dynamic,
        }
    }

    pub fn encode(&mut self, image: &[u8], width: u32, height: u32, color: ColorType)
        -> io::Result<()>
    {
        check_buffer_dimensions(image, width, height, color)?;
        let tuple_encoding = self.write_header(image, width, height, color)?;
        self.write_image(tuple_encoding, image)
    }

    /// Write the header and report back how the pixels should be written.
    fn write_header(&mut self, image: &[u8], width: u32, height: u32, c: ColorType)
        -> io::Result<TupleEncoding>
    {
        match self.header {
            HeaderStrategy::Dynamic
                => self.write_dynamic_header(width, height, c),
            HeaderStrategy::Subtype(subtype)
                => self.write_subtyped_header(subtype, width, height, c),
            HeaderStrategy::Chosen(ref header)
                => self.write_chosen_header(header, width, height, c),
        }
    }

    /// Choose any valid pnm format that the image can be expressed in and write its header.
    ///
    /// Returns how the body should be written if successful.
    fn write_dynamic_header(&mut self, width: u32, height: u32, color: ColorType)
        -> io::Result<TupleEncoding>
    {
        let depth = num_components(color) as u32;
        let (maxval, tupltype) = match color {
            ColorType::Gray(1) => (1, ArbitraryTuplType::BlackAndWhite),
            ColorType::GrayA(1) => (1, ArbitraryTuplType::BlackAndWhiteAlpha),
            ColorType::Gray(8) => (255, ArbitraryTuplType::Grayscale),
            ColorType::GrayA(8) => (255, ArbitraryTuplType::GrayscaleAlpha),
            ColorType::RGB(8) => (255, ArbitraryTuplType::RBG),
            ColorType::RGBA(8) => (255, ArbitraryTuplType::RGBAlpha),
            _ => return Err(io::Error::new(
                    io::ErrorKind::InvalidInput,
                    &format!("Writing colour type {:?} is not supported", color)[..]))
        };

        self.write_arbitrary_header(&ArbitraryHeader {
            width,
            height,
            depth,
            maxval,
            tupltype: Some(tupltype),
        })?;

        Ok(TupleEncoding::U8 {
            encoding: SampleEncoding::Binary,
            width,
            height,
            components: depth,
        })
    }

    /// Try to encode the image with the chosen format, give its corresponding pixel encoding type.
    fn write_subtyped_header(
        &mut self,
        subtype: PNMSubtype,
        width: u32,
        height: u32,
        color: ColorType)
        -> io::Result<TupleEncoding>
    {
        match (subtype, color) {
            (PNMSubtype::ArbitraryMap, color) => self.write_dynamic_header(width, height, color),
            (PNMSubtype::Pixmap(encoding), ColorType::RGB(8)) => {
                self.write_pixmap_header(&PixmapHeader {
                    encoding,
                    width,
                    height,
                    maxval: 255,
                }).map(|()| TupleEncoding::U8 {
                    encoding,
                    width,
                    height,
                    components: 3, // num_components(RGB(8)) == 3
                })
            },
            (PNMSubtype::Graymap(encoding), ColorType::Gray(8)) => {
                self.write_graymap_header(&GraymapHeader {
                    encoding,
                    width,
                    height,
                    maxwhite: 255,
                }).map(|()| TupleEncoding::U8 {
                    encoding,
                    width,
                    height,
                    components: 1, // num_components(Gray(8)) == 1
                })
            },
            (PNMSubtype::Bitmap(encoding), ColorType::Gray(8))
            | (PNMSubtype::Bitmap(encoding), ColorType::Gray(1)) => {
                self.write_bitmap_header(&BitmapHeader {
                    encoding: encoding,
                    width,
                    height,
                })?;
                match encoding {
                    SampleEncoding::Binary => Ok(TupleEncoding::PbmBits {
                        width,
                        height,
                    }),
                    SampleEncoding::Ascii => Ok(TupleEncoding::U8 {
                        encoding: SampleEncoding::Ascii,
                        width,
                        height,
                        components: 1,
                    })
                }
            },
            (_, _) => Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                "Color type can not be represented in the chosen format"))
        }
    }

    /// Try to encode the image with the chosen header, checking if values are correct.
    ///
    /// Returns how the body should be written if successful.
    fn write_chosen_header(
        &mut self,
        header: &PNMHeader,
        width: u32,
        height: u32,
        color: ColorType)
        -> io::Result<TupleEncoding>
    {
        let tupltype = check_chosen_header(&header, width, height, color)?;

        match header {
            &PNMHeader { encoded: Some(ref content), .. }
                => self.writer.write_all(content)?,
            &PNMHeader { decoded: HeaderRecord::Bitmap(ref header), .. }
                => self.write_bitmap_header(header)?,
            &PNMHeader { decoded: HeaderRecord::Graymap(ref header), .. }
                => self.write_graymap_header(header)?,
            &PNMHeader { decoded: HeaderRecord::Pixmap(ref header), .. }
                => self.write_pixmap_header(header)?,
            &PNMHeader { decoded: HeaderRecord::Arbitrary(ref header), .. }
                => self.write_arbitrary_header(header)?,
        };

        Ok(tupltype)
    }

    fn write_bitmap_header(&mut self, &BitmapHeader{ encoding, width, height }: &BitmapHeader)
        -> io::Result<()>
    {
        self.writer.write_all(PNMSubtype::Bitmap(encoding).magic_constant())?;
        write!(self.writer, "\n{} {}\n", width, height)
    }

    fn write_graymap_header(
        &mut self,
        &GraymapHeader{ encoding, width, height, maxwhite}: &GraymapHeader)
        -> io::Result<()>
    {
        self.writer.write_all(PNMSubtype::Graymap(encoding).magic_constant())?;
        write!(self.writer, "\n{} {} {}\n", width, height, maxwhite)
    }

    fn write_pixmap_header(
        &mut self,
        &PixmapHeader{ encoding, width, height, maxval}: &PixmapHeader)
        -> io::Result<()>
    {
        self.writer.write_all(PNMSubtype::Pixmap(encoding).magic_constant())?;
        write!(self.writer, "\n{} {} {}\n", width, height, maxval)
    }

    fn write_arbitrary_header(&mut self, &ArbitraryHeader{ width, height, depth, maxval, tupltype}: &ArbitraryHeader)
        -> io::Result<()>
    {
        let custom_fallback = String::new();
        let tupltype = match tupltype {
            None => "",
            Some(ArbitraryTuplType::BlackAndWhite) => "TUPLTYPE BLACKANDWHITE\n",
            Some(ArbitraryTuplType::BlackAndWhiteAlpha) => "TUPLTYPE BLACKANDWHITE_ALPHA\n",
            Some(ArbitraryTuplType::Grayscale) => "TUPLTYPE GRAYSCALE\n",
            Some(ArbitraryTuplType::GrayscaleAlpha) => "TUPLTYPE GRAYSCALE_ALPHA\n",
            Some(ArbitraryTuplType::RBG) => "TUPLTYPE RGB\n",
            Some(ArbitraryTuplType::RGBAlpha) => "TUPLTYPE RGB_ALPHA\n",
            Some(ArbitraryTuplType::Custom(ref custom)) => {
                custom_fallback = format!("TUPLTYPE {}", custom);
                &custom_fallback
            }
        };

        write!(self.writer, "P7\nWIDTH {}\nHEIGHT {}\nDEPTH {}\nMAXVAL {}\n{}ENDHDR",
            width, height, depth, maxval, tupltype)
    }

    fn write_image(&mut self, encoding: TupleEncoding, image: &[u8]) -> io::Result<()> {
        match encoding {
            TupleEncoding::U8 { encoding: SampleEncoding::Binary, .. }
                => self.writer.write_all(image),
            TupleEncoding::U8 { encoding: SampleEncoding::Ascii, .. } => {
                // Standard dictates to insert line breaks after 70 characters. Assumes that no
                // line breaks are written.
                struct AutoBreak<'a> {
                    wrapped: io::LineWriter<&'a mut Write>,
                    line_capacity: usize,
                    buffer: Vec<u8>,
                    needs_flush: bool,
                }

                impl<'a> Write for AutoBreak<'a> {
                    fn write(&mut self, buffer: &[u8]) -> io::Result<usize> {
                        if self.needs_flush {
                            self.flush()?;
                            assert!(self.buffer.len() == 0);
                        }

                        // Buffer may be longer than the capacity but there's no way around
                        if self.buffer.len() == 0 {
                            self.buffer.extend_from_slice(buffer);
                            return Ok(buffer.len());
                        }

                        if buffer.len() + self.buffer.len() > self.line_capacity {
                            self.needs_flush = true;
                            self.buffer.push(b'\n');
                            self.flush()?;
                            assert!(self.buffer.len() == 0);
                        }

                        self.buffer.extend_from_slice(buffer);
                        Ok(buffer.len())
                    }

                    fn flush(&mut self) -> io::Result<()> {
                        let written = self.wrapped.write(self.buffer.as_slice())?;

                        self.buffer.drain(0..written);
                        if self.buffer.len() > 0 {
                            return Err(io::Error::new(
                                io::ErrorKind::Interrupted,
                                "Line was not fully flushed"))
                        }

                        self.needs_flush = false;
                        self.wrapped.flush()
                    }
                }

                let auto_break_writer = AutoBreak {
                    wrapped: io::LineWriter::new(self.writer),
                    line_capacity: 70,
                    buffer: Vec::with_capacity(71),
                    needs_flush: false,
                };

                for value in image.iter() {
                    write!(auto_break_writer, "{} ", value)?;
                }
                Ok(())
            },
            TupleEncoding::PbmBits { width, height } => {
                /// These should have thrown errors previously.
                assert_eq!(width*height, image.len());
                assert!(image.len() > 0);

                let line_width = (width - 1)/8 + 1;

                // We'll be writing single bytes, so buffer
                let line_buffer = Vec::with_capacity(line_width as usize);

                for line in image.chunks(width as usize) {
                    for byte_bits in line.chunks(8) {
                        let byte = 0u8;
                        for i in 0..8 {
                            // Black pixels are encoded as 1s
                            if let Some(&0u8) = byte_bits.get(i) {
                                byte |= 1u8 << (7 - i)
                            }
                        }
                        line_buffer.push(byte)
                    }
                    self.writer.write_all(line_buffer.as_slice());
                    line_buffer.clear();
                }

                Ok(())
            },
            // _ => panic!()
        }

    }
}

fn check_buffer_dimensions(image: &[u8], width: u32, height: u32, color: ColorType)
    -> io::Result<()>
{
    let components = num_components(color);
    let width = width as usize;
    let height = height as usize;
    match Some(components)
        .and_then(|v| v.checked_mul(width))
        .and_then(|v| v.checked_mul(height)) {
        None => Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            &format!("Image dimensions invalid: {}x{}x{} (wxhxd)",
                width, height, components)[..])),
        Some(v) if v != image.len()
            => Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                &format!("Image buffer does not correspond to size and colour")[..])),
        Some(v) => Ok(())
    }
}

fn check_chosen_header(header: &PNMHeader, width: u32, height: u32, color: ColorType)
    -> io::Result<TupleEncoding>
{
    if header.width() != width || header.height() != height {
        return Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            "Chosen header does not match Image dimensions"));
    }

    // FIXME check other conditions …
    // if header

    Ok(TupleEncoding::U8 {
        encoding: SampleEncoding::Binary,
        width,
        height,
        components: num_components(color) as u32,
    })
}
<|endoftext|>


<commit_before>#![feature(nll)]

extern crate jemallocator;

#[global_allocator]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

extern crate regex;
extern crate bit_set;
extern crate chrono;
extern crate serde_json;
extern crate reqwest;
extern crate flate2;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate serde_derive;
extern crate pombase_rc_string;
extern crate uuid;
extern crate postgres;

pub mod db;
pub mod web;
pub mod types;
pub mod interpro;
pub mod api;
pub mod bio;
pub mod rnacentral;
pub mod annotation_util;
pub mod data_types;
pub mod api_data;
<commit_msg>Revert "Switch to jemallocator"<commit_after>#![feature(nll)]

extern crate regex;
extern crate bit_set;
extern crate chrono;
extern crate serde_json;
extern crate reqwest;
extern crate flate2;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate serde_derive;
extern crate pombase_rc_string;
extern crate uuid;
extern crate postgres;

pub mod db;
pub mod web;
pub mod types;
pub mod interpro;
pub mod api;
pub mod bio;
pub mod rnacentral;
pub mod annotation_util;
pub mod data_types;
pub mod api_data;
<|endoftext|>


<commit_before>use std::io::Read;
use std::io::BufReader;
use std::ascii::AsciiExt;

use color::{ColorType};
use image::{DecodingResult, ImageDecoder, ImageResult, ImageError};
extern crate byteorder;
use self::byteorder::{BigEndian, ByteOrder};

enum DecodeStrategy {
    Bytes,
    Ascii,
}

/// PPM decoder
pub struct PPMDecoder<R> {
    reader: BufReader<R>,
    width: u32,
    height: u32,
    maxwhite: u32,
    samples: u32,
    decoder: DecodeStrategy,
}

impl<R: Read> PPMDecoder<R> {
    /// Create a new decoder that decodes from the stream ```r```
    pub fn new(read: R) -> ImageResult<PPMDecoder<R>> {
        let mut buf = BufReader::new(read);
        let mut magic: [u8; 2] = [0, 0];
        try!(buf.read_exact(&mut magic[..])); // Skip magic constant
        if magic[0] != b'P' || (magic[1] != b'3' && magic[1] != b'6') {
            return Err(ImageError::FormatError("Expected magic constant for ppm, P3 or P6".to_string()));
        }

        let decoder = match magic[1] {
            b'3' => DecodeStrategy::Ascii,
            b'6' => DecodeStrategy::Bytes,
            _ => unreachable!(),
        };

        let width = try!(PPMDecoder::read_next_u32(&mut buf));
        let height = try!(PPMDecoder::read_next_u32(&mut buf));
        let maxwhite = try!(PPMDecoder::read_next_u32(&mut buf));

        if !(maxwhite <= u16::max_value() as u32) {
            return Err(ImageError::FormatError("Image maxval is not less or equal to 65535".to_string()))
        }

        Ok(PPMDecoder {
            reader: buf,
            width: width,
            height: height,
            maxwhite: maxwhite,
            samples: 3,
            decoder: decoder,
        })
    }

    /// Reads a string as well as a single whitespace after it, ignoring comments
    fn read_next_string(reader: &mut BufReader<R>) -> ImageResult<String> {
        let mut bytes = Vec::new();

        // pair input bytes with a bool mask to remove comments
        let mark_comments = reader
            .bytes()
            .scan(true, |partof, read| {
                let byte = match read {
                    Err(err) => return Some((*partof, Err(err))),
                    Ok(byte) => byte,
                };
                let cur_enabled = *partof && byte != b'#';
                let next_enabled = cur_enabled || (byte == b'\r' || byte == b'\n');
                *partof = next_enabled;
                return Some((cur_enabled, Ok(byte)));
            });

        for (_, byte) in mark_comments.filter(|ref e| e.0) {
            match byte {
                Ok(b'\t') | Ok(b'\n') | Ok(b'\x0b') | Ok(b'\x0c') | Ok(b'\r') | Ok(b' ') => {
                    if !bytes.is_empty() {
                        break // We're done as we already have some content
                    }
                },
                Ok(byte) => {
                    bytes.push(byte);
                },
                Err(_) => break,
            }
        }

        if bytes.is_empty() {
            return Err(ImageError::FormatError("Unexpected eof".to_string()))
        }

        if !bytes.as_slice().is_ascii() {
            return Err(ImageError::FormatError("Non ascii character in preamble".to_string()))
        }

        String::from_utf8(bytes).map_err(|_| ImageError::FormatError("Couldn't read preamble".to_string()))
    }

    fn read_next_u32(reader: &mut BufReader<R>) -> ImageResult<u32> {
        let s = try!(PPMDecoder::read_next_string(reader));
        s.parse::<u32>().map_err(|_| ImageError::FormatError("Invalid number in preamble".to_string()))
    }
}

impl<R: Read> ImageDecoder for PPMDecoder<R> {
    fn dimensions(&mut self) -> ImageResult<(u32, u32)> {
        Ok((self.width, self.height))
    }

    fn colortype(&mut self) -> ImageResult<ColorType> {
        match (self.bytewidth(), self.components()) {
            (1, 1) => Ok(ColorType::Gray(8)),
            (2, 1) => Ok(ColorType::Gray(16)),
            (1, 3) => Ok(ColorType::RGB(8)),
            (2, 3) => Ok(ColorType::RGB(16)),
            _ => Err(ImageError::FormatError("Don't know how to decode PPM with more than 16 bits".to_string())),
        }
    }

    fn row_len(&mut self) -> ImageResult<usize> {
        Ok((self.width*self.components()*self.bytewidth()) as usize)
    }

    fn read_scanline(&mut self, _buf: &mut [u8]) -> ImageResult<u32> {
        unimplemented!();
    }

    fn read_image(&mut self) -> ImageResult<DecodingResult> {
        let pixelcount = self.width
            .checked_mul(self.height)
            .and_then(|v| v.checked_mul(self.components()));

        let pixelcount = match pixelcount {
            Some(v) => v,
            _ => return Err(ImageError::DimensionError),
        };

        self.read(pixelcount)
    }
}

impl<R: Read> PPMDecoder<R> {
    fn bytewidth(&self) -> u32 {
        if self.maxwhite < 256 { 1 } else { 2 }
    }

    fn components(&self) -> u32 {
        self.samples
    }

    fn read(&mut self, count: u32) -> ImageResult<DecodingResult> {
        if self.bytewidth() == 1 {
            let mut data = vec![0 as u8; count as usize];
            self.read_u8(&mut data)?;
            Ok(DecodingResult::U8(data))
        } else if self.bytewidth() == 2 {
            let mut data = vec![0 as u16; count as usize];
            self.read_u16(&mut data)?;
            Ok(DecodingResult::U16(data))
        } else {
            Err(ImageError::FormatError("Invalid sample bitwidth".to_string()))
        }
    }

    fn read_u8(&mut self, mut buffer: &mut [u8]) -> ImageResult<()> {
        match self.decoder {
            DecodeStrategy::Bytes => match self.reader.read_exact(&mut buffer) {
                    Ok(_) => Ok(()),
                    Err(e) => Err(ImageError::IoError(e)),
                },
            DecodeStrategy::Ascii => {
                    self.read_ascii::<u8>(&mut buffer)
                }
        }
    }

    fn read_u16(&mut self, mut buffer: &mut [u16]) -> ImageResult<()> {
        match self.decoder {
            DecodeStrategy::Bytes => {
                    let mut bytebuffer = vec![0 as u8; buffer.len() * 2];
                    match self.reader.read_exact(&mut bytebuffer) {
                        Err(e) => return Err(ImageError::IoError(e)),
                        Ok(_) => {},
                    }
                    BigEndian::read_u16_into(&mut bytebuffer, &mut buffer);
                    Ok(())
                },
            DecodeStrategy::Ascii => {
                    self.read_ascii::<u16>(&mut buffer)
                }
        }
    }

    fn read_ascii<Basic: FromSample>(&mut self, buffer: &mut [Basic::T]) -> ImageResult<()> {
        for pixel in buffer {
            let value = self.read_sample()?;
            *pixel = Basic::try_convert(value)?;
        }
        Ok(())
    }

    fn read_sample(&mut self) -> ImageResult<u32> {
        let token = (&mut self.reader).bytes()
            .take_while(|v| match v {
                    &Err(_) => false,
                    &Ok(b'\t') | &Ok(b'\n') | &Ok(b'\x0b') | &Ok(b'\x0c') | &Ok(b'\r') | &Ok(b' ') => false,
                    _ => true,
                })
            .collect::<Result<Vec<u8>, _>>()?;
        if !token.is_ascii() {
            return Err(ImageError::FormatError("Non ascii character where sample value was expected".to_string()))
        }
        let string = String::from_utf8(token).map_err(|_| ImageError::FormatError("Error parsing sample".to_string()))?;
        string.parse::<u32>().map_err(|_| ImageError::FormatError("Error parsing sample value".to_string()))
    }
}

trait FromSample {
    type T;
    fn try_convert(u32) -> ImageResult<Self::T>;
}

impl FromSample for u8 {
    type T = u8;
    fn try_convert(val: u32) -> ImageResult<Self::T> {
        if val > u8::max_value() as u32 {
            Err(ImageError::FormatError("Sample value outside of bounds".to_string()))
        } else {
            Ok(val as u8)
        }
    }
}

impl FromSample for u16 {
    type T = u16;
    fn try_convert(val: u32) -> ImageResult<Self::T> {
        if val > u16::max_value() as u32 {
            Err(ImageError::FormatError("Sample value outside of bounds".to_string()))
        } else {
            Ok(val as u16)
        }
    }
}

/// Tests parsing binary buffers were written based on and validated against `pamfile` from
/// netpbm (http://netpbm.sourceforge.net/).
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn minimal_form() {
        // Violates current specification (October 2016 ) but accepted by both netpbm and ImageMagick
        decode_minimal_image(&b"P61 1 255 123"[..]);
        decode_minimal_image(&b"P6 1 1 255 123"[..]);
        decode_minimal_image(&b"P6 1 1 255 123\xFF"[..]); // Too long should not be an issue
    }

    #[test]
    fn comment_in_token() {
        decode_minimal_image(&b"P6 1 1 2#comment\n55 123"[..]); // Terminating LF
        decode_minimal_image(&b"P6 1 1 2#comment\r55 123"[..]); // Terminating CR
        decode_minimal_image(&b"P6 1 1#comment\n 255 123"[..]); // Comment after token
        decode_minimal_image(&b"P6 1 1 #comment\n255 123"[..]); // Comment before token
        decode_minimal_image(&b"P6#comment\n 1 1 255 123"[..]); // Begin of header
        decode_minimal_image(&b"P6 1 1 255#comment\n 123"[..]); // End of header
    }

    #[test]
    fn whitespace() {
        decode_minimal_image(&b"P6\x091\x091\x09255\x09123"[..]); // TAB
        decode_minimal_image(&b"P6\x0a1\x0a1\x0a255\x0a123"[..]); // LF
        decode_minimal_image(&b"P6\x0b1\x0b1\x0b255\x0b123"[..]); // VT
        decode_minimal_image(&b"P6\x0c1\x0c1\x0c255\x0c123"[..]); // FF
        decode_minimal_image(&b"P6\x0d1\x0d1\x0d255\x0d123"[..]); // CR
        // Spaces tested before
        decode_minimal_image(&b"P61\x09\x0a\x0b\x0c\x0d1 255 123"[..]); // All whitespace, combined
    }

    #[test]
    fn ascii_encoded() {
        decode_minimal_image(&b"P31 1 255 49 50 51"[..]);
        assert!(PPMDecoder::new(&b"P31 1 65535 65535 65535 65535"[..]).unwrap()
            .read_image().is_ok());
    }

    /// Tests for decoding error, assuming `encoded` is ppm encoding for the very simplistic image
    /// containing a single pixel with one byte values (1, 2, 3).
    fn decode_minimal_image(encoded: &[u8]) {
        let content = vec![49 as u8, 50, 51];
        let mut decoder = PPMDecoder::new(encoded).unwrap();

        assert_eq!(decoder.dimensions().unwrap(), (1, 1));
        assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8));
        assert_eq!(decoder.row_len().unwrap(), 3);
        assert_eq!(decoder.bytewidth(), 1);

        match decoder.read_image().unwrap() {
            DecodingResult::U8(image) => assert_eq!(image, content),
            _ => assert!(false),
        }
    }

    #[test]
    fn wrong_tag() {
        assert!(PPMDecoder::new(&b"P5 1 1 255 1"[..]).is_err());
    }

    #[test]
    fn invalid_characters() {
        assert!(PPMDecoder::new(&b"P6 1chars1 255 1"[..]).is_err()); // No text outside of comments
        assert!(PPMDecoder::new(&b"P6 1\xFF1 255 1"[..]).is_err()); // No invalid ascii chars
        assert!(PPMDecoder::new(&b"P6 0x01 1 255 1"[..]).is_err()); // Numbers only as decimal
    }

    /// These violate the narrow specification of ppm but are commonly supported in other programs.
    /// Fail fast and concise is important here as these might be received as input files.
    #[test]
    fn unsupported_extensions() {
        assert!(PPMDecoder::new(&b"P6 1 1 65536 1"[..]).is_err()); // No bitwidth above 16
    }
}
<commit_msg>Improve handling of ascii encoded information<commit_after>use std::io::Read;
use std::io::BufReader;
use std::ascii::AsciiExt;

use color::{ColorType};
use image::{DecodingResult, ImageDecoder, ImageResult, ImageError};
extern crate byteorder;
use self::byteorder::{BigEndian, ByteOrder};

enum DecodeStrategy {
    Bytes,
    Ascii,
}

/// PPM decoder
pub struct PPMDecoder<R> {
    reader: BufReader<R>,
    width: u32,
    height: u32,
    maxwhite: u32,
    depth: u32,
    decoder: DecodeStrategy,
}

impl<R: Read> PPMDecoder<R> {
    /// Create a new decoder that decodes from the stream ```r```
    pub fn new(read: R) -> ImageResult<PPMDecoder<R>> {
        let mut buf = BufReader::new(read);
        let mut magic: [u8; 2] = [0, 0];
        try!(buf.read_exact(&mut magic[..])); // Skip magic constant
        if magic[0] != b'P' {
            return Err(ImageError::FormatError("Expected magic constant for ppm, P3 or P6".to_string()));
        }

        let decoder = match magic[1] {
            b'3' => DecodeStrategy::Ascii,
            b'6' => DecodeStrategy::Bytes,
            _ => return Err(ImageError::FormatError("Expected magic constant for ppm, P3 or P6".to_string())),
        };

        let width = try!(PPMDecoder::read_next_u32(&mut buf));
        let height = try!(PPMDecoder::read_next_u32(&mut buf));
        let maxwhite = try!(PPMDecoder::read_next_u32(&mut buf));

        if !(maxwhite <= u16::max_value() as u32) {
            return Err(ImageError::FormatError("Image maxval is not less or equal to 65535".to_string()))
        }

        Ok(PPMDecoder {
            reader: buf,
            width: width,
            height: height,
            maxwhite: maxwhite,
            depth: 3,
            decoder: decoder,
        })
    }

    /// Reads a string as well as a single whitespace after it, ignoring comments
    fn read_next_string(reader: &mut BufReader<R>) -> ImageResult<String> {
        let mut bytes = Vec::new();

        // pair input bytes with a bool mask to remove comments
        let mark_comments = reader
            .bytes()
            .scan(true, |partof, read| {
                let byte = match read {
                    Err(err) => return Some((*partof, Err(err))),
                    Ok(byte) => byte,
                };
                let cur_enabled = *partof && byte != b'#';
                let next_enabled = cur_enabled || (byte == b'\r' || byte == b'\n');
                *partof = next_enabled;
                return Some((cur_enabled, Ok(byte)));
            });

        for (_, byte) in mark_comments.filter(|ref e| e.0) {
            match byte {
                Ok(b'\t') | Ok(b'\n') | Ok(b'\x0b') | Ok(b'\x0c') | Ok(b'\r') | Ok(b' ') => {
                    if !bytes.is_empty() {
                        break // We're done as we already have some content
                    }
                },
                Ok(byte) => {
                    bytes.push(byte);
                },
                Err(_) => break,
            }
        }

        if bytes.is_empty() {
            return Err(ImageError::FormatError("Unexpected eof".to_string()))
        }

        if !bytes.as_slice().is_ascii() {
            return Err(ImageError::FormatError("Non ascii character in preamble".to_string()))
        }

        String::from_utf8(bytes).map_err(|_| ImageError::FormatError("Couldn't read preamble".to_string()))
    }

    fn read_next_u32(reader: &mut BufReader<R>) -> ImageResult<u32> {
        let s = try!(PPMDecoder::read_next_string(reader));
        s.parse::<u32>().map_err(|_| ImageError::FormatError("Invalid number in preamble".to_string()))
    }
}

impl<R: Read> ImageDecoder for PPMDecoder<R> {
    fn dimensions(&mut self) -> ImageResult<(u32, u32)> {
        Ok((self.width, self.height))
    }

    fn colortype(&mut self) -> ImageResult<ColorType> {
        match (self.bytewidth(), self.components()) {
            (1, 1) => Ok(ColorType::Gray(8)),
            (2, 1) => Ok(ColorType::Gray(16)),
            (1, 3) => Ok(ColorType::RGB(8)),
            (2, 3) => Ok(ColorType::RGB(16)),
            _ => Err(ImageError::FormatError("Don't know how to decode PPM with more than 16 bits".to_string())),
        }
    }

    fn row_len(&mut self) -> ImageResult<usize> {
        Ok((self.width*self.components()*self.bytewidth()) as usize)
    }

    fn read_scanline(&mut self, _buf: &mut [u8]) -> ImageResult<u32> {
        unimplemented!();
    }

    fn read_image(&mut self) -> ImageResult<DecodingResult> {
        let pixelcount = self.width
            .checked_mul(self.height)
            .and_then(|v| v.checked_mul(self.components()));

        let pixelcount = match pixelcount {
            Some(v) => v,
            _ => return Err(ImageError::DimensionError),
        };

        self.read(pixelcount)
    }
}

impl<R: Read> PPMDecoder<R> {
    fn bytewidth(&self) -> u32 {
        if self.maxwhite < 256 { 1 } else { 2 }
    }

    fn components(&self) -> u32 {
        self.depth
    }

    fn read(&mut self, count: u32) -> ImageResult<DecodingResult> {
        if self.bytewidth() == 1 {
            let mut data = vec![0 as u8; count as usize];
            self.read_u8(&mut data)?;
            Ok(DecodingResult::U8(data))
        } else if self.bytewidth() == 2 {
            let mut data = vec![0 as u16; count as usize];
            self.read_u16(&mut data)?;
            Ok(DecodingResult::U16(data))
        } else {
            Err(ImageError::FormatError("Invalid sample bitwidth".to_string()))
        }
    }

    fn read_u8(&mut self, mut buffer: &mut [u8]) -> ImageResult<()> {
        match self.decoder {
            DecodeStrategy::Bytes => match self.reader.read_exact(&mut buffer) {
                    Ok(_) => Ok(()),
                    Err(e) => Err(ImageError::IoError(e)),
                },
            DecodeStrategy::Ascii => {
                    self.read_ascii::<u8>(&mut buffer)
                }
        }
    }

    fn read_u16(&mut self, mut buffer: &mut [u16]) -> ImageResult<()> {
        match self.decoder {
            DecodeStrategy::Bytes => {
                    let mut bytebuffer = vec![0 as u8; buffer.len() * 2];
                    match self.reader.read_exact(&mut bytebuffer) {
                        Err(e) => return Err(ImageError::IoError(e)),
                        Ok(_) => {},
                    }
                    BigEndian::read_u16_into(&mut bytebuffer, &mut buffer);
                    Ok(())
                },
            DecodeStrategy::Ascii => {
                    self.read_ascii::<u16>(&mut buffer)
                }
        }
    }

    fn read_ascii<Basic: FromSample>(&mut self, buffer: &mut [Basic::T]) -> ImageResult<()> {
        for pixel in buffer {
            let value = self.read_sample()?;
            *pixel = Basic::try_convert(value)?;
        }
        Ok(())
    }

    fn read_sample(&mut self) -> ImageResult<u32> {
        let istoken = |v: &Result<u8, _>| match v {
                &Err(_) => false,
                &Ok(b'\t') | &Ok(b'\n') | &Ok(b'\x0b') | &Ok(b'\x0c') | &Ok(b'\r') | &Ok(b' ') => false,
                _ => true,
            };
        let token = (&mut self.reader).bytes()
            .skip_while(|v| !istoken(v))
            .take_while(&istoken)
            .collect::<Result<Vec<u8>, _>>()?;
        if !token.is_ascii() {
            return Err(ImageError::FormatError("Non ascii character where sample value was expected".to_string()))
        }
        let string = String::from_utf8(token).map_err(|_| ImageError::FormatError("Error parsing sample".to_string()))?;
        string.parse::<u32>().map_err(|_| ImageError::FormatError("Error parsing sample value".to_string()))
    }
}

trait FromSample {
    type T;
    fn try_convert(u32) -> ImageResult<Self::T>;
}

impl FromSample for u8 {
    type T = u8;
    fn try_convert(val: u32) -> ImageResult<Self::T> {
        if val > u8::max_value() as u32 {
            Err(ImageError::FormatError("Sample value outside of bounds".to_string()))
        } else {
            Ok(val as u8)
        }
    }
}

impl FromSample for u16 {
    type T = u16;
    fn try_convert(val: u32) -> ImageResult<Self::T> {
        if val > u16::max_value() as u32 {
            Err(ImageError::FormatError("Sample value outside of bounds".to_string()))
        } else {
            Ok(val as u16)
        }
    }
}

/// Tests parsing binary buffers were written based on and validated against `pamfile` from
/// netpbm (http://netpbm.sourceforge.net/).
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn minimal_form() {
        // Violates current specification (October 2016 ) but accepted by both netpbm and ImageMagick
        decode_minimal_image(&b"P61 1 255 123"[..]);
        decode_minimal_image(&b"P6 1 1 255 123"[..]);
        decode_minimal_image(&b"P6 1 1 255 123\xFF"[..]); // Too long should not be an issue
    }

    #[test]
    fn comment_in_token() {
        decode_minimal_image(&b"P6 1 1 2#comment\n55 123"[..]); // Terminating LF
        decode_minimal_image(&b"P6 1 1 2#comment\r55 123"[..]); // Terminating CR
        decode_minimal_image(&b"P6 1 1#comment\n 255 123"[..]); // Comment after token
        decode_minimal_image(&b"P6 1 1 #comment\n255 123"[..]); // Comment before token
        decode_minimal_image(&b"P6#comment\n 1 1 255 123"[..]); // Begin of header
        decode_minimal_image(&b"P6 1 1 255#comment\n 123"[..]); // End of header
    }

    #[test]
    fn whitespace() {
        decode_minimal_image(&b"P6\x091\x091\x09255\x09123"[..]); // TAB
        decode_minimal_image(&b"P6\x0a1\x0a1\x0a255\x0a123"[..]); // LF
        decode_minimal_image(&b"P6\x0b1\x0b1\x0b255\x0b123"[..]); // VT
        decode_minimal_image(&b"P6\x0c1\x0c1\x0c255\x0c123"[..]); // FF
        decode_minimal_image(&b"P6\x0d1\x0d1\x0d255\x0d123"[..]); // CR
        // Spaces tested before
        decode_minimal_image(&b"P61\x09\x0a\x0b\x0c\x0d1 255 123"[..]); // All whitespace, combined
    }

    #[test]
    fn ascii_encoded() {
        decode_minimal_image(&b"P31 1 255 49 50 51"[..]);
        assert!(PPMDecoder::new(&b"P31 1 65535 65535 65535 65535"[..]).unwrap()
            .read_image().is_ok()); // Maximum sample size
        decode_minimal_image(&b"P31 1 255  49 50 51"[..]); // Whitespace after header
        decode_minimal_image(&b"P31 1 255 49\n\t 50\r\x0b\x0c51"[..]); // All forms of whitespace
    }

    /// Tests for decoding error, assuming `encoded` is ppm encoding for the very simplistic image
    /// containing a single pixel with one byte values (1, 2, 3).
    fn decode_minimal_image(encoded: &[u8]) {
        let content = vec![49 as u8, 50, 51];
        let mut decoder = PPMDecoder::new(encoded).unwrap();

        assert_eq!(decoder.dimensions().unwrap(), (1, 1));
        assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8));
        assert_eq!(decoder.row_len().unwrap(), 3);
        assert_eq!(decoder.bytewidth(), 1);

        match decoder.read_image().unwrap() {
            DecodingResult::U8(image) => assert_eq!(image, content),
            _ => assert!(false),
        }
    }

    #[test]
    fn wrong_tag() {
        assert!(PPMDecoder::new(&b"P5 1 1 255 1"[..]).is_err());
    }

    #[test]
    fn invalid_characters() {
        assert!(PPMDecoder::new(&b"P6 1chars1 255 1"[..]).is_err()); // No text outside of comments
        assert!(PPMDecoder::new(&b"P6 1\xFF1 255 1"[..]).is_err()); // No invalid ascii chars
        assert!(PPMDecoder::new(&b"P6 0x01 1 255 1"[..]).is_err()); // Numbers only as decimal
    }

    /// These violate the narrow specification of ppm but are commonly supported in other programs.
    /// Fail fast and concise is important here as these might be received as input files.
    #[test]
    fn unsupported_extensions() {
        assert!(PPMDecoder::new(&b"P6 1 1 65536 1"[..]).is_err()); // No bitwidth above 16
    }
}
<|endoftext|>


<commit_before>fn main() {
    child_window_exemple::child_window();
}

#[cfg(windows)]
mod child_window_exemple {

    extern crate winit;
    extern crate winapi;
    use std::thread;
    use self::winit::os::windows::{WindowBuilderExt, WindowExt};

    fn resize_callback(width: u32, height: u32) {
        println!("Window resized to {}x{}", width, height);
    }
    /**
    * Creates a main window and a child within it and handle their events separetely.
    * Currently windows only
    */
    pub fn child_window() {
        let window = winit::WindowBuilder::new()
            .with_title("A fantastic window!")
            .with_window_resize_callback(resize_callback)
            .build()
            .unwrap();

        let parent = window.get_hwnd() as winapi::HWND;
        let child = winit::WindowBuilder::new()
            .with_title("child window!")
            .with_window_resize_callback(resize_callback)
            .with_decorations(false)
            .with_dimensions(100, 100)
            .with_parent_window(parent)
            .build()
            .unwrap();

        let child_thread = thread::spawn(move || {
            for event in child.wait_events() {
                println!("child {:?}", event);

                match event {
                    winit::Event::Closed => break,
                    _ => (),
                }
            }
        });

        for event in window.wait_events() {
            println!("parent {:?}", event);

            match event {
                winit::Event::Closed => break,
                _ => (),
            }
        }

        child_thread.join().unwrap();
    }
}

#[cfg(not(windows))]
mod child_window_exemple {
    pub fn child_window() {}
}
<commit_msg>fix typo<commit_after>fn main() {
    child_window_example::child_window();
}

#[cfg(windows)]
mod child_window_example {

    extern crate winit;
    extern crate winapi;
    use std::thread;
    use self::winit::os::windows::{WindowBuilderExt, WindowExt};

    fn resize_callback(width: u32, height: u32) {
        println!("Window resized to {}x{}", width, height);
    }
    /**
    * Creates a main window and a child within it and handle their events separetely.
    * Currently windows only
    */
    pub fn child_window() {
        let window = winit::WindowBuilder::new()
            .with_title("A fantastic window!")
            .with_window_resize_callback(resize_callback)
            .build()
            .unwrap();

        let parent = window.get_hwnd() as winapi::HWND;
        let child = winit::WindowBuilder::new()
            .with_title("child window!")
            .with_window_resize_callback(resize_callback)
            .with_decorations(false)
            .with_dimensions(100, 100)
            .with_parent_window(parent)
            .build()
            .unwrap();

        let child_thread = thread::spawn(move || {
            for event in child.wait_events() {
                println!("child {:?}", event);

                match event {
                    winit::Event::Closed => break,
                    _ => (),
                }
            }
        });

        for event in window.wait_events() {
            println!("parent {:?}", event);

            match event {
                winit::Event::Closed => break,
                _ => (),
            }
        }

        child_thread.join().unwrap();
    }
}

#[cfg(not(windows))]
mod child_window_example {
    pub fn child_window() {}
}
<|endoftext|>


<commit_before>use std::path::posix::Path;
use std::io::fs::PathExtensions;
use std::io::process::Command;

mod io;

static TEMPLATE: &'static str = include_str!("template.toml");

pub fn main(path: Path) {
    if !path.exists() {
        let filename = path.filename().unwrap();
        let template = modified_template(TEMPLATE, filename);

        try_or_err!(io::create(&path, template.as_slice()), "Failed to create project file");

        match is_default_editor_set() {
            true  => io::open(&path),
            false => println!("Default editor is not set. Your config has been created and can be found in ~/.muxed/. Please define $EDITOR in your ~/.bashrc or similar file.")
        }
    } else {
        println!("Project already exists.");
    }
}

/// Run `which $EDITOR` to see if a default editor is defined on the system.
fn is_default_editor_set() -> bool {
  let output = match Command::new("which").arg("$EDITOR").output() {
      Ok(output) => output.output.to_string(),
      Err(e)     => fail!("failed to execute process: {}", e),
  };

  !output.is_empty()
}

fn modified_template(template: &str, project_name: &[u8]) -> String {
    let name = String::from_utf8(project_name.to_vec()).unwrap();
    template.replace("{file_name}", name.as_slice())
}

#[test]
fn populates_template_values() {
    let name   = "muxed projects".as_bytes();
    let value  = modified_template(TEMPLATE, name);
    let result = value.as_slice().contains("muxed project");
    assert!(result);
}

#[test]
fn removes_template_placeholders() {
    let name   = "muxed projects".as_bytes();
    let value  = modified_template(TEMPLATE, name);
    let result = !value.as_slice().contains("{file_name}");
    assert!(result);
}
//}
<commit_msg>Rename the function.<commit_after>use std::path::posix::Path;
use std::io::fs::PathExtensions;
use std::io::process::Command;

mod io;

static TEMPLATE: &'static str = include_str!("template.toml");

pub fn main(path: Path) {
    if !path.exists() {
        let filename = path.filename().unwrap();
        let template = modified_template(TEMPLATE, filename);

        try_or_err!(io::create(&path, template.as_slice()), "Failed to create project file");

        match is_default_editor_set() {
            true  => io::open(&path),
            false => println!("Default editor is not set. Your config has been created and can be found in ~/.muxed/. Please define $EDITOR in your ~/.bashrc or similar file.")
        }
    } else {
        println!("Project already exists.");
    }
}

/// Run `which $EDITOR` to see if a default editor is defined on the system.
fn is_default_editor_set() -> bool {
  let output = match Command::new("which").arg("$EDITOR").output() {
      Ok(output) => output.output.to_string(),
      Err(e)     => fail!("failed to execute process: {}", e),
  };

  !output.is_empty()
}

fn modified_template(template: &str, project_name: &[u8]) -> String {
    let name = String::from_utf8(project_name.to_vec()).unwrap();
    template.replace("{file_name}", name.as_slice())
}

#[test]
fn populates_template_placeholders() {
    let name   = "muxed projects".as_bytes();
    let value  = modified_template(TEMPLATE, name);
    let result = value.as_slice().contains("muxed project");
    assert!(result);
}

#[test]
fn removes_template_placeholders() {
    let name   = "muxed projects".as_bytes();
    let value  = modified_template(TEMPLATE, name);
    let result = !value.as_slice().contains("{file_name}");
    assert!(result);
}
<|endoftext|>


<commit_before>use std::path::Path;
use std::io::prelude::*;
use std::fs::File;
use yaml_rust::{YamlLoader, Yaml};
#[cfg(not(test))] use std::env::home_dir;

pub mod parser;
pub mod processor;

static MUXED_FOLDER: &'static str = "muxed";

pub fn main(project_name: &String) -> Vec<Yaml> {
    YamlLoader::load_from_str(&read(project_path(project_name))).unwrap()
}

pub fn project_path(project_name: &String) -> String {
    format!("{}/.{}/{}.yml", homedir_string(), &MUXED_FOLDER.to_string(), project_name)
}

fn read(config_str: String) -> String {
    let path = Path::new(&config_str);
    let mut s = String::new();
    let _ = File::open(path).expect("Config Read error").read_to_string(&mut s);

    return s
}

#[cfg(not(test))] fn homedir_string() -> String {
    match home_dir() {
        Some(dir) => format!("{}", dir.display()),
        None      => panic!("Impossible to get your home dir!")
    }
}

#[cfg(test)] fn homedir_string() -> String {
    String::from("/tmp")
}

#[test]
pub fn project_path_returns_muxed_in_homedir() {
    let path = format!("{}", project_path(&"test".to_string()));
    let new  = format!("{}", Path::new("/tmp/.muxed/test.yml").display());
    assert_eq!(path, new)
}
<commit_msg>Add mod and function docs to the project module<commit_after>//! The project module takes care of muxed related initialization. Locating the
/// users home directory. Finding the desired config files, and reading the
/// configs in.

use std::path::Path;
use std::io::prelude::*;
use std::fs::File;
use yaml_rust::{YamlLoader, Yaml};
#[cfg(not(test))] use std::env::home_dir;

pub mod parser;
pub mod processor;

/// The muxed project folder name. Should be located in the users home dir as a
/// hidden directory.
static MUXED_FOLDER: &'static str = "muxed";

/// Using the provided project name, locate the path to that project file. It
/// should be something similar to: `~/.muxed/my_project.yml`
/// Read in the contents of the config (which should be Yaml), and parse the
/// contents as yaml.
///
/// # Examples
///
/// Given the project name "compiler" and a project file found at:
/// `~/.muxed/compiler.yml`.
///
/// ```
/// let yaml: Vec<Yaml> = main("compiler".to_string());
/// ```
///
/// project_name: The name of the project, corresponding to the project config
/// file.
pub fn main(project_name: &String) -> Vec<Yaml> {
    YamlLoader::load_from_str(&read(project_path(project_name))).unwrap()
}

/// Project path locates the full path of the project file as a String. It's in
/// a string format because I had issues passing values of `Path`. `Path` would be
/// a more appropriate type to return, alas we are here.
///
/// # Examples
///
/// ```
/// let path: String = project_path("compiler".to_string());
/// println!("{}", path);
/// => "/home/vagrant/.muxed/compiler.yml"
/// ```
///
/// project_name: The name of the project, corresponding to the project config
/// file.
fn project_path(project_name: &String) -> String {
    format!("{}/.{}/{}.yml", homedir_string(), &MUXED_FOLDER.to_string(), project_name)
}

/// Read takes in the string path for a config file and returns the contents of
/// the file. Again we'de rather have a `Path` passed in to the function but we
/// I had issues with passing `Path` references or values.
///
/// config_str: The string path to the config file.
fn read(config_str: String) -> String {
    let path = Path::new(&config_str);
    let mut s = String::new();
    let _ = File::open(path).expect("Config Read error").read_to_string(&mut s);

    return s
}

/// Return the users homedir as a string.
#[cfg(not(test))] fn homedir_string() -> String {
    match home_dir() {
        Some(dir) => format!("{}", dir.display()),
        None      => panic!("Impossible to get your home dir!")
    }
}

/// Return the temp dir as the users home dir during testing.
#[cfg(test)] fn homedir_string() -> String {
    String::from("/tmp")
}

#[test]
pub fn project_path_returns_muxed_in_homedir() {
    let path = format!("{}", project_path(&"test".to_string()));
    let new  = format!("{}", Path::new("/tmp/.muxed/test.yml").display());
    assert_eq!(path, new)
}
<|endoftext|>


<commit_before>/// Implementation of Stochastic universal sampling
/// https://en.wikipedia.org/wiki/Stochastic_universal_sampling
/// Runtime: O(n)
/// Memory Usage: O(n) or O(1) (in place variant)

extern crate rand;

use self::rand::{thread_rng, Rng};

/// Chooses n samples by their weights. The greater their weights the more likely they get chosen.
///
/// @invariant sum of weights must not overflow.
/// @param samples The to be selected samples
/// @param weights Weights that get chosen by their weight/probability. One weight can be greater 1.
/// @param n Number of randomly chosen indices by weight.
/// @return randomly selected samples by their weights
pub fn random_choice<'a, T>(samples: &'a Vec<T>, weights: &Vec<f64>, n: usize) -> Vec<&'a T>{
    // TODO Check, if weight.len() > 0 and n > 0

    let sum:f64 = weights.iter().fold(0.0, |acc, &i| acc + i);
    let spoke_gap: f64 = sum / n as f64;

    // next_f64() ∈ [0.0, 1.0)
    let spin = thread_rng().next_f64() * spoke_gap;

    let mut i: usize = 0;
    let mut accumulated_weights = weights[0];
    let mut choices: Vec<&T> = Vec::with_capacity(n);
    let mut current_spoke: f64 = spin;

    for _ in 0 .. n {
        while accumulated_weights < current_spoke {
            i += 1;
            accumulated_weights += weights[i];
        }
        choices.push(&samples[i]);
        current_spoke += spoke_gap;
    }

    choices
}

pub fn random_choice_in_place<T: Copy>(samples: &mut Vec<T>, weights: &Vec<f64>) {
    // TODO Check, if weight.len() > 0 and n > 0
    let sum:f64 = weights.iter().fold(0.0, |acc, &i| acc + i);
    let n: usize = weights.len();
    let spoke_gap: f64 = sum / n as f64;

    // next_f64() ∈ [0.0, 1.0)
    let spin = thread_rng().next_f64() * spoke_gap;

    let mut j: usize = 0;
    let mut accumulated_weights = weights[0];
    let mut current_spoke: f64 = spin;

    for i in 0 .. n {
        while accumulated_weights < current_spoke {
            j += 1;
            accumulated_weights += weights[j];
        }
        samples[i] = samples[j];
        current_spoke += spoke_gap;
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_random_choice() {
        let test_vec: Vec<f64> = vec![3.1, 1.2, 1.3, 2.0];
        //let sum:f64 = test_vec.iter().fold(0.0, |acc, &i| acc + i);

        //assert_eq!(6.0, sum);

        let choices = super::random_choice(&test_vec, &test_vec, 4 as usize);

        for choice in choices {
            print!("{}, ", choice);
        }
    }
}<commit_msg>added primitive test for in place variant<commit_after>/// Implementation of Stochastic universal sampling
/// https://en.wikipedia.org/wiki/Stochastic_universal_sampling
/// Runtime: O(n)
/// Memory Usage: O(n) or O(1) (in place variant)

extern crate rand;

use self::rand::{thread_rng, Rng};

/// Chooses n samples by their weights. The greater their weights the more likely they get chosen.
///
/// @invariant sum of weights must not overflow.
/// @param samples The to be selected samples
/// @param weights Weights that get chosen by their weight/probability. One weight can be greater 1.
/// @param n Number of randomly chosen indices by weight.
/// @return randomly selected samples by their weights
pub fn random_choice<'a, T>(samples: &'a Vec<T>, weights: &Vec<f64>, n: usize) -> Vec<&'a T>{
    // TODO Check, if weight.len() > 0 and n > 0

    let sum:f64 = weights.iter().fold(0.0, |acc, &i| acc + i);
    let spoke_gap: f64 = sum / n as f64;

    // next_f64() ∈ [0.0, 1.0)
    let spin = thread_rng().next_f64() * spoke_gap;

    let mut i: usize = 0;
    let mut accumulated_weights = weights[0];
    let mut choices: Vec<&T> = Vec::with_capacity(n);
    let mut current_spoke: f64 = spin;

    for _ in 0 .. n {
        while accumulated_weights < current_spoke {
            i += 1;
            accumulated_weights += weights[i];
        }
        choices.push(&samples[i]);
        current_spoke += spoke_gap;
    }

    choices
}

pub fn random_choice_in_place<T: Copy>(samples: &mut Vec<T>, weights: &Vec<f64>) {
    // TODO Check, if weight.len() > 0 and n > 0
    let sum:f64 = weights.iter().fold(0.0, |acc, &i| acc + i);
    let n: usize = weights.len();
    let spoke_gap: f64 = sum / n as f64;

    // next_f64() ∈ [0.0, 1.0)
    let spin = thread_rng().next_f64() * spoke_gap;

    let mut j: usize = 0;
    let mut accumulated_weights = weights[0];
    let mut current_spoke: f64 = spin;

    for i in 0 .. n {
        while accumulated_weights < current_spoke {
            j += 1;
            accumulated_weights += weights[j];
        }
        samples[i] = samples[j];
        current_spoke += spoke_gap;
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_random_choice() {
        let test_vec: Vec<f64> = vec![3.1, 1.2, 1.3, 2.0];
        //let sum:f64 = test_vec.iter().fold(0.0, |acc, &i| acc + i);

        //assert_eq!(6.0, sum);

        let choices = super::random_choice(&test_vec, &test_vec, 4 as usize);

        for choice in choices {
            print!("{}, ", choice);
        }
    }

    #[test]
    fn test_random_choice_in_place() {
        let mut samples = vec!["hi", "this", "is", "a", "test!"];
        let weights: Vec<f64> = vec![1.0, 1.0, 1.0, 1.0, 1.0];

        super::random_choice_in_place(&mut samples, &weights);

        for sample in samples {
            print!("{}, ", sample);
        }
    }
}<|endoftext|>