<commit_before>use nom::{IResult, is_space};
use std::collections::{HashMap, HashSet};
use std::collections::hash_map::Entry;
use std::fmt::Debug;
use std::hash::Hash;
use std::iter::FromIterator;
use std::str::FromStr;

use util::parsing::*;

/// Structure containing the elements of type `A` in a equivalence class of type `B`
#[derive(Debug, Eq, PartialEq)]
pub struct EquivalenceClass<A, B>
    where A: Eq + Hash,
{
    label: B,
    set: Option<HashSet<A>>,
}

impl<A, B> From<(B, Option<Vec<A>>)> for EquivalenceClass<A, B>
    where A: Eq + Hash,
{
    fn from((label, set): (B, Option<Vec<A>>)) -> EquivalenceClass<A, B> {
        EquivalenceClass {
            label,
            set: set.and_then(|elements| Some(HashSet::from_iter(elements))),
        }
    }
}

/// A struct containing a remapping of elements of type `A` into their respective equivalence classes of type `B`.
#[derive(Clone, Debug)]
pub struct EquivalenceRelation<A, B>
    where A: Eq + Hash,
{
    map: HashMap<A, B>,
    default: B,
}

impl<A, B> PartialEq for EquivalenceRelation<A, B>
    where A: Eq + Hash,
          B: PartialEq,
{
    fn eq(&self, other: &Self) -> bool {
        self.default == other.default && self.map == other.map
    }
}

impl<A, B> EquivalenceRelation<A, B>
    where A: Eq + Hash,
          B: Clone + Eq + Hash,
{
    pub fn new(map: HashMap<B, HashSet<A>>, default: B) -> Self {
        match Self::new_safe(map, default) {
            Ok(relation) => relation,
            Err(error) => panic!(error),
        }
    }

    pub fn new_safe(map: HashMap<B, HashSet<A>>, default: B) -> Result<Self, String> {
        let mut relation_map = HashMap::new();
        for (class_name, members) in map {
            if class_name == default {
                return Err(String::from(
                    "There can only be one default class in the equivalence relation!"
                ));
            }

            for value in members {
                match relation_map.entry(value) {
                    Entry::Vacant(v) => {
                        v.insert(class_name.clone());
                    },
                    Entry::Occupied(_) => {
                        return Err(String::from(
                            "All classes of the equivalence relation must be disjoint!"
                        ));
                    },
                }
            }
        }

        Ok(EquivalenceRelation { map: relation_map, default })
    }

    // returns the equivalence class of a given value
    pub fn project(&self, key: &A) -> B {
        match self.map.get(key) {
            None => self.default.clone(),
            Some(e) => e.clone(),
        }
    }
}

impl<A, B> From<Vec<EquivalenceClass<A, B>>> for EquivalenceRelation<A, B>
    where A: Eq + Hash,
          B: Clone + Eq + Hash,
{
    fn from(classes: Vec<EquivalenceClass<A, B>>) -> EquivalenceRelation<A, B> {
        let mut map = HashMap::new();
        let mut default = None;

        for EquivalenceClass { label, set } in classes {
            if let Some(elements) = set {
                for element in elements {
                    map.insert(element, label.clone());
                }
            } else {
                default = Some(label);
            }
        }

        EquivalenceRelation { map, default: default.unwrap() }
    }
}

impl<A, B> FromStr for EquivalenceRelation<A, B>
    where A: Clone + Eq + Hash + FromStr,
          A::Err: Debug,
          B: Clone + Eq + Hash + FromStr,
          B::Err: Debug,
{
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut map = HashMap::new();
        let mut default = None;

        for l in s.lines() {
            if !l.is_empty() {
                match l.trim().parse()? {
                    EquivalenceClass { label, set: Some(elements) } => {
                        map.insert(label, elements);
                    },
                    EquivalenceClass { label, set: None } => {
                        default = Some(label);
                    },
                }
            }
        }

        if let Some(label) = default {
            if let Ok(relation) = EquivalenceRelation::new_safe(map, label) {
                return Ok(relation);
            }
        }

        Err(format!("Could not parse {}", s))
    }
}

impl <A, B> FromStr for EquivalenceClass<A, B>
    where A: Eq + FromStr + Hash,
          A::Err: Debug,
          B: FromStr,
          B::Err: Debug,
{
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match parse_set(s.as_bytes()) {
            IResult::Done(_, result) => Ok(result),
            _                        => Err(format!("Could not parse {}", s))
        }
    }
}

fn parse_set<A, B>(input: &[u8]) -> IResult<&[u8], EquivalenceClass<A, B>>
    where A: Eq + FromStr + Hash,
          A::Err: Debug,
          B: FromStr,
          B::Err: Debug,
{
    do_parse!(
        input,
        label: parse_token >>
            take_while!(is_space) >>
            set: alt!(
                do_parse!(
                    tag!("*") >> (None)
                )
                    |
                do_parse!(
                    the_set: parse_heap >> (Some(the_set))
                )
            ) >>
            (EquivalenceClass {
                label,
                set,
            })
    )
}

fn parse_heap<A>(input: &[u8]) -> IResult<&[u8], HashSet<A>>
    where A: Eq + FromStr + Hash,
          A::Err: Debug,
{
    match parse_vec(input, parse_token, "[", "]", ",") {
        IResult::Done(rest, parsed) => IResult::Done(rest, HashSet::from_iter(parsed)),
        IResult::Incomplete(needed) => IResult::Incomplete(needed),
        IResult::Error(error) => IResult::Error(error),
    }
}

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

    #[test]
    fn test_equivalence_relation_project() {
        let rel: EquivalenceRelation<u8, u8> = String::from("0 [0, 1]\n1 [2, 4]\n2 *").parse().unwrap();
        assert_eq!(0, rel.project(&1));
        assert_eq!(1, rel.project(&2));
        assert_eq!(2, rel.project(&3));
        assert_eq!(1, rel.project(&4));
    }

    #[test]
    fn test_equivalence_class_from_str_legal_input() {
        let legal_inputs = vec![
            ("0 [0, 1]", EquivalenceClass::from((0, Some(vec![0, 1])))),
            ("0  [1, 0]", EquivalenceClass::from((0, Some(vec![0, 1])))),
            ("0  [0, 1, 1]", EquivalenceClass::from((0, Some(vec![0, 1])))),
            ("0 *", EquivalenceClass::from((0, None))),
        ];

        for (legal_input, correct_class) in legal_inputs {
            assert_eq!(correct_class,
                       EquivalenceClass::from_str(legal_input).unwrap());
        }
    }

    #[test]
    fn test_equivalence_class_from_str_illegal_input() {
        let illegal_inputs = vec![
            " 0 [0, 1]",
            "[0, 1]",
            "*",
        ];

        for illegal_input in illegal_inputs {
            match EquivalenceClass::<u8, u8>::from_str(illegal_input) {
                Ok(parsed) =>
                    panic!("Was able to parse the illegal input \'{}\' as \'{:?}\'",
                           illegal_input, parsed),
                Err(_) => (),
            }
        }
    }

    #[test]
    fn test_equivalence_relation_from_str_legal_input() {
        let legal_inputs = vec![
            ("0 [0, 1]\n1 [2, 3]\n2 *", EquivalenceRelation::from(vec![
                EquivalenceClass::from((0, Some(vec![0, 1]))),
                EquivalenceClass::from((1, Some(vec![2, 3]))),
                EquivalenceClass::from((2, None)),
            ])),
        ];

        for (legal_input, correct_relation) in legal_inputs {
            assert_eq!(correct_relation,
                       EquivalenceRelation::from_str(legal_input).unwrap());
        }
    }

    #[test]
    fn test_equivalence_relation_from_str_illegal_input() {
        let illegal_inputs = vec![
            " 0 [0, 1]\n1 [2, 3]\n2 *",
            "0 [0, 1]1 [2, 3]2 *",
            "0 [0, 1]\n1 [1, 2]\n2 *",
        ];

        for illegal_input in illegal_inputs {
            match EquivalenceRelation::<u8, u8>::from_str(illegal_input) {
                Ok(parsed) =>
                    panic!("Was able to parse the illegal input \'{}\' as \'{:?}\'",
                           illegal_input, parsed),
                Err(_) => (),
            }
        }
    }
}
<commit_msg>src/approximation/equivalence_classes.rs: added tests for EquivalenceRelation::new()<commit_after>use nom::{IResult, is_space};
use std::collections::{HashMap, HashSet};
use std::collections::hash_map::Entry;
use std::fmt::Debug;
use std::hash::Hash;
use std::iter::FromIterator;
use std::str::FromStr;

use util::parsing::*;

/// Structure containing the elements of type `A` in a equivalence class of type `B`
#[derive(Debug, Eq, PartialEq)]
pub struct EquivalenceClass<A, B>
    where A: Eq + Hash,
{
    label: B,
    set: Option<HashSet<A>>,
}

impl<A, B> From<(B, Option<Vec<A>>)> for EquivalenceClass<A, B>
    where A: Eq + Hash,
{
    fn from((label, set): (B, Option<Vec<A>>)) -> EquivalenceClass<A, B> {
        EquivalenceClass {
            label,
            set: set.and_then(|elements| Some(HashSet::from_iter(elements))),
        }
    }
}

/// A struct containing a remapping of elements of type `A` into their respective equivalence classes of type `B`.
#[derive(Clone, Debug)]
pub struct EquivalenceRelation<A, B>
    where A: Eq + Hash,
{
    map: HashMap<A, B>,
    default: B,
}

impl<A, B> PartialEq for EquivalenceRelation<A, B>
    where A: Eq + Hash,
          B: PartialEq,
{
    fn eq(&self, other: &Self) -> bool {
        self.default == other.default && self.map == other.map
    }
}

impl<A, B> EquivalenceRelation<A, B>
    where A: Eq + Hash,
          B: Clone + Eq + Hash,
{
    pub fn new(map: HashMap<B, HashSet<A>>, default: B) -> Self {
        match Self::new_safe(map, default) {
            Ok(relation) => relation,
            Err(error) => panic!(error),
        }
    }

    pub fn new_safe(map: HashMap<B, HashSet<A>>, default: B) -> Result<Self, String> {
        let mut relation_map = HashMap::new();
        for (class_name, members) in map {
            if class_name == default {
                return Err(String::from(
                    "There can only be one default class in the equivalence relation!"
                ));
            }

            for value in members {
                match relation_map.entry(value) {
                    Entry::Vacant(v) => {
                        v.insert(class_name.clone());
                    },
                    Entry::Occupied(_) => {
                        return Err(String::from(
                            "All classes of the equivalence relation must be disjoint!"
                        ));
                    },
                }
            }
        }

        Ok(EquivalenceRelation { map: relation_map, default })
    }

    // returns the equivalence class of a given value
    pub fn project(&self, key: &A) -> B {
        match self.map.get(key) {
            None => self.default.clone(),
            Some(e) => e.clone(),
        }
    }
}

impl<A, B> From<Vec<EquivalenceClass<A, B>>> for EquivalenceRelation<A, B>
    where A: Eq + Hash,
          B: Clone + Eq + Hash,
{
    fn from(classes: Vec<EquivalenceClass<A, B>>) -> EquivalenceRelation<A, B> {
        let mut map = HashMap::new();
        let mut default = None;

        for EquivalenceClass { label, set } in classes {
            if let Some(elements) = set {
                for element in elements {
                    map.insert(element, label.clone());
                }
            } else {
                default = Some(label);
            }
        }

        EquivalenceRelation { map, default: default.unwrap() }
    }
}

impl<A, B> FromStr for EquivalenceRelation<A, B>
    where A: Clone + Eq + Hash + FromStr,
          A::Err: Debug,
          B: Clone + Eq + Hash + FromStr,
          B::Err: Debug,
{
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut map = HashMap::new();
        let mut default = None;

        for l in s.lines() {
            if !l.is_empty() {
                match l.trim().parse()? {
                    EquivalenceClass { label, set: Some(elements) } => {
                        map.insert(label, elements);
                    },
                    EquivalenceClass { label, set: None } => {
                        default = Some(label);
                    },
                }
            }
        }

        if let Some(label) = default {
            if let Ok(relation) = EquivalenceRelation::new_safe(map, label) {
                return Ok(relation);
            }
        }

        Err(format!("Could not parse {}", s))
    }
}

impl <A, B> FromStr for EquivalenceClass<A, B>
    where A: Eq + FromStr + Hash,
          A::Err: Debug,
          B: FromStr,
          B::Err: Debug,
{
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match parse_set(s.as_bytes()) {
            IResult::Done(_, result) => Ok(result),
            _                        => Err(format!("Could not parse {}", s))
        }
    }
}

fn parse_set<A, B>(input: &[u8]) -> IResult<&[u8], EquivalenceClass<A, B>>
    where A: Eq + FromStr + Hash,
          A::Err: Debug,
          B: FromStr,
          B::Err: Debug,
{
    do_parse!(
        input,
        label: parse_token >>
            take_while!(is_space) >>
            set: alt!(
                do_parse!(
                    tag!("*") >> (None)
                )
                    |
                do_parse!(
                    the_set: parse_heap >> (Some(the_set))
                )
            ) >>
            (EquivalenceClass {
                label,
                set,
            })
    )
}

fn parse_heap<A>(input: &[u8]) -> IResult<&[u8], HashSet<A>>
    where A: Eq + FromStr + Hash,
          A::Err: Debug,
{
    match parse_vec(input, parse_token, "[", "]", ",") {
        IResult::Done(rest, parsed) => IResult::Done(rest, HashSet::from_iter(parsed)),
        IResult::Incomplete(needed) => IResult::Incomplete(needed),
        IResult::Error(error) => IResult::Error(error),
    }
}

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

    #[test]
    fn test_equivalence_class_from_str_legal_input() {
        let legal_inputs = vec![
            ("0 [0, 1]", EquivalenceClass::from((0, Some(vec![0, 1])))),
            ("0  [1, 0]", EquivalenceClass::from((0, Some(vec![0, 1])))),
            ("0  [0, 1, 1]", EquivalenceClass::from((0, Some(vec![0, 1])))),
            ("0 *", EquivalenceClass::from((0, None))),
        ];

        for (legal_input, correct_class) in legal_inputs {
            assert_eq!(correct_class,
                       EquivalenceClass::from_str(legal_input).unwrap());
        }
    }

    #[test]
    fn test_equivalence_class_from_str_illegal_input() {
        let illegal_inputs = vec![
            " 0 [0, 1]",
            "[0, 1]",
            "*",
        ];

        for illegal_input in illegal_inputs {
            match EquivalenceClass::<u8, u8>::from_str(illegal_input) {
                Ok(parsed) =>
                    panic!("Was able to parse the illegal input \'{}\' as \'{:?}\'",
                           illegal_input, parsed),
                Err(_) => (),
            }
        }
    }

    #[test]
    fn test_equivalence_relation_project() {
        let rel: EquivalenceRelation<u8, u8> = String::from("0 [0, 1]\n1 [2, 4]\n2 *").parse().unwrap();
        assert_eq!(0, rel.project(&1));
        assert_eq!(1, rel.project(&2));
        assert_eq!(2, rel.project(&3));
        assert_eq!(1, rel.project(&4));
    }

    #[test]
    #[should_panic(
        expected="There can only be one default class in the equivalence relation!"
    )]
    fn test_equivalence_relation_new_colliding_default() {
        let mut map = HashMap::new();
        let classes = vec![
            (0, HashSet::from_iter(vec![0, 1])),
            (1, HashSet::from_iter(vec![2, 3])),
        ];

        for (label, elements) in classes {
            map.insert(label, elements);
        }

        EquivalenceRelation::new(map, 1);
    }

    #[test]
    #[should_panic(
        expected="All classes of the equivalence relation must be disjoint!"
    )]
    fn test_equivalence_relation_new_intersecting_classes() {
        let mut map = HashMap::new();
        let classes = vec![
            (0, HashSet::from_iter(vec![0, 1])),
            (1, HashSet::from_iter(vec![1, 2])),
        ];

        for (label, elements) in classes {
            map.insert(label, elements);
        }

        EquivalenceRelation::new(map, 2);
    }

    #[test]
    fn test_equivalence_relation_from_str_legal_input() {
        let legal_inputs = vec![
            ("0 [0, 1]\n1 [2, 3]\n2 *", EquivalenceRelation::from(vec![
                EquivalenceClass::from((0, Some(vec![0, 1]))),
                EquivalenceClass::from((1, Some(vec![2, 3]))),
                EquivalenceClass::from((2, None)),
            ])),
        ];

        for (legal_input, correct_relation) in legal_inputs {
            assert_eq!(correct_relation,
                       EquivalenceRelation::from_str(legal_input).unwrap());
        }
    }

    #[test]
    fn test_equivalence_relation_from_str_illegal_input() {
        let illegal_inputs = vec![
            " 0 [0, 1]\n1 [2, 3]\n2 *",
            "0 [0, 1]1 [2, 3]2 *",
            "0 [0, 1]\n1 [1, 2]\n2 *",
        ];

        for illegal_input in illegal_inputs {
            match EquivalenceRelation::<u8, u8>::from_str(illegal_input) {
                Ok(parsed) =>
                    panic!("Was able to parse the illegal input \'{}\' as \'{:?}\'",
                           illegal_input, parsed),
                Err(_) => (),
            }
        }
    }
}
<|endoftext|>


<commit_before>use futures::*;
use futures::stream::Stream;

pub struct StreamMerge2<S1, S2: Stream> {
    stream1: stream::Fuse<S1>,
    stream2: stream::Fuse<S2>,
    next_try_2: bool,
    queued_error: Option<S2::Error>,
}

pub fn stream_merge2<S1, S2>(stream1: S1, stream2: S2) -> StreamMerge2<S1, S2>
    where S1: Stream, S2: Stream<Error = S1::Error>
{
    StreamMerge2 {
        stream1: stream1.fuse(),
        stream2: stream2.fuse(),
        next_try_2: false,
        queued_error: None,
    }
}

/// An item returned from a merge stream, which represents an item from one or
/// both of the underlying streams.
pub enum Merged2Item<I1, I2> {
    /// An item from the first stream
    First(I1),
    /// An item from the second stream
    Second(I2),
}

fn poll2<S1, S2>(s1: &mut S1, s2: &mut S2)
    -> Poll<Option<Merged2Item<S1::Item, S2::Item>>, S1::Error>
        where
            S1 : Stream,
            S2 : Stream<Error = S1::Error>,
{
    match s1.poll() {
        Err(e) => Err(e),
        Ok(Async::NotReady) => match try_ready!(s2.poll()) {
            Some(item2) => Ok(Async::Ready(Some(Merged2Item::Second(item2)))),
            None => Ok(Async::NotReady),
        },
        Ok(Async::Ready(Some(item1))) => Ok(Async::Ready(Some(Merged2Item::First(item1)))),
        Ok(Async::Ready(None)) => match try_ready!(s2.poll()) {
            Some(item2) => Ok(Async::Ready(Some(Merged2Item::Second(item2)))),
            None => Ok(Async::Ready(None)),
        },
    }
}

impl<S1, S2> Stream for StreamMerge2<S1, S2>
    where S1: Stream, S2: Stream<Error = S1::Error>
{
    type Item = Merged2Item<S1::Item, S2::Item>;
    type Error = S1::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        if let Some(e) = self.queued_error.take() {
            return Err(e);
        }

        let r = if self.next_try_2 {
            poll2(&mut self.stream1, &mut self.stream2)
        } else {
            poll2(&mut self.stream2, &mut self.stream1)
                .map(|async: Async<Option<Merged2Item<S2::Item, S1::Item>>>| {
                    async.map(|option| {
                        option.map(|merged_item| {
                            match merged_item {
                                Merged2Item::First(a) => Merged2Item::Second(a),
                                Merged2Item::Second(a) => Merged2Item::First(a),
                            }
                        })
                    })
                })
        };

        self.next_try_2 = !self.next_try_2;

        r
    }
}
<commit_msg>Fixes issue #19, a double import error<commit_after>use futures::{Async, Poll};
use futures::stream::{self, Stream};

pub struct StreamMerge2<S1, S2: Stream> {
    stream1: stream::Fuse<S1>,
    stream2: stream::Fuse<S2>,
    next_try_2: bool,
    queued_error: Option<S2::Error>,
}

pub fn stream_merge2<S1, S2>(stream1: S1, stream2: S2) -> StreamMerge2<S1, S2>
    where S1: Stream, S2: Stream<Error = S1::Error>
{
    StreamMerge2 {
        stream1: stream1.fuse(),
        stream2: stream2.fuse(),
        next_try_2: false,
        queued_error: None,
    }
}

/// An item returned from a merge stream, which represents an item from one or
/// both of the underlying streams.
pub enum Merged2Item<I1, I2> {
    /// An item from the first stream
    First(I1),
    /// An item from the second stream
    Second(I2),
}

fn poll2<S1, S2>(s1: &mut S1, s2: &mut S2)
    -> Poll<Option<Merged2Item<S1::Item, S2::Item>>, S1::Error>
        where
            S1 : Stream,
            S2 : Stream<Error = S1::Error>,
{
    match s1.poll() {
        Err(e) => Err(e),
        Ok(Async::NotReady) => match try_ready!(s2.poll()) {
            Some(item2) => Ok(Async::Ready(Some(Merged2Item::Second(item2)))),
            None => Ok(Async::NotReady),
        },
        Ok(Async::Ready(Some(item1))) => Ok(Async::Ready(Some(Merged2Item::First(item1)))),
        Ok(Async::Ready(None)) => match try_ready!(s2.poll()) {
            Some(item2) => Ok(Async::Ready(Some(Merged2Item::Second(item2)))),
            None => Ok(Async::Ready(None)),
        },
    }
}

impl<S1, S2> Stream for StreamMerge2<S1, S2>
    where S1: Stream, S2: Stream<Error = S1::Error>
{
    type Item = Merged2Item<S1::Item, S2::Item>;
    type Error = S1::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        if let Some(e) = self.queued_error.take() {
            return Err(e);
        }

        let r = if self.next_try_2 {
            poll2(&mut self.stream1, &mut self.stream2)
        } else {
            poll2(&mut self.stream2, &mut self.stream1)
                .map(|async: Async<Option<Merged2Item<S2::Item, S1::Item>>>| {
                    async.map(|option| {
                        option.map(|merged_item| {
                            match merged_item {
                                Merged2Item::First(a) => Merged2Item::Second(a),
                                Merged2Item::Second(a) => Merged2Item::First(a),
                            }
                        })
                    })
                })
        };

        self.next_try_2 = !self.next_try_2;

        r
    }
}
<|endoftext|>


<commit_before>use super::{EdgeKey, FaceKey, Mesh};
use crate::{shapes::Shape, StrError};
use std::collections::HashMap;

pub struct MeshShapes {
    pub cells: Vec<Shape>,
    pub boundary_edges: HashMap<EdgeKey, Shape>,
    pub boundary_faces: HashMap<FaceKey, Shape>,
}

impl MeshShapes {
    pub fn new(mesh: &Mesh) -> Result<Self, StrError> {
        let mut fem_mesh = MeshShapes {
            cells: Vec::new(),
            boundary_edges: HashMap::new(),
            boundary_faces: HashMap::new(),
        };
        for cell in &mesh.cells {
            let nnode = cell.points.len();
            let mut shape = Shape::new(mesh.space_ndim, cell.geo_ndim, nnode)?;
            for m in 0..nnode {
                let point_id = cell.points[m];
                for j in 0..mesh.space_ndim {
                    shape.set_node(m, j, mesh.points[point_id].coords[j])?;
                }
            }
            fem_mesh.cells.push(shape);
        }
        for (edge_key, edge) in &mesh.boundary_edges {
            let nnode = edge.points.len();
            let mut shape = Shape::new(mesh.space_ndim, 1, nnode)?;
            for m in 0..nnode {
                let point_id = edge.points[m];
                for j in 0..mesh.space_ndim {
                    shape.set_node(m, j, mesh.points[point_id].coords[j])?;
                }
            }
            fem_mesh.boundary_edges.insert(*edge_key, shape);
        }
        for (face_key, face) in &mesh.boundary_faces {
            let nnode = face.points.len();
            let mut shape = Shape::new(mesh.space_ndim, 1, nnode)?;
            for m in 0..nnode {
                let point_id = face.points[m];
                for j in 0..mesh.space_ndim {
                    shape.set_node(m, j, mesh.points[point_id].coords[j])?;
                }
            }
            fem_mesh.boundary_faces.insert(*face_key, shape);
        }
        Ok(fem_mesh)
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use crate::{mesh::Mesh, StrError};

    use super::MeshShapes;

    #[test]
    fn from_text_and_strings_work() -> Result<(), StrError> {
        //
        //  3--------2--------5
        //  |        |        |
        //  |        |        |
        //  |        |        |
        //  0--------1--------4
        //
        let mesh = Mesh::from_text(
            r"# header
            # ndim npoint ncell
                 2      6     2

            # points
            # id   x   y
               0 0.0 0.0
               1 1.0 0.0
               2 1.0 1.0
               3 0.0 1.0
               4 2.0 0.0
               5 2.0 1.0

            # cells
            # id att geo_ndim npoint point_ids...
               0   1        2      4 0 1 2 3
               1   0        2      4 1 4 5 2",
        )?;

        let mesh_shapes = MeshShapes::new(&mesh)?;
        assert_eq!(
            format!("{}", mesh_shapes.cells[0].coords_transp),
            "┌         ┐\n\
             │ 0 1 1 0 │\n\
             │ 0 0 1 1 │\n\
             └         ┘"
        );
        assert_eq!(
            format!("{}", mesh_shapes.cells[1].coords_transp),
            "┌         ┐\n\
             │ 1 2 2 1 │\n\
             │ 0 0 1 1 │\n\
             └         ┘"
        );

        Ok(())
    }
}
<commit_msg>Improve tests<commit_after>use super::{EdgeKey, FaceKey, Mesh};
use crate::{shapes::Shape, StrError};
use std::collections::HashMap;

pub struct MeshShapes {
    pub cells: Vec<Shape>,
    pub boundary_edges: HashMap<EdgeKey, Shape>,
    pub boundary_faces: HashMap<FaceKey, Shape>,
}

impl MeshShapes {
    pub fn new(mesh: &Mesh) -> Result<Self, StrError> {
        let mut fem_mesh = MeshShapes {
            cells: Vec::new(),
            boundary_edges: HashMap::new(),
            boundary_faces: HashMap::new(),
        };
        for cell in &mesh.cells {
            let nnode = cell.points.len();
            let mut shape = Shape::new(mesh.space_ndim, cell.geo_ndim, nnode)?;
            for m in 0..nnode {
                let point_id = cell.points[m];
                for j in 0..mesh.space_ndim {
                    shape.set_node(m, j, mesh.points[point_id].coords[j])?;
                }
            }
            fem_mesh.cells.push(shape);
        }
        for (edge_key, edge) in &mesh.boundary_edges {
            let nnode = edge.points.len();
            let mut shape = Shape::new(mesh.space_ndim, 1, nnode)?;
            for m in 0..nnode {
                let point_id = edge.points[m];
                for j in 0..mesh.space_ndim {
                    shape.set_node(m, j, mesh.points[point_id].coords[j])?;
                }
            }
            fem_mesh.boundary_edges.insert(*edge_key, shape);
        }
        for (face_key, face) in &mesh.boundary_faces {
            let nnode = face.points.len();
            let mut shape = Shape::new(mesh.space_ndim, 1, nnode)?;
            for m in 0..nnode {
                let point_id = face.points[m];
                for j in 0..mesh.space_ndim {
                    shape.set_node(m, j, mesh.points[point_id].coords[j])?;
                }
            }
            fem_mesh.boundary_faces.insert(*face_key, shape);
        }
        Ok(fem_mesh)
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use crate::{mesh::Mesh, StrError};

    use super::MeshShapes;

    #[test]
    fn from_text_and_strings_work() -> Result<(), StrError> {
        //
        //  3--------2--------5
        //  |        |        |
        //  |        |        |
        //  |        |        |
        //  0--------1--------4
        //
        let mesh = Mesh::from_text(
            r"# header
            # ndim npoint ncell
                 2      6     2

            # points
            # id   x   y
               0 0.0 0.0
               1 1.0 0.0
               2 1.0 1.0
               3 0.0 1.0
               4 2.0 0.0
               5 2.0 1.0

            # cells
            # id att geo_ndim npoint point_ids...
               0   1        2      4 0 1 2 3
               1   0        2      4 1 4 5 2",
        )?;

        let mesh_shapes = MeshShapes::new(&mesh)?;
        assert_eq!(
            format!("{}", mesh_shapes.cells[0].coords_transp),
            "┌         ┐\n\
             │ 0 1 1 0 │\n\
             │ 0 0 1 1 │\n\
             └         ┘"
        );
        assert_eq!(
            format!("{}", mesh_shapes.cells[1].coords_transp),
            "┌         ┐\n\
             │ 1 2 2 1 │\n\
             │ 0 0 1 1 │\n\
             └         ┘"
        );
        assert_eq!(
            format!("{}", mesh_shapes.boundary_edges.get(&(0, 1)).unwrap().coords_transp),
            "┌     ┐\n\
             │ 0 1 │\n\
             │ 0 0 │\n\
             └     ┘"
        );
        assert_eq!(
            format!("{}", mesh_shapes.boundary_edges.get(&(1, 4)).unwrap().coords_transp),
            "┌     ┐\n\
             │ 1 2 │\n\
             │ 0 0 │\n\
             └     ┘"
        );
        assert_eq!(
            format!("{}", mesh_shapes.boundary_edges.get(&(2, 3)).unwrap().coords_transp),
            "┌     ┐\n\
             │ 1 0 │\n\
             │ 1 1 │\n\
             └     ┘"
        );
        assert_eq!(mesh_shapes.boundary_faces.len(), 0);

        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::collections::{HashMap, HashSet};
use std::ffi::OsStr;
use std::path::PathBuf;
use semver::Version;

use core::{PackageId, Package, Target};
use util::{self, CargoResult, Config, ProcessBuilder, process, join_paths};

/// A structure returning the result of a compilation.
pub struct Compilation<'cfg> {
    /// All libraries which were built for a package.
    ///
    /// This is currently used for passing --extern flags to rustdoc tests later
    /// on.
    pub libraries: HashMap<PackageId, Vec<(Target, PathBuf)>>,

    /// An array of all tests created during this compilation.
    pub tests: Vec<(Package, String, PathBuf)>,

    /// An array of all binaries created.
    pub binaries: Vec<PathBuf>,

    /// All directires for the output of native build commands.
    ///
    /// This is currently used to drive some entries which are added to the
    /// LD_LIBRARY_PATH as appropriate.
    // TODO: deprecated, remove
    pub native_dirs: HashSet<PathBuf>,

    /// Root output directory (for the local package's artifacts)
    pub root_output: PathBuf,

    /// Output directory for rust dependencies
    pub deps_output: PathBuf,

    /// Library search path for compiler plugins and build scripts
    /// which have dynamic dependencies.
    pub plugins_dylib_path: PathBuf,

    /// Extra environment variables that were passed to compilations and should
    /// be passed to future invocations of programs.
    pub extra_env: HashMap<PackageId, Vec<(String, String)>>,

    pub to_doc_test: Vec<Package>,

    /// Features per package enabled during this compilation.
    pub cfgs: HashMap<PackageId, HashSet<String>>,

    pub target: String,

    config: &'cfg Config,
}

impl<'cfg> Compilation<'cfg> {
    pub fn new(config: &'cfg Config) -> Compilation<'cfg> {
        Compilation {
            libraries: HashMap::new(),
            native_dirs: HashSet::new(),  // TODO: deprecated, remove
            root_output: PathBuf::from("/"),
            deps_output: PathBuf::from("/"),
            plugins_dylib_path: PathBuf::from("/"),
            tests: Vec::new(),
            binaries: Vec::new(),
            extra_env: HashMap::new(),
            to_doc_test: Vec::new(),
            cfgs: HashMap::new(),
            config: config,
            target: String::new(),
        }
    }

    /// See `process`.
    pub fn rustc_process(&self, pkg: &Package) -> CargoResult<ProcessBuilder> {
        self.fill_env(self.config.rustc()?.process(), pkg, true)
    }

    /// See `process`.
    pub fn rustdoc_process(&self, pkg: &Package) -> CargoResult<ProcessBuilder> {
        self.fill_env(process(&*self.config.rustdoc()?), pkg, false)
    }

    /// See `process`.
    pub fn host_process<T: AsRef<OsStr>>(&self, cmd: T, pkg: &Package)
                                         -> CargoResult<ProcessBuilder> {
        self.fill_env(process(cmd), pkg, true)
    }

    /// See `process`.
    pub fn target_process<T: AsRef<OsStr>>(&self, cmd: T, pkg: &Package)
                                           -> CargoResult<ProcessBuilder> {
        self.fill_env(process(cmd), pkg, false)
    }

    /// Prepares a new process with an appropriate environment to run against
    /// the artifacts produced by the build process.
    ///
    /// The package argument is also used to configure environment variables as
    /// well as the working directory of the child process.
    fn fill_env(&self, mut cmd: ProcessBuilder, pkg: &Package, is_host: bool)
                -> CargoResult<ProcessBuilder> {

        let mut search_path = if is_host {
            vec![self.plugins_dylib_path.clone()]
        } else {
            let mut search_path = vec![];

            // Add -L arguments, after stripping off prefixes like "native=" or "framework=".
            for dir in self.native_dirs.iter() {
                let dir = match dir.to_str() {
                    Some(s) => {
                        let mut parts = s.splitn(2, '=');
                        match (parts.next(), parts.next()) {
                            (Some("native"), Some(path)) |
                            (Some("crate"), Some(path)) |
                            (Some("dependency"), Some(path)) |
                            (Some("framework"), Some(path)) |
                            (Some("all"), Some(path)) => path.into(),
                            _ => dir.clone(),
                        }
                    }
                    None => dir.clone(),
                };
                search_path.push(dir);
            }
            search_path.push(self.root_output.clone());
            search_path.push(self.deps_output.clone());
            search_path
        };

        search_path.extend(util::dylib_path().into_iter());
        let search_path = join_paths(&search_path, util::dylib_path_envvar())?;

        cmd.env(util::dylib_path_envvar(), &search_path);
        if let Some(env) = self.extra_env.get(pkg.package_id()) {
            for &(ref k, ref v) in env {
                cmd.env(k, v);
            }
        }

        let metadata = pkg.manifest().metadata();

        cmd.env("CARGO_MANIFEST_DIR", pkg.root())
           .env("CARGO_PKG_VERSION_MAJOR", &pkg.version().major.to_string())
           .env("CARGO_PKG_VERSION_MINOR", &pkg.version().minor.to_string())
           .env("CARGO_PKG_VERSION_PATCH", &pkg.version().patch.to_string())
           .env("CARGO_PKG_VERSION_PRE", &pre_version_component(pkg.version()))
           .env("CARGO_PKG_VERSION", &pkg.version().to_string())
           .env("CARGO_PKG_NAME", &pkg.name())
           .env("CARGO_PKG_DESCRIPTION", metadata.description.as_ref().unwrap_or(&String::new()))
           .env("CARGO_PKG_HOMEPAGE", metadata.homepage.as_ref().unwrap_or(&String::new()))
           .env("CARGO_PKG_AUTHORS", &pkg.authors().join(":"))
           .cwd(pkg.root());
        Ok(cmd)
    }
}

fn pre_version_component(v: &Version) -> String {
    if v.pre.is_empty() {
        return String::new();
    }

    let mut ret = String::new();

    for (i, x) in v.pre.iter().enumerate() {
        if i != 0 { ret.push('.') };
        ret.push_str(&x.to_string());
    }

    ret
}
<commit_msg>Attempt to solve #3366, regarding spurious shared library search paths.<commit_after>use std::collections::{HashMap, HashSet};
use std::ffi::OsStr;
use std::path::PathBuf;
use semver::Version;

use core::{PackageId, Package, Target};
use util::{self, CargoResult, Config, ProcessBuilder, process, join_paths};

/// A structure returning the result of a compilation.
pub struct Compilation<'cfg> {
    /// All libraries which were built for a package.
    ///
    /// This is currently used for passing --extern flags to rustdoc tests later
    /// on.
    pub libraries: HashMap<PackageId, Vec<(Target, PathBuf)>>,

    /// An array of all tests created during this compilation.
    pub tests: Vec<(Package, String, PathBuf)>,

    /// An array of all binaries created.
    pub binaries: Vec<PathBuf>,

    /// All directories for the output of native build commands.
    ///
    /// This is currently used to drive some entries which are added to the
    /// LD_LIBRARY_PATH as appropriate.
    // TODO: deprecated, remove
    pub native_dirs: HashSet<PathBuf>,

    /// Root output directory (for the local package's artifacts)
    pub root_output: PathBuf,

    /// Output directory for rust dependencies
    pub deps_output: PathBuf,

    /// Library search path for compiler plugins and build scripts
    /// which have dynamic dependencies.
    pub plugins_dylib_path: PathBuf,

    /// Extra environment variables that were passed to compilations and should
    /// be passed to future invocations of programs.
    pub extra_env: HashMap<PackageId, Vec<(String, String)>>,

    pub to_doc_test: Vec<Package>,

    /// Features per package enabled during this compilation.
    pub cfgs: HashMap<PackageId, HashSet<String>>,

    pub target: String,

    config: &'cfg Config,
}

impl<'cfg> Compilation<'cfg> {
    pub fn new(config: &'cfg Config) -> Compilation<'cfg> {
        Compilation {
            libraries: HashMap::new(),
            native_dirs: HashSet::new(),  // TODO: deprecated, remove
            root_output: PathBuf::from("/"),
            deps_output: PathBuf::from("/"),
            plugins_dylib_path: PathBuf::from("/"),
            tests: Vec::new(),
            binaries: Vec::new(),
            extra_env: HashMap::new(),
            to_doc_test: Vec::new(),
            cfgs: HashMap::new(),
            config: config,
            target: String::new(),
        }
    }

    /// See `process`.
    pub fn rustc_process(&self, pkg: &Package) -> CargoResult<ProcessBuilder> {
        self.fill_env(self.config.rustc()?.process(), pkg, true)
    }

    /// See `process`.
    pub fn rustdoc_process(&self, pkg: &Package) -> CargoResult<ProcessBuilder> {
        self.fill_env(process(&*self.config.rustdoc()?), pkg, false)
    }

    /// See `process`.
    pub fn host_process<T: AsRef<OsStr>>(&self, cmd: T, pkg: &Package)
                                         -> CargoResult<ProcessBuilder> {
        self.fill_env(process(cmd), pkg, true)
    }

    /// See `process`.
    pub fn target_process<T: AsRef<OsStr>>(&self, cmd: T, pkg: &Package)
                                           -> CargoResult<ProcessBuilder> {
        self.fill_env(process(cmd), pkg, false)
    }

    /// Prepares a new process with an appropriate environment to run against
    /// the artifacts produced by the build process.
    ///
    /// The package argument is also used to configure environment variables as
    /// well as the working directory of the child process.
    fn fill_env(&self, mut cmd: ProcessBuilder, pkg: &Package, is_host: bool)
                -> CargoResult<ProcessBuilder> {

        let mut search_path = if is_host {
            vec![self.plugins_dylib_path.clone()]
        } else {
            let mut search_path = vec![];

            // Add -L arguments, after stripping off prefixes like "native="
            // or "framework=" and filtering out directories *not* inside our
            // output directory, since they are likely spurious and can cause
            // clashes with system shared libraries (issue #3366).
            for dir in self.native_dirs.iter() {
                let dir = match dir.to_str() {
                    Some(s) => {
                        let mut parts = s.splitn(2, '=');
                        match (parts.next(), parts.next()) {
                            (Some("native"), Some(path)) |
                            (Some("crate"), Some(path)) |
                            (Some("dependency"), Some(path)) |
                            (Some("framework"), Some(path)) |
                            (Some("all"), Some(path)) => path.into(),
                            _ => dir.clone(),
                        }
                    }
                    None => dir.clone(),
                };

                if dir.starts_with(&self.root_output) {
                    search_path.push(dir);
                }
            }
            search_path.push(self.root_output.clone());
            search_path.push(self.deps_output.clone());
            search_path
        };

        search_path.extend(util::dylib_path().into_iter());
        let search_path = join_paths(&search_path, util::dylib_path_envvar())?;

        cmd.env(util::dylib_path_envvar(), &search_path);
        if let Some(env) = self.extra_env.get(pkg.package_id()) {
            for &(ref k, ref v) in env {
                cmd.env(k, v);
            }
        }

        let metadata = pkg.manifest().metadata();

        cmd.env("CARGO_MANIFEST_DIR", pkg.root())
           .env("CARGO_PKG_VERSION_MAJOR", &pkg.version().major.to_string())
           .env("CARGO_PKG_VERSION_MINOR", &pkg.version().minor.to_string())
           .env("CARGO_PKG_VERSION_PATCH", &pkg.version().patch.to_string())
           .env("CARGO_PKG_VERSION_PRE", &pre_version_component(pkg.version()))
           .env("CARGO_PKG_VERSION", &pkg.version().to_string())
           .env("CARGO_PKG_NAME", &pkg.name())
           .env("CARGO_PKG_DESCRIPTION", metadata.description.as_ref().unwrap_or(&String::new()))
           .env("CARGO_PKG_HOMEPAGE", metadata.homepage.as_ref().unwrap_or(&String::new()))
           .env("CARGO_PKG_AUTHORS", &pkg.authors().join(":"))
           .cwd(pkg.root());
        Ok(cmd)
    }
}

fn pre_version_component(v: &Version) -> String {
    if v.pre.is_empty() {
        return String::new();
    }

    let mut ret = String::new();

    for (i, x) in v.pre.iter().enumerate() {
        if i != 0 { ret.push('.') };
        ret.push_str(&x.to_string());
    }

    ret
}
<|endoftext|>


<commit_before>//
// Sysinfo
//
// Copyright (c) 2015 Guillaume Gomez
//

use std::fmt::{self, Formatter, Debug};
use libc::{c_int, gid_t, kill, pid_t, uid_t};

use ::ProcessExt;

/// Enum describing the different status of a process.
#[derive(Clone, Debug)]
pub enum ProcessStatus {
    /// Process being created by fork.
    Idle,
    /// Currently runnable.
    Run,
    /// Sleeping on an address.
    Sleep,
    /// Process debugging or suspension.
    Stop,
    /// Awaiting collection by parent.
    Zombie,
    /// Unknown.
    Unknown(u32),
}

impl From<u32> for ProcessStatus {
    fn from(status: u32) -> ProcessStatus {
        match status {
            1 => ProcessStatus::Idle,
            2 => ProcessStatus::Run,
            3 => ProcessStatus::Sleep,
            4 => ProcessStatus::Stop,
            5 => ProcessStatus::Zombie,
            x => ProcessStatus::Unknown(x),
        }
    }
}

impl ProcessStatus {
    /// Used to display `ProcessStatus`.
    pub fn to_string(&self) -> &str {
        match *self {
            ProcessStatus::Idle       => "Idle",
            ProcessStatus::Run        => "Runnable",
            ProcessStatus::Sleep      => "Sleeping",
            ProcessStatus::Stop       => "Stopped",
            ProcessStatus::Zombie     => "Zombie",
            ProcessStatus::Unknown(_) => "Unknown",
        }
    }
}

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

/// Struct containing a process' information.
#[derive(Clone)]
pub struct Process {
    /// Name of the program.
    pub name: String,
    /// Command line, split into arguments.
    pub cmd: Vec<String>,
    /// Path to the executable.
    pub exe: String,
    /// Pid of the process.
    pub pid: pid_t,
    /// Pid of the parent process.
    pub parent: Option<pid_t>,
    /// Environment of the process.
    pub environ: Vec<String>,
    /// Current working directory.
    pub cwd: String,
    /// Path of the root directory.
    pub root: String,
    /// Memory usage (in kB).
    pub memory: u64,
    utime: u64,
    stime: u64,
    old_utime: u64,
    old_stime: u64,
    /// Time of process launch (in seconds).
    pub start_time: u64,
    updated: bool,
    /// Total cpu usage.
    pub cpu_usage: f32,
    /// User id of the process owner.
    pub uid: uid_t,
    /// Group id of the process owner.
    pub gid: gid_t,
    /// status of process (idle, run, zombie, etc)
    pub status: Option<ProcessStatus>,
}

impl ProcessExt for Process {
    fn new(pid: pid_t, parent: Option<pid_t>, start_time: u64) -> Process {
        Process {
            name: String::new(),
            pid: pid,
            parent: parent,
            cmd: Vec::new(),
            environ: Vec::new(),
            exe: String::new(),
            cwd: String::new(),
            root: String::new(),
            memory: 0,
            cpu_usage: 0.,
            utime: 0,
            stime: 0,
            old_utime: 0,
            old_stime: 0,
            updated: true,
            start_time: start_time,
            uid: 0,
            gid: 0,
            status: None,
        }
    }

    fn kill(&self, signal: ::Signal) -> bool {
        unsafe { kill(self.pid, signal as c_int) == 0 }
    }
}

#[allow(unused_must_use)]
impl Debug for Process {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        writeln!(f, "pid: {}", self.pid);
        writeln!(f, "parent: {:?}", self.parent);
        writeln!(f, "name: {}", self.name);
        writeln!(f, "environment:");
        for var in &self.environ {
            if !var.is_empty() {
                writeln!(f, "\t{}", var);
            }
        }
        writeln!(f, "command:");
        for arg in &self.cmd {
            writeln!(f, "\t{}", arg);
        }
        writeln!(f, "executable path: {}", self.exe);
        writeln!(f, "current working directory: {}", self.cwd);
        writeln!(f, "owner/group: {}:{}", self.uid, self.gid);
        writeln!(f, "memory usage: {} kB", self.memory);
        writeln!(f, "cpu usage: {}%", self.cpu_usage);
        writeln!(f, "status: {}", match self.status {
            Some(ref v) => v.to_string(),
            None        => "Unknown",
        });
        write!(f, "root path: {}", self.root)
    }
}

pub fn compute_cpu_usage(p: &mut Process, time: u64, task_time: u64) {
    let system_time_delta = task_time - p.old_utime;
    let time_delta = time - p.old_stime;
    p.old_utime = task_time;
    p.old_stime = time;
    p.cpu_usage = if time_delta == 0 {
        0f32
    } else {
        (system_time_delta as f64 * 100f64 / time_delta as f64) as f32
    };
    if p.cpu_usage > 100f32 {
        p.cpu_usage = 100f32;
    }
    p.updated = true;
}

/*pub fn set_time(p: &mut Process, utime: u64, stime: u64) {
    p.old_utime = p.utime;
    p.old_stime = p.stime;
    p.utime = utime;
    p.stime = stime;
    p.updated = true;
}*/

pub fn has_been_updated(p: &mut Process) -> bool {
    let old = p.updated;
    p.updated = false;
    old
}
<commit_msg>Remove 100% limit<commit_after>//
// Sysinfo
//
// Copyright (c) 2015 Guillaume Gomez
//

use std::fmt::{self, Formatter, Debug};
use libc::{c_int, gid_t, kill, pid_t, uid_t};

use ::ProcessExt;

/// Enum describing the different status of a process.
#[derive(Clone, Debug)]
pub enum ProcessStatus {
    /// Process being created by fork.
    Idle,
    /// Currently runnable.
    Run,
    /// Sleeping on an address.
    Sleep,
    /// Process debugging or suspension.
    Stop,
    /// Awaiting collection by parent.
    Zombie,
    /// Unknown.
    Unknown(u32),
}

impl From<u32> for ProcessStatus {
    fn from(status: u32) -> ProcessStatus {
        match status {
            1 => ProcessStatus::Idle,
            2 => ProcessStatus::Run,
            3 => ProcessStatus::Sleep,
            4 => ProcessStatus::Stop,
            5 => ProcessStatus::Zombie,
            x => ProcessStatus::Unknown(x),
        }
    }
}

impl ProcessStatus {
    /// Used to display `ProcessStatus`.
    pub fn to_string(&self) -> &str {
        match *self {
            ProcessStatus::Idle       => "Idle",
            ProcessStatus::Run        => "Runnable",
            ProcessStatus::Sleep      => "Sleeping",
            ProcessStatus::Stop       => "Stopped",
            ProcessStatus::Zombie     => "Zombie",
            ProcessStatus::Unknown(_) => "Unknown",
        }
    }
}

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

/// Struct containing a process' information.
#[derive(Clone)]
pub struct Process {
    /// Name of the program.
    pub name: String,
    /// Command line, split into arguments.
    pub cmd: Vec<String>,
    /// Path to the executable.
    pub exe: String,
    /// Pid of the process.
    pub pid: pid_t,
    /// Pid of the parent process.
    pub parent: Option<pid_t>,
    /// Environment of the process.
    pub environ: Vec<String>,
    /// Current working directory.
    pub cwd: String,
    /// Path of the root directory.
    pub root: String,
    /// Memory usage (in kB).
    pub memory: u64,
    utime: u64,
    stime: u64,
    old_utime: u64,
    old_stime: u64,
    /// Time of process launch (in seconds).
    pub start_time: u64,
    updated: bool,
    /// Total cpu usage.
    pub cpu_usage: f32,
    /// User id of the process owner.
    pub uid: uid_t,
    /// Group id of the process owner.
    pub gid: gid_t,
    /// status of process (idle, run, zombie, etc)
    pub status: Option<ProcessStatus>,
}

impl ProcessExt for Process {
    fn new(pid: pid_t, parent: Option<pid_t>, start_time: u64) -> Process {
        Process {
            name: String::new(),
            pid: pid,
            parent: parent,
            cmd: Vec::new(),
            environ: Vec::new(),
            exe: String::new(),
            cwd: String::new(),
            root: String::new(),
            memory: 0,
            cpu_usage: 0.,
            utime: 0,
            stime: 0,
            old_utime: 0,
            old_stime: 0,
            updated: true,
            start_time: start_time,
            uid: 0,
            gid: 0,
            status: None,
        }
    }

    fn kill(&self, signal: ::Signal) -> bool {
        unsafe { kill(self.pid, signal as c_int) == 0 }
    }
}

#[allow(unused_must_use)]
impl Debug for Process {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        writeln!(f, "pid: {}", self.pid);
        writeln!(f, "parent: {:?}", self.parent);
        writeln!(f, "name: {}", self.name);
        writeln!(f, "environment:");
        for var in &self.environ {
            if !var.is_empty() {
                writeln!(f, "\t{}", var);
            }
        }
        writeln!(f, "command:");
        for arg in &self.cmd {
            writeln!(f, "\t{}", arg);
        }
        writeln!(f, "executable path: {}", self.exe);
        writeln!(f, "current working directory: {}", self.cwd);
        writeln!(f, "owner/group: {}:{}", self.uid, self.gid);
        writeln!(f, "memory usage: {} kB", self.memory);
        writeln!(f, "cpu usage: {}%", self.cpu_usage);
        writeln!(f, "status: {}", match self.status {
            Some(ref v) => v.to_string(),
            None        => "Unknown",
        });
        write!(f, "root path: {}", self.root)
    }
}

pub fn compute_cpu_usage(p: &mut Process, time: u64, task_time: u64) {
    let system_time_delta = task_time - p.old_utime;
    let time_delta = time - p.old_stime;
    p.old_utime = task_time;
    p.old_stime = time;
    p.cpu_usage = if time_delta == 0 {
        0f32
    } else {
        (system_time_delta as f64 * 100f64 / time_delta as f64) as f32
    };
    p.updated = true;
}

/*pub fn set_time(p: &mut Process, utime: u64, stime: u64) {
    p.old_utime = p.utime;
    p.old_stime = p.stime;
    p.utime = utime;
    p.stime = stime;
    p.updated = true;
}*/

pub fn has_been_updated(p: &mut Process) -> bool {
    let old = p.updated;
    p.updated = false;
    old
}
<|endoftext|>


<commit_before>use storage::file::FileHeaderSpec as FHS;

pub fn get_spec() -> FHS {
    FHS::Map {
        keys: vec![
            FHS::Key { name: "URL", value_type: Box::new(FHS::Text) },
            FHS::Key { name: "TAGS",
                  value_type: Box::new(FHS::Array {
                      allowed_types: vec![FHS::Text]
                  }),
            },
        ],
    }
}

<commit_msg>Split header spec into smaller functions<commit_after>use storage::file::FileHeaderSpec as FHS;

pub fn get_spec() -> FHS {
    FHS::Map { keys: vec![ url_key(), tags_key() ] }
}

fn url_key() -> FHS {
    FHS::Key { name: "URL", value_type: Box::new(FHS::Text) }
}

fn tags_key() -> FHS {
    FHS::Key { name: "TAGS", value_type: Box::new(text_array()) }
}

fn text_array() -> FHS {
    FHS::Array { allowed_types: vec![FHS::Text] }
}

<|endoftext|>


<commit_before>use std::borrow::ToOwned;
use std::collections::HashSet;
use std::ffi::AsOsStr;
use std::fs::PathExt;
use std::fs;
use std::io::{Read,Write};
use std::io;
use std::path::AsPath;
use std::path;
use std::process;

use atomicwrites::{AtomicFile,DisallowOverwrite};
use email::rfc5322::Rfc5322Parser;
use uuid::Uuid;
use vobject::{Component,Property,parse_component,write_component};

use cli::Configuration;

pub fn handle_process(process: &mut process::Child) -> io::Result<()> {
    let exitcode = try!(process.wait());
    if !exitcode.success() {
        return Err(io::Error::new(
            io::ErrorKind::Other,
            "",
            Some(format!("{}", exitcode))
        ));
    };
    Ok(())
}

struct IndexIterator {
    linebuffer: Vec<String>
}

impl IndexIterator {
    fn new(output: &String) -> IndexIterator {
        let rv = output.split('\n').map(|x| x.to_string()).collect();
        IndexIterator {
            linebuffer: rv
        }
    }
}

impl Iterator for IndexIterator {
    type Item = IndexItem;

    fn next(&mut self) -> Option<IndexItem> {
        match self.linebuffer.pop() {
            Some(x) => Some(IndexItem::new(x)),
            None => None
        }
    }
}

struct IndexItem {
    pub email: String,
    pub name: String,
    pub filepath: Option<path::PathBuf>
}

impl IndexItem {
    fn new(line: String) -> IndexItem {
        let mut parts = line.split('\t');

        IndexItem {
            email: parts.next().unwrap_or("").to_string(),
            name: parts.next().unwrap_or("").to_string(),
            filepath: match parts.next() {
                Some(x) => Some(path::PathBuf::new(x)),
                None => None
            }
        }
    }
}

pub struct Contact {
    pub component: Component,
    pub path: path::PathBuf
}

impl Contact {
    pub fn from_file<P: AsOsStr + path::AsPath + ?Sized>(path: &P) -> io::Result<Contact> {
        // FIXME: Why is "AsOsStr" above necessary? File::open has a sig w/o it
        let mut contact_file = try!(fs::File::open(&path));
        let contact_string = {
            let mut x = String::new();
            try!(contact_file.read_to_string(&mut x));
            x
        };

        let item = match parse_component(contact_string.as_slice()) {
            Ok(x) => x,
            Err(e) => return Err(io::Error::new(
                io::ErrorKind::Other,
                "Error while parsing contact",
                Some(format!("{}", e))
            ))
        };

        Ok(Contact { component: item, path: path.as_path().to_owned() })
    }

    pub fn generate(fullname: Option<&str>, email: Option<&str>, dir: &path::Path) -> Contact {
        let (uid, contact_path) = {
            let mut uid;
            let mut contact_path;
            loop {
                uid = Uuid::new_v4().to_simple_string();
                contact_path = dir.join(&format!("{}.vcf", uid));
                if !(*contact_path).exists() {
                    break
                }
            };
            (uid, contact_path)
        };
        Contact { path: contact_path, component: generate_component(uid, fullname, email) }
    }

    pub fn write_create(&self) -> io::Result<()> {
        let string = write_component(&self.component);
        let af = AtomicFile::new(&self.path, DisallowOverwrite);

        af.write(|f| {
            f.write_all(string.as_bytes())
        })
    }
}

fn generate_component(uid: String, fullname: Option<&str>, email: Option<&str>) -> Component {
    let mut comp = Component::new("VCARD");

    match fullname {
        Some(x) => comp.all_props_mut("FN").push(Property::new(x)),
        None => ()
    };

    match email {
        Some(x) => comp.all_props_mut("EMAIL").push(Property::new(x)),
        None => ()
    };
    comp.all_props_mut("UID").push(Property::new(uid.as_slice()));
    comp
}

pub fn index_query<'a>(config: &Configuration, query: &str) -> io::Result<IndexIterator> {
    let mut process = try!(
        command_from_config(config.grep_cmd.as_slice())
        .arg(query.as_slice())
        .stderr(process::Stdio::inherit())
        .spawn());

    {
        let mut index_fp = try!(fs::File::open(&config.index_path));
        let mut stdin = process.stdin.take().unwrap();
        let mut line: Vec<u8> = vec![];
        try!(index_fp.read_to_end(&mut line));
        try!(stdin.write_all(line.as_slice()));
    }

    try!(handle_process(&mut process));

    let stream = match process.stdout.as_mut() {
        Some(x) => x,
        None => return Err(io::Error::new(
            io::ErrorKind::ResourceUnavailable,
            "Failed to get stdout from grep process.",
            None
        ))
    };

    let mut output = String::new();
    try!(stream.read_to_string(&mut output));
    Ok(IndexIterator::new(&output))
}

/// Better than index_query if you're only interested in the filepath, as duplicate entries will be
/// removed.
pub fn file_query(config: &Configuration, query: &str) -> io::Result<HashSet<path::PathBuf>> {
    let mut rv: HashSet<path::PathBuf> = HashSet::new();
    rv.extend(
        try!(index_query(config, query)).filter_map(|x| x.filepath)
    );
    Ok(rv)
}

pub fn index_item_from_contact(contact: &Contact) -> io::Result<String> {
    let name = match contact.component.single_prop("FN") {
        Some(name) => name.value_as_string(),
        None => return Err(io::Error::new(
            io::ErrorKind::Other,
            "No name found.",
            None
        ))
    };

    let emails = contact.component.all_props("EMAIL");
    let mut rv = String::new();
    for email in emails.iter() {
        rv.push_str(format!("{}\t{}\t{}\n", email.value_as_string(), name, contact.path.display()).as_slice());
    };
    Ok(rv)
}

/// Return a tuple (fullname, email)
pub fn parse_from_header<'a>(s: &'a String) -> (Option<&'a str>, Option<&'a str>) {
    let mut split = s.rsplitn(1, ' ');
    let email = match split.next() {
        Some(x) => Some(x.trim_left_matches('<').trim_right_matches('>')),
        None => Some(s.as_slice())
    };
    let name = split.next();
    (name, email)
}

/// Given an email, return value of From header.
pub fn read_sender_from_email(email: &str) -> Option<String> {
    let mut parser = Rfc5322Parser::new(email);
    while !parser.eof() {
        match parser.consume_header() {
            Some(header) => {
                if header.name == "From" {
                    return header.get_value().ok()
                };
            },
            None => return None
        };
    };
    None
}

/// Write sender from given email as .vcf file to given directory.
pub fn add_contact_from_email(contact_dir: &path::Path, email_input: &str) -> io::Result<Contact> {
    let from_header = match read_sender_from_email(email_input) {
        Some(x) => x,
        None => return Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            "Couldn't find From-header in email.",
            None
        ))
    };
    let (fullname, email) = parse_from_header(&from_header);
    let contact = Contact::generate(fullname, email, contact_dir);
    try!(contact.write_create());
    Ok(contact)
}

fn command_from_config(config_val: &str) -> process::Command {
    let mut parts = config_val.split(' ');
    let main = parts.next().unwrap();
    let rest: Vec<_> = parts.map(|x| x.to_string()).collect();
    let mut rv = process::Command::new(main);
    rv.args(rest.as_slice());
    rv
}
<commit_msg>Fix grep invocation<commit_after>use std::borrow::ToOwned;
use std::collections::HashSet;
use std::ffi::AsOsStr;
use std::fs::PathExt;
use std::fs;
use std::io::{Read,Write};
use std::io;
use std::path::AsPath;
use std::path;
use std::process;

use atomicwrites::{AtomicFile,DisallowOverwrite};
use email::rfc5322::Rfc5322Parser;
use uuid::Uuid;
use vobject::{Component,Property,parse_component,write_component};

use cli::Configuration;

pub fn handle_process(process: &mut process::Child) -> io::Result<()> {
    let exitcode = try!(process.wait());
    if !exitcode.success() {
        return Err(io::Error::new(
            io::ErrorKind::Other,
            "",
            Some(format!("{}", exitcode))
        ));
    };
    Ok(())
}

struct IndexIterator {
    linebuffer: Vec<String>
}

impl IndexIterator {
    fn new(output: &String) -> IndexIterator {
        let rv = output.split('\n').map(|x| x.to_string()).collect();
        IndexIterator {
            linebuffer: rv
        }
    }
}

impl Iterator for IndexIterator {
    type Item = IndexItem;

    fn next(&mut self) -> Option<IndexItem> {
        match self.linebuffer.pop() {
            Some(x) => Some(IndexItem::new(x)),
            None => None
        }
    }
}

struct IndexItem {
    pub email: String,
    pub name: String,
    pub filepath: Option<path::PathBuf>
}

impl IndexItem {
    fn new(line: String) -> IndexItem {
        let mut parts = line.split('\t');

        IndexItem {
            email: parts.next().unwrap_or("").to_string(),
            name: parts.next().unwrap_or("").to_string(),
            filepath: match parts.next() {
                Some(x) => Some(path::PathBuf::new(x)),
                None => None
            }
        }
    }
}

pub struct Contact {
    pub component: Component,
    pub path: path::PathBuf
}

impl Contact {
    pub fn from_file<P: AsOsStr + path::AsPath + ?Sized>(path: &P) -> io::Result<Contact> {
        // FIXME: Why is "AsOsStr" above necessary? File::open has a sig w/o it
        let mut contact_file = try!(fs::File::open(&path));
        let contact_string = {
            let mut x = String::new();
            try!(contact_file.read_to_string(&mut x));
            x
        };

        let item = match parse_component(contact_string.as_slice()) {
            Ok(x) => x,
            Err(e) => return Err(io::Error::new(
                io::ErrorKind::Other,
                "Error while parsing contact",
                Some(format!("{}", e))
            ))
        };

        Ok(Contact { component: item, path: path.as_path().to_owned() })
    }

    pub fn generate(fullname: Option<&str>, email: Option<&str>, dir: &path::Path) -> Contact {
        let (uid, contact_path) = {
            let mut uid;
            let mut contact_path;
            loop {
                uid = Uuid::new_v4().to_simple_string();
                contact_path = dir.join(&format!("{}.vcf", uid));
                if !(*contact_path).exists() {
                    break
                }
            };
            (uid, contact_path)
        };
        Contact { path: contact_path, component: generate_component(uid, fullname, email) }
    }

    pub fn write_create(&self) -> io::Result<()> {
        let string = write_component(&self.component);
        let af = AtomicFile::new(&self.path, DisallowOverwrite);

        af.write(|f| {
            f.write_all(string.as_bytes())
        })
    }
}

fn generate_component(uid: String, fullname: Option<&str>, email: Option<&str>) -> Component {
    let mut comp = Component::new("VCARD");

    match fullname {
        Some(x) => comp.all_props_mut("FN").push(Property::new(x)),
        None => ()
    };

    match email {
        Some(x) => comp.all_props_mut("EMAIL").push(Property::new(x)),
        None => ()
    };
    comp.all_props_mut("UID").push(Property::new(uid.as_slice()));
    comp
}

pub fn index_query<'a>(config: &Configuration, query: &str) -> io::Result<IndexIterator> {
    let mut process = try!(
        command_from_config(config.grep_cmd.as_slice())
        .arg(query.as_slice())
        .stdin(process::Stdio::piped())
        .stderr(process::Stdio::inherit())
        .spawn());

    {
        let mut index_fp = try!(fs::File::open(&config.index_path));
        let mut stdin = process.stdin.take().unwrap();
        let mut line: Vec<u8> = vec![];
        try!(index_fp.read_to_end(&mut line));
        try!(stdin.write_all(line.as_slice()));
    }

    try!(handle_process(&mut process));

    let stream = match process.stdout.as_mut() {
        Some(x) => x,
        None => return Err(io::Error::new(
            io::ErrorKind::ResourceUnavailable,
            "Failed to get stdout from grep process.",
            None
        ))
    };

    let mut output = String::new();
    try!(stream.read_to_string(&mut output));
    Ok(IndexIterator::new(&output))
}

/// Better than index_query if you're only interested in the filepath, as duplicate entries will be
/// removed.
pub fn file_query(config: &Configuration, query: &str) -> io::Result<HashSet<path::PathBuf>> {
    let mut rv: HashSet<path::PathBuf> = HashSet::new();
    rv.extend(
        try!(index_query(config, query)).filter_map(|x| x.filepath)
    );
    Ok(rv)
}

pub fn index_item_from_contact(contact: &Contact) -> io::Result<String> {
    let name = match contact.component.single_prop("FN") {
        Some(name) => name.value_as_string(),
        None => return Err(io::Error::new(
            io::ErrorKind::Other,
            "No name found.",
            None
        ))
    };

    let emails = contact.component.all_props("EMAIL");
    let mut rv = String::new();
    for email in emails.iter() {
        rv.push_str(format!("{}\t{}\t{}\n", email.value_as_string(), name, contact.path.display()).as_slice());
    };
    Ok(rv)
}

/// Return a tuple (fullname, email)
pub fn parse_from_header<'a>(s: &'a String) -> (Option<&'a str>, Option<&'a str>) {
    let mut split = s.rsplitn(1, ' ');
    let email = match split.next() {
        Some(x) => Some(x.trim_left_matches('<').trim_right_matches('>')),
        None => Some(s.as_slice())
    };
    let name = split.next();
    (name, email)
}

/// Given an email, return value of From header.
pub fn read_sender_from_email(email: &str) -> Option<String> {
    let mut parser = Rfc5322Parser::new(email);
    while !parser.eof() {
        match parser.consume_header() {
            Some(header) => {
                if header.name == "From" {
                    return header.get_value().ok()
                };
            },
            None => return None
        };
    };
    None
}

/// Write sender from given email as .vcf file to given directory.
pub fn add_contact_from_email(contact_dir: &path::Path, email_input: &str) -> io::Result<Contact> {
    let from_header = match read_sender_from_email(email_input) {
        Some(x) => x,
        None => return Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            "Couldn't find From-header in email.",
            None
        ))
    };
    let (fullname, email) = parse_from_header(&from_header);
    let contact = Contact::generate(fullname, email, contact_dir);
    try!(contact.write_create());
    Ok(contact)
}

fn command_from_config(config_val: &str) -> process::Command {
    let mut parts = config_val.split(' ');
    let main = parts.next().unwrap();
    let rest: Vec<_> = parts.map(|x| x.to_string()).collect();
    let mut rv = process::Command::new(main);
    rv.args(rest.as_slice());
    rv
}
<|endoftext|>


<commit_before>//! Pipeline specialization types.

use std::{borrow::Cow, ops::Range, slice};

/// Specialization constant for pipelines.
///
/// Specialization constants allow for easy configuration of
/// multiple similar pipelines. For example, there may be a
/// boolean exposed to the shader that switches the specularity on/off
/// provided via a specialization constant.
/// That would produce separate PSO's for the "on" and "off" states
/// but they share most of the internal stuff and are fast to produce.
/// More importantly, they are fast to execute, since the driver
/// can optimize out the branch on that other PSO creation.
#[derive(Debug, Clone, Hash, PartialEq)]
pub struct SpecializationConstant {
    /// Constant identifier in shader source.
    pub id: u32,
    /// Value to override specialization constant.
    pub range: Range<u16>,
}

/// Specialization information structure.
#[derive(Debug, Clone)]
pub struct Specialization<'a> {
    /// Constant array.
    pub constants: Cow<'a, [SpecializationConstant]>,
    /// Raw data.
    pub data: Cow<'a, [u8]>,
}

impl Specialization<'_> {
    /// Empty specialization instance.
    pub const EMPTY: Self = Specialization {
        constants: Cow::Borrowed(&[]),
        data: Cow::Borrowed(&[]),
    };
}

impl Default for Specialization<'_> {
    fn default() -> Self {
        Specialization::EMPTY
    }
}

#[doc(hidden)]
#[derive(Debug, Default)]
pub struct SpecializationStorage {
    constants: Vec<SpecializationConstant>,
    data: Vec<u8>,
}

/// List of specialization constants.
#[doc(hidden)]
pub trait SpecConstList: Sized {
    fn fold(self, storage: &mut SpecializationStorage);
}

impl<T> From<T> for Specialization<'_>
where
    T: SpecConstList,
{
    fn from(list: T) -> Self {
        let mut storage = SpecializationStorage::default();
        list.fold(&mut storage);
        Specialization {
            data: Cow::Owned(storage.data),
            constants: Cow::Owned(storage.constants),
        }
    }
}

#[doc(hidden)]
#[derive(Debug)]
pub struct SpecConstListNil;

#[doc(hidden)]
#[derive(Debug)]
pub struct SpecConstListCons<H, T> {
    pub head: (u32, H),
    pub tail: T,
}

impl SpecConstList for SpecConstListNil {
    fn fold(self, _storage: &mut SpecializationStorage) {}
}

impl<H, T> SpecConstList for SpecConstListCons<H, T>
where
    T: SpecConstList,
{
    fn fold(self, storage: &mut SpecializationStorage) {
        let size = std::mem::size_of::<H>();
        assert!(storage.data.len() + size <= u16::max_value() as usize);
        let offset = storage.data.len() as u16;
        storage.data.extend_from_slice(unsafe {
            // Inspecting bytes is always safe.
            slice::from_raw_parts(&self.head.1 as *const H as *const u8, size)
        });
        storage.constants.push(SpecializationConstant {
            id: self.head.0,
            range: offset .. offset + size as u16,
        });
        self.tail.fold(storage)
    }
}

/// Macro for specifying list of specialization constatns for `EntryPoint`.
#[macro_export]
macro_rules! spec_const_list {
    (@ $(,)?) => {
        $crate::pso::SpecConstListNil
    };

    (@ $head_id:expr => $head_constant:expr $(,$tail_id:expr => $tail_constant:expr)* $(,)?) => {
        $crate::pso::SpecConstListCons {
            head: ($head_id, $head_constant),
            tail: $crate::spec_const_list!(@ $($tail_id:expr => $tail_constant:expr),*),
        }
    };

    ($($id:expr => $constant:expr),* $(,)?) => {
        $crate::spec_const_list!(@ $($id => $constant),*).into()
    };

    ($($constant:expr),* $(,)?) => {
        {
            let mut counter = 0;
            $crate::spec_const_list!(@ $({ counter += 1; counter - 1 } => $constant),*).into()
        }
    };
}
<commit_msg>fix incorrect syntax in spec_const_list macro<commit_after>//! Pipeline specialization types.

use std::{borrow::Cow, ops::Range, slice};

/// Specialization constant for pipelines.
///
/// Specialization constants allow for easy configuration of
/// multiple similar pipelines. For example, there may be a
/// boolean exposed to the shader that switches the specularity on/off
/// provided via a specialization constant.
/// That would produce separate PSO's for the "on" and "off" states
/// but they share most of the internal stuff and are fast to produce.
/// More importantly, they are fast to execute, since the driver
/// can optimize out the branch on that other PSO creation.
#[derive(Debug, Clone, Hash, PartialEq)]
pub struct SpecializationConstant {
    /// Constant identifier in shader source.
    pub id: u32,
    /// Value to override specialization constant.
    pub range: Range<u16>,
}

/// Specialization information structure.
#[derive(Debug, Clone)]
pub struct Specialization<'a> {
    /// Constant array.
    pub constants: Cow<'a, [SpecializationConstant]>,
    /// Raw data.
    pub data: Cow<'a, [u8]>,
}

impl Specialization<'_> {
    /// Empty specialization instance.
    pub const EMPTY: Self = Specialization {
        constants: Cow::Borrowed(&[]),
        data: Cow::Borrowed(&[]),
    };
}

impl Default for Specialization<'_> {
    fn default() -> Self {
        Specialization::EMPTY
    }
}

#[doc(hidden)]
#[derive(Debug, Default)]
pub struct SpecializationStorage {
    constants: Vec<SpecializationConstant>,
    data: Vec<u8>,
}

/// List of specialization constants.
#[doc(hidden)]
pub trait SpecConstList: Sized {
    fn fold(self, storage: &mut SpecializationStorage);
}

impl<T> From<T> for Specialization<'_>
where
    T: SpecConstList,
{
    fn from(list: T) -> Self {
        let mut storage = SpecializationStorage::default();
        list.fold(&mut storage);
        Specialization {
            data: Cow::Owned(storage.data),
            constants: Cow::Owned(storage.constants),
        }
    }
}

#[doc(hidden)]
#[derive(Debug)]
pub struct SpecConstListNil;

#[doc(hidden)]
#[derive(Debug)]
pub struct SpecConstListCons<H, T> {
    pub head: (u32, H),
    pub tail: T,
}

impl SpecConstList for SpecConstListNil {
    fn fold(self, _storage: &mut SpecializationStorage) {}
}

impl<H, T> SpecConstList for SpecConstListCons<H, T>
where
    T: SpecConstList,
{
    fn fold(self, storage: &mut SpecializationStorage) {
        let size = std::mem::size_of::<H>();
        assert!(storage.data.len() + size <= u16::max_value() as usize);
        let offset = storage.data.len() as u16;
        storage.data.extend_from_slice(unsafe {
            // Inspecting bytes is always safe.
            slice::from_raw_parts(&self.head.1 as *const H as *const u8, size)
        });
        storage.constants.push(SpecializationConstant {
            id: self.head.0,
            range: offset .. offset + size as u16,
        });
        self.tail.fold(storage)
    }
}

/// Macro for specifying list of specialization constatns for `EntryPoint`.
#[macro_export]
macro_rules! spec_const_list {
    (@ $(,)?) => {
        $crate::pso::SpecConstListNil
    };

    (@ $head_id:expr => $head_constant:expr $(,$tail_id:expr => $tail_constant:expr)* $(,)?) => {
        $crate::pso::SpecConstListCons {
            head: ($head_id, $head_constant),
            tail: $crate::spec_const_list!(@ $($tail_id => $tail_constant),*),
        }
    };

    ($($id:expr => $constant:expr),* $(,)?) => {
        $crate::spec_const_list!(@ $($id => $constant),*).into()
    };

    ($($constant:expr),* $(,)?) => {
        {
            let mut counter = 0;
            $crate::spec_const_list!(@ $({ counter += 1; counter - 1 } => $constant),*).into()
        }
    };
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;

pub use self::builder::MessageBuilder;

mod builder;
#[cfg(test)]
mod test;
mod to_json;

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Message {
    uuid: String,
    name: Option<String>,
    message: String,
    values: BTreeMap<String, String>
}

impl Message {
    pub fn uuid(&self) -> &String {
        &self.uuid
    }

    pub fn name(&self) -> Option<&String> {
        self.name.as_ref()
    }

    pub fn get(&self, key: &str) -> Option<&String> {
        self.values.get(key)
    }

    pub fn values(&self) -> &BTreeMap<String, String> {
        &self.values
    }

    pub fn insert(&mut self, key: &str, value: &str) {
        self.values.insert(key.to_string(), value.to_string());
    }

    pub fn ids(&self) -> IdIterator {
        IdIterator {
            message: self,
            state: 0
        }
    }
}

pub struct IdIterator<'a> {
    message: &'a Message,
    state: u8
}

impl<'a> Iterator for IdIterator<'a> {
    type Item = &'a String;
    fn next(&mut self) -> Option<Self::Item> {
        match self.state {
            0 => {
                self.state += 1;
                Some(self.message.uuid())
            },
            1 => {
                self.state += 1;
                self.message.name()
            },
            _ => None
        }
    }
}
<commit_msg>Message: add message() getter method<commit_after>use std::collections::BTreeMap;

pub use self::builder::MessageBuilder;

mod builder;
#[cfg(test)]
mod test;
mod to_json;

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Message {
    uuid: String,
    name: Option<String>,
    message: String,
    values: BTreeMap<String, String>
}

impl Message {
    pub fn uuid(&self) -> &String {
        &self.uuid
    }

    pub fn name(&self) -> Option<&String> {
        self.name.as_ref()
    }

    pub fn message(&self) -> &String {
        &self.message
    }

    pub fn get(&self, key: &str) -> Option<&String> {
        self.values.get(key)
    }

    pub fn values(&self) -> &BTreeMap<String, String> {
        &self.values
    }

    pub fn insert(&mut self, key: &str, value: &str) {
        self.values.insert(key.to_string(), value.to_string());
    }

    pub fn ids(&self) -> IdIterator {
        IdIterator {
            message: self,
            state: 0
        }
    }
}

pub struct IdIterator<'a> {
    message: &'a Message,
    state: u8
}

impl<'a> Iterator for IdIterator<'a> {
    type Item = &'a String;
    fn next(&mut self) -> Option<Self::Item> {
        match self.state {
            0 => {
                self.state += 1;
                Some(self.message.uuid())
            },
            1 => {
                self.state += 1;
                self.message.name()
            },
            _ => None
        }
    }
}
<|endoftext|>


<commit_before>extern mod std;

use std::{io, vec, ptr, os};
use std::libc::{c_uint};

mod crypto {
  use std::libc::{c_uint};
#[link_args = "-lcrypto"]
  extern {
    fn SHA1(src: *u8, sz: c_uint, out: *u8) -> *u8;
    fn MD5(src: *u8, sz: c_uint, out: *u8) -> *u8;
    fn SHA224(src: *u8, sz: c_uint, out: *u8) -> *u8;
    fn SHA256(src: *u8, sz: c_uint, out: *u8) -> *u8;
    fn SHA384(src: *u8, sz: c_uint, out: *u8) -> *u8;
    fn SHA512(src: *u8, sz: c_uint, out: *u8) -> *u8;
  }
}

enum HashMethod { MD5, SHA1, SHA224, SHA256, SHA384, SHA512 }

struct HashEngine {
  engine:      (extern "C" unsafe fn(*u8, c_uint, *u8) -> *u8),
  digest_size: uint,
  block_size:  uint
}

impl HashEngine {
  fn new(engine: HashMethod) -> ~HashEngine {
    match engine {
      MD5    => ~HashEngine{ engine: crypto::MD5,    digest_size: 16, block_size: 64  },
      SHA1   => ~HashEngine{ engine: crypto::SHA1,   digest_size: 20, block_size: 64  },
      SHA224 => ~HashEngine{ engine: crypto::SHA224, digest_size: 28, block_size: 64  },
      SHA256 => ~HashEngine{ engine: crypto::SHA256, digest_size: 32, block_size: 64  },
      SHA384 => ~HashEngine{ engine: crypto::SHA384, digest_size: 48, block_size: 64  },
      SHA512 => ~HashEngine{ engine: crypto::SHA512, digest_size: 64, block_size: 128 }
    }
  }

  fn hash(&self, data: ~[u8]) -> ~Digest {
    let hash_func = self.engine;
    Digest::new(
      unsafe {
        vec::from_buf(
          hash_func(
            vec::raw::to_ptr(data),
            data.len() as c_uint, ptr::null()
          ),
          self.digest_size
        )
      }
    )
  }

  fn hmac(&self, key: ~[u8], message: ~[u8]) -> ~Digest {
    let computed_key = match key.len() {
      len if len > self.block_size => self.zero_pad(self.hash(key).digest),
      len if len < self.block_size => self.zero_pad(key),
      _ => key
    };

    let o_key_pad = HashEngine::xor_with(computed_key, 0x5c);
    let i_key_pad = HashEngine::xor_with(computed_key, 0x36);

    self.hash(o_key_pad + self.hash(i_key_pad + message).digest)
  }

  priv fn xor_with(subject: &[u8], val: u8) -> ~[u8] {
    do subject.map |&c| { val ^ c }
  }

  priv fn zero_pad(&self, subject: ~[u8]) -> ~[u8] {
    subject + vec::from_elem(self.block_size - subject.len(), 0)
  }
}

struct Digest { digest: ~[u8] }

impl Digest {
  fn new(digest: ~[u8]) -> ~Digest { return ~Digest{ digest: digest } }

  fn hexdigest(&self) -> ~str {
    let mut acc = ~"";
    for self.digest.iter().advance |&byte| { acc = acc.append(fmt!("%02x", byte as uint)); }
    acc
  }
}

fn sha1(data: ~[u8]) -> ~Digest {
  HashEngine::new(SHA1).hash(data)
}

fn sha224(data: ~[u8]) -> ~Digest {
  HashEngine::new(SHA224).hash(data)
}

fn sha256(data: ~[u8]) -> ~Digest {
  HashEngine::new(SHA256).hash(data)
}

fn sha384(data: ~[u8]) -> ~Digest {
  HashEngine::new(SHA384).hash(data)
}

fn sha512(data: ~[u8]) -> ~Digest {
  HashEngine::new(SHA512).hash(data)
}

fn md5(data: ~[u8]) -> ~Digest {
  HashEngine::new(MD5).hash(data)
}

fn hmac_md5(key: ~[u8], message: ~[u8]) -> ~Digest {
  HashEngine::new(MD5).hmac(key, message)
}

fn hmac_sha1(key: ~[u8], message: ~[u8]) -> ~Digest {
  HashEngine::new(SHA1).hmac(key, message)
}

fn hmac_sha256(key: ~[u8], message: ~[u8]) -> ~Digest {
  HashEngine::new(SHA256).hmac(key, message)
}

fn hmac_sha512(key: ~[u8], message: ~[u8]) -> ~Digest {
  HashEngine::new(SHA512).hmac(key, message)
}

fn main() {
  if os::args().len() < 2 { fail!(~"Nothing to hash: supply an argument") }
  let args = ~os::args();
  io::println(sha1(args[1].as_bytes().to_owned()).hexdigest());
}

#[test]
fn test_sha1() {
  assert_eq!(sha1("testing SHA1".as_bytes().to_owned()).hexdigest(), ~"a07bb2f7f56b7b47e54fd9e29b4629c8967dde4c");
}

#[test]
fn test_md5() {
  assert_eq!(md5("testing MD5".as_bytes().to_owned()).hexdigest(), ~"da35df95d34f166890fa759f5e00e94c");
}

#[test]
fn test_hmac_sha1_with_a_64_byte_key() {
  assert_eq!(
    hmac_sha1("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".as_bytes().to_owned(), "some data to hmac".as_bytes().to_owned()).hexdigest(),
    ~"d6264ce636b593e6c5b43c90ec4ca3550032c99f"
  )
}

#[test]
fn test_hmac_sha1_with_a_too_long_key() {
  assert_eq!(
    hmac_sha1("keyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".as_bytes().to_owned(), "some data to hmac".as_bytes().to_owned()).hexdigest(),
    ~"4361f0a10ae7fc1ce33d2795e998d0e526a38815"
  )
}

#[test]
fn test_hmac_sha1_with_a_too_short_key() {
  assert_eq!(
    hmac_sha1("my key".as_bytes().to_owned(), "some data to hmac".as_bytes().to_owned()).hexdigest(),
    ~"331c9bf4d7dc8ad7e9bab2f566c8612042a9f4e2"
  )
}

#[test]
fn test_hmac_sha256() {
  assert_eq!(
    hmac_sha256("my key".as_bytes().to_owned(), "some data to hmac".as_bytes().to_owned()).hexdigest(),
    ~"17764a8a2e8c23ae3b9e1781c5ebeb5754c7920806021032e9133051e10118be"
  );
}

#[test]
fn test_hmac_sha512() {
  assert_eq!(
    hmac_sha512("my key".as_bytes().to_owned(), "some data to hmac".as_bytes().to_owned()).hexdigest(),
    ~"b54973feba2e436c4f0911855c80e7320d72edd37b359d6474d714718c52775f163832b79214e9fa9d400208d21372a465b2cda2a1d5ab488bbc02b0daea9626"
  );
}

#[test]
fn test_hmac_md5() {
  assert_eq!(hmac_md5("my key".as_bytes().to_owned(), "some data to hmac".as_bytes().to_owned()).hexdigest(), ~"befd13e00ee07549520ade402c664a3a");
}
<commit_msg>Much more idiomatic pattern matching thanks to guys on HN.<commit_after>extern mod std;

use std::{io, vec, ptr, os};
use std::libc::{c_uint};

mod crypto {
  use std::libc::{c_uint};
#[link_args = "-lcrypto"]
  extern {
    fn SHA1(src: *u8, sz: c_uint, out: *u8) -> *u8;
    fn MD5(src: *u8, sz: c_uint, out: *u8) -> *u8;
    fn SHA224(src: *u8, sz: c_uint, out: *u8) -> *u8;
    fn SHA256(src: *u8, sz: c_uint, out: *u8) -> *u8;
    fn SHA384(src: *u8, sz: c_uint, out: *u8) -> *u8;
    fn SHA512(src: *u8, sz: c_uint, out: *u8) -> *u8;
  }
}

enum HashMethod { MD5, SHA1, SHA224, SHA256, SHA384, SHA512 }

struct HashEngine {
  engine:      (extern "C" unsafe fn(*u8, c_uint, *u8) -> *u8),
  digest_size: uint,
  block_size:  uint
}

impl HashEngine {
  fn new(engine: HashMethod) -> ~HashEngine {
    match engine {
      MD5    => ~HashEngine{ engine: crypto::MD5,    digest_size: 16, block_size: 64  },
      SHA1   => ~HashEngine{ engine: crypto::SHA1,   digest_size: 20, block_size: 64  },
      SHA224 => ~HashEngine{ engine: crypto::SHA224, digest_size: 28, block_size: 64  },
      SHA256 => ~HashEngine{ engine: crypto::SHA256, digest_size: 32, block_size: 64  },
      SHA384 => ~HashEngine{ engine: crypto::SHA384, digest_size: 48, block_size: 64  },
      SHA512 => ~HashEngine{ engine: crypto::SHA512, digest_size: 64, block_size: 128 }
    }
  }

  fn hash(&self, data: ~[u8]) -> ~Digest {
    let hash_func = self.engine;

    Digest::new(
      unsafe {
        vec::from_buf(
          hash_func(
            vec::raw::to_ptr(data),
            data.len() as c_uint, ptr::null()
          ),
          self.digest_size
        )
      }
    )
  }

  fn hmac(&self, key: ~[u8], message: ~[u8]) -> ~Digest {
    let computed_key = match key.len().cmp(&self.block_size) {
      Less => self.zero_pad(key),
      Equal => key,
      Greater => self.zero_pad(self.hash(key).digest),
    };

    let o_key_pad = HashEngine::xor_with(computed_key, 0x5c);
    let i_key_pad = HashEngine::xor_with(computed_key, 0x36);

    self.hash(o_key_pad + self.hash(i_key_pad + message).digest)
  }

  priv fn xor_with(subject: &[u8], val: u8) -> ~[u8] {
    do subject.map |&c| { val ^ c }
  }

  priv fn zero_pad(&self, subject: ~[u8]) -> ~[u8] {
    subject + vec::from_elem(self.block_size - subject.len(), 0)
  }
}

struct Digest { digest: ~[u8] }

impl Digest {
  fn new(digest: ~[u8]) -> ~Digest { return ~Digest{ digest: digest } }

  fn hexdigest(&self) -> ~str {
    let mut acc = ~"";
    for self.digest.iter().advance |&byte| { acc = acc.append(fmt!("%02x", byte as uint)); }
    acc
  }
}

fn sha1(data: ~[u8]) -> ~Digest {
  HashEngine::new(SHA1).hash(data)
}

fn sha224(data: ~[u8]) -> ~Digest {
  HashEngine::new(SHA224).hash(data)
}

fn sha256(data: ~[u8]) -> ~Digest {
  HashEngine::new(SHA256).hash(data)
}

fn sha384(data: ~[u8]) -> ~Digest {
  HashEngine::new(SHA384).hash(data)
}

fn sha512(data: ~[u8]) -> ~Digest {
  HashEngine::new(SHA512).hash(data)
}

fn md5(data: ~[u8]) -> ~Digest {
  HashEngine::new(MD5).hash(data)
}

fn hmac_md5(key: ~[u8], message: ~[u8]) -> ~Digest {
  HashEngine::new(MD5).hmac(key, message)
}

fn hmac_sha1(key: ~[u8], message: ~[u8]) -> ~Digest {
  HashEngine::new(SHA1).hmac(key, message)
}

fn hmac_sha256(key: ~[u8], message: ~[u8]) -> ~Digest {
  HashEngine::new(SHA256).hmac(key, message)
}

fn hmac_sha512(key: ~[u8], message: ~[u8]) -> ~Digest {
  HashEngine::new(SHA512).hmac(key, message)
}

fn main() {
  if os::args().len() < 2 { fail!(~"Nothing to hash: supply an argument") }
  let args = ~os::args();
  io::println(sha1(args[1].as_bytes().to_owned()).hexdigest());
}

#[test]
fn test_sha1() {
  assert_eq!(sha1("testing SHA1".as_bytes().to_owned()).hexdigest(), ~"a07bb2f7f56b7b47e54fd9e29b4629c8967dde4c");
}

#[test]
fn test_md5() {
  assert_eq!(md5("testing MD5".as_bytes().to_owned()).hexdigest(), ~"da35df95d34f166890fa759f5e00e94c");
}

#[test]
fn test_hmac_sha1_with_a_64_byte_key() {
  assert_eq!(
    hmac_sha1("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".as_bytes().to_owned(), "some data to hmac".as_bytes().to_owned()).hexdigest(),
    ~"d6264ce636b593e6c5b43c90ec4ca3550032c99f"
  )
}

#[test]
fn test_hmac_sha1_with_a_too_long_key() {
  assert_eq!(
    hmac_sha1("keyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".as_bytes().to_owned(), "some data to hmac".as_bytes().to_owned()).hexdigest(),
    ~"4361f0a10ae7fc1ce33d2795e998d0e526a38815"
  )
}

#[test]
fn test_hmac_sha1_with_a_too_short_key() {
  assert_eq!(
    hmac_sha1("my key".as_bytes().to_owned(), "some data to hmac".as_bytes().to_owned()).hexdigest(),
    ~"331c9bf4d7dc8ad7e9bab2f566c8612042a9f4e2"
  )
}

#[test]
fn test_hmac_sha256() {
  assert_eq!(
    hmac_sha256("my key".as_bytes().to_owned(), "some data to hmac".as_bytes().to_owned()).hexdigest(),
    ~"17764a8a2e8c23ae3b9e1781c5ebeb5754c7920806021032e9133051e10118be"
  );
}

#[test]
fn test_hmac_sha512() {
  assert_eq!(
    hmac_sha512("my key".as_bytes().to_owned(), "some data to hmac".as_bytes().to_owned()).hexdigest(),
    ~"b54973feba2e436c4f0911855c80e7320d72edd37b359d6474d714718c52775f163832b79214e9fa9d400208d21372a465b2cda2a1d5ab488bbc02b0daea9626"
  );
}

#[test]
fn test_hmac_md5() {
  assert_eq!(hmac_md5("my key".as_bytes().to_owned(), "some data to hmac".as_bytes().to_owned()).hexdigest(), ~"befd13e00ee07549520ade402c664a3a");
}
<|endoftext|>