<commit_before>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::fmt;
use std::path::PathBuf;

// from parent
use ERes;
use err;
use read_file;
use footprint;

extern crate rustysexp;
use self::rustysexp::Sexp;

pub struct Layout {
    pub version:i64,
    pub elements:Vec<Element>,
}

#[derive(Clone)]
pub enum Element {
    Module(footprint::Module),
    Net(Net),
    NetClass(NetClass),
    Other(Sexp),
}

#[derive(Clone,PartialEq)]
pub struct Net {
    pub num:i64,
    pub name:String,
}

#[derive(Clone,PartialEq)]
pub struct NetClass {
    pub name:String,
    pub desc:String,
    pub clearance:f64,
    pub trace_width:f64,
    pub via_dia:f64,
    pub via_drill:f64,
    pub uvia_dia:f64,
    pub uvia_drill:f64,
    pub nets:Vec<String>,
}

impl Layout {
    pub fn new() -> Layout {
        Layout {
            version:0,
            elements:vec![],
        }
    }

    pub fn insert_dummy_setup(&mut self) {
        self.elements.push(Element::Other(Sexp::List(vec![Sexp::String(String::from("setup"))])))
    }

    pub fn modify_module<F>(&mut self, reference:&String, fun:F) -> ERes<()>
        where F:Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements[..] {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference(reference) {
                        return Ok(fun(m))
                    }
                },
                Element::Net(_) => (),
                Element::NetClass(_) => (),
                Element::Other(_) => (),
            }
        }
        Err(format!("did not find module with reference {}", reference))
    }
}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(kicad_pcb (version {})", self.version));
        for element in &self.elements[..] {
            try!(writeln!(f, "  {}", element));
            try!(writeln!(f, ""));
        }
        writeln!(f, ")")
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Other(ref s) => write!(f, "{}", s),
            Element::Module(ref s) => write!(f, "{}", s),
            Element::Net(ref s) => write!(f, "{}", s),
            Element::NetClass(ref s) => write!(f, "{}", s),
        }
    }
}

impl fmt::Display for Net {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.name.contains("(") || self.name.contains(")") || self.name.len()==0 {
            write!(f, "(net {} \"{}\")", self.num, self.name)
        } else {
            write!(f, "(net {} {})", self.num, self.name)
        }
    }
}
impl fmt::Display for NetClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(net_class {} \"{}\" ", self.name, self.desc));
        try!(write!(f, "(clearance {}) ", self.clearance));
        try!(write!(f, "(trace_width {}) ", self.trace_width));
        try!(write!(f, "(via_dia {}) ", self.via_dia));
        try!(write!(f, "(via_drill {}) ", self.via_drill));
        try!(write!(f, "(uvia_dia {}) ", self.uvia_dia));
        try!(write!(f, "(uvia_drill {}) ", self.uvia_drill));
        for net in &self.nets {
            if net.contains("(") || net.contains(")") {
                try!(write!(f, "(add_net \"{}\")", net))
            } else {
                try!(write!(f, "(add_net {})", net))
            }
        }
        write!(f, ")")

    }
}

fn parse_version(e:&Sexp) -> ERes<i64> {
    let l = try!(e.slice_atom("version"));
    l[0].i()
}

fn parse_other(e:&Sexp) -> Element {
    let e2 = e.clone();
    Element::Other(e2)
}

fn parse_module(e:&Sexp) -> ERes<Element> {
    let e2 = e.clone();
    let m = try!(footprint::parse_module(e2));
    Ok(Element::Module(m))
}

fn parse_net(e:&Sexp) -> ERes<Element> {
    let l = try!(e.slice_atom("net"));
    let num = try!(l[0].i());
    let name = try!(l[1].string()).clone();
    Ok(Element::Net(Net { name:name, num:num }))
}

fn parse_net_class(e:&Sexp) -> ERes<Element> {
    fn parse(e:&Sexp, name:&str) -> ERes<f64> {
        let l = try!(e.slice_atom(name));
        l[0].f()
    }
    let l = try!(e.slice_atom("net_class"));
    let name = try!(l[0].string()).clone();
    let desc = try!(l[1].string()).clone();
    let mut clearance = 0.1524;
    let mut trace_width = 0.2032;
    let mut via_dia = 0.675;
    let mut via_drill = 0.25;
    let mut uvia_dia = 0.508;
    let mut uvia_drill = 0.127;
    let mut nets = vec![];
    for x in &l[2..] {
        let list_name = try!(x.list_name());
        let xn = &list_name[..];
        match xn {
            "add_net" => {
                let l1 = try!(x.slice_atom("add_net"));
                nets.push(try!(l1[0].string()).clone())
            },
            "clearance" => clearance = try!(parse(x, xn)),
            "trace_width" => trace_width = try!(parse(x, xn)),
            "via_dia" => via_dia = try!(parse(x, xn)),
            "via_drill" => via_drill = try!(parse(x, xn)),
            "uvia_dia" => uvia_dia = try!(parse(x, xn)),
            "uvia_drill" => uvia_drill = try!(parse(x, xn)),
            _ => return Err(format!("unknown net_class field {}", list_name))
        }
    }
    let net_class = NetClass {
        name:name, desc:desc, clearance:clearance, via_dia:via_dia,
        via_drill:via_drill, uvia_dia:uvia_dia, uvia_drill:uvia_drill,
        nets:nets, trace_width:trace_width,
    };
    Ok(Element::NetClass(net_class))
}

fn parse(s: &str) -> ERes<Layout> {
    let exp = match rustysexp::parse_str(s) {
        Ok(s) => s,
        Err(x) => return Err(format!("ParseError: {}", x)),
    };
    let l1 = try!(exp.slice_atom("kicad_pcb"));
    let mut layout = Layout::new();

    for ref e in l1 {
        match &try!(e.list_name())[..] {
            "version" => layout.version = try!(parse_version(e)),
            "module" => layout.elements.push(try!(parse_module(e))),
            "net" => layout.elements.push(try!(parse_net(e))),
            "net_class" => layout.elements.push(try!(parse_net_class(e))),
            _ => layout.elements.push(parse_other(e)),
        }
    }
    Ok(layout)
}

pub fn parse_str(s: &str) -> ERes<Layout> {
    parse(s)
}

pub fn parse_file(filename: &PathBuf) -> ERes<Layout> {
    let name = filename.to_str().unwrap();
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("io error: {}", x))
    });
    parse(&s[..])
}
<commit_msg>net and netclass accessors<commit_after>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::fmt;
use std::path::PathBuf;

// from parent
use ERes;
use err;
use read_file;
use footprint;

extern crate rustysexp;
use self::rustysexp::Sexp;

pub struct Layout {
    pub version:i64,
    pub elements:Vec<Element>,
}

#[derive(Clone)]
pub enum Element {
    Module(footprint::Module),
    Net(Net),
    NetClass(NetClass),
    Other(Sexp),
}

#[derive(Clone,PartialEq)]
pub struct Net {
    pub num:i64,
    pub name:String,
}

#[derive(Clone,PartialEq)]
pub struct NetClass {
    pub name:String,
    pub desc:String,
    pub clearance:f64,
    pub trace_width:f64,
    pub via_dia:f64,
    pub via_drill:f64,
    pub uvia_dia:f64,
    pub uvia_drill:f64,
    pub nets:Vec<String>,
}

impl Layout {
    pub fn new() -> Layout {
        Layout {
            version:0,
            elements:vec![],
        }
    }

    pub fn insert_dummy_setup(&mut self) {
        self.elements.push(Element::Other(Sexp::List(vec![Sexp::String(String::from("setup"))])))
    }

    pub fn nets(&self) -> Vec<&Net> {
        let mut v = vec![];
        for element in &self.elements {
            match *element {
                Element::Net(ref net) => v.push(net),
                _ => (),
            }
        }
        v
    }

    pub fn netclasses(&self) -> Vec<&NetClass> {
        let mut v = vec![];
        for element in &self.elements {
            match *element {
                Element::NetClass(ref net_class) => v.push(net_class),
                _ => (),
            }
        }
        v
    }

    pub fn modify_module<F>(&mut self, reference:&String, fun:F) -> ERes<()>
        where F:Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements[..] {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference(reference) {
                        return Ok(fun(m))
                    }
                },
                Element::Net(_) => (),
                Element::NetClass(_) => (),
                Element::Other(_) => (),
            }
        }
        Err(format!("did not find module with reference {}", reference))
    }
}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(kicad_pcb (version {})", self.version));
        for element in &self.elements[..] {
            try!(writeln!(f, "  {}", element));
            try!(writeln!(f, ""));
        }
        writeln!(f, ")")
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Other(ref s) => write!(f, "{}", s),
            Element::Module(ref s) => write!(f, "{}", s),
            Element::Net(ref s) => write!(f, "{}", s),
            Element::NetClass(ref s) => write!(f, "{}", s),
        }
    }
}

impl fmt::Display for Net {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.name.contains("(") || self.name.contains(")") || self.name.len()==0 {
            write!(f, "(net {} \"{}\")", self.num, self.name)
        } else {
            write!(f, "(net {} {})", self.num, self.name)
        }
    }
}
impl fmt::Display for NetClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(net_class {} \"{}\" ", self.name, self.desc));
        try!(write!(f, "(clearance {}) ", self.clearance));
        try!(write!(f, "(trace_width {}) ", self.trace_width));
        try!(write!(f, "(via_dia {}) ", self.via_dia));
        try!(write!(f, "(via_drill {}) ", self.via_drill));
        try!(write!(f, "(uvia_dia {}) ", self.uvia_dia));
        try!(write!(f, "(uvia_drill {}) ", self.uvia_drill));
        for net in &self.nets {
            if net.contains("(") || net.contains(")") {
                try!(write!(f, "(add_net \"{}\")", net))
            } else {
                try!(write!(f, "(add_net {})", net))
            }
        }
        write!(f, ")")

    }
}

fn parse_version(e:&Sexp) -> ERes<i64> {
    let l = try!(e.slice_atom("version"));
    l[0].i()
}

fn parse_other(e:&Sexp) -> Element {
    let e2 = e.clone();
    Element::Other(e2)
}

fn parse_module(e:&Sexp) -> ERes<Element> {
    let e2 = e.clone();
    let m = try!(footprint::parse_module(e2));
    Ok(Element::Module(m))
}

fn parse_net(e:&Sexp) -> ERes<Element> {
    let l = try!(e.slice_atom("net"));
    let num = try!(l[0].i());
    let name = try!(l[1].string()).clone();
    Ok(Element::Net(Net { name:name, num:num }))
}

fn parse_net_class(e:&Sexp) -> ERes<Element> {
    fn parse(e:&Sexp, name:&str) -> ERes<f64> {
        let l = try!(e.slice_atom(name));
        l[0].f()
    }
    let l = try!(e.slice_atom("net_class"));
    let name = try!(l[0].string()).clone();
    let desc = try!(l[1].string()).clone();
    let mut clearance = 0.1524;
    let mut trace_width = 0.2032;
    let mut via_dia = 0.675;
    let mut via_drill = 0.25;
    let mut uvia_dia = 0.508;
    let mut uvia_drill = 0.127;
    let mut nets = vec![];
    for x in &l[2..] {
        let list_name = try!(x.list_name());
        let xn = &list_name[..];
        match xn {
            "add_net" => {
                let l1 = try!(x.slice_atom("add_net"));
                nets.push(try!(l1[0].string()).clone())
            },
            "clearance" => clearance = try!(parse(x, xn)),
            "trace_width" => trace_width = try!(parse(x, xn)),
            "via_dia" => via_dia = try!(parse(x, xn)),
            "via_drill" => via_drill = try!(parse(x, xn)),
            "uvia_dia" => uvia_dia = try!(parse(x, xn)),
            "uvia_drill" => uvia_drill = try!(parse(x, xn)),
            _ => return Err(format!("unknown net_class field {}", list_name))
        }
    }
    let net_class = NetClass {
        name:name, desc:desc, clearance:clearance, via_dia:via_dia,
        via_drill:via_drill, uvia_dia:uvia_dia, uvia_drill:uvia_drill,
        nets:nets, trace_width:trace_width,
    };
    Ok(Element::NetClass(net_class))
}

fn parse(s: &str) -> ERes<Layout> {
    let exp = match rustysexp::parse_str(s) {
        Ok(s) => s,
        Err(x) => return Err(format!("ParseError: {}", x)),
    };
    let l1 = try!(exp.slice_atom("kicad_pcb"));
    let mut layout = Layout::new();

    for ref e in l1 {
        match &try!(e.list_name())[..] {
            "version" => layout.version = try!(parse_version(e)),
            "module" => layout.elements.push(try!(parse_module(e))),
            "net" => layout.elements.push(try!(parse_net(e))),
            "net_class" => layout.elements.push(try!(parse_net_class(e))),
            _ => layout.elements.push(parse_other(e)),
        }
    }
    Ok(layout)
}

pub fn parse_str(s: &str) -> ERes<Layout> {
    parse(s)
}

pub fn parse_file(filename: &PathBuf) -> ERes<Layout> {
    let name = filename.to_str().unwrap();
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("io error: {}", x))
    });
    parse(&s[..])
}
<|endoftext|>


<commit_before>// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A one-dimensional length, tagged with its units.

use scale_factor::ScaleFactor;
use num::Zero;

use num_lib::NumCast;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::cmp::Ordering;
use std::ops::{Add, Sub, Mul, Div, Neg};
use std::marker::PhantomData;

/// A one-dimensional distance, with value represented by `T` and unit of measurement `Unit`.
///
/// `T` can be any numeric type, for example a primitive type like u64 or f32.
///
/// `Unit` is not used in the representation of a Length value. It is used only at compile time
/// to ensure that a Length stored with one unit is converted explicitly before being used in an
/// expression that requires a different unit.  It may be a type without values, such as an empty
/// enum.
///
/// You can multiply a Length by a `scale_factor::ScaleFactor` to convert it from one unit to
/// another.  See the ScaleFactor docs for an example.
// Uncomment the derive, and remove the macro call, once heapsize gets
// PhantomData<T> support.
#[derive(Copy, RustcDecodable, RustcEncodable, Debug)]
#[cfg_attr(feature = "heap_size", derive(HeapSizeOf))]
pub struct Length<Unit, T>(pub T, PhantomData<Unit>);

impl<Unit,T> Deserialize for Length<Unit,T> where T: Deserialize {
    fn deserialize<D>(deserializer: &mut D) -> Result<Length<Unit,T>,D::Error>
                      where D: Deserializer {
        Ok(Length(try!(Deserialize::deserialize(deserializer)), PhantomData))
    }
}

impl<Unit,T> Serialize for Length<Unit,T> where T: Serialize {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(),S::Error> where S: Serializer {
        self.0.serialize(serializer)
    }
}

impl<Unit, T> Length<Unit, T> {
    pub fn new(x: T) -> Length<Unit, T> {
        Length(x, PhantomData)
    }
}

impl<Unit, T: Clone> Length<Unit, T> {
    pub fn get(&self) -> T {
        self.0.clone()
    }
}

// length + length
impl<U, T: Clone + Add<T, Output=T>> Add for Length<U, T> {
    type Output = Length<U, T>;
    fn add(self, other: Length<U, T>) -> Length<U, T> {
        Length::new(self.get() + other.get())
    }
}

// length - length
impl<U, T: Clone + Sub<T, Output=T>> Sub<Length<U, T>> for Length<U, T> {
    type Output = Length<U, T>;
    fn sub(self, other: Length<U, T>) -> <Self as Sub>::Output {
        Length::new(self.get() - other.get())
    }
}

// length * scaleFactor
impl<Src, Dst, T: Clone + Mul<T, Output=T>> Mul<ScaleFactor<Src, Dst, T>> for Length<Src, T> {
    type Output = Length<Dst, T>;
    #[inline]
    fn mul(self, scale: ScaleFactor<Src, Dst, T>) -> Length<Dst, T> {
        Length::new(self.get() * scale.get())
    }
}

// length / scaleFactor
impl<Src, Dst, T: Clone + Div<T, Output=T>> Div<ScaleFactor<Src, Dst, T>> for Length<Dst, T> {
    type Output = Length<Src, T>;
    #[inline]
    fn div(self, scale: ScaleFactor<Src, Dst, T>) -> Length<Src, T> {
        Length::new(self.get() / scale.get())
    }
}

// -length
impl <U, T:Clone + Neg<Output=T>> Neg for Length<U, T> {
    type Output = Length<U, T>;
    #[inline]
    fn neg(self) -> Length<U, T> {
        Length::new(-self.get())
    }
}

impl<Unit, T0: NumCast + Clone> Length<Unit, T0> {
    /// Cast from one numeric representation to another, preserving the units.
    pub fn cast<T1: NumCast + Clone>(&self) -> Option<Length<Unit, T1>> {
        NumCast::from(self.get()).map(Length::new)
    }
}

// FIXME: Switch to `derive(Clone, PartialEq, PartialOrd, Zero)` after this Rust issue is fixed:
// https://github.com/mozilla/rust/issues/7671

impl<Unit, T: Clone> Clone for Length<Unit, T> {
    fn clone(&self) -> Length<Unit, T> {
        Length::new(self.get())
    }
}

impl<Unit, T: Clone + PartialEq> PartialEq for Length<Unit, T> {
    fn eq(&self, other: &Length<Unit, T>) -> bool { self.get().eq(&other.get()) }
}

impl<Unit, T: Clone + PartialOrd> PartialOrd for Length<Unit, T> {
    fn partial_cmp(&self, other: &Length<Unit, T>) -> Option<Ordering> {
        self.get().partial_cmp(&other.get())
    }
}

impl<Unit, T: Clone + Eq> Eq for Length<Unit, T> {}

impl<Unit, T: Clone + Ord> Ord for Length<Unit, T> {
    fn cmp(&self, other: &Length<Unit, T>) -> Ordering { self.get().cmp(&other.get()) }
}

impl<Unit, T: Zero> Zero for Length<Unit, T> {
    fn zero() -> Length<Unit, T> {
        Length::new(Zero::zero())
    }
}

#[cfg(test)]
mod tests {
    use super::Length;
    use scale_factor::ScaleFactor;

    #[derive(Debug)]
    enum Inch {}
    #[derive(Debug)]
    enum Mm {}

    #[test]
    fn test_length() {
        let mm_per_inch: ScaleFactor<Inch, Mm, f32> = ScaleFactor::new(25.4);

        let one_foot: Length<Inch, f32> = Length::new(12.0);
        let two_feet = one_foot.clone() + one_foot.clone();
        let zero_feet = one_foot.clone() - one_foot.clone();

        assert_eq!(one_foot.get(), 12.0);
        assert_eq!(two_feet.get(), 24.0);
        assert_eq!(zero_feet.get(), 0.0);

        assert!(one_foot == one_foot);
        assert!(two_feet != one_foot);

        assert!(zero_feet <  one_foot);
        assert!(zero_feet <= one_foot);
        assert!(two_feet  >  one_foot);
        assert!(two_feet  >= one_foot);

        assert!(  two_feet <= two_feet);
        assert!(  two_feet >= two_feet);
        assert!(!(two_feet >  two_feet));
        assert!(!(two_feet <  two_feet));

        let one_foot_in_mm: Length<Mm, f32> = one_foot.clone() * mm_per_inch.clone();

        assert_eq!(one_foot_in_mm, Length::new(304.8));

        let back_to_inches: Length<Inch, f32> = one_foot_in_mm / mm_per_inch;
        assert_eq!(one_foot, back_to_inches);

        let int_foot: Length<Inch, isize> = one_foot.cast().unwrap();
        assert_eq!(int_foot.get(), 12);

        let negative_one_foot = -one_foot;
        assert_eq!(negative_one_foot.get(), -12.0);

        let negative_two_feet = -two_feet;
        assert_eq!(negative_two_feet.get(), -24.0);

        let zero_feet: Length<Inch, f32> = Length::new(0.0);
        let negative_zero_feet = -zero_feet;
        assert_eq!(negative_zero_feet.get(), 0.0);
    }
}
<commit_msg>Add Length / Length -> ScaleFactor division<commit_after>// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A one-dimensional length, tagged with its units.

use scale_factor::ScaleFactor;
use num::Zero;

use num_lib::NumCast;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::cmp::Ordering;
use std::ops::{Add, Sub, Mul, Div, Neg};
use std::marker::PhantomData;

/// A one-dimensional distance, with value represented by `T` and unit of measurement `Unit`.
///
/// `T` can be any numeric type, for example a primitive type like u64 or f32.
///
/// `Unit` is not used in the representation of a Length value. It is used only at compile time
/// to ensure that a Length stored with one unit is converted explicitly before being used in an
/// expression that requires a different unit.  It may be a type without values, such as an empty
/// enum.
///
/// You can multiply a Length by a `scale_factor::ScaleFactor` to convert it from one unit to
/// another.  See the ScaleFactor docs for an example.
// Uncomment the derive, and remove the macro call, once heapsize gets
// PhantomData<T> support.
#[derive(Copy, RustcDecodable, RustcEncodable, Debug)]
#[cfg_attr(feature = "heap_size", derive(HeapSizeOf))]
pub struct Length<Unit, T>(pub T, PhantomData<Unit>);

impl<Unit,T> Deserialize for Length<Unit,T> where T: Deserialize {
    fn deserialize<D>(deserializer: &mut D) -> Result<Length<Unit,T>,D::Error>
                      where D: Deserializer {
        Ok(Length(try!(Deserialize::deserialize(deserializer)), PhantomData))
    }
}

impl<Unit,T> Serialize for Length<Unit,T> where T: Serialize {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(),S::Error> where S: Serializer {
        self.0.serialize(serializer)
    }
}

impl<Unit, T> Length<Unit, T> {
    pub fn new(x: T) -> Length<Unit, T> {
        Length(x, PhantomData)
    }
}

impl<Unit, T: Clone> Length<Unit, T> {
    pub fn get(&self) -> T {
        self.0.clone()
    }
}

// length + length
impl<U, T: Clone + Add<T, Output=T>> Add for Length<U, T> {
    type Output = Length<U, T>;
    fn add(self, other: Length<U, T>) -> Length<U, T> {
        Length::new(self.get() + other.get())
    }
}

// length - length
impl<U, T: Clone + Sub<T, Output=T>> Sub<Length<U, T>> for Length<U, T> {
    type Output = Length<U, T>;
    fn sub(self, other: Length<U, T>) -> <Self as Sub>::Output {
        Length::new(self.get() - other.get())
    }
}

// length / length
impl<Src, Dst, T: Clone + Div<T, Output=T>> Div<Length<Src, T>> for Length<Dst, T> {
    type Output = ScaleFactor<Src, Dst, T>;
    #[inline]
    fn div(self, other: Length<Src, T>) -> ScaleFactor<Src, Dst, T> {
        ScaleFactor::new(self.get() / other.get())
    }
}

// length * scaleFactor
impl<Src, Dst, T: Clone + Mul<T, Output=T>> Mul<ScaleFactor<Src, Dst, T>> for Length<Src, T> {
    type Output = Length<Dst, T>;
    #[inline]
    fn mul(self, scale: ScaleFactor<Src, Dst, T>) -> Length<Dst, T> {
        Length::new(self.get() * scale.get())
    }
}

// length / scaleFactor
impl<Src, Dst, T: Clone + Div<T, Output=T>> Div<ScaleFactor<Src, Dst, T>> for Length<Dst, T> {
    type Output = Length<Src, T>;
    #[inline]
    fn div(self, scale: ScaleFactor<Src, Dst, T>) -> Length<Src, T> {
        Length::new(self.get() / scale.get())
    }
}

// -length
impl <U, T:Clone + Neg<Output=T>> Neg for Length<U, T> {
    type Output = Length<U, T>;
    #[inline]
    fn neg(self) -> Length<U, T> {
        Length::new(-self.get())
    }
}

impl<Unit, T0: NumCast + Clone> Length<Unit, T0> {
    /// Cast from one numeric representation to another, preserving the units.
    pub fn cast<T1: NumCast + Clone>(&self) -> Option<Length<Unit, T1>> {
        NumCast::from(self.get()).map(Length::new)
    }
}

// FIXME: Switch to `derive(Clone, PartialEq, PartialOrd, Zero)` after this Rust issue is fixed:
// https://github.com/mozilla/rust/issues/7671

impl<Unit, T: Clone> Clone for Length<Unit, T> {
    fn clone(&self) -> Length<Unit, T> {
        Length::new(self.get())
    }
}

impl<Unit, T: Clone + PartialEq> PartialEq for Length<Unit, T> {
    fn eq(&self, other: &Length<Unit, T>) -> bool { self.get().eq(&other.get()) }
}

impl<Unit, T: Clone + PartialOrd> PartialOrd for Length<Unit, T> {
    fn partial_cmp(&self, other: &Length<Unit, T>) -> Option<Ordering> {
        self.get().partial_cmp(&other.get())
    }
}

impl<Unit, T: Clone + Eq> Eq for Length<Unit, T> {}

impl<Unit, T: Clone + Ord> Ord for Length<Unit, T> {
    fn cmp(&self, other: &Length<Unit, T>) -> Ordering { self.get().cmp(&other.get()) }
}

impl<Unit, T: Zero> Zero for Length<Unit, T> {
    fn zero() -> Length<Unit, T> {
        Length::new(Zero::zero())
    }
}

#[cfg(test)]
mod tests {
    use super::Length;
    use scale_factor::ScaleFactor;

    #[derive(Debug, Copy, Clone)]
    enum Inch {}
    #[derive(Debug, Copy, Clone)]
    enum Mm {}

    #[test]
    fn test_length() {
        let mm_per_inch: ScaleFactor<Inch, Mm, f32> = ScaleFactor::new(25.4);

        let one_foot: Length<Inch, f32> = Length::new(12.0);
        let two_feet = one_foot.clone() + one_foot.clone();
        let zero_feet = one_foot.clone() - one_foot.clone();

        assert_eq!(one_foot.get(), 12.0);
        assert_eq!(two_feet.get(), 24.0);
        assert_eq!(zero_feet.get(), 0.0);

        assert!(one_foot == one_foot);
        assert!(two_feet != one_foot);

        assert!(zero_feet <  one_foot);
        assert!(zero_feet <= one_foot);
        assert!(two_feet  >  one_foot);
        assert!(two_feet  >= one_foot);

        assert!(  two_feet <= two_feet);
        assert!(  two_feet >= two_feet);
        assert!(!(two_feet >  two_feet));
        assert!(!(two_feet <  two_feet));

        let one_foot_in_mm: Length<Mm, f32> = one_foot * mm_per_inch;

        assert_eq!(one_foot_in_mm, Length::new(304.8));
        assert_eq!(one_foot_in_mm / one_foot, mm_per_inch);

        let back_to_inches: Length<Inch, f32> = one_foot_in_mm / mm_per_inch;
        assert_eq!(one_foot, back_to_inches);

        let int_foot: Length<Inch, isize> = one_foot.cast().unwrap();
        assert_eq!(int_foot.get(), 12);

        let negative_one_foot = -one_foot;
        assert_eq!(negative_one_foot.get(), -12.0);

        let negative_two_feet = -two_feet;
        assert_eq!(negative_two_feet.get(), -24.0);

        let zero_feet: Length<Inch, f32> = Length::new(0.0);
        let negative_zero_feet = -zero_feet;
        assert_eq!(negative_zero_feet.get(), 0.0);
    }
}
<|endoftext|>


<commit_before>pub mod api;

#[derive(Debug, Clone)]
pub enum Error {
	Api(api::Api),
	Json,
	Http,
	Unknown,
}

impl Error {
	pub fn is_api_error(self) -> bool
	{
		match self
		{
			Error::Api(_) => true,
			Error::Json => false,
			Error::Http => false,
			_ => false,
		}
	}

	pub fn is_http_err(self) -> bool
	{
		match self
		{
			Error::Api(_) => false,
			Error::Json => false,
			Error::Http => true,
			_ => false,
		}
	}

	pub fn is_json_error(self) -> bool
	{
		match self
		{
			Error::Api(_) => false,
			Error::Json => true,
			Error::Http => false,
			_ => false,
		}
	}
}
<commit_msg>preparing for better error handling<commit_after>pub mod api;
pub mod http;

use std;
use std::fmt;

#[derive(Debug)]
pub enum Error {
	Api(api::Api),
	Json,
	Http,
	Unknown,
}

impl Error {
	pub fn is_api_error(self) -> bool
	{
		match self
		{
			Error::Api(_) => true,
			Error::Json => false,
			Error::Http => false,
			_ => false,
		}
	}

	pub fn is_http_err(self) -> bool
	{
		match self
		{
			Error::Api(_) => false,
			Error::Json => false,
			Error::Http => true,
			_ => false,
		}
	}

	pub fn is_json_error(self) -> bool
	{
		match self
		{
			Error::Api(_) => false,
			Error::Json => true,
			Error::Http => false,
			_ => false,
		}
	}
}

impl fmt::Display for Error {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "{:?}", self)
	}
}

impl std::error::Error for Error {
	fn description(&self) -> &str {
		"general error"
	}
}
<|endoftext|>


<commit_before>native "rust" mod rustrt {
  fn rust_file_is_dir(str path) -> int;
}

fn path_sep() -> str {
    ret _str.from_char(os_fs.path_sep);
}

type path = str;

fn dirname(path p) -> path {
    auto sep = path_sep();
    assert (_str.byte_len(sep) == 1u);
    let int i = _str.rindex(p, sep.(0));
    if (i == -1) {
        // FIXME: the '/' character is a path separator on all 3 platforms we
        // support. This should probably be generalized a bit more in the
        // future, but for now this should work.
        i = _str.rindex(p, '/');
        if (i == -1) {
            ret p;
        }
    }
    ret _str.substr(p, 0u, i as uint);
}

fn connect(path pre, path post) -> path {
    auto len = _str.byte_len(pre);
    if (pre.(len - 1u) == (os_fs.path_sep as u8)) { // Trailing '/'?
        ret pre + post;
    }
    ret pre + path_sep() + post;
}

fn file_is_dir(path p) -> bool {
  ret rustrt.rust_file_is_dir(p) != 0;
}

fn list_dir(path p) -> vec[str] {
  auto pl = _str.byte_len(p);
  if (pl == 0u || p.(pl - 1u) as char != os_fs.path_sep) {
    p += path_sep();
  }
  let vec[str] full_paths = vec();
  for (str filename in os_fs.list_dir(p)) {
    if (!_str.eq(filename, ".")) {if (!_str.eq(filename, "..")) {
      _vec.push[str](full_paths, p + filename);
    }}
  }
  ret full_paths;
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Because good hackers at least check to see if the code compiles.<commit_after>native "rust" mod rustrt {
  fn rust_file_is_dir(str path) -> int;
}

fn path_sep() -> str {
    ret _str.from_char(os_fs.path_sep);
}

type path = str;

fn dirname(path p) -> path {
    auto sep = path_sep();
    assert (_str.byte_len(sep) == 1u);
    let int i = _str.rindex(p, sep.(0));
    if (i == -1) {
        // FIXME: the '/' character is a path separator on all 3 platforms we
        // support. This should probably be generalized a bit more in the
        // future, but for now this should work.
        i = _str.rindex(p, '/' as u8);
        if (i == -1) {
            ret p;
        }
    }
    ret _str.substr(p, 0u, i as uint);
}

fn connect(path pre, path post) -> path {
    auto len = _str.byte_len(pre);
    if (pre.(len - 1u) == (os_fs.path_sep as u8)) { // Trailing '/'?
        ret pre + post;
    }
    ret pre + path_sep() + post;
}

fn file_is_dir(path p) -> bool {
  ret rustrt.rust_file_is_dir(p) != 0;
}

fn list_dir(path p) -> vec[str] {
  auto pl = _str.byte_len(p);
  if (pl == 0u || p.(pl - 1u) as char != os_fs.path_sep) {
    p += path_sep();
  }
  let vec[str] full_paths = vec();
  for (str filename in os_fs.list_dir(p)) {
    if (!_str.eq(filename, ".")) {if (!_str.eq(filename, "..")) {
      _vec.push[str](full_paths, p + filename);
    }}
  }
  ret full_paths;
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>use std::num::Float;
use std::f64;
use ast::{Ast, ConstKind, FuncKind, OpKind};
use ast::AstVal::*;
use ast::FuncKind::*;
use ast::OpKind::*;
use ast::ConstKind::*;
use ast::AstBranch::*;
use errors::{CalcrResult, CalcrError};

pub fn eval_eq(ast: &Ast) -> CalcrResult<f64> {
    match ast.val {
        Func(ref f) => eval_func(f, ast),
        Op(ref o) => eval_op(o, ast),
        Const(ref c) => eval_const(c),
        Num(ref n) => Ok(*n),
        Paren => {
            if let Unary(ref child) = ast.branches {
                eval_eq(child)
            } else {
                Err(CalcrError {
                    desc: "Internal error - expected Paren to have unary branch".to_string(),
                    span: None,
                })
            }
        },
    }
}

fn eval_func(f: &FuncKind, ast: &Ast) -> CalcrResult<f64> {
    if let Unary(ref child) = ast.branches {
        let arg = try!(eval_eq(&*child));
        match *f {
            Sin => Ok(arg.sin()),
            Cos => Ok(arg.cos()),
            Tan => Ok(arg.tan()),
            Asin => Ok(arg.asin()),
            Acos => Ok(arg.acos()),
            Atan => Ok(arg.atan()),
            Abs => Ok(arg.abs()),
            Exp => Ok(arg.exp()),
            Sqrt => {
                if arg < 0.0 {
                    Err(CalcrError {
                        desc: "Cannot take the square root of a negative number".to_string(),
                        span: Some(child.get_total_span()),
                    })
                } else {
                    Ok(arg.sqrt())
                }
            },
            Ln => {
                if arg <= 0.0 {
                    Err(CalcrError {
                        desc: "Cannot take the logarithm of a non-positive number".to_string(),
                        span: Some(child.get_total_span()),
                    })
                } else {
                    Ok(arg.ln())
                }
            },
            Log =>  {
                if arg <= 0.0 {
                    Err(CalcrError {
                        desc: "Cannot take the logarithm of a non-positive number".to_string(),
                        span: Some(child.get_total_span()),
                    })
                } else {
                    Ok(arg.log10())
                }
            },
        }
    } else {
        Err(CalcrError {
            desc: "Interal error - expected AstFunc to have unary branch".to_string(),
            span: None,
        })
    }
}

fn eval_op(op: &OpKind, ast: &Ast) -> CalcrResult<f64> {
    match ast.branches {
        Binary(ref lhs, ref rhs) => {
            let (lhs, rhs) = (try!(eval_eq(&*lhs)), try!(eval_eq(&*rhs)));
            match *op {
                Plus => Ok(lhs + rhs),
                Minus => Ok(lhs - rhs),
                Mult => Ok(lhs * rhs),
                Div => Ok(lhs / rhs),
                Pow => Ok(lhs.powf(rhs)),
                _ => Err(CalcrError {
                    desc: "Internal error - expected AstOp to have binary branch".to_string(),
                    span: None,
                })
            }
        },
        Unary(ref child) => {
            let val = try!(eval_eq(&*child));
            match *op {
                Neg => Ok(-val),
                Fact => evalf_fact(val, child),
                _ => Err(CalcrError {
                    desc: "Internal error - expected AstOp to have unary branch".to_string(),
                    span: None,
                })
            }
        },
        Leaf => Err(CalcrError {
            desc: "Internal error - AstOp nodes may not be leaf nodes".to_string(),
            span: None,
        })
    }
}

fn eval_const(c: &ConstKind) -> CalcrResult<f64> {
    Ok(match *c {
        Pi => f64::consts::PI,
        E => (1.0).exp(),
        Phi => 1.6180339887498948482,
    })
}

fn evalf_fact(mut num: f64, child: &Ast) -> CalcrResult<f64> {
    if num.fract() == 0.0 && num >= 0.0 {
        let mut out = 1.0;
        while num > 0.0 {
            out *= num;
            num -= 1.0;
        }
        Ok(out)
    } else {
        Err(CalcrError {
            desc: "The factorial function only accepts positive whole numbers".to_string(),
            span: Some(child.get_total_span()),
        })
    }
}<commit_msg>Update to new rustc version<commit_after>use std::f64;
use ast::{Ast, ConstKind, FuncKind, OpKind};
use ast::AstVal::*;
use ast::FuncKind::*;
use ast::OpKind::*;
use ast::ConstKind::*;
use ast::AstBranch::*;
use errors::{CalcrResult, CalcrError};

pub fn eval_eq(ast: &Ast) -> CalcrResult<f64> {
    match ast.val {
        Func(ref f) => eval_func(f, ast),
        Op(ref o) => eval_op(o, ast),
        Const(ref c) => eval_const(c),
        Num(ref n) => Ok(*n),
        Paren => {
            if let Unary(ref child) = ast.branches {
                eval_eq(child)
            } else {
                Err(CalcrError {
                    desc: "Internal error - expected Paren to have unary branch".to_string(),
                    span: None,
                })
            }
        },
    }
}

fn eval_func(f: &FuncKind, ast: &Ast) -> CalcrResult<f64> {
    if let Unary(ref child) = ast.branches {
        let arg = try!(eval_eq(&*child));
        match *f {
            Sin => Ok(arg.sin()),
            Cos => Ok(arg.cos()),
            Tan => Ok(arg.tan()),
            Asin => Ok(arg.asin()),
            Acos => Ok(arg.acos()),
            Atan => Ok(arg.atan()),
            Abs => Ok(arg.abs()),
            Exp => Ok(arg.exp()),
            Sqrt => {
                if arg < 0.0 {
                    Err(CalcrError {
                        desc: "Cannot take the square root of a negative number".to_string(),
                        span: Some(child.get_total_span()),
                    })
                } else {
                    Ok(arg.sqrt())
                }
            },
            Ln => {
                if arg <= 0.0 {
                    Err(CalcrError {
                        desc: "Cannot take the logarithm of a non-positive number".to_string(),
                        span: Some(child.get_total_span()),
                    })
                } else {
                    Ok(arg.ln())
                }
            },
            Log =>  {
                if arg <= 0.0 {
                    Err(CalcrError {
                        desc: "Cannot take the logarithm of a non-positive number".to_string(),
                        span: Some(child.get_total_span()),
                    })
                } else {
                    Ok(arg.log10())
                }
            },
        }
    } else {
        Err(CalcrError {
            desc: "Interal error - expected AstFunc to have unary branch".to_string(),
            span: None,
        })
    }
}

fn eval_op(op: &OpKind, ast: &Ast) -> CalcrResult<f64> {
    match ast.branches {
        Binary(ref lhs, ref rhs) => {
            let (lhs, rhs) = (try!(eval_eq(&*lhs)), try!(eval_eq(&*rhs)));
            match *op {
                Plus => Ok(lhs + rhs),
                Minus => Ok(lhs - rhs),
                Mult => Ok(lhs * rhs),
                Div => Ok(lhs / rhs),
                Pow => Ok(lhs.powf(rhs)),
                _ => Err(CalcrError {
                    desc: "Internal error - expected AstOp to have binary branch".to_string(),
                    span: None,
                })
            }
        },
        Unary(ref child) => {
            let val = try!(eval_eq(&*child));
            match *op {
                Neg => Ok(-val),
                Fact => evalf_fact(val, child),
                _ => Err(CalcrError {
                    desc: "Internal error - expected AstOp to have unary branch".to_string(),
                    span: None,
                })
            }
        },
        Leaf => Err(CalcrError {
            desc: "Internal error - AstOp nodes may not be leaf nodes".to_string(),
            span: None,
        })
    }
}

fn eval_const(c: &ConstKind) -> CalcrResult<f64> {
    Ok(match *c {
        Pi => f64::consts::PI,
        E => (1.0f64).exp(),
        Phi => 1.6180339887498948482,
    })
}

fn evalf_fact(mut num: f64, child: &Ast) -> CalcrResult<f64> {
    if num.fract() == 0.0 && num >= 0.0 {
        let mut out = 1.0;
        while num > 0.0 {
            out *= num;
            num -= 1.0;
        }
        Ok(out)
    } else {
        Err(CalcrError {
            desc: "The factorial function only accepts positive whole numbers".to_string(),
            span: Some(child.get_total_span()),
        })
    }
}<|endoftext|>


<commit_before>#[macro_use]
extern crate enum_map;

use enum_map::{EnumMap, Internal, IntoIter};

use std::cell::RefCell;
use std::collections::HashSet;
use std::marker::PhantomData;

#[derive(Copy, Clone, Debug, EnumMap, PartialEq)]
enum Example {
    A,
    B,
    C,
}

#[test]
fn test_bool() {
    let mut map = enum_map! { false => 24, true => 42 };
    assert_eq!(map[false], 24);
    assert_eq!(map[true], 42);
    map[false] += 1;
    assert_eq!(map[false], 25);
    for (key, item) in &mut map {
        if !key {
            *item += 1;
        }
    }
    assert_eq!(map[false], 26);
    assert_eq!(map[true], 42);
}

#[test]
fn test_clone() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(map.clone(), map);
}

#[test]
fn test_debug() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(format!("{:?}", map), "{false: 3, true: 5}");
}

#[test]
fn test_hash() {
    let map = enum_map! { false => 3, true => 5 };
    let mut set = HashSet::new();
    set.insert(map);
    assert!(set.contains(&map));
}

#[test]
fn discriminants() {
    #[derive(Debug, EnumMap, PartialEq)]
    enum Discriminants {
        A = 2000,
        B = 3000,
        C = 1000,
    }
    let mut map = EnumMap::new();
    map[Discriminants::A] = 3;
    map[Discriminants::B] = 2;
    map[Discriminants::C] = 1;
    let mut pairs = map.iter();
    assert_eq!(pairs.next(), Some((Discriminants::A, &3)));
    assert_eq!(pairs.next(), Some((Discriminants::B, &2)));
    assert_eq!(pairs.next(), Some((Discriminants::C, &1)));
    assert_eq!(pairs.next(), None);
}

#[test]
fn extend() {
    let mut map = enum_map! { _ => 0 };
    map.extend(vec![(Example::A, 3)]);
    map.extend(vec![(&Example::B, &4)]);
    assert_eq!(
        map,
        enum_map! { Example:: A => 3, Example:: B => 4, Example::C => 0 }
    );
}

#[test]
fn huge_enum() {
    #[derive(EnumMap)]
    enum Example {
        A,
        B,
        C,
        D,
        E,
        F,
        G,
        H,
        I,
        J,
        K,
        L,
        M,
        N,
        O,
        P,
        Q,
        R,
        S,
        T,
        U,
        V,
        W,
        X,
        Y,
        Z,
        Aa,
        Bb,
        Cc,
        Dd,
        Ee,
        Ff,
        Gg,
        Hh,
        Ii,
        Jj,
        Kk,
        Ll,
        Mm,
        Nn,
        Oo,
        Pp,
        Qq,
        Rr,
        Ss,
        Tt,
        Uu,
        Vv,
        Ww,
        Xx,
        Yy,
        Zz,
    }

    let map = enum_map! { _ => 2 };
    assert_eq!(map[Example::Xx], 2);
}

#[test]
fn iterator_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter()
            .len(),
        3
    );
}

#[test]
fn iter_mut_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter_mut()
            .len(),
        3
    );
}

#[test]
fn iterator_next_back() {
    assert_eq!(
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .iter()
            .next_back(),
        Some((Example::C, &3))
    );
}

#[test]
fn iter_mut_next_back() {
    assert_eq!(
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .iter_mut()
            .next_back(),
        Some((Example::C, &mut 3))
    );
}

#[test]
fn into_iter() {
    let mut iter = enum_map! { true => 5, false => 7 }.into_iter();
    assert_eq!(iter.next(), Some((false, 7)));
    assert_eq!(iter.next(), Some((true, 5)));
    assert_eq!(iter.next(), None);
    assert_eq!(iter.next(), None);
}

struct DropReporter<'a> {
    into: &'a RefCell<Vec<usize>>,
    value: usize,
}

impl<'a> Drop for DropReporter<'a> {
    fn drop(&mut self) {
        self.into.borrow_mut().push(self.value);
    }
}

#[test]
fn into_iter_drop() {
    let dropped = RefCell::new(Vec::new());
    let mut a: IntoIter<Example, _> = enum_map! {
        k => DropReporter {
            into: &dropped,
            value: k as usize,
        },
    }.into_iter();
    assert_eq!(a.next().unwrap().0, Example::A);
    assert_eq!(*dropped.borrow(), &[0]);
    drop(a);
    assert_eq!(*dropped.borrow(), &[0, 1, 2]);
}

#[test]
fn test_u8() {
    let mut map = enum_map! { b'a' => 4, _ => 0 };
    map[b'c'] = 3;
    assert_eq!(map[b'a'], 4);
    assert_eq!(map[b'b'], 0);
    assert_eq!(map[b'c'], 3);
    assert_eq!(map.iter().next(), Some((0, &0)));
}

#[derive(EnumMap)]
enum Void {}

#[test]
fn empty_map() {
    let void: EnumMap<Void, Void> = enum_map!{};
    assert!(void.is_empty());
}

#[test]
#[should_panic]
fn empty_value() {
    let _void: EnumMap<bool, Void> = enum_map! { _ => unreachable!() };
}

#[derive(Clone, Copy)]
enum X {
    A(PhantomData<*const ()>),
}

impl<V> Internal<V> for X {
    type Array = [V; 1];

    fn slice(array: &[V; 1]) -> &[V] {
        array
    }

    fn slice_mut(array: &mut [V; 1]) -> &mut [V] {
        array
    }

    fn from_usize(arg: usize) -> X {
        assert_eq!(arg, 0);
        X::A(PhantomData)
    }

    fn to_usize(self) -> usize {
        0
    }

    fn from_function<F: FnMut(Self) -> V>(mut f: F) -> [V; 1] {
        [f(X::A(PhantomData))]
    }
}

fn assert_sync_send<T: Sync + Send>(_: T) {}

#[test]
fn assert_enum_map_does_not_copy_sync_send_dependency_of_keys() {
    let mut map = enum_map! { X::A(PhantomData) => true };
    assert_sync_send(map);
    assert_sync_send(&map);
    assert_sync_send(&mut map);
    assert_sync_send(map.iter());
    assert_sync_send(map.iter_mut());
    assert_sync_send(map.into_iter());
}<commit_msg>Update Send/Sync test from 0.2 to 0.3<commit_after>#[macro_use]
extern crate enum_map;

use enum_map::{Enum, EnumMap, IntoIter};

use std::cell::RefCell;
use std::collections::HashSet;
use std::marker::PhantomData;

#[derive(Copy, Clone, Debug, EnumMap, PartialEq)]
enum Example {
    A,
    B,
    C,
}

#[test]
fn test_bool() {
    let mut map = enum_map! { false => 24, true => 42 };
    assert_eq!(map[false], 24);
    assert_eq!(map[true], 42);
    map[false] += 1;
    assert_eq!(map[false], 25);
    for (key, item) in &mut map {
        if !key {
            *item += 1;
        }
    }
    assert_eq!(map[false], 26);
    assert_eq!(map[true], 42);
}

#[test]
fn test_clone() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(map.clone(), map);
}

#[test]
fn test_debug() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(format!("{:?}", map), "{false: 3, true: 5}");
}

#[test]
fn test_hash() {
    let map = enum_map! { false => 3, true => 5 };
    let mut set = HashSet::new();
    set.insert(map);
    assert!(set.contains(&map));
}

#[test]
fn discriminants() {
    #[derive(Debug, EnumMap, PartialEq)]
    enum Discriminants {
        A = 2000,
        B = 3000,
        C = 1000,
    }
    let mut map = EnumMap::new();
    map[Discriminants::A] = 3;
    map[Discriminants::B] = 2;
    map[Discriminants::C] = 1;
    let mut pairs = map.iter();
    assert_eq!(pairs.next(), Some((Discriminants::A, &3)));
    assert_eq!(pairs.next(), Some((Discriminants::B, &2)));
    assert_eq!(pairs.next(), Some((Discriminants::C, &1)));
    assert_eq!(pairs.next(), None);
}

#[test]
fn extend() {
    let mut map = enum_map! { _ => 0 };
    map.extend(vec![(Example::A, 3)]);
    map.extend(vec![(&Example::B, &4)]);
    assert_eq!(
        map,
        enum_map! { Example:: A => 3, Example:: B => 4, Example::C => 0 }
    );
}

#[test]
fn huge_enum() {
    #[derive(EnumMap)]
    enum Example {
        A,
        B,
        C,
        D,
        E,
        F,
        G,
        H,
        I,
        J,
        K,
        L,
        M,
        N,
        O,
        P,
        Q,
        R,
        S,
        T,
        U,
        V,
        W,
        X,
        Y,
        Z,
        Aa,
        Bb,
        Cc,
        Dd,
        Ee,
        Ff,
        Gg,
        Hh,
        Ii,
        Jj,
        Kk,
        Ll,
        Mm,
        Nn,
        Oo,
        Pp,
        Qq,
        Rr,
        Ss,
        Tt,
        Uu,
        Vv,
        Ww,
        Xx,
        Yy,
        Zz,
    }

    let map = enum_map! { _ => 2 };
    assert_eq!(map[Example::Xx], 2);
}

#[test]
fn iterator_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter()
            .len(),
        3
    );
}

#[test]
fn iter_mut_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter_mut()
            .len(),
        3
    );
}

#[test]
fn iterator_next_back() {
    assert_eq!(
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .iter()
            .next_back(),
        Some((Example::C, &3))
    );
}

#[test]
fn iter_mut_next_back() {
    assert_eq!(
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .iter_mut()
            .next_back(),
        Some((Example::C, &mut 3))
    );
}

#[test]
fn into_iter() {
    let mut iter = enum_map! { true => 5, false => 7 }.into_iter();
    assert_eq!(iter.next(), Some((false, 7)));
    assert_eq!(iter.next(), Some((true, 5)));
    assert_eq!(iter.next(), None);
    assert_eq!(iter.next(), None);
}

struct DropReporter<'a> {
    into: &'a RefCell<Vec<usize>>,
    value: usize,
}

impl<'a> Drop for DropReporter<'a> {
    fn drop(&mut self) {
        self.into.borrow_mut().push(self.value);
    }
}

#[test]
fn into_iter_drop() {
    let dropped = RefCell::new(Vec::new());
    let mut a: IntoIter<Example, _> = enum_map! {
        k => DropReporter {
            into: &dropped,
            value: k as usize,
        },
    }.into_iter();
    assert_eq!(a.next().unwrap().0, Example::A);
    assert_eq!(*dropped.borrow(), &[0]);
    drop(a);
    assert_eq!(*dropped.borrow(), &[0, 1, 2]);
}

#[test]
fn test_u8() {
    let mut map = enum_map! { b'a' => 4, _ => 0 };
    map[b'c'] = 3;
    assert_eq!(map[b'a'], 4);
    assert_eq!(map[b'b'], 0);
    assert_eq!(map[b'c'], 3);
    assert_eq!(map.iter().next(), Some((0, &0)));
}

#[derive(EnumMap)]
enum Void {}

#[test]
fn empty_map() {
    let void: EnumMap<Void, Void> = enum_map!{};
    assert!(void.is_empty());
}

#[test]
#[should_panic]
fn empty_value() {
    let _void: EnumMap<bool, Void> = enum_map! { _ => unreachable!() };
}

#[derive(Clone, Copy)]
enum X {
    A(PhantomData<*const ()>),
}

impl<V> Enum<V> for X {
    type Array = [V; 1];
    const POSSIBLE_VALUES: usize = 1;

    fn slice(array: &[V; 1]) -> &[V] {
        array
    }

    fn slice_mut(array: &mut [V; 1]) -> &mut [V] {
        array
    }

    fn from_usize(arg: usize) -> X {
        assert_eq!(arg, 0);
        X::A(PhantomData)
    }

    fn to_usize(self) -> usize {
        0
    }

    fn from_function<F: FnMut(Self) -> V>(mut f: F) -> [V; 1] {
        [f(X::A(PhantomData))]
    }
}

fn assert_sync_send<T: Sync + Send>(_: T) {}

#[test]
fn assert_enum_map_does_not_copy_sync_send_dependency_of_keys() {
    let mut map = enum_map! { X::A(PhantomData) => true };
    assert_sync_send(map);
    assert_sync_send(&map);
    assert_sync_send(&mut map);
    assert_sync_send(map.iter());
    assert_sync_send(map.iter_mut());
    assert_sync_send(map.into_iter());
}<|endoftext|>


<commit_before>//! Functions and data-structures for working with descriptor tables.
use crate::segmentation::SegmentSelector;
use core::fmt;
use core::mem::size_of;

/// A struct describing a pointer to a descriptor table (GDT / IDT).
/// This is in a format suitable for giving to 'lgdt' or 'lidt'.
#[repr(C, packed)]
pub struct DescriptorTablePointer<Entry> {
    /// Size of the DT.
    pub limit: u16,
    /// Pointer to the memory region containing the DT.
    pub base: *const Entry,
}

impl<T> Default for DescriptorTablePointer<T> {
    fn default() -> DescriptorTablePointer<T> {
        DescriptorTablePointer {
            limit: 0,
            base: core::ptr::null(),
        }
    }
}

impl<T> DescriptorTablePointer<T> {
    pub fn new(tbl: &T) -> Self {
        // GDT, LDT, and IDT all expect the limit to be set to "one less".
        // See Intel 3a, Section 3.5.1 "Segment Descriptor Tables" and
        // Section 6.10 "Interrupt Descriptor Table (IDT)".
        let len = size_of::<T>() - 1;
        assert!(len < 0x10000);
        DescriptorTablePointer {
            base: tbl as *const T,
            limit: len as u16,
        }
    }

    pub fn new_from_slice(slice: &[T]) -> Self {
        // GDT, LDT, and IDT all expect the limit to be set to "one less".
        // See Intel 3a, Section 3.5.1 "Segment Descriptor Tables" and
        // Section 6.10 "Interrupt Descriptor Table (IDT)".
        let len = slice.len() * size_of::<T>() - 1;
        assert!(len < 0x10000);
        DescriptorTablePointer {
            base: slice.as_ptr(),
            limit: len as u16,
        }
    }
}

impl<T> fmt::Debug for DescriptorTablePointer<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "DescriptorTablePointer ({} {:?})", { self.limit }, { self.base } )
    }
}

/// Load the GDTR register with the specified base and limit.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn lgdt<T>(gdt: &DescriptorTablePointer<T>) {
    llvm_asm!("lgdt ($0)" :: "r" (gdt) : "memory");
}

/// Retrieve base and limit from the GDTR register.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn sgdt<T>(idt: &mut DescriptorTablePointer<T>) {
    llvm_asm!("sgdt ($0)" : "=r" (idt as *mut DescriptorTablePointer<T>) :: "memory");
}

/// Loads the segment selector into the selector field of the local
/// descriptor table register (LDTR).
///
/// After the segment selector is loaded in the LDTR,
/// the processor uses the segment selector to locate
/// the segment descriptor for the LDT in the global
/// descriptor table (GDT).
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn load_ldtr(selector: SegmentSelector) {
    llvm_asm!("lldt $0" :: "r" (selector.bits()) : "memory");
}

/// Returns the segment selector from the local descriptor table register (LDTR).
///
/// The returned segment selector points to the segment descriptor
/// (located in the GDT) for the current LDT.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn ldtr() -> SegmentSelector {
    let selector: u16;
    llvm_asm!("sldt $0" : "=r"(selector));
    SegmentSelector::from_raw(selector)
}

/// Load the IDTR register with the specified base and limit.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn lidt<T>(idt: &DescriptorTablePointer<T>) {
    llvm_asm!("lidt ($0)" :: "r" (idt) : "memory");
}

/// Retrieve base and limit from the IDTR register.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn sidt<T>(idt: &mut DescriptorTablePointer<T>) {
    llvm_asm!("sidt ($0)" : "=r" (idt as *mut DescriptorTablePointer<T>) :: "memory");
}
<commit_msg>sgdt and friends should use +r register constraint<commit_after>//! Functions and data-structures for working with descriptor tables.
use crate::segmentation::SegmentSelector;
use core::fmt;
use core::mem::size_of;

/// A struct describing a pointer to a descriptor table (GDT / IDT).
/// This is in a format suitable for giving to 'lgdt' or 'lidt'.
#[repr(C, packed)]
pub struct DescriptorTablePointer<Entry> {
    /// Size of the DT.
    pub limit: u16,
    /// Pointer to the memory region containing the DT.
    pub base: *const Entry,
}

impl<T> Default for DescriptorTablePointer<T> {
    fn default() -> DescriptorTablePointer<T> {
        DescriptorTablePointer {
            limit: 0,
            base: core::ptr::null(),
        }
    }
}

impl<T> DescriptorTablePointer<T> {
    pub fn new(tbl: &T) -> Self {
        // GDT, LDT, and IDT all expect the limit to be set to "one less".
        // See Intel 3a, Section 3.5.1 "Segment Descriptor Tables" and
        // Section 6.10 "Interrupt Descriptor Table (IDT)".
        let len = size_of::<T>() - 1;
        assert!(len < 0x10000);
        DescriptorTablePointer {
            base: tbl as *const T,
            limit: len as u16,
        }
    }

    pub fn new_from_slice(slice: &[T]) -> Self {
        // GDT, LDT, and IDT all expect the limit to be set to "one less".
        // See Intel 3a, Section 3.5.1 "Segment Descriptor Tables" and
        // Section 6.10 "Interrupt Descriptor Table (IDT)".
        let len = slice.len() * size_of::<T>() - 1;
        assert!(len < 0x10000);
        DescriptorTablePointer {
            base: slice.as_ptr(),
            limit: len as u16,
        }
    }
}

impl<T> fmt::Debug for DescriptorTablePointer<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "DescriptorTablePointer ({} {:?})", { self.limit }, { self.base } )
    }
}

/// Load the GDTR register with the specified base and limit.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn lgdt<T>(gdt: &DescriptorTablePointer<T>) {
    llvm_asm!("lgdt ($0)" :: "r" (gdt) : "memory");
}

/// Retrieve base and limit from the GDTR register.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn sgdt<T>(idt: &mut DescriptorTablePointer<T>) {
    llvm_asm!("sgdt ($0)" : "+r" (idt as *mut DescriptorTablePointer<T>) :: "memory");
}

/// Loads the segment selector into the selector field of the local
/// descriptor table register (LDTR).
///
/// After the segment selector is loaded in the LDTR,
/// the processor uses the segment selector to locate
/// the segment descriptor for the LDT in the global
/// descriptor table (GDT).
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn load_ldtr(selector: SegmentSelector) {
    llvm_asm!("lldt $0" :: "r" (selector.bits()) : "memory");
}

/// Returns the segment selector from the local descriptor table register (LDTR).
///
/// The returned segment selector points to the segment descriptor
/// (located in the GDT) for the current LDT.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn ldtr() -> SegmentSelector {
    let selector: u16;
    llvm_asm!("sldt $0" : "+r"(selector));
    SegmentSelector::from_raw(selector)
}

/// Load the IDTR register with the specified base and limit.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn lidt<T>(idt: &DescriptorTablePointer<T>) {
    llvm_asm!("lidt ($0)" :: "r" (idt) : "memory");
}

/// Retrieve base and limit from the IDTR register.
///
/// # Safety
/// Needs CPL 0.
pub unsafe fn sidt<T>(idt: &mut DescriptorTablePointer<T>) {
    llvm_asm!("sidt ($0)" : "+r" (idt as *mut DescriptorTablePointer<T>) :: "memory");
}
<|endoftext|>


<commit_before>use crate::filesystem;
use crate::walk;

/// Whether or not to show
pub struct FileTypes {
    pub files: bool,
    pub directories: bool,
    pub symlinks: bool,
    pub sockets: bool,
    pub pipes: bool,
    pub executables_only: bool,
    pub empty_only: bool,
}

impl Default for FileTypes {
    fn default() -> FileTypes {
        FileTypes {
            files: false,
            directories: false,
            symlinks: false,
            sockets: false,
            pipes: false,
            executables_only: false,
            empty_only: false,
        }
    }
}

impl FileTypes {
    pub fn should_ignore(&self, entry: &walk::DirEntry) -> bool {
        if let Some(ref entry_type) = entry.file_type() {
            (!self.files && entry_type.is_file())
                || (!self.directories && entry_type.is_dir())
                || (!self.symlinks && entry_type.is_symlink())
                || (!self.sockets && filesystem::is_socket(*entry_type))
                || (!self.pipes && filesystem::is_pipe(*entry_type))
                || (self.executables_only
                    && !entry
                        .metadata()
                        .map(|m| filesystem::is_executable(&m))
                        .unwrap_or(false))
                || (self.empty_only && !filesystem::is_empty(&entry))
                || !(entry_type.is_file()
                    || entry_type.is_dir()
                    || entry_type.is_symlink()
                    || filesystem::is_socket(*entry_type)
                    || filesystem::is_pipe(*entry_type))
        } else {
            true
        }
    }
}
<commit_msg>Remove an unnecessary reference. (#864)<commit_after>use crate::filesystem;
use crate::walk;

/// Whether or not to show
pub struct FileTypes {
    pub files: bool,
    pub directories: bool,
    pub symlinks: bool,
    pub sockets: bool,
    pub pipes: bool,
    pub executables_only: bool,
    pub empty_only: bool,
}

impl Default for FileTypes {
    fn default() -> FileTypes {
        FileTypes {
            files: false,
            directories: false,
            symlinks: false,
            sockets: false,
            pipes: false,
            executables_only: false,
            empty_only: false,
        }
    }
}

impl FileTypes {
    pub fn should_ignore(&self, entry: &walk::DirEntry) -> bool {
        if let Some(ref entry_type) = entry.file_type() {
            (!self.files && entry_type.is_file())
                || (!self.directories && entry_type.is_dir())
                || (!self.symlinks && entry_type.is_symlink())
                || (!self.sockets && filesystem::is_socket(*entry_type))
                || (!self.pipes && filesystem::is_pipe(*entry_type))
                || (self.executables_only
                    && !entry
                        .metadata()
                        .map(|m| filesystem::is_executable(&m))
                        .unwrap_or(false))
                || (self.empty_only && !filesystem::is_empty(entry))
                || !(entry_type.is_file()
                    || entry_type.is_dir()
                    || entry_type.is_symlink()
                    || filesystem::is_socket(*entry_type)
                    || filesystem::is_pipe(*entry_type))
        } else {
            true
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Michael 'ExpHP' Lamparski
//
// Licensed under the terms of the MIT License, available at:
//  http://opensource.org/licenses/MIT
// and also included in the file COPYING at the root of this distribution.
// This file may not be copied, modified, or distributed except according
// to those terms.

use std::default::Default;
use std::ops::{Add,Sub,Mul,Div,Rem};
use std::cmp::{min,max};
use std::collections::HashMap;
use std::hash::Hash;

use num;
use num::{One,FromPrimitive};
use num::Num;

// TODO After all this time I still don't like the name; it's too easy to
//  confuse with `Factorizer`... yet I can't think of a better alternative.
//  `PrimeFactorMap`?... bleh.
/// An integer stored as its prime factorization.
///
/// A `Factorization` represents a non-negative integer stored in the form
///
/// ```text
/// pow(p1, n1) * pow(p2, n2) * ... * pow(pN, nN)
/// ```
///
/// where `p1, p2, ...` are prime numbers (or zero) and `n1, n2, ...` are positive
/// integers. Some properties are easier to compute in this form, such as the euler
/// totient, or a sum of divisors. Also of note is that because the prime factorization
/// of any given number is unique, any two `Factorization`s constructed from the same
/// `x` are equal.
///
/// A special case is permitted to allow zero, defined as `{0: 1}`. Zero to any greater
/// power, or in combination with other factors is not permitted. Also worthy of note
/// is that the factorization of `1` is an empty map.
/// Negative numbers are not permitted as most of the special mathematical properties
/// are not defined for them.
///
/// One caveat:  It is not feasible for `Factorization` to enforce that the prime
///  factors it is built from are actually prime.  This is the job of the
///  `Factorizer` used to produce it!  The behavior of any mathematical method
///  on a `Factorization` with a composite factor is **undefined**. (in the sense
///  of nonsensical results; not in the sense that the safety guidelines of Rust
///  may be violated)
#[derive(Eq,PartialEq,Debug,Clone)]
pub struct Factorization<K>
 where K: Eq + Hash,
{
	// powers are currently usize for consistency with the pow() functions
	//  in both std::num and the num crate.
	powers: HashMap<K, usize>,
}

// TODO: some of Factorization's methods need to be special cased for Zero

impl<K> Factorization<K>
 where K: Eq + Hash,
{

	/// Set the power of a prime factor in the `Factorization`. `key` is
	///  assumed to be prime (or zero). Note that while composite numbers
	///  may be accepted, the behavior of the resulting `Factorization` is
	///  ill-defined.
	pub fn set(self: &mut Self, key: K, pwr: usize)
	{
		match pwr {
			0 => self.powers.remove(&key),
			_ => self.powers.insert(key, pwr),
		};
	}

	/// Get the power of a prime factor in the `Factorization`. `key` is
	///  assumed to be prime (or zero). The value returned for non-prime
	///  keys is undefined.
	pub fn get(self: &Self, key: &K) -> usize
	{
		match self.powers.get(key) {
			None      => 0,
			Some(pwr) => *pwr,
		}
	}

	/// Create a `Factorization` for the given number, which is assumed to be
	///  prime (or zero).  Note that while composite numbers may be accepted,
	///  the behavior of the resulting `Factorization` is ill-defined.
	pub fn from_prime(prime: K) -> Self
	{
		let mut map = HashMap::new();
		map.insert(prime, 1usize);

		Factorization { powers: map }
	}

	// TODO: Make doctests less tedious-looking by using something like
	//        factorize(20), once such a function exists.

	/// Compute the integer represented by the `Factorization`.
	///
	/// # Example:
	///
	/// ```
	/// use factor::factorize;
	///
	/// let f = factorize(20u64);
	/// assert_eq!(f.product(), 20);
	/// ```
	pub fn product(self: &Self) -> K
	 where K: Clone + One,
	{
		// product( pow(p[i], n[i]) )
		let mut result: K = One::one();
		for (k,v) in self.powers.iter() {
			result = result * num::pow(k.clone(), v.clone());
		};
		result
	}

	/// Compute the total number of positive integers which evenly divide
	///  the number represented by the `Factorization` (including 1 and the
	///  number itself).
	///
	/// # Example:
	///
	/// ```
	/// use factor::factorize;
	///
	/// let f = factorize(20u64);
	/// assert_eq!(f.count_divisors(), 6);
	/// ```
	pub fn count_divisors(self: &Self) -> K
	 where K: Clone + FromPrimitive + One,
	{
		// product( n[i]+1 );  we're counting the possible ways to select a power
		//                      from 0 to n[i] (inclusive) for each prime p[i]
		let mut result: K = One::one();
		for (_,v) in self.powers.iter() {
			result = result * FromPrimitive::from_usize(v.clone() + 1).unwrap();
		};
		result
	}

	/// Compute the sum of all positive integers which evenly divide the number
	///  represented by the `Factorization` (including 1 and the number itself).
	///
	/// # Example:
	///
	/// ```
	/// use factor::factorize;
	///
	/// let f = factorize(20u64);
	/// assert_eq!(f.sum_divisors(), 42);
	/// ```
	pub fn sum_divisors(self: &Self) -> K
	 where K: Clone + One + Num,
	{
		// A geometric series for each factor
		let mut result: K = One::one();
		for (k,v) in self.powers.iter() {
			result = result * (num::pow(k.clone(), v.clone() + 1) - One::one());
			result = result / (k.clone() - One::one());
		};
		result
	}

	/// Compute the Euler totient `phi(x)`, the total number of
	///  positive integers less than `x` that are coprime to `x`.
	///
	/// # Example:
	///
	/// ```
	/// use factor::factorize;
	///
	/// let f = factorize(20u64);
	/// assert_eq!(f.totient(), 8);
	/// ```
	pub fn totient(self: &Self) -> K
	 where K: Clone + One + Num,
	{
		// product( (p[i] - 1) * pow(p[i], n[i]-1) )
		let mut result: K = One::one();
		for (k,v) in self.powers.iter() {
			result = result * num::pow(k.clone(), v.clone() - 1);
			result = result * (k.clone() - One::one());
		};
		return result;
	}

	// TODO: pending unboxed abstract types
	// fn iter_divisors(self: &Self) -> Iterator<K>

	/// Get the square root.
	///
	/// If the `Factorization` represents a perfect square, returns
	///  a `Some(Factorization)` representing the square root.
	///  Otherwise, returns `None`.
	///
	/// # Example:
	///
	/// ```
	/// use factor::factorize;
	///
	/// let mut f = factorize(20u64);
	/// assert!(f.sqrt().is_none());    // 20 is not square!
	///
	/// f = f * factorize(5);
	/// assert_eq!(f.sqrt().unwrap().product(), 10);  // sqrt(100)
	/// ```
	pub fn sqrt(self: &Self) -> Option<Self>
	 where K: Clone,
	{
		let mut result = self.clone();
		for (_,v) in result.powers.iter_mut() {

			if *v % 2 == 1 {
				return None; // Odd power!  Abort!  Abort!
			};

			*v = *v / 2;
		};
		Some(result)
	}

	// TODO: Docs & test
	pub fn pow(self: &Self, pwr: usize) -> Self
	 where K: Clone,
	{
		let mut result = self.clone();
		for (_,v) in result.powers.iter_mut() {
			*v = *v * pwr;
		};
		result
	}

	// TODO: Docs & test
	pub fn gcd(self: &Self, other: &Self) -> Self
	 where K: Clone,
	{
		// Iterate through shorter list
		if other.powers.len() < self.powers.len() {
			return self.gcd(other);
		};

		let mut result: Self = One::one();
		for (k,v) in other.powers.clone().into_iter() {
			result.set(k.clone(), min(self.get(&k), v));
		};
		result
	}

	// TODO: Docs & test
	pub fn lcm(self: &Self, other: &Self) -> Self
	 where K: Clone,
	{
		let mut result = self.clone();
		for (k,v) in other.powers.clone().into_iter() {
			result.set(k.clone(), max(self.get(&k), v));
		};
		result
	}

	// TODO: Reasonable (?) methods to implement
	// pub fn is_multiple_of(self: &Self, other: &Self) -> bool
}

impl<K> One
for Factorization<K>
 where K: Eq + Clone + Hash,
{
	/// Creates a Factorization representing `1`.
	fn one() -> Self
	{ Factorization { powers: HashMap::new() } }
}

impl<K> Default
for Factorization<K>
 where K: Eq + Clone + Hash,
{
	/// Creates a Factorization representing `1`.
	fn default() -> Self
	{ One::one() }
}

impl<K> Mul<Factorization<K>>
for Factorization<K>
 where K: Eq + Clone + Hash,
{
	type Output = Self;
	fn mul(self: Self, other: Self) -> Self
	{
		let mut result = self;
		for (k,v) in other.powers.into_iter() {
			let current = result.get(&k); // owned proxy
			result.set(k.clone(), current + v);
		}
		result
	}
}
<commit_msg>Add adapter methods for `HashMap`s and iteration<commit_after>// Copyright 2015 Michael 'ExpHP' Lamparski
//
// Licensed under the terms of the MIT License, available at:
//  http://opensource.org/licenses/MIT
// and also included in the file COPYING at the root of this distribution.
// This file may not be copied, modified, or distributed except according
// to those terms.

use std::default::Default;
use std::ops::{Add,Sub,Mul,Div,Rem};
use std::cmp::{min,max};
use std::collections::HashMap;
use std::collections::hash_map;
use std::hash::Hash;

use num;
use num::{One,FromPrimitive};
use num::Num;

// TODO After all this time I still don't like the name; it's too easy to
//  confuse with `Factorizer`... yet I can't think of a better alternative.
//  `PrimeFactorMap`?... bleh.
/// An integer stored as its prime factorization.
///
/// A `Factorization` represents a non-negative integer stored in the form
///
/// ```text
/// pow(p1, n1) * pow(p2, n2) * ... * pow(pN, nN)
/// ```
///
/// where `p1, p2, ...` are prime numbers (or zero) and `n1, n2, ...` are positive
/// integers. Some properties are easier to compute in this form, such as the euler
/// totient, or a sum of divisors. Also of note is that because the prime factorization
/// of any given number is unique, any two `Factorization`s constructed from the same
/// `x` are equal.
///
/// A special case is permitted to allow zero, defined as `{0: 1}`. Zero to any greater
/// power, or in combination with other factors is not permitted. Also worthy of note
/// is that the factorization of `1` is an empty map.
/// Negative numbers are not permitted as most of the special mathematical properties
/// are not defined for them.
///
/// One caveat:  It is not feasible for `Factorization` to enforce that the prime
///  factors it is built from are actually prime.  This is the job of the
///  `Factorizer` used to produce it!  The behavior of any mathematical method
///  on a `Factorization` with a composite factor is **undefined**. (in the sense
///  of nonsensical results; not in the sense that the safety guidelines of Rust
///  may be violated)
#[derive(Eq,PartialEq,Debug,Clone)]
pub struct Factorization<K>
 where K: Eq + Hash,
{
	// powers are currently usize for consistency with the pow() functions
	//  in both std::num and the num crate.
	powers: HashMap<K, usize>,
}

// TODO: some of Factorization's methods need to be special cased for Zero

impl<K> Factorization<K>
 where K: Eq + Hash,
{

	/// Set the power of a prime factor in the `Factorization`. `key` is
	///  assumed to be prime (or zero). Note that while composite numbers
	///  may be accepted, the behavior of the resulting `Factorization` is
	///  ill-defined.
	pub fn set(self: &mut Self, key: K, pwr: usize)
	{
		match pwr {
			0 => self.powers.remove(&key),
			_ => self.powers.insert(key, pwr),
		};
	}

	/// Get the power of a prime factor in the `Factorization`. `key` is
	///  assumed to be prime (or zero). The value returned for non-prime
	///  keys is undefined.
	pub fn get(self: &Self, key: &K) -> usize
	{
		match self.powers.get(key) {
			None      => 0,
			Some(pwr) => *pwr,
		}
	}

	/// Create a `Factorization` for the given number, which is assumed to be
	///  prime (or zero).  Note that while composite numbers may be accepted,
	///  the behavior of the resulting `Factorization` is ill-defined.
	pub fn from_prime(prime: K) -> Self
	{
		let mut map = HashMap::new();
		map.insert(prime, 1usize);

		Factorization { powers: map }
	}

	// TODO: Make doctests less tedious-looking by using something like
	//        factorize(20), once such a function exists.

	/// Compute the integer represented by the `Factorization`.
	///
	/// # Example:
	///
	/// ```
	/// use factor::factorize;
	///
	/// let f = factorize(20u64);
	/// assert_eq!(f.product(), 20);
	/// ```
	pub fn product(self: &Self) -> K
	 where K: Clone + One,
	{
		// product( pow(p[i], n[i]) )
		let mut result: K = One::one();
		for (k,v) in self.powers.iter() {
			result = result * num::pow(k.clone(), v.clone());
		};
		result
	}

	/// Compute the total number of positive integers which evenly divide
	///  the number represented by the `Factorization` (including 1 and the
	///  number itself).
	///
	/// # Example:
	///
	/// ```
	/// use factor::factorize;
	///
	/// let f = factorize(20u64);
	/// assert_eq!(f.count_divisors(), 6);
	/// ```
	pub fn count_divisors(self: &Self) -> K
	 where K: Clone + FromPrimitive + One,
	{
		// product( n[i]+1 );  we're counting the possible ways to select a power
		//                      from 0 to n[i] (inclusive) for each prime p[i]
		let mut result: K = One::one();
		for (_,v) in self.powers.iter() {
			result = result * FromPrimitive::from_usize(v.clone() + 1).unwrap();
		};
		result
	}

	/// Compute the sum of all positive integers which evenly divide the number
	///  represented by the `Factorization` (including 1 and the number itself).
	///
	/// # Example:
	///
	/// ```
	/// use factor::factorize;
	///
	/// let f = factorize(20u64);
	/// assert_eq!(f.sum_divisors(), 42);
	/// ```
	pub fn sum_divisors(self: &Self) -> K
	 where K: Clone + One + Num,
	{
		// A geometric series for each factor
		let mut result: K = One::one();
		for (k,v) in self.powers.iter() {
			result = result * (num::pow(k.clone(), v.clone() + 1) - One::one());
			result = result / (k.clone() - One::one());
		};
		result
	}

	/// Compute the Euler totient `phi(x)`, the total number of
	///  positive integers less than `x` that are coprime to `x`.
	///
	/// # Example:
	///
	/// ```
	/// use factor::factorize;
	///
	/// let f = factorize(20u64);
	/// assert_eq!(f.totient(), 8);
	/// ```
	pub fn totient(self: &Self) -> K
	 where K: Clone + One + Num,
	{
		// product( (p[i] - 1) * pow(p[i], n[i]-1) )
		let mut result: K = One::one();
		for (k,v) in self.powers.iter() {
			result = result * num::pow(k.clone(), v.clone() - 1);
			result = result * (k.clone() - One::one());
		};
		return result;
	}

	// TODO: pending unboxed abstract types
	// fn iter_divisors(self: &Self) -> Iterator<K>

	/// Get the square root.
	///
	/// If the `Factorization` represents a perfect square, returns
	///  a `Some(Factorization)` representing the square root.
	///  Otherwise, returns `None`.
	///
	/// # Example:
	///
	/// ```
	/// use factor::factorize;
	///
	/// let mut f = factorize(20u64);
	/// assert!(f.sqrt().is_none());    // 20 is not square!
	///
	/// f = f * factorize(5);
	/// assert_eq!(f.sqrt().unwrap().product(), 10);  // sqrt(100)
	/// ```
	pub fn sqrt(self: &Self) -> Option<Self>
	 where K: Clone,
	{
		let mut result = self.clone();
		for (_,v) in result.powers.iter_mut() {

			if *v % 2 == 1 {
				return None; // Odd power!  Abort!  Abort!
			};

			*v = *v / 2;
		};
		Some(result)
	}

	// TODO: Docs & test
	pub fn pow(self: &Self, pwr: usize) -> Self
	 where K: Clone,
	{
		let mut result = self.clone();
		for (_,v) in result.powers.iter_mut() {
			*v = *v * pwr;
		};
		result
	}

	// TODO: Docs & test
	pub fn gcd(self: &Self, other: &Self) -> Self
	 where K: Clone,
	{
		// Iterate through shorter list
		if other.powers.len() < self.powers.len() {
			return self.gcd(other);
		};

		let mut result: Self = One::one();
		for (k,v) in other.powers.clone().into_iter() {
			result.set(k.clone(), min(self.get(&k), v));
		};
		result
	}

	// TODO: Docs & test
	pub fn lcm(self: &Self, other: &Self) -> Self
	 where K: Clone,
	{
		let mut result = self.clone();
		for (k,v) in other.powers.clone().into_iter() {
			result.set(k.clone(), max(self.get(&k), v));
		};
		result
	}

	/// Iterate over unique prime factors.
	pub fn primes(self: &Self) -> hash_map::Keys<K, usize> { self.powers.keys() }
	/// Iterate over `(prime, power)` pairs.
	pub fn iter(self: &Self) -> hash_map::Iter<K, usize> { self.powers.iter() }

	/// Immutably borrow the underlying `HashMap`.
	pub fn as_hash_map(self: &Self) -> &HashMap<K, usize> { &self.powers }
	/// Consume to obtain the underlying `HashMap`.
	pub fn into_hash_map(self: Self) -> HashMap<K, usize> { self.powers }

	// TODO: Reasonable (?) methods to implement
	// pub fn is_multiple_of(self: &Self, other: &Self) -> bool
}

impl<K> One
for Factorization<K>
 where K: Eq + Clone + Hash,
{
	/// Creates a Factorization representing `1`.
	fn one() -> Self
	{ Factorization { powers: HashMap::new() } }
}

impl<K> Default
for Factorization<K>
 where K: Eq + Clone + Hash,
{
	/// Creates a Factorization representing `1`.
	fn default() -> Self
	{ One::one() }
}

impl<K> Mul<Factorization<K>>
for Factorization<K>
 where K: Eq + Clone + Hash,
{
	type Output = Self;
	fn mul(self: Self, other: Self) -> Self
	{
		let mut result = self;
		for (k,v) in other.powers.into_iter() {
			let current = result.get(&k); // owned proxy
			result.set(k.clone(), current + v);
		}
		result
	}
}
<|endoftext|>


<commit_before>fn factsum(n: usize) -> usize {
    n.to_string()
     .chars()
     .map(|c| {
         match c {
             '0' => 1,
             '1' => 1,
             '2' => 2,
             '3' => 6,
             '4' => 24,
             '5' => 120,
             '6' => 720,
             '7' => 5040,
             '8' => 40320,
             '9' => 362880,
             _ => panic!(),
         }
     })
     .fold(0, |x, acc| acc + x)
}

fn fill(cache: &mut Vec<usize>, i: usize) -> usize {
    let mut chain = vec![i];
    let mut next = i;
    loop {
        next = factsum(next);
        if chain.contains(&next) {
            return chain.len();
        } else if cache.len() > next && cache[next] != 0 {
            return chain.len() + cache[next];
        } else {
            chain.push(next);
        }
    }
}

pub fn main() {
    const MAX: usize = 1_000_000;
    let mut cache: Vec<usize> = vec![0; MAX];
    let mut count = 0;
    for i in 0..MAX {
        let chainlength = fill(&mut cache, i);
        cache[i] = chainlength;
        if chainlength == 60 {
            count += 1;
        }
    }
    println!("{}", count);
}
<commit_msg>switch to common function<commit_after>use common::digit_fact_sum;

fn fill(cache: &mut Vec<usize>, i: usize) -> usize {
    let mut chain = vec![i];
    let mut next = i;
    loop {
        next = digit_fact_sum(next);
        if chain.contains(&next) {
            return chain.len();
        } else if cache.len() > next && cache[next] != 0 {
            return chain.len() + cache[next];
        } else {
            chain.push(next);
        }
    }
}

pub fn main() {
    const MAX: usize = 1_000_000;
    let mut cache: Vec<usize> = vec![0; MAX];
    let mut count = 0;
    for i in 0..MAX {
        let chainlength = fill(&mut cache, i);
        cache[i] = chainlength;
        if chainlength == 60 {
            count += 1;
        }
    }
    println!("{}", count);
}
<|endoftext|>


<commit_before>//! Frame parsers and data handlers
//!
//! Parse various frame types and return a fully-constructed object. See individual functions for
//! their descriptions.

use structs::{Frame, Callsign, InformationField};
use constants;
use util;

pub fn parse_frame(raw_frame: &[u8]) -> Frame {
    for win in raw_frame.windows(2) {
        if win == constants::ADDR_INFO_DELIM {
            return parse_frame_ax25(raw_frame);
        }
    }
    parse_frame_text(raw_frame)
}

pub fn parse_frame_text(raw_frame: &[u8]) -> Frame {
    // src>dest[,path]:info
    let src_dest:  usize = raw_frame.iter().position(|x| *x == b'>').unwrap();
    let path_info: usize = raw_frame.iter().position(|x| *x == b':').unwrap();

    let source: Callsign = parse_callsign_text(&raw_frame[..src_dest]);
    let mut dest: Callsign = Callsign::new();
    let info: InformationField = parse_info_field(&raw_frame[(path_info + 1)..]);

    // Full path slice
    let mut _path: Vec<Callsign> = Vec::new();
    let _paths: &[u8] = &raw_frame[src_dest + 1..path_info];
    for (ind, path) in _paths.split(|x| *x == b',').enumerate() {
        if ind == 0 {
            dest = parse_callsign_text(path);
        } else {
            _path.push(parse_callsign_text(path));
        }
    }
    Frame {
        source: source,
        destination: dest,
        path: _path,
        info: info
    }
}

pub fn parse_frame_ax25(raw_frame: &[u8]) -> Frame {
    let mut _frame: &[u8] = raw_frame;
    let mut kiss_call: bool = false;

    if _frame.starts_with(&[constants::KISS_DATA_FRAME]) {
        let mut ind: usize = 0;
        for (id, byt) in _frame.iter().enumerate() {
            if byt == &constants::KISS_DATA_FRAME {
                continue;
            } else {
                ind = id;
                break;
            }
        }
        _frame = &_frame[ind..];
        kiss_call = true;
    }
    if _frame.ends_with(&[constants::KISS_DATA_FRAME]) {
        let mut ind: usize = 0;
        for (id, byt) in _frame.iter().rev().enumerate() {
            if byt == &constants::KISS_DATA_FRAME {
                continue;
            } else {
                ind = id;
                break;
            }
        }
        _frame = &_frame[..(_frame.len() - ind)];
        kiss_call = true;
    }

    let mut info_pos: usize = 0;
    for win in _frame.windows(2) {
        if win == constants::ADDR_INFO_DELIM {
            break;
        }
        info_pos += 1;
    }
    let (frame_addressing, _) = _frame.split_at(info_pos);
    let (_, mut info_field)   = _frame.split_at(info_pos + 2);
    if info_field.ends_with(&[0xff, 0x07]) {
        info_field = &info_field[..(info_field.len() - 2)];
    }
    let dest: Callsign = parse_callsign_ax25(&frame_addressing, kiss_call);
    let src: Callsign = parse_callsign_ax25(&frame_addressing[7..], kiss_call);

    let mut path: Vec<Callsign> = Vec::new();
    for chunk in frame_addressing[14..].chunks(7) {
        path.push(parse_callsign_ax25(chunk, false));
    }

    Frame {
        source: src,
        destination: dest,
        path: path,
        info: parse_info_field(info_field),
    }
}

pub fn parse_callsign(raw_callsign: &[u8]) -> Callsign {
    parse_callsign_text(raw_callsign)
}

pub fn parse_callsign_text(raw_callsign: &[u8]) -> Callsign {
    let mut _callsign: String = String::from_utf8(raw_callsign.to_vec()).unwrap();
    let mut ssid: u8 = 0;
    let mut digi: bool = false;

    if _callsign.contains('*') {
        _callsign.trim_matches('*');
        digi = true;
    }
    let pos: Option<usize> = _callsign.find('-');
    match pos {
        Some(x) => {
            _callsign = {
                let (call, id): (&str, &str) = _callsign.split_at(x);
                ssid = id[1..].parse::<u8>().unwrap();
                call.to_string()
            };
        },
        None => {}
    }
    Callsign {
        callsign: _callsign,
        ssid: ssid,
        digi: digi
    }
}

pub fn parse_callsign_ax25(raw_callsign: &[u8], kiss_call: bool) -> Callsign {
    // based on ax.25 v2.0 protocol, NOT v2.2
    let mut _callsign: Vec<u8> = Vec::new();
    let mut digi: bool = false;

    for chunk in raw_callsign[..6].iter() {
        let mut _chunk = chunk & 0xFF;
        // shift 1 bit
        _chunk = _chunk >> 1;
        if (_chunk as char).is_alphanumeric() {
            _callsign.push(_chunk);
        }
    }

    // seventh byte is ssid or digi
    let seven_chunk: u8 = raw_callsign[6] & 0xFF;
    let ssid = (seven_chunk >> 1) & 0x0F;

    // fixme - see python module
    if kiss_call {
        if (seven_chunk >> 1 & 0x80) == 1 {
            digi = true;
        }
    } else {
        if (seven_chunk & 0x80) == 1 {
            digi = true;
        }
    }
    Callsign {
        callsign: String::from_utf8(_callsign).unwrap(),
        ssid: ssid,
        digi: digi
    }
}

pub fn parse_info_field(raw_data: &[u8]) -> InformationField {
    let first_byte: &u8 = raw_data.first().unwrap();
    let data_type: String = constants::DATA_TYPE_MAP.get(first_byte).unwrap().to_string();
    InformationField {
        data: raw_data.to_vec(),
        data_type: data_type,
        safe: true
    }
}

pub fn default_data_handler(data: &[u8], data_type: &str) -> String {
    String::new()
}
<commit_msg>default_data_handler<commit_after>//! Frame parsers and data handlers
//!
//! Parse various frame types and return a fully-constructed object. See individual functions for
//! their descriptions.

use structs::{Frame, Callsign, InformationField};
use constants;
use util;

pub fn parse_frame(raw_frame: &[u8]) -> Frame {
    for win in raw_frame.windows(2) {
        if win == constants::ADDR_INFO_DELIM {
            return parse_frame_ax25(raw_frame);
        }
    }
    parse_frame_text(raw_frame)
}

pub fn parse_frame_text(raw_frame: &[u8]) -> Frame {
    // src>dest[,path]:info
    let src_dest:  usize = raw_frame.iter().position(|x| *x == b'>').unwrap();
    let path_info: usize = raw_frame.iter().position(|x| *x == b':').unwrap();

    let source: Callsign = parse_callsign_text(&raw_frame[..src_dest]);
    let mut dest: Callsign = Callsign::new();
    let info: InformationField = parse_info_field(&raw_frame[(path_info + 1)..]);

    // Full path slice
    let mut _path: Vec<Callsign> = Vec::new();
    let _paths: &[u8] = &raw_frame[src_dest + 1..path_info];
    for (ind, path) in _paths.split(|x| *x == b',').enumerate() {
        if ind == 0 {
            dest = parse_callsign_text(path);
        } else {
            _path.push(parse_callsign_text(path));
        }
    }
    Frame {
        source: source,
        destination: dest,
        path: _path,
        info: info
    }
}

pub fn parse_frame_ax25(raw_frame: &[u8]) -> Frame {
    let mut _frame: &[u8] = raw_frame;
    let mut kiss_call: bool = false;

    if _frame.starts_with(&[constants::KISS_DATA_FRAME]) {
        let mut ind: usize = 0;
        for (id, byt) in _frame.iter().enumerate() {
            if byt == &constants::KISS_DATA_FRAME {
                continue;
            } else {
                ind = id;
                break;
            }
        }
        _frame = &_frame[ind..];
        kiss_call = true;
    }
    if _frame.ends_with(&[constants::KISS_DATA_FRAME]) {
        let mut ind: usize = 0;
        for (id, byt) in _frame.iter().rev().enumerate() {
            if byt == &constants::KISS_DATA_FRAME {
                continue;
            } else {
                ind = id;
                break;
            }
        }
        _frame = &_frame[..(_frame.len() - ind)];
        kiss_call = true;
    }

    let mut info_pos: usize = 0;
    for win in _frame.windows(2) {
        if win == constants::ADDR_INFO_DELIM {
            break;
        }
        info_pos += 1;
    }
    let (frame_addressing, _) = _frame.split_at(info_pos);
    let (_, mut info_field)   = _frame.split_at(info_pos + 2);
    if info_field.ends_with(&[0xff, 0x07]) {
        info_field = &info_field[..(info_field.len() - 2)];
    }
    let dest: Callsign = parse_callsign_ax25(&frame_addressing, kiss_call);
    let src: Callsign = parse_callsign_ax25(&frame_addressing[7..], kiss_call);

    let mut path: Vec<Callsign> = Vec::new();
    for chunk in frame_addressing[14..].chunks(7) {
        path.push(parse_callsign_ax25(chunk, false));
    }

    Frame {
        source: src,
        destination: dest,
        path: path,
        info: parse_info_field(info_field),
    }
}

pub fn parse_callsign(raw_callsign: &[u8]) -> Callsign {
    parse_callsign_text(raw_callsign)
}

pub fn parse_callsign_text(raw_callsign: &[u8]) -> Callsign {
    let mut _callsign: String = String::from_utf8(raw_callsign.to_vec()).unwrap();
    let mut ssid: u8 = 0;
    let mut digi: bool = false;

    if _callsign.contains('*') {
        _callsign.trim_matches('*');
        digi = true;
    }
    let pos: Option<usize> = _callsign.find('-');
    match pos {
        Some(x) => {
            _callsign = {
                let (call, id): (&str, &str) = _callsign.split_at(x);
                ssid = id[1..].parse::<u8>().unwrap();
                call.to_string()
            };
        },
        None => {}
    }
    Callsign {
        callsign: _callsign,
        ssid: ssid,
        digi: digi
    }
}

pub fn parse_callsign_ax25(raw_callsign: &[u8], kiss_call: bool) -> Callsign {
    // based on ax.25 v2.0 protocol, NOT v2.2
    let mut _callsign: Vec<u8> = Vec::new();
    let mut digi: bool = false;

    for chunk in raw_callsign[..6].iter() {
        let mut _chunk = chunk & 0xFF;
        // shift 1 bit
        _chunk = _chunk >> 1;
        if (_chunk as char).is_alphanumeric() {
            _callsign.push(_chunk);
        }
    }

    // seventh byte is ssid or digi
    let seven_chunk: u8 = raw_callsign[6] & 0xFF;
    let ssid = (seven_chunk >> 1) & 0x0F;

    // fixme - see python module
    if kiss_call {
        if (seven_chunk >> 1 & 0x80) == 1 {
            digi = true;
        }
    } else {
        if (seven_chunk & 0x80) == 1 {
            digi = true;
        }
    }
    Callsign {
        callsign: String::from_utf8(_callsign).unwrap(),
        ssid: ssid,
        digi: digi
    }
}

pub fn parse_info_field(raw_data: &[u8]) -> InformationField {
    let first_byte: &u8 = raw_data.first().unwrap();
    let data_type: String = constants::DATA_TYPE_MAP.get(first_byte).unwrap().to_string();
    InformationField {
        data: raw_data.to_vec(),
        data_type: data_type,
        safe: true
    }
}

pub fn default_data_handler(data: &[u8], data_type: u8) -> InformationField {
    let _data_type: String = constants::DATA_TYPE_MAP.get(&data_type).unwrap().to_string();
    InformationField {
        data: data.to_vec(),
        data_type: _data_type,
        safe: false
    }
}
<|endoftext|>


<commit_before>//! Helper module to compute a CRC32 checksum

use std::io;
use std::io::prelude::*;

use crc32fast::Hasher;

/// Reader that validates the CRC32 when it reaches the EOF.
pub struct Crc32Reader<R>
{
    inner: R,
    hasher: Hasher,
    check: u32,
}

impl<R> Crc32Reader<R>
{
    /// Get a new Crc32Reader which check the inner reader against checksum.
    pub fn new(inner: R, checksum: u32) -> Crc32Reader<R>
    {
        Crc32Reader
        {
            inner: inner,
            hasher: Hasher::new(),
            check: checksum,
        }
    }

    fn check_matches(&self) -> bool
    {
        self.check == self.hasher.clone().finalize()
    }

    pub fn into_inner(self) -> R {
        self.inner
    }
}

impl<R: Read> Read for Crc32Reader<R>
{
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize>
    {
        let count = match self.inner.read(buf)
        {
            Ok(0) if !self.check_matches() => { return Err(io::Error::new(io::ErrorKind::Other, "Invalid checksum")) },
            Ok(n) => n,
            Err(e) => return Err(e),
        };
        self.hasher.update(&buf[0..count]);
        Ok(count)
    }
}
<commit_msg>Add some simple crc32 reader tests<commit_after>//! Helper module to compute a CRC32 checksum

use std::io;
use std::io::prelude::*;

use crc32fast::Hasher;

/// Reader that validates the CRC32 when it reaches the EOF.
pub struct Crc32Reader<R>
{
    inner: R,
    hasher: Hasher,
    check: u32,
}

impl<R> Crc32Reader<R>
{
    /// Get a new Crc32Reader which check the inner reader against checksum.
    pub fn new(inner: R, checksum: u32) -> Crc32Reader<R>
    {
        Crc32Reader
        {
            inner: inner,
            hasher: Hasher::new(),
            check: checksum,
        }
    }

    fn check_matches(&self) -> bool
    {
        self.check == self.hasher.clone().finalize()
    }

    pub fn into_inner(self) -> R {
        self.inner
    }
}

impl<R: Read> Read for Crc32Reader<R>
{
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize>
    {
        let count = match self.inner.read(buf)
        {
            Ok(0) if !self.check_matches() => { return Err(io::Error::new(io::ErrorKind::Other, "Invalid checksum")) },
            Ok(n) => n,
            Err(e) => return Err(e),
        };
        self.hasher.update(&buf[0..count]);
        Ok(count)
    }
}

#[cfg(test)]
mod tests
{
    use super::*;
    use std::io::Read;
    use std::io::Cursor;

    #[test]
    fn test_empty_reader()
    {
        let data: &[u8] = b"";
        let mut buf = [0; 1];

        let mut reader = Crc32Reader::new(data, 0);
        assert_eq!(reader.read(&mut buf).unwrap(), 0);

        let mut reader = Crc32Reader::new(data, 1);
        assert!(reader.read(&mut buf).unwrap_err().to_string().contains("Invalid checksum"));
    }

    #[test]
    fn test_byte_by_byte()
    {
        let data: &[u8] = b"1234";
        let mut buf = [0; 1];

        let mut reader = Crc32Reader::new(data, 0x9be3e0a3);
        assert_eq!(reader.read(&mut buf).unwrap(), 1);
        assert_eq!(reader.read(&mut buf).unwrap(), 1);
        assert_eq!(reader.read(&mut buf).unwrap(), 1);
        assert_eq!(reader.read(&mut buf).unwrap(), 1);
        assert_eq!(reader.read(&mut buf).unwrap(), 0);
        // Can keep reading 0 bytes after the end
        assert_eq!(reader.read(&mut buf).unwrap(), 0);
    }
}
<|endoftext|>