<commit_before>use std::fs;
use std::io::prelude::*;
use std::process::Command;
use std::collections::HashMap;
use std::io::BufReader;
use problem::{LpProblem, Problem};
use problem::{LpFileFormat};
use std::fs::File;
use std::io::Error;

#[derive(Debug, PartialEq)]
pub enum Status {
    Optimal,
    SubOptimal,
    Infeasible,
    Unbounded,
    NotSolved,
}

pub trait SolverTrait {
    type P: Problem;
    fn run(&self, problem: &Self::P) -> Result<(Status, HashMap<String,f32>), String>;
}

pub struct GurobiSolver {
    name: String,
    command_name: String,
    temp_solution_file: String,
}
pub struct CbcSolver {
    name: String,
    command_name: String,
    temp_solution_file: String,
}
pub struct GlpkSolver {
    name: String,
    command_name: String,
    temp_solution_file: String,
}

impl GurobiSolver {
    pub fn new() -> GurobiSolver {
        GurobiSolver { name: "Gurobi".to_string(), command_name: "gurobi_cl".to_string(), temp_solution_file: "sol.sol".to_string() }
    }
    pub fn command_name(&self, command_name: String) -> GurobiSolver {
        GurobiSolver { name: self.name.clone(), command_name: command_name, temp_solution_file: self.temp_solution_file.clone() }
    }
    fn read_solution(&self) -> Result<(Status, HashMap<String, f32>), String> {
        fn read_specific_solution(f: &File) -> Result<(Status, HashMap<String, f32>), String> {

            let mut vars_value: HashMap<_,_> = HashMap::new();
            let mut file = BufReader::new(f);
            let mut buffer = String::new();
            let _ = file.read_line(&mut buffer);

            if let Some(_) = buffer.split(" ").next() {
                for line in file.lines() {
                    let l = line.unwrap();

                    // Gurobi version 7 add comments on the header file
                    if let Some('#') = l.chars().next() {continue}

                    let result_line: Vec<_> = l.split_whitespace().collect();
                    if result_line.len() == 2 {
                        match result_line[1].parse::<f32>() {
                            Ok(n) => {
                                vars_value.insert(result_line[0].to_string(), n);
                            },
                            Err(e) => return Err(format!("{}", e.to_string()))
                        }
                    } else {
                        return Err("Incorrect solution format".to_string())
                    }
                }
            }else{
                return Err("Incorrect solution format".to_string())
            }
            Ok((Status::Optimal, vars_value))
        }

        match File::open(&self.temp_solution_file) {
            Ok(f) => {
                let res = try!(read_specific_solution(&f));
                let _ = fs::remove_file(&self.temp_solution_file);
                Ok(res)
            },
            Err(_) => return Err("Cannot open file".to_string())
        }
    }
}
impl CbcSolver {
    pub fn new() -> CbcSolver {
        CbcSolver { name: "Cbc".to_string(), command_name: "cbc".to_string(), temp_solution_file: "sol.sol".to_string() }
    }
    pub fn command_name(&self, command_name: String) -> CbcSolver {
        CbcSolver { name: self.name.clone(), command_name: command_name, temp_solution_file: self.temp_solution_file.clone() }
    }

    fn read_solution(&self) -> Result<(Status, HashMap<String, f32>), String> {
        fn read_specific_solution(f: &File) -> Result<(Status, HashMap<String, f32>), String> {
            let mut vars_value: HashMap<_, _> = HashMap::new();

            let mut file = BufReader::new(f);
            let mut buffer = String::new();
            let _ = file.read_line(&mut buffer);
            let mut status = Status::SubOptimal;

            if let Some(status_line) = buffer.split(" ").next() {
                if status_line.contains("Optimal") {
                    status = Status::Optimal;
                }
                for line in file.lines() {
                    let l = line.unwrap();
                    let result_line: Vec<_> = l.split_whitespace().collect();
                    if result_line.len() == 4 {
                        match result_line[2].parse::<f32>() {
                            Ok(n) => {
                                vars_value.insert(result_line[1].to_string(), n);
                            },
                            Err(e) => return Err(format!("{}", e.to_string()))
                        }
                    } else {
                        return Err("Incorrect solution format".to_string())
                    }
                }
            } else {
                return Err("Incorrect solution format".to_string())
            }
            Ok((status, vars_value))
        }

        match File::open(&self.temp_solution_file) {
            Ok(f) => {
                let res = try!(read_specific_solution(&f));
                let _ = fs::remove_file(&self.temp_solution_file);
                Ok(res)
            },
            Err(_) => return Err("Cannot open file".to_string())
        }
    }
}
impl GlpkSolver {
    pub fn new() -> GlpkSolver {
        GlpkSolver { name: "Glpk".to_string(), command_name: "glpsol".to_string(), temp_solution_file: "sol.sol".to_string() }
    }
    pub fn command_name(&self, command_name: String) -> GlpkSolver {
        GlpkSolver { name: self.name.clone(), command_name: command_name, temp_solution_file: self.temp_solution_file.clone() }
    }
    fn read_solution(&self) -> Result<(Status, HashMap<String, f32>), String> {
        fn read_specific_solution(f: &File) -> Result<(Status, HashMap<String, f32>), String> {
            fn read_size(line: Option<Result<String, Error>>) -> Result<usize, String> {
                match line {
                    Some(Ok(l)) => {
                        match l.split_whitespace().nth(1) {
                            Some(value) => match value.parse::<usize>() {
                                Ok(v) => Ok(v),
                                _ => return Err("Incorrect solution format".to_string())
                            },
                            _ => return Err("Incorrect solution format".to_string())
                        }
                    },
                    _ => return Err("Incorrect solution format".to_string())
                }
            }
            let mut vars_value: HashMap<_, _> = HashMap::new();

            let file = BufReader::new(f);

            let mut iter = file.lines();
            let row = match read_size(iter.nth(1)) {
                Ok(value) => value,
                Err(e) => return Err(e.to_string())
            };
            let col = match read_size(iter.nth(0)) {
                Ok(value) => value,
                Err(e) => return Err(e.to_string())
            };
            let status = match iter.nth(1) {
                Some(Ok(status_line)) => {
                    match &status_line[12..] {
                        "INTEGER OPTIMAL" | "OPTIMAL" => Status::Optimal,
                        "INFEASIBLE (FINAL)" => Status::Infeasible,
                        "INTEGER UNDEFINED" | "UNDEFINED" => Status::NotSolved,
                        "UNBOUNDED" => Status::Unbounded,
                        _ => return Err("Incorrect solution format".to_string())
                    }
                },
                _ => return Err("Incorrect solution format".to_string())
            };
            let mut result_lines = iter.skip(row + 7);
            for _ in 0..col {
                let line = match result_lines.next() {
                    Some(Ok(l)) => l,
                    _ => return Err("Incorrect solution format".to_string())
                };
                let result_line: Vec<_> = line.split_whitespace().collect();
                if result_line.len() == 5 {
                    match result_line[3].parse::<f32>() {
                        Ok(n) => {
                            vars_value.insert(result_line[1].to_string(), n);
                        },
                        Err(e) => return Err(e.to_string())
                    }
                } else {
                    return Err("Incorrect solution format".to_string())
                }
            }
            Ok((status, vars_value))
        }

        match File::open(&self.temp_solution_file) {
            Ok(f) => {
                let res = try!(read_specific_solution(&f));
                let _ = fs::remove_file(&self.temp_solution_file);
                Ok(res)
            },
            Err(_) => return Err("Cannot open file".to_string())
        }
    }
}

impl SolverTrait for GurobiSolver {
    type P = LpProblem;
    fn run(&self, problem: &Self::P) -> Result<(Status, HashMap<String,f32>), String> {

        let file_model = "test.lp";

        match problem.write_lp(file_model) {
            Ok(_) => {
                match Command::new(&self.command_name).arg(format!("ResultFile={}", self.temp_solution_file)).arg(file_model).output() {
                    Ok(r) => {
                        let mut status = Status::SubOptimal;
                        if String::from_utf8(r.stdout).expect("").contains("Optimal solution found") {
                            status = Status::Optimal;
                        }
                        if r.status.success() {
                            let (_, res) = try!(self.read_solution());
                            Ok((status, res))
                        } else {
                            Err(r.status.to_string())
                        }
                    },
                    Err(_) => Err(format!("Error running the {} solver", self.name)),
                }
            },
            Err(e) => Err(e.to_string()),
        }
    }
}

impl SolverTrait for CbcSolver {
    type P = LpProblem;
    fn run(&self, problem: &Self::P) -> Result<(Status, HashMap<String,f32>), String> {

        let file_model = "test.lp";

        match problem.write_lp(file_model) {
            Ok(_) => {
                match Command::new(&self.command_name).arg(file_model).arg("solve").arg("solution").arg(&self.temp_solution_file).output() {
                    Ok(r) => {
                        if r.status.success(){
                            self.read_solution()
                        }else{
                            Err(r.status.to_string())
                        }
                    },
                    Err(_) => Err(format!("Error running the {} solver", self.name)),
                }
            },
            Err(e) => Err(e.to_string()),
        }
    }
}

impl SolverTrait for GlpkSolver {
    type P = LpProblem;
    fn run(&self, problem: &Self::P) -> Result<(Status, HashMap<String,f32>), String> {

        let file_model:&str = "test.lp";

        match problem.write_lp(file_model) {
            Ok(_) => {
                match Command::new(&self.command_name).arg("--lp").arg(file_model).arg("-o").arg(&self.temp_solution_file).output() {
                    Ok(r) => {
                        if r.status.success() {
                            self.read_solution()
                        } else {
                            Err(r.status.to_string())
                        }
                    },
                    Err(_) => Err(format!("Error running the {} solver", self.name)),
                }
            },
            Err(e) => Err(e.to_string()),
        }
    }
}<commit_msg>Add missing solution statuses for Cbc<commit_after>use std::fs;
use std::io::prelude::*;
use std::process::Command;
use std::collections::HashMap;
use std::io::BufReader;
use problem::{LpProblem, Problem};
use problem::{LpFileFormat};
use std::fs::File;
use std::io::Error;

#[derive(Debug, PartialEq)]
pub enum Status {
    Optimal,
    SubOptimal,
    Infeasible,
    Unbounded,
    NotSolved,
}

pub trait SolverTrait {
    type P: Problem;
    fn run(&self, problem: &Self::P) -> Result<(Status, HashMap<String,f32>), String>;
}

pub struct GurobiSolver {
    name: String,
    command_name: String,
    temp_solution_file: String,
}
pub struct CbcSolver {
    name: String,
    command_name: String,
    temp_solution_file: String,
}
pub struct GlpkSolver {
    name: String,
    command_name: String,
    temp_solution_file: String,
}

impl GurobiSolver {
    pub fn new() -> GurobiSolver {
        GurobiSolver { name: "Gurobi".to_string(), command_name: "gurobi_cl".to_string(), temp_solution_file: "sol.sol".to_string() }
    }
    pub fn command_name(&self, command_name: String) -> GurobiSolver {
        GurobiSolver { name: self.name.clone(), command_name: command_name, temp_solution_file: self.temp_solution_file.clone() }
    }
    fn read_solution(&self) -> Result<(Status, HashMap<String, f32>), String> {
        fn read_specific_solution(f: &File) -> Result<(Status, HashMap<String, f32>), String> {

            let mut vars_value: HashMap<_,_> = HashMap::new();
            let mut file = BufReader::new(f);
            let mut buffer = String::new();
            let _ = file.read_line(&mut buffer);

            if let Some(_) = buffer.split(" ").next() {
                for line in file.lines() {
                    let l = line.unwrap();

                    // Gurobi version 7 add comments on the header file
                    if let Some('#') = l.chars().next() {continue}

                    let result_line: Vec<_> = l.split_whitespace().collect();
                    if result_line.len() == 2 {
                        match result_line[1].parse::<f32>() {
                            Ok(n) => {
                                vars_value.insert(result_line[0].to_string(), n);
                            },
                            Err(e) => return Err(format!("{}", e.to_string()))
                        }
                    } else {
                        return Err("Incorrect solution format".to_string())
                    }
                }
            }else{
                return Err("Incorrect solution format".to_string())
            }
            Ok((Status::Optimal, vars_value))
        }

        match File::open(&self.temp_solution_file) {
            Ok(f) => {
                let res = try!(read_specific_solution(&f));
                let _ = fs::remove_file(&self.temp_solution_file);
                Ok(res)
            },
            Err(_) => return Err("Cannot open file".to_string())
        }
    }
}
impl CbcSolver {
    pub fn new() -> CbcSolver {
        CbcSolver { name: "Cbc".to_string(), command_name: "cbc".to_string(), temp_solution_file: "sol.sol".to_string() }
    }
    pub fn command_name(&self, command_name: String) -> CbcSolver {
        CbcSolver { name: self.name.clone(), command_name: command_name, temp_solution_file: self.temp_solution_file.clone() }
    }

    fn read_solution(&self) -> Result<(Status, HashMap<String, f32>), String> {
        fn read_specific_solution(f: &File) -> Result<(Status, HashMap<String, f32>), String> {
            let mut vars_value: HashMap<_, _> = HashMap::new();

            let mut file = BufReader::new(f);
            let mut buffer = String::new();
            let _ = file.read_line(&mut buffer);

            let status = if let Some(status_line) = buffer.split_whitespace().next() {
                match status_line.split_whitespace().next() {
                    Some("Optimal") => Status::Optimal,
                    // Infeasible status is either "Infeasible" or "Integer infeasible"
                    Some("Infeasible") | Some("Integer") => Status::Infeasible,
                    Some("Unbounded") => Status::Unbounded,
                    // "Stopped" can be "on time", "on iterations", "on difficulties" or "on ctrl-c"
                    Some("Stopped") => Status::SubOptimal,
                    _ => Status::NotSolved
                }
            } else {
                return Err("Incorrect solution format".to_string())
            };
            for line in file.lines() {
                let l = line.unwrap();
                let result_line: Vec<_> = l.split_whitespace().collect();
                if result_line.len() == 4 {
                    match result_line[2].parse::<f32>() {
                        Ok(n) => {
                            vars_value.insert(result_line[1].to_string(), n);
                        },
                        Err(e) => return Err(e.to_string())
                    }
                } else {
                    return Err("Incorrect solution format".to_string())
                }
            }
            Ok((status, vars_value))
        }

        match File::open(&self.temp_solution_file) {
            Ok(f) => {
                let res = try!(read_specific_solution(&f));
                let _ = fs::remove_file(&self.temp_solution_file);
                Ok(res)
            },
            Err(_) => return Err("Cannot open file".to_string())
        }
    }
}
impl GlpkSolver {
    pub fn new() -> GlpkSolver {
        GlpkSolver { name: "Glpk".to_string(), command_name: "glpsol".to_string(), temp_solution_file: "sol.sol".to_string() }
    }
    pub fn command_name(&self, command_name: String) -> GlpkSolver {
        GlpkSolver { name: self.name.clone(), command_name: command_name, temp_solution_file: self.temp_solution_file.clone() }
    }
    fn read_solution(&self) -> Result<(Status, HashMap<String, f32>), String> {
        fn read_specific_solution(f: &File) -> Result<(Status, HashMap<String, f32>), String> {
            fn read_size(line: Option<Result<String, Error>>) -> Result<usize, String> {
                match line {
                    Some(Ok(l)) => {
                        match l.split_whitespace().nth(1) {
                            Some(value) => match value.parse::<usize>() {
                                Ok(v) => Ok(v),
                                _ => return Err("Incorrect solution format".to_string())
                            },
                            _ => return Err("Incorrect solution format".to_string())
                        }
                    },
                    _ => return Err("Incorrect solution format".to_string())
                }
            }
            let mut vars_value: HashMap<_, _> = HashMap::new();

            let file = BufReader::new(f);

            let mut iter = file.lines();
            let row = match read_size(iter.nth(1)) {
                Ok(value) => value,
                Err(e) => return Err(e.to_string())
            };
            let col = match read_size(iter.nth(0)) {
                Ok(value) => value,
                Err(e) => return Err(e.to_string())
            };
            let status = match iter.nth(1) {
                Some(Ok(status_line)) => {
                    match &status_line[12..] {
                        "INTEGER OPTIMAL" | "OPTIMAL" => Status::Optimal,
                        "INFEASIBLE (FINAL)" => Status::Infeasible,
                        "INTEGER UNDEFINED" | "UNDEFINED" => Status::NotSolved,
                        "UNBOUNDED" => Status::Unbounded,
                        _ => return Err("Incorrect solution format".to_string())
                    }
                },
                _ => return Err("Incorrect solution format".to_string())
            };
            let mut result_lines = iter.skip(row + 7);
            for _ in 0..col {
                let line = match result_lines.next() {
                    Some(Ok(l)) => l,
                    _ => return Err("Incorrect solution format".to_string())
                };
                let result_line: Vec<_> = line.split_whitespace().collect();
                if result_line.len() == 5 {
                    match result_line[3].parse::<f32>() {
                        Ok(n) => {
                            vars_value.insert(result_line[1].to_string(), n);
                        },
                        Err(e) => return Err(e.to_string())
                    }
                } else {
                    return Err("Incorrect solution format".to_string())
                }
            }
            Ok((status, vars_value))
        }

        match File::open(&self.temp_solution_file) {
            Ok(f) => {
                let res = try!(read_specific_solution(&f));
                let _ = fs::remove_file(&self.temp_solution_file);
                Ok(res)
            },
            Err(_) => return Err("Cannot open file".to_string())
        }
    }
}

impl SolverTrait for GurobiSolver {
    type P = LpProblem;
    fn run(&self, problem: &Self::P) -> Result<(Status, HashMap<String,f32>), String> {

        let file_model = "test.lp";

        match problem.write_lp(file_model) {
            Ok(_) => {
                match Command::new(&self.command_name).arg(format!("ResultFile={}", self.temp_solution_file)).arg(file_model).output() {
                    Ok(r) => {
                        let mut status = Status::SubOptimal;
                        if String::from_utf8(r.stdout).expect("").contains("Optimal solution found") {
                            status = Status::Optimal;
                        }
                        if r.status.success() {
                            let (_, res) = try!(self.read_solution());
                            Ok((status, res))
                        } else {
                            Err(r.status.to_string())
                        }
                    },
                    Err(_) => Err(format!("Error running the {} solver", self.name)),
                }
            },
            Err(e) => Err(e.to_string()),
        }
    }
}

impl SolverTrait for CbcSolver {
    type P = LpProblem;
    fn run(&self, problem: &Self::P) -> Result<(Status, HashMap<String,f32>), String> {

        let file_model = "test.lp";

        match problem.write_lp(file_model) {
            Ok(_) => {
                match Command::new(&self.command_name).arg(file_model).arg("solve").arg("solution").arg(&self.temp_solution_file).output() {
                    Ok(r) => {
                        if r.status.success(){
                            self.read_solution()
                        }else{
                            Err(r.status.to_string())
                        }
                    },
                    Err(_) => Err(format!("Error running the {} solver", self.name)),
                }
            },
            Err(e) => Err(e.to_string()),
        }
    }
}

impl SolverTrait for GlpkSolver {
    type P = LpProblem;
    fn run(&self, problem: &Self::P) -> Result<(Status, HashMap<String,f32>), String> {

        let file_model:&str = "test.lp";

        match problem.write_lp(file_model) {
            Ok(_) => {
                match Command::new(&self.command_name).arg("--lp").arg(file_model).arg("-o").arg(&self.temp_solution_file).output() {
                    Ok(r) => {
                        if r.status.success() {
                            self.read_solution()
                        } else {
                            Err(r.status.to_string())
                        }
                    },
                    Err(_) => Err(format!("Error running the {} solver", self.name)),
                }
            },
            Err(e) => Err(e.to_string()),
        }
    }
}<|endoftext|>


<commit_before>// Copyright (c) 2017 Gilad Naaman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

/// Produces a range instance representing the sub-slice containing the specified member.
///
/// This macro provides 2 forms of differing functionalities.
///
/// The first form is identical to the appearance of the `offset_of!` macro.
///
/// ```ignore
/// span_of!(Struct, member)
/// ```
///
/// The second form of `span_of!` returns a sub-slice which starts at one field, and ends at another.
/// The general pattern of this form is:
///
/// ```ignore
/// // Exclusive
/// span_of!(Struct, member_a .. member_b)
/// // Inclusive
/// span_of!(Struct, member_a ..= member_b)
///
/// // Open-ended ranges
/// span_of!(Struct, .. end)
/// span_of!(Struct, start ..)
/// ```
///
/// *Note*:
/// This macro uses recursion in order to resolve the range expressions, so there is a limit to
/// the complexity of the expression.
/// In order to raise the limit, the compiler's recursion limit should be lifted.
///
/// ## Examples
/// ```
/// #[macro_use]
/// extern crate memoffset;
///
/// #[repr(C, packed)]
/// struct Florp {
///     a: u32
/// }
///
/// #[repr(C, packed)]
/// struct Blarg {
///     x: u64,
///     y: [u8; 56],
///     z: Florp,
///     egg: [[u8; 4]; 4]
/// }
///
/// fn main() {
///     assert_eq!(0..8,   span_of!(Blarg, x));
///     assert_eq!(8..84,  span_of!(Blarg, y ..));
///     assert_eq!(0..64,  span_of!(Blarg, x ..= y));
/// }
/// ```
#[macro_export]
macro_rules! span_of {
    (@helper  $root:ident, [] ..=) => {
        compile_error!("Expected a range, found '..='")
    };
    (@helper $root:ident, [] ..) => {
        compile_error!("Expected a range, found '..'")
    };
    // Lots of UB due to taking references to uninitialized fields! But that can currently
    // not be avoided.
    // No explicit begin for range.
    (@helper $root:ident, $parent:tt, [] ..) => {{
        ($root as usize,
         $root as usize + $crate::mem::size_of_val(&(*$root)))
    }};
    (@helper $root:ident, $parent:tt, [] ..= $field:tt) => {{
        field_check!($parent, $field);
        ($root as usize,
         &(*$root).$field as *const _ as usize + $crate::mem::size_of_val(&(*$root).$field))
    }};
    (@helper $root:ident, $parent:tt, [] .. $field:tt) => {{
        field_check!($parent, $field);
        ($root as usize, &(*$root).$field as *const _ as usize)
    }};
    // Explicit begin and end for range.
    (@helper $root:ident, $parent:tt, # $begin:tt [] ..= $end:tt) => {{
        field_check!($parent, $begin);
        field_check!($parent, $end);
        (&(*$root).$begin as *const _ as usize,
         &(*$root).$end as *const _ as usize + $crate::mem::size_of_val(&(*$root).$end))
    }};
    (@helper $root:ident, $parent:tt, # $begin:tt [] .. $end:tt) => {{
        field_check!($parent, $begin);
        field_check!($parent, $end);
        (&(*$root).$begin as *const _ as usize,
         &(*$root).$end as *const _ as usize)
    }};
    // No explicit end for range.
    (@helper $root:ident, $parent:tt, # $begin:tt [] ..) => {{
        field_check!($parent, $begin);
        (&(*$root).$begin as *const _ as usize,
         $root as usize + $crate::mem::size_of_val(&*$root))
    }};
    (@helper $root:ident, $parent:tt, # $begin:tt [] ..=) => {{
        compile_error!(
            "Found inclusive range to the end of a struct. Did you mean '..' instead of '..='?")
    }};
    // Just one field.
    (@helper $root:ident, $parent:tt, # $begin:tt []) => {{
        field_check!($parent, $begin);
        (&(*$root).$begin as *const _ as usize,
         &(*$root).$begin as *const _ as usize + $crate::mem::size_of_val(&(*$root).$begin))
    }};
    // Parsing.
    (@helper $root:ident, $parent:tt, $(# $begin:tt)+ [] $tt:tt $($rest:tt)*) => {{
        span_of!(@helper $root, $parent, $(#$begin)* #$tt [] $($rest)*)
    }};
    (@helper $root:ident, $parent:tt, [] $tt:tt $($rest:tt)*) => {{
        span_of!(@helper $root, $parent, #$tt [] $($rest)*)
    }};

    // Entry point.
    ($sty:tt, $($exp:tt)+) => ({
        unsafe {
            // Get a base pointer.
            $crate::let_base_ptr!(root, $sty);
            let base = root as usize;
            let (begin, end) = span_of!(@helper root, $sty, [] $($exp)*);
            begin-base..end-base
        }
    });
}

#[cfg(test)]
mod tests {
    use core::mem;

    #[repr(C, packed)]
    struct Foo {
        a: u32,
        b: [u8; 4],
        c: i64,
    }

    #[test]
    fn span_simple() {
        assert_eq!(span_of!(Foo, a), 0..4);
        assert_eq!(span_of!(Foo, b), 4..8);
        assert_eq!(span_of!(Foo, c), 8..16);
    }

    #[test]
    fn span_forms() {
        #[repr(C, packed)]
        struct Florp {
            a: u32,
        }

        #[repr(C, packed)]
        struct Blarg {
            x: u64,
            y: [u8; 56],
            z: Florp,
            egg: [[u8; 4]; 4],
        }

        // Love me some brute force
        assert_eq!(0..8, span_of!(Blarg, x));
        assert_eq!(64..68, span_of!(Blarg, z));
        assert_eq!(68..mem::size_of::<Blarg>(), span_of!(Blarg, egg));

        assert_eq!(8..64, span_of!(Blarg, y..z));
        assert_eq!(0..64, span_of!(Blarg, x..=y));
    }

    #[test]
    fn ig_test() {
        #[repr(C)]
        struct Member {
            foo: u32,
        }

        #[repr(C)]
        struct Test {
            x: u64,
            y: [u8; 56],
            z: Member,
            egg: [[u8; 4]; 4],
        }

        assert_eq!(span_of!(Test, ..x), 0..0);
        assert_eq!(span_of!(Test, ..=x), 0..8);
        assert_eq!(span_of!(Test, ..y), 0..8);
        assert_eq!(span_of!(Test, ..=y), 0..64);
        assert_eq!(span_of!(Test, ..z), 0..64);
        assert_eq!(span_of!(Test, ..=z), 0..68);
        assert_eq!(span_of!(Test, ..egg), 0..68);
        assert_eq!(span_of!(Test, ..=egg), 0..84);
        assert_eq!(span_of!(Test, ..), 0..mem::size_of::<Test>());
        assert_eq!(
            span_of!(Test, x..),
            offset_of!(Test, x)..mem::size_of::<Test>()
        );
        assert_eq!(
            span_of!(Test, y..),
            offset_of!(Test, y)..mem::size_of::<Test>()
        );

        assert_eq!(
            span_of!(Test, z..),
            offset_of!(Test, z)..mem::size_of::<Test>()
        );
        assert_eq!(
            span_of!(Test, egg..),
            offset_of!(Test, egg)..mem::size_of::<Test>()
        );
        assert_eq!(
            span_of!(Test, x..y),
            offset_of!(Test, x)..offset_of!(Test, y)
        );
        assert_eq!(
            span_of!(Test, x..=y),
            offset_of!(Test, x)..offset_of!(Test, y) + mem::size_of::<[u8; 56]>()
        );
    }
}
<commit_msg>span_of: test packed and not-packed separately; not-packed passes on Miri<commit_after>// Copyright (c) 2017 Gilad Naaman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

/// Produces a range instance representing the sub-slice containing the specified member.
///
/// This macro provides 2 forms of differing functionalities.
///
/// The first form is identical to the appearance of the `offset_of!` macro.
///
/// ```ignore
/// span_of!(Struct, member)
/// ```
///
/// The second form of `span_of!` returns a sub-slice which starts at one field, and ends at another.
/// The general pattern of this form is:
///
/// ```ignore
/// // Exclusive
/// span_of!(Struct, member_a .. member_b)
/// // Inclusive
/// span_of!(Struct, member_a ..= member_b)
///
/// // Open-ended ranges
/// span_of!(Struct, .. end)
/// span_of!(Struct, start ..)
/// ```
///
/// *Note*:
/// This macro uses recursion in order to resolve the range expressions, so there is a limit to
/// the complexity of the expression.
/// In order to raise the limit, the compiler's recursion limit should be lifted.
///
/// ## Examples
/// ```
/// #[macro_use]
/// extern crate memoffset;
///
/// #[repr(C, packed)]
/// struct Florp {
///     a: u32
/// }
///
/// #[repr(C, packed)]
/// struct Blarg {
///     x: u64,
///     y: [u8; 56],
///     z: Florp,
///     egg: [[u8; 4]; 4]
/// }
///
/// fn main() {
///     assert_eq!(0..8,   span_of!(Blarg, x));
///     assert_eq!(8..84,  span_of!(Blarg, y ..));
///     assert_eq!(0..64,  span_of!(Blarg, x ..= y));
/// }
/// ```
#[macro_export]
macro_rules! span_of {
    (@helper  $root:ident, [] ..=) => {
        compile_error!("Expected a range, found '..='")
    };
    (@helper $root:ident, [] ..) => {
        compile_error!("Expected a range, found '..'")
    };
    // Lots of UB due to taking references to uninitialized fields! But that can currently
    // not be avoided.
    // No explicit begin for range.
    (@helper $root:ident, $parent:tt, [] ..) => {{
        ($root as usize,
         $root as usize + $crate::mem::size_of_val(&(*$root)))
    }};
    (@helper $root:ident, $parent:tt, [] ..= $field:tt) => {{
        field_check!($parent, $field);
        ($root as usize,
         &(*$root).$field as *const _ as usize + $crate::mem::size_of_val(&(*$root).$field))
    }};
    (@helper $root:ident, $parent:tt, [] .. $field:tt) => {{
        field_check!($parent, $field);
        ($root as usize, &(*$root).$field as *const _ as usize)
    }};
    // Explicit begin and end for range.
    (@helper $root:ident, $parent:tt, # $begin:tt [] ..= $end:tt) => {{
        field_check!($parent, $begin);
        field_check!($parent, $end);
        (&(*$root).$begin as *const _ as usize,
         &(*$root).$end as *const _ as usize + $crate::mem::size_of_val(&(*$root).$end))
    }};
    (@helper $root:ident, $parent:tt, # $begin:tt [] .. $end:tt) => {{
        field_check!($parent, $begin);
        field_check!($parent, $end);
        (&(*$root).$begin as *const _ as usize,
         &(*$root).$end as *const _ as usize)
    }};
    // No explicit end for range.
    (@helper $root:ident, $parent:tt, # $begin:tt [] ..) => {{
        field_check!($parent, $begin);
        (&(*$root).$begin as *const _ as usize,
         $root as usize + $crate::mem::size_of_val(&*$root))
    }};
    (@helper $root:ident, $parent:tt, # $begin:tt [] ..=) => {{
        compile_error!(
            "Found inclusive range to the end of a struct. Did you mean '..' instead of '..='?")
    }};
    // Just one field.
    (@helper $root:ident, $parent:tt, # $begin:tt []) => {{
        field_check!($parent, $begin);
        (&(*$root).$begin as *const _ as usize,
         &(*$root).$begin as *const _ as usize + $crate::mem::size_of_val(&(*$root).$begin))
    }};
    // Parsing.
    (@helper $root:ident, $parent:tt, $(# $begin:tt)+ [] $tt:tt $($rest:tt)*) => {{
        span_of!(@helper $root, $parent, $(#$begin)* #$tt [] $($rest)*)
    }};
    (@helper $root:ident, $parent:tt, [] $tt:tt $($rest:tt)*) => {{
        span_of!(@helper $root, $parent, #$tt [] $($rest)*)
    }};

    // Entry point.
    ($sty:tt, $($exp:tt)+) => ({
        unsafe {
            // Get a base pointer.
            $crate::let_base_ptr!(root, $sty);
            let base = root as usize;
            let (begin, end) = span_of!(@helper root, $sty, [] $($exp)*);
            begin-base..end-base
        }
    });
}

#[cfg(test)]
mod tests {
    use core::mem;

    #[test]
    fn span_simple() {
        #[repr(C)]
        struct Foo {
            a: u32,
            b: [u8; 2],
            c: i64,
        }

        assert_eq!(span_of!(Foo, a), 0..4);
        assert_eq!(span_of!(Foo, b), 4..6);
        assert_eq!(span_of!(Foo, c), 8..8+8);
    }

    #[test]
    #[cfg(not(miri))] // this creates unaligned references
    fn span_simple_packed() {
        #[repr(C, packed)]
        struct Foo {
            a: u32,
            b: [u8; 2],
            c: i64,
        }

        assert_eq!(span_of!(Foo, a), 0..4);
        assert_eq!(span_of!(Foo, b), 4..6);
        assert_eq!(span_of!(Foo, c), 6..6+8);
    }

    #[test]
    fn span_forms() {
        #[repr(C)]
        struct Florp {
            a: u32,
        }

        #[repr(C)]
        struct Blarg {
            x: u64,
            y: [u8; 56],
            z: Florp,
            egg: [[u8; 4]; 5],
        }

        // Love me some brute force
        assert_eq!(0..8, span_of!(Blarg, x));
        assert_eq!(64..68, span_of!(Blarg, z));
        assert_eq!(68..mem::size_of::<Blarg>(), span_of!(Blarg, egg));

        assert_eq!(8..64, span_of!(Blarg, y..z));
        assert_eq!(0..64, span_of!(Blarg, x..=y));
    }

    #[test]
    fn ig_test() {
        #[repr(C)]
        struct Member {
            foo: u32,
        }

        #[repr(C)]
        struct Test {
            x: u64,
            y: [u8; 56],
            z: Member,
            egg: [[u8; 4]; 4],
        }

        assert_eq!(span_of!(Test, ..x), 0..0);
        assert_eq!(span_of!(Test, ..=x), 0..8);
        assert_eq!(span_of!(Test, ..y), 0..8);
        assert_eq!(span_of!(Test, ..=y), 0..64);
        assert_eq!(span_of!(Test, ..z), 0..64);
        assert_eq!(span_of!(Test, ..=z), 0..68);
        assert_eq!(span_of!(Test, ..egg), 0..68);
        assert_eq!(span_of!(Test, ..=egg), 0..84);
        assert_eq!(span_of!(Test, ..), 0..mem::size_of::<Test>());
        assert_eq!(
            span_of!(Test, x..),
            offset_of!(Test, x)..mem::size_of::<Test>()
        );
        assert_eq!(
            span_of!(Test, y..),
            offset_of!(Test, y)..mem::size_of::<Test>()
        );

        assert_eq!(
            span_of!(Test, z..),
            offset_of!(Test, z)..mem::size_of::<Test>()
        );
        assert_eq!(
            span_of!(Test, egg..),
            offset_of!(Test, egg)..mem::size_of::<Test>()
        );
        assert_eq!(
            span_of!(Test, x..y),
            offset_of!(Test, x)..offset_of!(Test, y)
        );
        assert_eq!(
            span_of!(Test, x..=y),
            offset_of!(Test, x)..offset_of!(Test, y) + mem::size_of::<[u8; 56]>()
        );
    }
}
<|endoftext|>


<commit_before>pub mod framed;
pub mod server;
pub mod proto;
pub mod client;
pub mod shortcut;

pub static STANDALONE_ADDRESS: &'static str = "STANDALONE";

lazy_static! {
    pub static ref STANDALONE_ADDRESS_STRING: String = String::from(STANDALONE_ADDRESS);
}<commit_msg>server id for standalone serve<commit_after>use bifrost_hasher::hash_str;

pub mod framed;
pub mod server;
pub mod proto;
pub mod client;
pub mod shortcut;

pub static STANDALONE_ADDRESS: &'static str = "STANDALONE";

lazy_static! {
    pub static ref STANDALONE_ADDRESS_STRING: String = String::from(STANDALONE_ADDRESS);
    pub static ref STANDALONE_SERVER_ID: u64 = hash_str(&STANDALONE_ADDRESS_STRING);
}<|endoftext|>


<commit_before>//! TLC5955 PWM Led driver

use generic_array::{GenericArray, ArrayLength};
use static_ref::Static;
use core::marker::Unsize;
use semihosting::hio;
use core::fmt::Write;
use core::ops::DerefMut;
use dma2::{self, DMA, Dma, Buffer, DMAStream};

const CHANNELS_PER_TLC: u8 = 48;
const LEDS_PER_CHIP: u8 = CHANNELS_PER_TLC / 3;
const DC_DATA: u8 = 0x6A;
const DC_BITS: u32 = 7;
const MC_DATA: u8 = 5;
const MC_BITS: u32 = 3;
const BC_DATA: u8 = 110;
const BC_BITS: u32 = 7;

pub trait TLCHardwareLayer {
    fn as_gpio(&self);
    fn as_spi(&self);
    fn latch(&self, delay: u32);
    fn write_bit(&self, bit: u8);
    fn delay(&self, count: u16);
    fn read_write_byte(&self, byte: u8) -> u8;
    fn write<B>(&self, tx_buffer: &Static<Buffer<B>>,
        rx_buffer: &Static<Buffer<B>>)where B: Unsize<[u8]>;
    fn wait<B>(&self, buffer: &Static<Buffer<B>>)where B: Unsize<[u8]>;
    fn dump_buffer(&self, buffer: &[u8]);
    fn debug(&self, data: &str);
}
// struct TLC5955<T: FixedSizeArray<u8>> {
// struct TLC5955<N: ArrayLength<u8>> {

struct RGB<T> {
    red: T,
    green: T,
    blue: T,
}

impl Default for RGB<u8> {
    fn default() -> RGB<u8> {
        RGB { red: 0, blue: 0, green: 0}
    }
}

impl Default for RGB<u16> {
    fn default() -> RGB<u16> {
        RGB { red: 0, blue: 0, green: 0}
    }
}

pub struct TLC5955 {
    no_chips: u8,
    function_data: u8,
    brightness: RGB<u8>,
    max_current: RGB<u8>,
}

impl TLC5955 {
    pub fn new(no_chips: u8) -> TLC5955 {
        TLC5955 {
            no_chips: no_chips,
            function_data: 0,
            brightness: Default::default(),
            max_current: Default::default(),
        }
    }

    pub fn setup<B, I>(&mut self,
        tx_buffer: &Static<Buffer<B>>,
        rx_buffer: &Static<Buffer<B>>,
        interface: &I)
        where I: TLCHardwareLayer, B: Unsize<[u8]>
    {
        interface.debug("Sending control register data to TLC5955\n");
        self.fill_control_data(&mut *tx_buffer.borrow_mut());
        interface.dump_buffer(&*tx_buffer.borrow_mut());
        self.send_data(true, tx_buffer, rx_buffer, interface);

        clear_buffer(&mut *tx_buffer.borrow_mut());
        interface.debug("Read data after zeros.\n");
        self.send_data(true, tx_buffer, rx_buffer, interface);
        shift_buffer_by_7(&mut *rx_buffer.borrow_mut());

        self.fill_control_data(&mut *tx_buffer.borrow_mut());
        if !compare_buffers(&*tx_buffer.borrow(), &*rx_buffer.borrow()) {
            interface.debug("Ouch, read control data does not match!\n");
            interface.dump_buffer(&*rx_buffer.borrow_mut());
            loop {}
        }

        // Send the control data the second time.
        self.send_data(true, tx_buffer, rx_buffer, interface);

        clear_buffer(&mut *tx_buffer.borrow_mut());
        {
            let buffer: &mut[u8] = &mut *tx_buffer.borrow_mut();
            buffer[72] = 255;
            buffer[70] = 150;
            buffer[68] = 210;
        }

        interface.debug("Load GS Data\n");
        interface.dump_buffer(&*tx_buffer.borrow_mut());
        self.send_data(true, tx_buffer, rx_buffer, interface);
        interface.debug("Read GS Data\n");
        interface.dump_buffer(&*rx_buffer.borrow_mut());
        loop {}
    }

    pub fn send_data<B, I>(&self, is_control: bool,
        tx_buffer: &Static<Buffer<B>>,
        rx_buffer: &Static<Buffer<B>>,
        interface: &I)
        where I: TLCHardwareLayer, B: Unsize<[u8]>
    {
        /*
        interface.as_gpio();
        if is_control {
            interface.write_bit(1);
        }
        else {
            interface.write_bit(0);
        }
        interface.as_spi();
        */
        {
            let tx_buff: &mut [u8] = &mut *tx_buffer.borrow_mut();
            let rx_buff: &mut [u8] = &mut *rx_buffer.borrow_mut();

            for (txb, rxb) in tx_buff.iter_mut().zip(rx_buff.iter_mut()) {
                *rxb = interface.read_write_byte(*txb);
            }
        }

        // interface.write(tx_buffer, rx_buffer);
        // interface.wait(tx_buffer);
        // interface.wait(rx_buffer);
        interface.latch(1);
    }

    pub fn set_function_data(&mut self, dsprpt: bool, tmgrst: bool, rfresh: bool, espwm: bool, lsdvlt: bool) {
        let mut data: u8 = 0;
        data |= if dsprpt { 1 << 0 } else { 0 };
        data |= if tmgrst { 1 << 0 } else { 0 };
        data |= if rfresh { 1 << 0 } else { 0 };
        data |= if espwm { 1 << 0 } else { 0 };
        data |= if lsdvlt { 1 << 0 } else { 0 };
        self.function_data = data;
    }

    pub fn setall_dcdata<B>(self, buffer: &Static<Buffer<B>>, value: u8)
        where B: Unsize<[u8]> {
        let buffer: &mut[u8] = buffer.lock_mut();

        for index in 0..buffer.len() {
            buffer[index] = value;
        }
    }

    pub fn set_dcdata<B>(self, buffer: &Static<Buffer<B>>,
                                 led_num: u16, red: u8, green: u8, blue: u8)
        where B: Unsize<[u8]> {
        let buffer: &mut[u8] = buffer.lock_mut();
        let index = (led_num * 3) as usize;

        buffer[index] = red;
        buffer[index + 1] = green;
        buffer[index + 2] = blue;
    }

    pub fn set_brightness_current(&mut self, red: u8, green: u8, blue: u8) {
        self.brightness = RGB { red: red, blue: blue, green: green };
    }

    pub fn setall_led<B>(self, buffer: &Static<Buffer<B>>,
                                 red: u16, green: u16, blue: u16)
        where B: Unsize<[u16]> {
        let buffer: &mut[u16] = buffer.lock_mut();
        let no_leds = LEDS_PER_CHIP * self.no_chips;

        for index in 0..no_leds {
            let idx = (index * 3) as usize;
            buffer[idx + 0] = red;
            buffer[idx + 1] = green;
            buffer[idx + 2] = blue;
        }
    }

    pub fn set_led<B>(self, buffer: &Static<Buffer<B>>,
                              led_num: u16, red: u16, green: u16, blue: u16)
        where B: Unsize<[u16]> {
        let buffer: &mut[u16] = buffer.lock_mut();
        let index = (led_num * 3) as usize;

        buffer[index] = red;
        buffer[index + 1] = green;
        buffer[index + 2] = blue;
    }

    pub fn set_max_current(&mut self, red: u8, green: u8, blue: u8) {
        self.max_current = RGB { red: red, blue: blue, green: green };
    }

    fn fill_control_data(&mut self, buffer: &mut[u8]) {
        let mut pos = 0;
        for index in 0..CHANNELS_PER_TLC {
            pos = add_bits(buffer, DC_DATA as u32, DC_BITS, pos);
        }

        for index in 0..3 {
            pos = add_bits(buffer, MC_DATA as u32, MC_BITS, pos);
        }

        for index in 0..3 {
            pos = add_bits(buffer, BC_DATA as u32, BC_BITS, pos);
        }
        pos = add_bits(buffer, 0x0B as u32, 5, pos);
        pos = 760;
        add_bits(buffer, 0x196 as u32, 9, pos);
    }
}

fn add_bits(buffer: &mut[u8], mut val: u32, mut size: u32, mut pos: usize) -> usize {
    let len = buffer.len();
    while (size > 0) {
        if (val & 1) > 0 {
            buffer[len - 1 -  (pos >> 3)] |= 1 << (pos & 7);
        }
        val >>= 1;
        pos += 1;
        size -= 1;
    }
    return pos;
}

fn clear_buffer(buffer: &mut[u8]) {
    for index in 0..buffer.len() {
        buffer[index] = 0;
    }
}

fn compare_buffers(buffer1: &[u8], buffer2: &[u8]) -> bool {
    buffer1.iter().eq(buffer2)
}

fn shift_buffer_by_7(buffer: &mut [u8]) {
    let mut old: u8 = 0;
    for index in 0..buffer.len() {
        let mut val = buffer[index];
        buffer[index] = old.wrapping_shl(1) | val.wrapping_shr(7);
        old = val;
    }
}<commit_msg>Works with smaller buffer<commit_after>//! TLC5955 PWM Led driver

use generic_array::{GenericArray, ArrayLength};
use static_ref::Static;
use core::marker::Unsize;
use semihosting::hio;
use core::fmt::Write;
use core::ops::DerefMut;
use dma2::{self, DMA, Dma, Buffer, DMAStream};

const CHANNELS_PER_TLC: u8 = 48;
const LEDS_PER_CHIP: u8 = CHANNELS_PER_TLC / 3;
const DC_DATA: u8 = 0x6A;
const DC_BITS: u32 = 7;
const MC_DATA: u8 = 5;
const MC_BITS: u32 = 3;
const BC_DATA: u8 = 110;
const BC_BITS: u32 = 7;

pub trait TLCHardwareLayer {
    fn as_gpio(&self);
    fn as_spi(&self);
    fn latch(&self, delay: u32);
    fn write_bit(&self, bit: u8);
    fn delay(&self, count: u16);
    fn read_write_byte(&self, byte: u8) -> u8;
    fn write<B>(&self, tx_buffer: &Static<Buffer<B>>,
        rx_buffer: &Static<Buffer<B>>)where B: Unsize<[u8]>;
    fn wait<B>(&self, buffer: &Static<Buffer<B>>)where B: Unsize<[u8]>;
    fn dump_buffer(&self, buffer: &[u8]);
    fn debug(&self, data: &str);
}
// struct TLC5955<T: FixedSizeArray<u8>> {
// struct TLC5955<N: ArrayLength<u8>> {

struct RGB<T> {
    red: T,
    green: T,
    blue: T,
}

impl Default for RGB<u8> {
    fn default() -> RGB<u8> {
        RGB { red: 0, blue: 0, green: 0}
    }
}

impl Default for RGB<u16> {
    fn default() -> RGB<u16> {
        RGB { red: 0, blue: 0, green: 0}
    }
}

pub struct TLC5955 {
    no_chips: u8,
    function_data: u8,
    brightness: RGB<u8>,
    max_current: RGB<u8>,
}

impl TLC5955 {
    pub fn new(no_chips: u8) -> TLC5955 {
        TLC5955 {
            no_chips: no_chips,
            function_data: 0,
            brightness: Default::default(),
            max_current: Default::default(),
        }
    }

    pub fn setup<B, I>(&mut self,
        tx_buffer: &Static<Buffer<B>>,
        rx_buffer: &Static<Buffer<B>>,
        interface: &I)
        where I: TLCHardwareLayer, B: Unsize<[u8]>
    {
        interface.debug("Sending control register data to TLC5955\n");
        self.fill_control_data(&mut *tx_buffer.borrow_mut());
        interface.dump_buffer(&*tx_buffer.borrow_mut());
        self.send_data(true, tx_buffer, rx_buffer, interface);

        clear_buffer(&mut *tx_buffer.borrow_mut());
        interface.debug("Read data after zeros.\n");
        self.send_data(true, tx_buffer, rx_buffer, interface);

        self.fill_control_data(&mut *tx_buffer.borrow_mut());
        if !compare_buffers(&*tx_buffer.borrow(), &*rx_buffer.borrow()) {
            interface.debug("Ouch, read control data does not match!\n");
            interface.dump_buffer(&*rx_buffer.borrow_mut());
            loop {}
        }

        // Send the control data the second time.
        self.send_data(true, tx_buffer, rx_buffer, interface);

        clear_buffer(&mut *tx_buffer.borrow_mut());
        {
            let buffer: &mut[u8] = &mut *tx_buffer.borrow_mut();
            buffer[71] = 255;
            buffer[69] = 150;
            buffer[67] = 210;
        }

        interface.debug("Load GS Data\n");
        interface.dump_buffer(&*tx_buffer.borrow_mut());
        self.send_data(false, tx_buffer, rx_buffer, interface);
        interface.debug("Read GS Data\n");
        interface.dump_buffer(&*rx_buffer.borrow_mut());
        loop {}
    }

    pub fn send_data<B, I>(&self, is_control: bool,
        tx_buffer: &Static<Buffer<B>>,
        rx_buffer: &Static<Buffer<B>>,
        interface: &I)
        where I: TLCHardwareLayer, B: Unsize<[u8]>
    {
        interface.delay(2000);
        interface.as_gpio();
        if is_control {
            interface.write_bit(1);
        }
        else {
            interface.write_bit(0);
        }
        interface.as_spi();
        {
            let tx_buff: &mut [u8] = &mut *tx_buffer.borrow_mut();
            let rx_buff: &mut [u8] = &mut *rx_buffer.borrow_mut();

            for (txb, rxb) in tx_buff.iter_mut().zip(rx_buff.iter_mut()) {
                *rxb = interface.read_write_byte(*txb);
            }
        }

        // interface.write(tx_buffer, rx_buffer);
        // interface.wait(tx_buffer);
        // interface.wait(rx_buffer);
        interface.latch(1);
    }

    pub fn set_function_data(&mut self, dsprpt: bool, tmgrst: bool, rfresh: bool, espwm: bool, lsdvlt: bool) {
        let mut data: u8 = 0;
        data |= if dsprpt { 1 << 0 } else { 0 };
        data |= if tmgrst { 1 << 0 } else { 0 };
        data |= if rfresh { 1 << 0 } else { 0 };
        data |= if espwm { 1 << 0 } else { 0 };
        data |= if lsdvlt { 1 << 0 } else { 0 };
        self.function_data = data;
    }

    pub fn setall_dcdata<B>(self, buffer: &Static<Buffer<B>>, value: u8)
        where B: Unsize<[u8]> {
        let buffer: &mut[u8] = buffer.lock_mut();

        for index in 0..buffer.len() {
            buffer[index] = value;
        }
    }

    pub fn set_dcdata<B>(self, buffer: &Static<Buffer<B>>,
                                 led_num: u16, red: u8, green: u8, blue: u8)
        where B: Unsize<[u8]> {
        let buffer: &mut[u8] = buffer.lock_mut();
        let index = (led_num * 3) as usize;

        buffer[index] = red;
        buffer[index + 1] = green;
        buffer[index + 2] = blue;
    }

    pub fn set_brightness_current(&mut self, red: u8, green: u8, blue: u8) {
        self.brightness = RGB { red: red, blue: blue, green: green };
    }

    pub fn setall_led<B>(self, buffer: &Static<Buffer<B>>,
                                 red: u16, green: u16, blue: u16)
        where B: Unsize<[u16]> {
        let buffer: &mut[u16] = buffer.lock_mut();
        let no_leds = LEDS_PER_CHIP * self.no_chips;

        for index in 0..no_leds {
            let idx = (index * 3) as usize;
            buffer[idx + 0] = red;
            buffer[idx + 1] = green;
            buffer[idx + 2] = blue;
        }
    }

    pub fn set_led<B>(self, buffer: &Static<Buffer<B>>,
                              led_num: u16, red: u16, green: u16, blue: u16)
        where B: Unsize<[u16]> {
        let buffer: &mut[u16] = buffer.lock_mut();
        let index = (led_num * 3) as usize;

        buffer[index] = red;
        buffer[index + 1] = green;
        buffer[index + 2] = blue;
    }

    pub fn set_max_current(&mut self, red: u8, green: u8, blue: u8) {
        self.max_current = RGB { red: red, blue: blue, green: green };
    }

    fn fill_control_data(&mut self, buffer: &mut[u8]) {
        let mut pos = 0;
        for index in 0..CHANNELS_PER_TLC {
            pos = add_bits(buffer, DC_DATA as u32, DC_BITS, pos);
        }

        for index in 0..3 {
            pos = add_bits(buffer, MC_DATA as u32, MC_BITS, pos);
        }

        for index in 0..3 {
            pos = add_bits(buffer, BC_DATA as u32, BC_BITS, pos);
        }
        pos = add_bits(buffer, 0x0B as u32, 5, pos);
        pos = 760;
        add_bits(buffer, 0x96 as u32, 8, pos);
    }
}

fn add_bits(buffer: &mut[u8], mut val: u32, mut size: u32, mut pos: usize) -> usize {
    let len = buffer.len();
    while (size > 0) {
        if (val & 1) > 0 {
            buffer[len - 1 -  (pos >> 3)] |= 1 << (pos & 7);
        }
        val >>= 1;
        pos += 1;
        size -= 1;
    }
    return pos;
}

fn clear_buffer(buffer: &mut[u8]) {
    for index in 0..buffer.len() {
        buffer[index] = 0;
    }
}

fn compare_buffers(buffer1: &[u8], buffer2: &[u8]) -> bool {
    buffer1.iter().eq(buffer2)
}

fn shift_buffer_by_7(buffer: &mut [u8]) {
    let mut old: u8 = 0;
    for index in 0..buffer.len() {
        let mut val = buffer[index];
        buffer[index] = old.wrapping_shl(1) | val.wrapping_shr(7);
        old = val;
    }
}<|endoftext|>


<commit_before>mod reader;
mod writer;

pub use self::reader::StreamingParser;
pub use self::writer::Writer;<commit_msg>Add warning to xml writer<commit_after>mod reader;
mod writer;

pub use self::reader::StreamingParser;

/// WIP: Does not work correctly
pub use self::writer::Writer;<|endoftext|>


<commit_before>#![feature(test)]

extern crate bip_disk;
extern crate bip_metainfo;
extern crate futures;
extern crate test;
extern crate rand;

#[cfg(test)]
mod benches {
    use std::fs;

    use bip_disk::fs::NativeFileSystem;
    use bip_disk::fs_cache::FileHandleCache;
    use bip_disk::{DiskManagerBuilder, IDiskMessage, ODiskMessage, InfoHash, Block, BlockMetadata, FileSystem};
    use bip_metainfo::{DirectAccessor, MetainfoBuilder, MetainfoFile, PieceLength};
    use futures::stream::{self, Stream};
    use futures::sink::{self, Sink};
    use rand::{self, Rng};
    use test::Bencher;

    /// Set to true if you are playing around with anything that could affect file
    /// sizes for an existing or new benchmarks. As a precaution, if the disk manager
    /// sees an existing file with a different size but same name as one of the files
    /// in the torrent, it wont touch it and a TorrentError will be generated.
    const WIPE_DATA_DIR: bool = false;

    // TODO: Benchmark multi file torrents!!!

    /// Generates a torrent with a single file of the given length.
    ///
    /// Returns both the torrent file, as well as the (random) data of the file.
    fn generate_single_file_torrent(piece_len: usize, file_len: usize) -> (MetainfoFile, Vec<u8>) {
        let mut rng = rand::weak_rng();

        let file_bytes: Vec<u8> = rng.gen_iter().take(file_len).collect();

        let metainfo_bytes = {
            let accessor = DirectAccessor::new("benchmark_file", &file_bytes[..]);

            MetainfoBuilder::new()
                .set_piece_length(PieceLength::Custom(piece_len))
                .build_as_bytes(1, accessor, |_| ())
                .unwrap()
        };
        let metainfo = MetainfoFile::from_bytes(&metainfo_bytes)
            .unwrap();

        (metainfo, file_bytes)
    }

    /// Adds the given metainfo file to the given sender, and waits for the added notification.
    fn add_metainfo_file<S, R>(metainfo: MetainfoFile, block_send: &mut sink::Wait<S>, block_recv: &mut stream::Wait<R>)
        where S: Sink<SinkItem=IDiskMessage, SinkError=()>, R: Stream<Item=ODiskMessage, Error=()> {
        block_send.send(IDiskMessage::AddTorrent(metainfo)).unwrap();

        for res_message in block_recv {
            match res_message.unwrap() {
                ODiskMessage::TorrentAdded(_)      => { break; },
                ODiskMessage::FoundGoodPiece(_, _) => (),
                _                                  => panic!("Didn't Receive TorrentAdded")
            }
        }
    }

    /// Pushes the given bytes as piece blocks to the given sender, and blocks until all notifications
    /// of the blocks being processed have been received (does not check piece messages).
    fn process_blocks<S, R>(piece_length: usize, block_length: usize, hash: InfoHash, bytes: &[u8],
                            block_send: &mut sink::Wait<S>, block_recv: &mut stream::Wait<R>)
        where S: Sink<SinkItem=IDiskMessage, SinkError=()>, R: Stream<Item=ODiskMessage, Error=()> {
        let mut blocks_sent = 0;

        for (piece_index, piece) in bytes.chunks(piece_length).enumerate() {
            for (block_index, block) in piece.chunks(block_length).enumerate() {
                let block_offset = block_index * block_length;
                let block = Block::new(BlockMetadata::new(hash, piece_index as u64, block_offset as u64, block.len()), block.to_vec());

                block_send.send(IDiskMessage::ProcessBlock(block)).unwrap();
                blocks_sent += 1;
            }
        }

        for res_message in block_recv {
            match res_message.unwrap() {
                ODiskMessage::BlockProcessed(_)    => { blocks_sent -= 1 },
                ODiskMessage::FoundGoodPiece(_, _) => (),
                ODiskMessage::FoundBadPiece(_, _)  => (),
                _                                  => panic!("Unexpected Message Received In process_blocks")
            }

            if blocks_sent == 0 {
                break;
            }
        }
    }

    /// Benchmarking method to setup a torrent file with the given attributes, and benchmark the block processing code.
    fn bench_process_file_with_fs<F>(b: &mut Bencher, piece_length: usize, block_length: usize, file_length: usize, fs: F)
        where F: FileSystem + Send + Sync + 'static {
        let (metainfo, bytes) = generate_single_file_torrent(piece_length, file_length);
        let info_hash = metainfo.info_hash();

        let disk_manager = DiskManagerBuilder::new()
            .with_pending_buffer_size(1000000)
            .with_completed_buffer_size(1000000)
            .build(fs);

        let (d_send, d_recv) = disk_manager.split();

        let mut block_d_send = d_send.wait();
        let mut block_d_recv = d_recv.wait();

        add_metainfo_file(metainfo, &mut block_d_send, &mut block_d_recv);

        b.iter(|| process_blocks(piece_length, block_length, info_hash, &bytes[..], &mut block_d_send, &mut block_d_recv))
    }

    #[bench]
    fn bench_native_fs_1_mb_pieces_128_kb_blocks(b: &mut Bencher) {
        let piece_length = 1 * 1024 * 1024;
        let block_length = 128 * 1024;
        let file_length = 2 * 1024 * 1024;
        let data_directory = "target/bench_data/bench_native_fs_1_mb_pieces_128_kb_blocks";

        if WIPE_DATA_DIR {
            let _ = fs::remove_dir_all(data_directory);
        }
        let filesystem = NativeFileSystem::with_directory(data_directory);

        bench_process_file_with_fs(b, piece_length, block_length, file_length, filesystem);
    }

    #[bench]
    fn bench_native_fs_1_mb_pieces_16_kb_blocks(b: &mut Bencher) {
        let piece_length = 1 * 1024 * 1024;
        let block_length = 16 * 1024;
        let file_length = 2 * 1024 * 1024;
        let data_directory = "target/bench_data/bench_native_fs_1_mb_pieces_16_kb_blocks";

        if WIPE_DATA_DIR {
            let _ = fs::remove_dir_all(data_directory);
        }
        let filesystem = NativeFileSystem::with_directory(data_directory);

        bench_process_file_with_fs(b, piece_length, block_length, file_length, filesystem);
    }

    #[bench]
    fn bench_native_fs_1_mb_pieces_2_kb_blocks(b: &mut Bencher) {
        let piece_length = 1 * 1024 * 1024;
        let block_length = 2 * 1024;
        let file_length = 2 * 1024 * 1024;
        let data_directory = "target/bench_data/bench_native_fs_1_mb_pieces_2_kb_blocks";

        if WIPE_DATA_DIR {
            let _ = fs::remove_dir_all(data_directory);
        }
        let filesystem = NativeFileSystem::with_directory(data_directory);

        bench_process_file_with_fs(b, piece_length, block_length, file_length, filesystem);
    }

    #[bench]
    fn bench_file_handle_cache_fs_1_mb_pieces_128_kb_blocks(b: &mut Bencher) {
        let piece_length = 1 * 1024 * 1024;
        let block_length = 128 * 1024;
        let file_length = 2 * 1024 * 1024;
        let data_directory = "target/bench_data/bench_native_fs_1_mb_pieces_128_kb_blocks";

        if WIPE_DATA_DIR {
            let _ = fs::remove_dir_all(data_directory);
        }
        let filesystem = FileHandleCache::new(NativeFileSystem::with_directory(data_directory), 1);

        bench_process_file_with_fs(b, piece_length, block_length, file_length, filesystem);
    }

    #[bench]
    fn bench_file_handle_cache_fs_1_mb_pieces_16_kb_blocks(b: &mut Bencher) {
        let piece_length = 1 * 1024 * 1024;
        let block_length = 16 * 1024;
        let file_length = 2 * 1024 * 1024;
        let data_directory = "target/bench_data/bench_native_fs_1_mb_pieces_16_kb_blocks";

        if WIPE_DATA_DIR {
            let _ = fs::remove_dir_all(data_directory);
        }
        let filesystem = FileHandleCache::new(NativeFileSystem::with_directory(data_directory), 1);

        bench_process_file_with_fs(b, piece_length, block_length, file_length, filesystem);
    }

    #[bench]
    fn bench_file_handle_cache_fs_1_mb_pieces_2_kb_blocks(b: &mut Bencher) {
        let piece_length = 1 * 1024 * 1024;
        let block_length = 2 * 1024;
        let file_length = 2 * 1024 * 1024;
        let data_directory = "target/bench_data/bench_native_fs_1_mb_pieces_2_kb_blocks";

        if WIPE_DATA_DIR {
            let _ = fs::remove_dir_all(data_directory);
        }
        let filesystem = FileHandleCache::new(NativeFileSystem::with_directory(data_directory), 1);

        bench_process_file_with_fs(b, piece_length, block_length, file_length, filesystem);
    }
}<commit_msg>Update bip_disk Benches For New API<commit_after>#![feature(test)]

extern crate bip_disk;
extern crate bip_metainfo;
extern crate futures;
extern crate test;
extern crate rand;

#[cfg(test)]
mod benches {
    use std::fs;

    use bip_disk::fs::NativeFileSystem;
    use bip_disk::fs_cache::FileHandleCache;
    use bip_disk::{DiskManagerBuilder, IDiskMessage, ODiskMessage, InfoHash, Block, BlockMetadata, FileSystem};
    use bip_metainfo::{DirectAccessor, MetainfoBuilder, MetainfoFile, PieceLength};
    use futures::stream::{self, Stream};
    use futures::sink::{self, Sink};
    use rand::{self, Rng};
    use test::Bencher;

    /// Set to true if you are playing around with anything that could affect file
    /// sizes for an existing or new benchmarks. As a precaution, if the disk manager
    /// sees an existing file with a different size but same name as one of the files
    /// in the torrent, it wont touch it and a TorrentError will be generated.
    const WIPE_DATA_DIR: bool = false;

    // TODO: Benchmark multi file torrents!!!

    /// Generates a torrent with a single file of the given length.
    ///
    /// Returns both the torrent file, as well as the (random) data of the file.
    fn generate_single_file_torrent(piece_len: usize, file_len: usize) -> (MetainfoFile, Vec<u8>) {
        let mut rng = rand::weak_rng();

        let file_bytes: Vec<u8> = rng.gen_iter().take(file_len).collect();

        let metainfo_bytes = {
            let accessor = DirectAccessor::new("benchmark_file", &file_bytes[..]);

            MetainfoBuilder::new()
                .set_piece_length(PieceLength::Custom(piece_len))
                .build_as_bytes(1, accessor, |_| ())
                .unwrap()
        };
        let metainfo = MetainfoFile::from_bytes(&metainfo_bytes)
            .unwrap();

        (metainfo, file_bytes)
    }

    /// Adds the given metainfo file to the given sender, and waits for the added notification.
    fn add_metainfo_file<S, R>(metainfo: MetainfoFile, block_send: &mut sink::Wait<S>, block_recv: &mut stream::Wait<R>)
        where S: Sink<SinkItem=IDiskMessage, SinkError=()>, R: Stream<Item=ODiskMessage, Error=()> {
        block_send.send(IDiskMessage::AddTorrent(metainfo)).unwrap();

        for res_message in block_recv {
            match res_message.unwrap() {
                ODiskMessage::TorrentAdded(_)      => { break; },
                ODiskMessage::FoundGoodPiece(_, _) => (),
                _                                  => panic!("Didn't Receive TorrentAdded")
            }
        }
    }

    /// Pushes the given bytes as piece blocks to the given sender, and blocks until all notifications
    /// of the blocks being processed have been received (does not check piece messages).
    fn process_blocks<S, R>(piece_length: usize, block_length: usize, hash: InfoHash, bytes: &[u8],
                            block_send: &mut sink::Wait<S>, block_recv: &mut stream::Wait<R>)
        where S: Sink<SinkItem=IDiskMessage, SinkError=()>, R: Stream<Item=ODiskMessage, Error=()> {
        let mut blocks_sent = 0;

        for (piece_index, piece) in bytes.chunks(piece_length).enumerate() {
            for (block_index, block) in piece.chunks(block_length).enumerate() {
                let block_offset = block_index * block_length;
                let block = Block::new(BlockMetadata::new(hash, piece_index as u64, block_offset as u64, block.len()), block.to_vec());

                block_send.send(IDiskMessage::ProcessBlock(block)).unwrap();
                blocks_sent += 1;
            }
        }

        for res_message in block_recv {
            match res_message.unwrap() {
                ODiskMessage::BlockProcessed(_)    => { blocks_sent -= 1 },
                ODiskMessage::FoundGoodPiece(_, _) => (),
                ODiskMessage::FoundBadPiece(_, _)  => (),
                _                                  => panic!("Unexpected Message Received In process_blocks")
            }

            if blocks_sent == 0 {
                break;
            }
        }
    }

    /// Benchmarking method to setup a torrent file with the given attributes, and benchmark the block processing code.
    fn bench_process_file_with_fs<F>(b: &mut Bencher, piece_length: usize, block_length: usize, file_length: usize, fs: F)
        where F: FileSystem + Send + Sync + 'static {
        let (metainfo, bytes) = generate_single_file_torrent(piece_length, file_length);
        let info_hash = metainfo.info_hash();

        let disk_manager = DiskManagerBuilder::new()
            .with_sink_buffer_capacity(1000000)
            .with_stream_buffer_capacity(1000000)
            .build(fs);

        let (d_send, d_recv) = disk_manager.split();

        let mut block_d_send = d_send.wait();
        let mut block_d_recv = d_recv.wait();

        add_metainfo_file(metainfo, &mut block_d_send, &mut block_d_recv);

        b.iter(|| process_blocks(piece_length, block_length, info_hash, &bytes[..], &mut block_d_send, &mut block_d_recv))
    }

    #[bench]
    fn bench_native_fs_1_mb_pieces_128_kb_blocks(b: &mut Bencher) {
        let piece_length = 1 * 1024 * 1024;
        let block_length = 128 * 1024;
        let file_length = 2 * 1024 * 1024;
        let data_directory = "target/bench_data/bench_native_fs_1_mb_pieces_128_kb_blocks";

        if WIPE_DATA_DIR {
            let _ = fs::remove_dir_all(data_directory);
        }
        let filesystem = NativeFileSystem::with_directory(data_directory);

        bench_process_file_with_fs(b, piece_length, block_length, file_length, filesystem);
    }

    #[bench]
    fn bench_native_fs_1_mb_pieces_16_kb_blocks(b: &mut Bencher) {
        let piece_length = 1 * 1024 * 1024;
        let block_length = 16 * 1024;
        let file_length = 2 * 1024 * 1024;
        let data_directory = "target/bench_data/bench_native_fs_1_mb_pieces_16_kb_blocks";

        if WIPE_DATA_DIR {
            let _ = fs::remove_dir_all(data_directory);
        }
        let filesystem = NativeFileSystem::with_directory(data_directory);

        bench_process_file_with_fs(b, piece_length, block_length, file_length, filesystem);
    }

    #[bench]
    fn bench_native_fs_1_mb_pieces_2_kb_blocks(b: &mut Bencher) {
        let piece_length = 1 * 1024 * 1024;
        let block_length = 2 * 1024;
        let file_length = 2 * 1024 * 1024;
        let data_directory = "target/bench_data/bench_native_fs_1_mb_pieces_2_kb_blocks";

        if WIPE_DATA_DIR {
            let _ = fs::remove_dir_all(data_directory);
        }
        let filesystem = NativeFileSystem::with_directory(data_directory);

        bench_process_file_with_fs(b, piece_length, block_length, file_length, filesystem);
    }

    #[bench]
    fn bench_file_handle_cache_fs_1_mb_pieces_128_kb_blocks(b: &mut Bencher) {
        let piece_length = 1 * 1024 * 1024;
        let block_length = 128 * 1024;
        let file_length = 2 * 1024 * 1024;
        let data_directory = "target/bench_data/bench_native_fs_1_mb_pieces_128_kb_blocks";

        if WIPE_DATA_DIR {
            let _ = fs::remove_dir_all(data_directory);
        }
        let filesystem = FileHandleCache::new(NativeFileSystem::with_directory(data_directory), 1);

        bench_process_file_with_fs(b, piece_length, block_length, file_length, filesystem);
    }

    #[bench]
    fn bench_file_handle_cache_fs_1_mb_pieces_16_kb_blocks(b: &mut Bencher) {
        let piece_length = 1 * 1024 * 1024;
        let block_length = 16 * 1024;
        let file_length = 2 * 1024 * 1024;
        let data_directory = "target/bench_data/bench_native_fs_1_mb_pieces_16_kb_blocks";

        if WIPE_DATA_DIR {
            let _ = fs::remove_dir_all(data_directory);
        }
        let filesystem = FileHandleCache::new(NativeFileSystem::with_directory(data_directory), 1);

        bench_process_file_with_fs(b, piece_length, block_length, file_length, filesystem);
    }

    #[bench]
    fn bench_file_handle_cache_fs_1_mb_pieces_2_kb_blocks(b: &mut Bencher) {
        let piece_length = 1 * 1024 * 1024;
        let block_length = 2 * 1024;
        let file_length = 2 * 1024 * 1024;
        let data_directory = "target/bench_data/bench_native_fs_1_mb_pieces_2_kb_blocks";

        if WIPE_DATA_DIR {
            let _ = fs::remove_dir_all(data_directory);
        }
        let filesystem = FileHandleCache::new(NativeFileSystem::with_directory(data_directory), 1);

        bench_process_file_with_fs(b, piece_length, block_length, file_length, filesystem);
    }
}<|endoftext|>


<commit_before>#![feature(core)]
#![feature(rand)]
/**
 * Simulate Bell's quantum entanglement experiments
 */

use std::rand::random;
use std::fmt;

use Direction::{SpinUp, SpinDown, SpinSuper};
use Plan::{Trivial, OddBall};

#[derive(Copy, Debug, PartialEq)]
enum Direction {
    SpinUp,
    SpinDown,
    SpinSuper,
}

impl fmt::Display for Direction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let r = match self {
            &SpinUp => "SpinUp",
            &SpinDown => "SpinDown",
            &SpinSuper => "SpinSuper"
        };
        write!(f, "{}", r)
    }
}

impl fmt::Display for Detector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Detector::{D12, D3, D9};
        let r = match self {
            &D12 => "12 oclock",
            &D3 => "3 oclock",
            &D9 => "9 oclock"
        };
        write!(f, "{}", r)
    }
}

struct Pair<T> {
    lhs: T,
    rhs: T
}

struct Particle {
    spin: Direction
}

enum Plan {
    Trivial, // up-up-up -> down-down-down
    OddBall  // up-down-up -> down-up-down
}

#[derive(Debug, PartialEq)]
enum Detector {
    D12, // 12 o'clock
    D3, // 3 o'clock
    D9, // 9 o' clock
}

impl Particle {
    fn new_pair () -> Pair<Particle> {
        let d1 = SpinSuper;
        let d2 = SpinSuper;
        let p1 = Particle{spin: d1};
        let p2 = Particle{spin: d2};

        return Pair{lhs: p1, rhs: p2};
    }

    pub fn measure (&mut self, detector: &Detector) {
        self.spin = match detector {
            &Detector::D12 => SpinUp,
            &Detector::D3 => match rand32() {
                0.0  ... 0.25 => SpinDown,
                0.25 ... 1.00 => SpinUp,
                _ => unreachable!()
            },
            &Detector::D9 => match rand32() {
                0.0  ... 0.25 => SpinDown,
                0.25 ... 1.00 => SpinUp,
                _ => unreachable!()
            },
        };
    }

    // NOTE on spooky and premeditated only if measured in the same
    // direction must the spins be opposite

    // measure with with a message
    pub fn spooky (&mut self, friend: &mut Particle) -> Pair<Direction> {

        let detector1 = Detector::D12;
        let detector2 = Particle::get_detector_direction();

        self.measure (&detector1);

        if detector1 == detector2 { // 1/3
            friend.spin = match self.spin {
                SpinUp => SpinDown,
                SpinDown => SpinUp,
                _ => unreachable!()
            };
        } else { // 2/3
            friend.measure(&detector2);
        }

        return Pair{lhs: self.spin, rhs: friend.spin};
    }

    fn get_detector_direction () -> Detector {

        let detector = match rand32() {
            0.0       ... 0.3333333 => Detector::D12,
            0.3333333 ... 0.6666666 => Detector::D3,
            0.6666666 ... 1.00 => Detector::D9,
            _ => unreachable!()
        };

        return detector;
    }

    pub fn hidden_information (&mut self, friend: &mut Particle, plan: Plan) -> Pair<Direction> {

        let detector = Particle::get_detector_direction();
        let spin = match plan {
            Trivial => SpinUp,
            OddBall => match detector {
                Detector::D3 => SpinDown,
                _ => SpinUp
            }
        };
        friend.spin = spin;

        let detector = Particle::get_detector_direction();
        let spin = match plan {
            Trivial => SpinDown,
            OddBall => match detector {
                Detector::D3 => SpinUp,
                _ => SpinDown
            }
        };
        self.spin = spin;

        return Pair{lhs: self.spin, rhs: friend.spin};
    }
}

fn rand32 () -> f32 {
    return random::<f32>();
}

/**
 * run spooky for trials number of trials
 */
fn run_spooky (trials: f64) {
    let mut num_different: f64 = 0f64;

    let mut lhs;
    let mut rhs;

    for _ in 0 .. trials as usize {
        let particles = Particle::new_pair();
        lhs = particles.lhs;
        rhs = particles.rhs;

        lhs.spooky(&mut rhs);

        if lhs.spin != rhs.spin {
            num_different += 1.0;
        }
    }

    println!("Percent different for spooky {}%", 100f64 * (num_different) / trials as f64);
    println!("      Should be about 1/2 or 50%");
}

/**
 * Run test for hidden information, set the plan_probability to choose
 * OddBall vs Trivial
 */
fn run_hidden(trials: f64, plan_probability: f32) {

    let mut num_different = 0f64;
    let mut lhs;
    let mut rhs;

    for _ in 0 .. trials as usize {
        let particles = Particle::new_pair();
        lhs = particles.lhs;
        rhs = particles.rhs;

        if rand32() < plan_probability {
            lhs.hidden_information(&mut rhs, OddBall);
        } else {
            lhs.hidden_information(&mut rhs, Trivial);
        }

        //println!("lhs.spin {}, rhs.spin {}", lhs.spin, rhs.spin);
        if lhs.spin != rhs.spin {
            num_different += 1.0;
        }
    }

    println!("Percent different for hidden info {}%", 100f64 * (num_different) / trials as f64);
    println!("  Should be greater than 5/9th or {}%", 100.0 * 5.0/9.0);
    println!("With OddBall choosen {}% of the time and Trivial {}% of the time",
             100.0 * plan_probability,
             100.0 * (1.0 - plan_probability));

}

// hidden_information should give +55.6% difference, spooky would give 50%
fn main () {

    let trials: f64 = 1000000f64;

    run_spooky(trials);
    run_hidden(trials, 0.5);
    run_hidden(trials, 1.0);
    run_hidden(trials, 0.0);
}
<commit_msg>add a benchmark of sorts<commit_after>#![feature(core)]
#![feature(rand)]
/**
 * Simulate Bell's quantum entanglement experiments
 */

extern crate test;

use std::rand::random;
use std::fmt;

use Direction::{SpinUp, SpinDown, SpinSuper};
use Plan::{Trivial, OddBall};

#[derive(Copy, Debug, PartialEq)]
enum Direction {
    SpinUp,
    SpinDown,
    SpinSuper,
}

impl fmt::Display for Direction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let r = match self {
            &SpinUp => "SpinUp",
            &SpinDown => "SpinDown",
            &SpinSuper => "SpinSuper"
        };
        write!(f, "{}", r)
    }
}

impl fmt::Display for Detector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Detector::{D12, D3, D9};
        let r = match self {
            &D12 => "12 oclock",
            &D3 => "3 oclock",
            &D9 => "9 oclock"
        };
        write!(f, "{}", r)
    }
}

struct Pair<T> {
    lhs: T,
    rhs: T
}

struct Particle {
    spin: Direction
}

enum Plan {
    Trivial, // up-up-up -> down-down-down
    OddBall  // up-down-up -> down-up-down
}

#[derive(Debug, PartialEq)]
enum Detector {
    D12, // 12 o'clock
    D3, // 3 o'clock
    D9, // 9 o' clock
}

impl Particle {
    fn new_pair () -> Pair<Particle> {
        let d1 = SpinSuper;
        let d2 = SpinSuper;
        let p1 = Particle{spin: d1};
        let p2 = Particle{spin: d2};

        return Pair{lhs: p1, rhs: p2};
    }

    pub fn measure (&mut self, detector: &Detector) {
        self.spin = match detector {
            &Detector::D12 => SpinUp,
            &Detector::D3 => match rand32() {
                0.0  ... 0.25 => SpinDown,
                0.25 ... 1.00 => SpinUp,
                _ => unreachable!()
            },
            &Detector::D9 => match rand32() {
                0.0  ... 0.25 => SpinDown,
                0.25 ... 1.00 => SpinUp,
                _ => unreachable!()
            },
        };
    }

    // NOTE on spooky and premeditated only if measured in the same
    // direction must the spins be opposite

    // measure with with a message
    pub fn spooky (&mut self, friend: &mut Particle) -> Pair<Direction> {

        let detector1 = Detector::D12;
        let detector2 = Particle::get_detector_direction();

        self.measure (&detector1);

        if detector1 == detector2 { // 1/3
            friend.spin = match self.spin {
                SpinUp => SpinDown,
                SpinDown => SpinUp,
                _ => unreachable!()
            };
        } else { // 2/3
            friend.measure(&detector2);
        }

        return Pair{lhs: self.spin, rhs: friend.spin};
    }

    fn get_detector_direction () -> Detector {

        let detector = match rand32() {
            0.0       ... 0.3333333 => Detector::D12,
            0.3333333 ... 0.6666666 => Detector::D3,
            0.6666666 ... 1.00 => Detector::D9,
            _ => unreachable!()
        };

        return detector;
    }

    pub fn hidden_information (&mut self, friend: &mut Particle, plan: Plan) -> Pair<Direction> {

        let detector = Particle::get_detector_direction();
        let spin = match plan {
            Trivial => SpinUp,
            OddBall => match detector {
                Detector::D3 => SpinDown,
                _ => SpinUp
            }
        };
        friend.spin = spin;

        let detector = Particle::get_detector_direction();
        let spin = match plan {
            Trivial => SpinDown,
            OddBall => match detector {
                Detector::D3 => SpinUp,
                _ => SpinDown
            }
        };
        self.spin = spin;

        return Pair{lhs: self.spin, rhs: friend.spin};
    }
}

fn rand32 () -> f32 {
    return random::<f32>();
}

/**
 * run spooky for trials number of trials
 */
fn run_spooky (trials: f64) {
    let mut num_different: f64 = 0f64;

    let mut lhs;
    let mut rhs;

    for _ in 0 .. trials as usize {
        let particles = Particle::new_pair();
        lhs = particles.lhs;
        rhs = particles.rhs;

        lhs.spooky(&mut rhs);

        if lhs.spin != rhs.spin {
            num_different += 1.0;
        }
    }

    println!("Percent different for spooky {}%", 100f64 * (num_different) / trials as f64);
    println!("      Should be about 1/2 or 50%");
}

/**
 * Run test for hidden information, set the plan_probability to choose
 * OddBall vs Trivial
 */
fn run_hidden(trials: f64, plan_probability: f32) {

    let mut num_different = 0f64;
    let mut lhs;
    let mut rhs;

    for _ in 0 .. trials as usize {
        let particles = Particle::new_pair();
        lhs = particles.lhs;
        rhs = particles.rhs;

        if rand32() < plan_probability {
            lhs.hidden_information(&mut rhs, OddBall);
        } else {
            lhs.hidden_information(&mut rhs, Trivial);
        }

        //println!("lhs.spin {}, rhs.spin {}", lhs.spin, rhs.spin);
        if lhs.spin != rhs.spin {
            num_different += 1.0;
        }
    }

    println!("Percent different for hidden info {}%", 100f64 * (num_different) / trials as f64);
    println!("  Should be greater than 5/9th or {}%", 100.0 * 5.0/9.0);
    println!("With OddBall choosen {}% of the time and Trivial {}% of the time",
             100.0 * plan_probability,
             100.0 * (1.0 - plan_probability));

}

// hidden_information should give +55.6% difference, spooky would give 50%
fn main () {

    let trials: f64 = 1000000f64;

    run_spooky(trials);
    run_hidden(trials, 0.5);
    run_hidden(trials, 1.0);
    run_hidden(trials, 0.0);
}

#[bench]
fn run_linear (b: &mut test::Bencher) {

    b.iter(|| {

        let trials: f64 = 10f64;

        run_spooky(trials);
        run_hidden(trials, 0.5);
        run_hidden(trials, 1.0);
        run_hidden(trials, 0.0);

        //range(0, BENCH_SIZE).map(fibonacci).collect::<Vec<u32>>()
    })

}
<|endoftext|>


<commit_before>//! Hardware Abstraction Layer
//!
//! The goal of this module is to abstract the machine/architecture so that
//! the API is the same no matter the underlying hardware.
//!
//! For now only Xen (x86/x86_64) is supported. A goal for the future would
//! be to be compatible with the virtio standard as well and support Xen arm

pub use self::hw_imp::*;
pub use self::arch_imp::*;

pub mod xen;

mod hw_imp {
    use super::xen;

    #[inline]
    pub fn local_irq_disable() {
        xen::disable_upcalls();
    }

    #[inline]
    pub fn local_irq_enable() {
        xen::enable_upcalls();
    }

    #[inline]
    pub fn local_irq_save() -> usize {
        xen::disable_upcalls() as usize
    }

    #[inline]
    pub fn local_irq_restore(state: usize) {
        xen::set_upcalls_state(state as u8);
    }
}

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[path="arch/x86.rs"]
mod arch;

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod arch_imp {
    pub mod intrinsics {
        pub use core::intrinsics::atomic_xchg;

        pub use hal::arch::atomic_set_bit;
        pub use hal::arch::atomic_clear_bit;

        pub use hal::arch::first_bit;

        pub use hal::arch::wmb;
    }
}
<commit_msg>doc: Add doc for uni::hal::local_irq_*<commit_after>//! Hardware Abstraction Layer
//!
//! The goal of this module is to abstract the machine/architecture so that
//! the API is the same no matter the underlying hardware.
//!
//! For now only Xen (x86/x86_64) is supported. A goal for the future would
//! be to be compatible with the virtio standard as well and support Xen arm

pub use self::hw_imp::*;
pub use self::arch_imp::*;

pub mod xen;

mod hw_imp {
    use super::xen;

    #[inline]
    /// Disable local interrupt delivery
    pub fn local_irq_disable() {
        xen::disable_upcalls();
    }

    #[inline]
    /// Enable local interrupt delivery
    pub fn local_irq_enable() {
        xen::enable_upcalls();
    }

    #[inline]
    /// Disable local interrupt delivery and return the previous state of
    /// interrupt delivery
    pub fn local_irq_save() -> usize {
        xen::disable_upcalls() as usize
    }

    #[inline]
    /// Restore a local interrupt delivery state
    pub fn local_irq_restore(state: usize) {
        xen::set_upcalls_state(state as u8);
    }
}

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[path="arch/x86.rs"]
mod arch;

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod arch_imp {
    pub mod intrinsics {
        pub use core::intrinsics::atomic_xchg;

        pub use hal::arch::atomic_set_bit;
        pub use hal::arch::atomic_clear_bit;

        pub use hal::arch::first_bit;

        pub use hal::arch::wmb;
    }
}
<|endoftext|>


<commit_before>// High-level bindings to Cairo.

use core::libc::*;
use cairo::{CAIRO_STATUS_SUCCESS, cairo_format_t, cairo_status_t, cairo_surface_t, cairo_t};
use cairo::bindgen::{cairo_create, cairo_fill, cairo_image_surface_create};
use cairo::bindgen::{cairo_image_surface_get_data, cairo_image_surface_get_format};
use cairo::bindgen::{cairo_image_surface_get_height, cairo_image_surface_get_stride};
use cairo::bindgen::{cairo_image_surface_get_width, cairo_rectangle, cairo_set_line_width};
use cairo::bindgen::{cairo_set_source_rgb, cairo_stroke, cairo_surface_destroy};
use cairo::bindgen::{cairo_surface_reference};
use core::cast::{reinterpret_cast, transmute};

// FIXME: We should have a hierarchy of surfaces, but this needs to wait on case classes.
pub struct ImageSurface {
    cairo_surface: *cairo_surface_t,
}

impl Drop for ImageSurface {
    fn finalize(&self) {
        unsafe {
            cairo_surface_destroy(self.cairo_surface);
        }
    }
}

pub impl ImageSurface {
    fn width(&self)  -> c_int {
        unsafe {
            cairo_image_surface_get_width(self.cairo_surface)
        }
    }
    fn height(&self) -> c_int {
        unsafe {
            cairo_image_surface_get_height(self.cairo_surface)
        }
    }
    fn stride(&self) -> c_int {
        unsafe {
            cairo_image_surface_get_stride(self.cairo_surface)
        }
    }
    fn format(&self) -> c_int    {
        unsafe {
            cairo_image_surface_get_format(self.cairo_surface)
        }
    }

    fn data(&self) -> &'self [u8] {
        unsafe {
            let buffer = cairo_image_surface_get_data(self.cairo_surface);
            let len = (self.stride() * self.height()) as uint;
            return vec::raw::buf_as_slice(buffer, len, |x| transmute(x));
        }
    }
}

// Should be private.
fn image_surface_from_cairo_surface(cairo_surface: *cairo_surface_t) -> ImageSurface {
    fail_unless!(!cairo_surface.is_null());
    ImageSurface { cairo_surface: cairo_surface }
}

pub fn ImageSurface(format: cairo_format_t, width: c_int, height: c_int) -> ImageSurface {
    unsafe {
        let cairo_surface = cairo_image_surface_create(format, width, height);
        if cairo_surface.is_null() {
            fail!(~"couldn't create Cairo image surface");
        }
        return image_surface_from_cairo_surface(cairo_surface);
    }
}

impl ImageSurface {
    /*fn write_to_png_stream(buffer: &BytesWriter) -> Result<(),cairo_status_t> unsafe {
        extern fn write_fn(closure: *c_void, data: *c_uchar, len: c_uint)
                        -> cairo_status_t unsafe {
            let writer: *BytesWriter = reinterpret_cast(&closure);
            do buf_as_slice(data, len as uint) |bytes| {
                (*writer).write(bytes);
            }
            return CAIRO_STATUS_SUCCESS;
        }

        let buffer_ptr = reinterpret_cast(&buffer);
        let status = cairo_surface_write_to_png_stream(self.cairo_surface, write_fn, buffer_ptr);
        if status != CAIRO_STATUS_SUCCESS {
            return Err(status);
        }

        return Ok(());
    }*/

    fn clone(&self) -> ImageSurface {
        unsafe {
            cairo_surface_reference(self.cairo_surface);
            return image_surface_from_cairo_surface(self.cairo_surface);
        }
    }
}

struct Context {
    cairo_context: *cairo_t,
}

impl Context {
    fn set_line_width(&self, width: c_double) {
        unsafe {
            cairo_set_line_width(self.cairo_context, width);
        }
    }

    fn set_source_rgb(&self, r: c_double, g: c_double, b: c_double) {
        unsafe {
            cairo_set_source_rgb(self.cairo_context, r, g, b);
        }
    }

    fn rectangle(&self, x: c_double, y: c_double, width: c_double, height: c_double) {
        unsafe {
            cairo_rectangle(self.cairo_context, x, y, width, height);
        }
    }

    fn stroke(&self) {
        unsafe {
            cairo_stroke(self.cairo_context);
        }
    }

    fn fill(&self) {
        unsafe {
            cairo_fill(self.cairo_context);
        }
    }
}

fn make_context(surface: &ImageSurface) -> Context {
    unsafe {
        Context {
            cairo_context: cairo_create(surface.cairo_surface)
        }
    }
}
<commit_msg>Change fail_unless! to assert! and remove unused imports.<commit_after>// High-level bindings to Cairo.

use core::libc::*;
use cairo::{cairo_format_t, cairo_surface_t, cairo_t};
use cairo::bindgen::{cairo_create, cairo_fill, cairo_image_surface_create};
use cairo::bindgen::{cairo_image_surface_get_data, cairo_image_surface_get_format};
use cairo::bindgen::{cairo_image_surface_get_height, cairo_image_surface_get_stride};
use cairo::bindgen::{cairo_image_surface_get_width, cairo_rectangle, cairo_set_line_width};
use cairo::bindgen::{cairo_set_source_rgb, cairo_stroke, cairo_surface_destroy};
use cairo::bindgen::{cairo_surface_reference};
use core::cast::transmute;

// FIXME: We should have a hierarchy of surfaces, but this needs to wait on case classes.
pub struct ImageSurface {
    cairo_surface: *cairo_surface_t,
}

impl Drop for ImageSurface {
    fn finalize(&self) {
        unsafe {
            cairo_surface_destroy(self.cairo_surface);
        }
    }
}

pub impl ImageSurface {
    fn width(&self)  -> c_int {
        unsafe {
            cairo_image_surface_get_width(self.cairo_surface)
        }
    }
    fn height(&self) -> c_int {
        unsafe {
            cairo_image_surface_get_height(self.cairo_surface)
        }
    }
    fn stride(&self) -> c_int {
        unsafe {
            cairo_image_surface_get_stride(self.cairo_surface)
        }
    }
    fn format(&self) -> c_int    {
        unsafe {
            cairo_image_surface_get_format(self.cairo_surface)
        }
    }

    fn data(&self) -> &'self [u8] {
        unsafe {
            let buffer = cairo_image_surface_get_data(self.cairo_surface);
            let len = (self.stride() * self.height()) as uint;
            return vec::raw::buf_as_slice(buffer, len, |x| transmute(x));
        }
    }
}

// Should be private.
fn image_surface_from_cairo_surface(cairo_surface: *cairo_surface_t) -> ImageSurface {
    assert!(!cairo_surface.is_null());
    ImageSurface { cairo_surface: cairo_surface }
}

pub fn ImageSurface(format: cairo_format_t, width: c_int, height: c_int) -> ImageSurface {
    unsafe {
        let cairo_surface = cairo_image_surface_create(format, width, height);
        if cairo_surface.is_null() {
            fail!(~"couldn't create Cairo image surface");
        }
        return image_surface_from_cairo_surface(cairo_surface);
    }
}

impl ImageSurface {
    /*fn write_to_png_stream(buffer: &BytesWriter) -> Result<(),cairo_status_t> unsafe {
        extern fn write_fn(closure: *c_void, data: *c_uchar, len: c_uint)
                        -> cairo_status_t unsafe {
            let writer: *BytesWriter = reinterpret_cast(&closure);
            do buf_as_slice(data, len as uint) |bytes| {
                (*writer).write(bytes);
            }
            return CAIRO_STATUS_SUCCESS;
        }

        let buffer_ptr = reinterpret_cast(&buffer);
        let status = cairo_surface_write_to_png_stream(self.cairo_surface, write_fn, buffer_ptr);
        if status != CAIRO_STATUS_SUCCESS {
            return Err(status);
        }

        return Ok(());
    }*/

    fn clone(&self) -> ImageSurface {
        unsafe {
            cairo_surface_reference(self.cairo_surface);
            return image_surface_from_cairo_surface(self.cairo_surface);
        }
    }
}

struct Context {
    cairo_context: *cairo_t,
}

impl Context {
    fn set_line_width(&self, width: c_double) {
        unsafe {
            cairo_set_line_width(self.cairo_context, width);
        }
    }

    fn set_source_rgb(&self, r: c_double, g: c_double, b: c_double) {
        unsafe {
            cairo_set_source_rgb(self.cairo_context, r, g, b);
        }
    }

    fn rectangle(&self, x: c_double, y: c_double, width: c_double, height: c_double) {
        unsafe {
            cairo_rectangle(self.cairo_context, x, y, width, height);
        }
    }

    fn stroke(&self) {
        unsafe {
            cairo_stroke(self.cairo_context);
        }
    }

    fn fill(&self) {
        unsafe {
            cairo_fill(self.cairo_context);
        }
    }
}

fn make_context(surface: &ImageSurface) -> Context {
    unsafe {
        Context {
            cairo_context: cairo_create(surface.cairo_surface)
        }
    }
}
<|endoftext|>