<commit_before>use std::cmp::Ordering;
use std::hash::{Hash, Hasher};

use ring::digest::Algorithm;

use hashutils::HashUtils;
use tree::Tree;

/// An inclusion proof represent the fact that a `value` is a member
/// of a `MerkleTree` with root hash `root_hash`, and hash function `algorithm`.
#[cfg_attr(feature = "serialization-serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug)]
pub struct Proof<T> {
    /// The hashing algorithm used in the original `MerkleTree`
    #[cfg_attr(feature = "serialization-serde", serde(with = "algorithm_serde"))]
    pub algorithm: &'static Algorithm,

    /// The hash of the root of the original `MerkleTree`
    pub root_hash: Vec<u8>,

    /// The first `Lemma` of the `Proof`
    pub lemma: Lemma,

    /// The value concerned by this `Proof`
    pub value: T,
}

#[cfg(feature = "serialization-serde")]
mod algorithm_serde {
    use ring::digest::{self, Algorithm};
    use serde::de::Error;
    use serde::{Deserialize, Deserializer, Serialize, Serializer};

    pub fn serialize<S: Serializer>(
        algorithm: &'static Algorithm,
        se: S,
    ) -> Result<S::Ok, S::Error> {
        // The `Debug` implementation of `Algorithm` prints its ID.
        format!("{:?}", algorithm).serialize(se)
    }

    pub fn deserialize<'de, D: Deserializer<'de>>(de: D) -> Result<&'static Algorithm, D::Error> {
        match Deserialize::deserialize(de)? {
            "SHA1" => Ok(&digest::SHA1),
            "SHA256" => Ok(&digest::SHA256),
            "SHA384" => Ok(&digest::SHA384),
            "SHA512" => Ok(&digest::SHA512),
            "SHA512_256" => Ok(&digest::SHA512_256),
            _ => Err(D::Error::custom("unknown hash algorithm")),
        }
    }

    mod test {
        use super::*;
        use ring::digest::{
            SHA1 as sha1, SHA256 as sha256, SHA384 as sha384, SHA512 as sha512,
            SHA512_256 as sha512_256,
        };

        static SHA1: &Algorithm = &sha1;
        static SHA256: &Algorithm = &sha256;
        static SHA384: &Algorithm = &sha384;
        static SHA512: &Algorithm = &sha512;
        static SHA512_256: &Algorithm = &sha512_256;

        #[test]
        fn test_serialize_known_algorithms() {
            extern crate serde_json;

            for alg in [SHA1, SHA256, SHA384, SHA512, SHA512_256].iter() {
                let mut serializer = serde_json::Serializer::with_formatter(
                    vec![],
                    serde_json::ser::PrettyFormatter::new(),
                );

                let _ = serialize(alg, &mut serializer).expect(&format!("{:?}", alg));
                let alg_ = deserialize(&mut serde_json::Deserializer::from_slice(
                    &serializer.into_inner()[..],
                )).expect(&format!("{:?}", alg));

                assert_eq!(*alg, alg_);
            }
        }

        #[test]
        #[should_panic(expected = "unknown hash algorithm")]
        fn test_serialize_unknown_algorithm() {
            extern crate serde_json;
            {
                let alg_str = "\"BLAKE2b\"";
                let mut deserializer = serde_json::Deserializer::from_str(alg_str);
                let _ = deserialize(&mut deserializer).expect(&format!("{:?}", alg_str));
            }
        }
    }
}

impl<T: PartialEq> PartialEq for Proof<T> {
    fn eq(&self, other: &Proof<T>) -> bool {
        self.root_hash == other.root_hash && self.lemma == other.lemma && self.value == other.value
    }
}

impl<T: Eq> Eq for Proof<T> {}

impl<T: Ord> PartialOrd for Proof<T> {
    fn partial_cmp(&self, other: &Proof<T>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<T: Ord> Ord for Proof<T> {
    fn cmp(&self, other: &Proof<T>) -> Ordering {
        self.root_hash
            .cmp(&other.root_hash)
            .then(self.value.cmp(&other.value))
            .then_with(|| self.lemma.cmp(&other.lemma))
    }
}

impl<T: Hash> Hash for Proof<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.root_hash.hash(state);
        self.lemma.hash(state);
        self.value.hash(state);
    }
}

impl<T> Proof<T> {
    /// Constructs a new `Proof`
    pub fn new(algorithm: &'static Algorithm, root_hash: Vec<u8>, lemma: Lemma, value: T) -> Self {
        Proof {
            algorithm,
            root_hash,
            lemma,
            value,
        }
    }

    /// Checks whether this inclusion proof is well-formed,
    /// and whether its root hash matches the given `root_hash`.
    pub fn validate(&self, root_hash: &[u8]) -> bool {
        if self.root_hash != root_hash || self.lemma.node_hash != root_hash {
            return false;
        }

        self.lemma.validate(self.algorithm)
    }
}

/// A `Lemma` holds the hash of a node, the hash of its sibling node,
/// and a sub lemma, whose `node_hash`, when combined with this `sibling_hash`
/// must be equal to this `node_hash`.
#[cfg_attr(feature = "serialization-serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Lemma {
    pub node_hash: Vec<u8>,
    pub sibling_hash: Option<Positioned<Vec<u8>>>,
    pub sub_lemma: Option<Box<Lemma>>,
}

impl Lemma {
    /// Attempts to generate a proof that the a value with hash `needle` is a member of the given `tree`.
    pub fn new<T>(tree: &Tree<T>, needle: &[u8]) -> Option<Lemma> {
        match *tree {
            Tree::Empty { .. } => None,

            Tree::Leaf { ref hash, .. } => Lemma::new_leaf_proof(hash, needle),

            Tree::Node {
                ref hash,
                ref left,
                ref right,
            } => Lemma::new_tree_proof(hash, needle, left, right),
        }
    }

    fn new_leaf_proof(hash: &[u8], needle: &[u8]) -> Option<Lemma> {
        if *hash == *needle {
            Some(Lemma {
                node_hash: hash.into(),
                sibling_hash: None,
                sub_lemma: None,
            })
        } else {
            None
        }
    }

    fn new_tree_proof<T>(
        hash: &[u8],
        needle: &[u8],
        left: &Tree<T>,
        right: &Tree<T>,
    ) -> Option<Lemma> {
        Lemma::new(left, needle)
            .map(|lemma| {
                let right_hash = right.hash().clone();
                let sub_lemma = Some(Positioned::Right(right_hash));
                (lemma, sub_lemma)
            })
            .or_else(|| {
                let sub_lemma = Lemma::new(right, needle);
                sub_lemma.map(|lemma| {
                    let left_hash = left.hash().clone();
                    let sub_lemma = Some(Positioned::Left(left_hash));
                    (lemma, sub_lemma)
                })
            })
            .map(|(sub_lemma, sibling_hash)| Lemma {
                node_hash: hash.into(),
                sibling_hash,
                sub_lemma: Some(Box::new(sub_lemma)),
            })
    }

    fn validate(&self, algorithm: &'static Algorithm) -> bool {
        match self.sub_lemma {
            None => self.sibling_hash.is_none(),

            Some(ref sub) => match self.sibling_hash {
                None => false,

                Some(Positioned::Left(ref hash)) => {
                    let combined = algorithm.hash_nodes(hash, &sub.node_hash);
                    let hashes_match = combined.as_ref() == self.node_hash.as_slice();
                    hashes_match && sub.validate(algorithm)
                }

                Some(Positioned::Right(ref hash)) => {
                    let combined = algorithm.hash_nodes(&sub.node_hash, hash);
                    let hashes_match = combined.as_ref() == self.node_hash.as_slice();
                    hashes_match && sub.validate(algorithm)
                }
            },
        }
    }
}

/// Tags a value so that we know from which branch of a `Tree` (if any) it was found.
#[cfg_attr(feature = "serialization-serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Positioned<T> {
    /// The value was found in the left branch
    Left(T),

    /// The value was found in the right branch
    Right(T),
}
<commit_msg>Add dummy proof.rs file to avoid rustfmt failing<commit_after>use std::cmp::Ordering;
use std::hash::{Hash, Hasher};

use ring::digest::Algorithm;

use hashutils::HashUtils;
use tree::Tree;

/// An inclusion proof represent the fact that a `value` is a member
/// of a `MerkleTree` with root hash `root_hash`, and hash function `algorithm`.
#[cfg_attr(
    feature = "serialization-serde",
    derive(Serialize, Deserialize)
)]
#[derive(Clone, Debug)]
pub struct Proof<T> {
    /// The hashing algorithm used in the original `MerkleTree`
    #[cfg_attr(
        feature = "serialization-serde",
        serde(with = "algorithm_serde")
    )]
    pub algorithm: &'static Algorithm,

    /// The hash of the root of the original `MerkleTree`
    pub root_hash: Vec<u8>,

    /// The first `Lemma` of the `Proof`
    pub lemma: Lemma,

    /// The value concerned by this `Proof`
    pub value: T,
}

#[cfg(feature = "serialization-serde")]
mod algorithm_serde {
    use ring::digest::{self, Algorithm};
    use serde::de::Error;
    use serde::{Deserialize, Deserializer, Serialize, Serializer};

    pub fn serialize<S: Serializer>(
        algorithm: &'static Algorithm,
        se: S,
    ) -> Result<S::Ok, S::Error> {
        // The `Debug` implementation of `Algorithm` prints its ID.
        format!("{:?}", algorithm).serialize(se)
    }

    pub fn deserialize<'de, D: Deserializer<'de>>(de: D) -> Result<&'static Algorithm, D::Error> {
        match Deserialize::deserialize(de)? {
            "SHA1" => Ok(&digest::SHA1),
            "SHA256" => Ok(&digest::SHA256),
            "SHA384" => Ok(&digest::SHA384),
            "SHA512" => Ok(&digest::SHA512),
            "SHA512_256" => Ok(&digest::SHA512_256),
            _ => Err(D::Error::custom("unknown hash algorithm")),
        }
    }

    mod test {
        use super::*;
        use ring::digest::{
            SHA1 as sha1, SHA256 as sha256, SHA384 as sha384, SHA512 as sha512,
            SHA512_256 as sha512_256,
        };

        static SHA1: &Algorithm = &sha1;
        static SHA256: &Algorithm = &sha256;
        static SHA384: &Algorithm = &sha384;
        static SHA512: &Algorithm = &sha512;
        static SHA512_256: &Algorithm = &sha512_256;

        #[test]
        fn test_serialize_known_algorithms() {
            extern crate serde_json;

            for alg in [SHA1, SHA256, SHA384, SHA512, SHA512_256].iter() {
                let mut serializer = serde_json::Serializer::with_formatter(
                    vec![],
                    serde_json::ser::PrettyFormatter::new(),
                );

                let _ = serialize(alg, &mut serializer).expect(&format!("{:?}", alg));
                let alg_ = deserialize(&mut serde_json::Deserializer::from_slice(
                    &serializer.into_inner()[..],
                )).expect(&format!("{:?}", alg));

                assert_eq!(*alg, alg_);
            }
        }

        #[test]
        #[should_panic(expected = "unknown hash algorithm")]
        fn test_serialize_unknown_algorithm() {
            extern crate serde_json;
            {
                let alg_str = "\"BLAKE2b\"";
                let mut deserializer = serde_json::Deserializer::from_str(alg_str);
                let _ = deserialize(&mut deserializer).expect(&format!("{:?}", alg_str));
            }
        }
    }
}

impl<T: PartialEq> PartialEq for Proof<T> {
    fn eq(&self, other: &Proof<T>) -> bool {
        self.root_hash == other.root_hash && self.lemma == other.lemma && self.value == other.value
    }
}

impl<T: Eq> Eq for Proof<T> {}

impl<T: Ord> PartialOrd for Proof<T> {
    fn partial_cmp(&self, other: &Proof<T>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<T: Ord> Ord for Proof<T> {
    fn cmp(&self, other: &Proof<T>) -> Ordering {
        self.root_hash
            .cmp(&other.root_hash)
            .then(self.value.cmp(&other.value))
            .then_with(|| self.lemma.cmp(&other.lemma))
    }
}

impl<T: Hash> Hash for Proof<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.root_hash.hash(state);
        self.lemma.hash(state);
        self.value.hash(state);
    }
}

impl<T> Proof<T> {
    /// Constructs a new `Proof`
    pub fn new(algorithm: &'static Algorithm, root_hash: Vec<u8>, lemma: Lemma, value: T) -> Self {
        Proof {
            algorithm,
            root_hash,
            lemma,
            value,
        }
    }

    /// Checks whether this inclusion proof is well-formed,
    /// and whether its root hash matches the given `root_hash`.
    pub fn validate(&self, root_hash: &[u8]) -> bool {
        if self.root_hash != root_hash || self.lemma.node_hash != root_hash {
            return false;
        }

        self.lemma.validate(self.algorithm)
    }
}

/// A `Lemma` holds the hash of a node, the hash of its sibling node,
/// and a sub lemma, whose `node_hash`, when combined with this `sibling_hash`
/// must be equal to this `node_hash`.
#[cfg_attr(
    feature = "serialization-serde",
    derive(Serialize, Deserialize)
)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Lemma {
    pub node_hash: Vec<u8>,
    pub sibling_hash: Option<Positioned<Vec<u8>>>,
    pub sub_lemma: Option<Box<Lemma>>,
}

impl Lemma {
    /// Attempts to generate a proof that the a value with hash `needle` is a member of the given `tree`.
    pub fn new<T>(tree: &Tree<T>, needle: &[u8]) -> Option<Lemma> {
        match *tree {
            Tree::Empty { .. } => None,

            Tree::Leaf { ref hash, .. } => Lemma::new_leaf_proof(hash, needle),

            Tree::Node {
                ref hash,
                ref left,
                ref right,
            } => Lemma::new_tree_proof(hash, needle, left, right),
        }
    }

    fn new_leaf_proof(hash: &[u8], needle: &[u8]) -> Option<Lemma> {
        if *hash == *needle {
            Some(Lemma {
                node_hash: hash.into(),
                sibling_hash: None,
                sub_lemma: None,
            })
        } else {
            None
        }
    }

    fn new_tree_proof<T>(
        hash: &[u8],
        needle: &[u8],
        left: &Tree<T>,
        right: &Tree<T>,
    ) -> Option<Lemma> {
        Lemma::new(left, needle)
            .map(|lemma| {
                let right_hash = right.hash().clone();
                let sub_lemma = Some(Positioned::Right(right_hash));
                (lemma, sub_lemma)
            })
            .or_else(|| {
                let sub_lemma = Lemma::new(right, needle);
                sub_lemma.map(|lemma| {
                    let left_hash = left.hash().clone();
                    let sub_lemma = Some(Positioned::Left(left_hash));
                    (lemma, sub_lemma)
                })
            })
            .map(|(sub_lemma, sibling_hash)| Lemma {
                node_hash: hash.into(),
                sibling_hash,
                sub_lemma: Some(Box::new(sub_lemma)),
            })
    }

    fn validate(&self, algorithm: &'static Algorithm) -> bool {
        match self.sub_lemma {
            None => self.sibling_hash.is_none(),

            Some(ref sub) => match self.sibling_hash {
                None => false,

                Some(Positioned::Left(ref hash)) => {
                    let combined = algorithm.hash_nodes(hash, &sub.node_hash);
                    let hashes_match = combined.as_ref() == self.node_hash.as_slice();
                    hashes_match && sub.validate(algorithm)
                }

                Some(Positioned::Right(ref hash)) => {
                    let combined = algorithm.hash_nodes(&sub.node_hash, hash);
                    let hashes_match = combined.as_ref() == self.node_hash.as_slice();
                    hashes_match && sub.validate(algorithm)
                }
            },
        }
    }
}

/// Tags a value so that we know from which branch of a `Tree` (if any) it was found.
#[cfg_attr(
    feature = "serialization-serde",
    derive(Serialize, Deserialize)
)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Positioned<T> {
    /// The value was found in the left branch
    Left(T),

    /// The value was found in the right branch
    Right(T),
}
<|endoftext|>


<commit_before>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

use std::fmt::Show;
use std::fmt;
use std::str::CharOffsets;

use super::version::Version;

#[deriving(PartialEq,Clone)]
pub struct VersionReq {
    predicates: Vec<Predicate>
}

#[deriving(PartialEq,Clone)]
enum Op {
    Ex,   // Exact
    Gt,   // Greater than
    GtEq, // Greater than or equal to
    Lt,   // Less than
    LtEq  // Less than or equal to
}

#[deriving(PartialEq,Clone)]
struct Predicate {
    op: Op,
    major: u32,
    minor: Option<u32>,
    patch: Option<u32>
}

struct PredBuilder {
    op: Option<Op>,
    major: Option<u32>,
    minor: Option<u32>,
    patch: Option<u32>
}

impl VersionReq {
    pub fn any() -> VersionReq {
        VersionReq { predicates: vec!() }
    }

    pub fn parse(input: &str) -> Result<VersionReq, String> {
        let mut lexer = Lexer::new(input);
        let mut builder = PredBuilder::new();
        let mut predicates = Vec::new();

        for token in lexer {
            match token {
                Sigil(x) => try!(builder.set_sigil(x)),
                AlphaNum(x) => try!(builder.set_version_part(x)),
                Dot => (), // Nothing to do for now
                _ => unimplemented!()
            }
        }

        if lexer.is_error() {
            return Err("invalid version requirement".to_string());
        }

        predicates.push(try!(builder.build()));

        Ok(VersionReq { predicates: predicates })
    }

    pub fn exact(version: &Version) -> VersionReq {
        VersionReq { predicates: vec!(Predicate::exact(version)) }
    }

    pub fn matches(&self, version: &Version) -> bool {
        self.predicates.iter().all(|p| p.matches(version))
    }
}

impl Predicate {
    pub fn exact(version: &Version) -> Predicate {
        Predicate {
            op: Ex,
            major: version.major,
            minor: Some(version.minor),
            patch: Some(version.patch)
        }
    }

    pub fn matches(&self, ver: &Version) -> bool {
        match self.op {
            Ex => self.is_exact(ver),
            Gt => self.is_greater(ver),
            GtEq => self.is_exact(ver) || self.is_greater(ver),
            _ => false // not implemented
        }
    }

    fn is_exact(&self, ver: &Version) -> bool {
        if self.major != ver.major {
            return false;
        }

        match self.minor {
            Some(minor) => {
                if minor != ver.minor {
                    return false;
                }
            }
            None => return true
        }

        match self.patch {
            Some(patch) => {
                if patch != ver.patch {
                    return false;
                }
            }
            None => return true
        }

        true
    }

    fn is_greater(self, ver: &Version) -> bool {
        if self.major != ver.major {
            return self.major > ver.major;
        }

        match self.minor {
            Some(minor) => {
                if minor != ver.minor {
                    return minor > ver.minor
                }
            }
            None => return false
        }

        match self.patch {
            Some(patch) => {
                if patch != ver.patch {
                    return patch > ver.patch
                }
            }

            None => return false
        }

        false
    }
}

impl PredBuilder {
    fn new() -> PredBuilder {
        PredBuilder {
            op: None,
            major: None,
            minor: None,
            patch: None
        }
    }

    fn set_sigil(&mut self, sigil: &str) -> Result<(), String> {
        if self.op.is_some() {
            return Err("op already set".to_string());
        }

        match Op::from_sigil(sigil) {
            Some(op) => self.op = Some(op),
            _ => return Err("invalid sigil".to_string())
        }

        Ok(())
    }

    fn set_version_part(&mut self, part: &str) -> Result<(), String> {
        if self.op.is_none() {
            // If no op is specified, then the predicate is an exact match on
            // the version
            self.op = Some(Ex);
        }

        if self.major.is_none() {
            self.major = Some(try!(parse_version_part(part)));
        }
        else if self.minor.is_none() {
            self.minor = Some(try!(parse_version_part(part)));
        }
        else if self.patch.is_none() {
            self.patch = Some(try!(parse_version_part(part)));
        }

        Ok(())
    }

    /// Validates that a version predicate can be created given the present
    /// information.
    fn build(&self) -> Result<Predicate, String> {
        let op = match self.op {
            Some(x) => x,
            None => return Err("op required".to_string())
        };

        let major = match self.major {
            Some(x) => x,
            None => return Err("major version required".to_string())
        };

        Ok(Predicate {
            op: op,
            major: major,
            minor: self.minor,
            patch: self.patch
        })
    }
}

struct Lexer<'a> {
    c: char,
    idx: uint,
    iter: CharOffsets<'a>,
    mark: Option<uint>,
    input: &'a str,
    state: LexState
}

#[deriving(Show,PartialEq)]
enum LexState {
    LexInit,
    LexStart,
    LexAlphaNum,
    LexSigil,
    LexErr,
    LexWin
}

#[deriving(Show)]
enum Token<'a> {
    Sigil(&'a str),
    AlphaNum(&'a str),
    Comma,
    Dot
}

impl<'a> Lexer<'a> {
    fn new(input: &'a str) -> Lexer<'a> {
        Lexer {
            c: '\0',
            idx: 0,
            iter: input.char_indices(),
            mark: None,
            input: input,
            state: LexInit
        }
    }

    fn is_error(&self) -> bool {
        self.state == LexErr
    }

    fn mark(&mut self, at: uint) {
        self.mark = Some(at)
    }

    fn flush(&mut self, to: uint, kind: LexState) -> Option<Token<'a>> {
        match self.mark {
            Some(mark) => {
                if to <= mark {
                    return None;
                }

                let s = self.input.slice(mark, to);

                self.mark = None;

                match kind {
                    LexAlphaNum => Some(AlphaNum(s)),
                    LexSigil => Some(Sigil(s)),
                    _ => None // bug
                }
            }
            None => None
        }
    }
}

impl<'a> Iterator<Token<'a>> for Lexer<'a> {
    fn next(&mut self) -> Option<Token<'a>> {
        let mut c;
        let mut idx = 0;

        macro_rules! next(
            () => (
                match self.iter.next() {
                    Some((n_idx, n_char)) => {
                        c = n_char;
                        idx = n_idx;
                    }
                    _ => {
                      let s = self.state;
                      return self.flush(idx + 1, s)
                    }
                }
            ))

        macro_rules! flush(
            ($s:expr) => ({
                self.c = c;
                self.idx = idx;
                self.flush(idx, $s)
            }))

        if self.state == LexInit {
            self.state = LexStart;
            next!();
        } else {
            c = self.c;
            idx = self.idx;
        }

        loop {
            match self.state {
                LexStart => {
                    if c.is_whitespace() {
                        next!(); // Ignore
                    }
                    else if c.is_alphanumeric() {
                        self.mark(idx);
                        self.state = LexAlphaNum;
                        next!();
                    }
                    else if is_sigil(c) {
                        self.mark(idx);
                        self.state = LexSigil;
                        next!();
                    }
                    else if c == '.' {
                        self.state = LexInit;
                        return Some(Dot);
                    }
                    else if c == ',' {
                        self.state = LexInit;
                        return Some(Comma);
                    } else {
                        self.state = LexErr;
                        return None;
                    }
                }
                LexAlphaNum => {
                    if c.is_alphanumeric() {
                        next!();
                    } else {
                        self.state = LexStart;
                        return flush!(LexAlphaNum);
                    }
                }
                LexSigil => {
                    if is_sigil(c) {
                        next!();
                    } else {
                        self.state = LexStart;
                        return flush!(LexSigil);
                    }
                }
                LexErr | LexWin => return None,
                LexInit => return None // bug
            }
        }
    }
}

impl Op {
    fn from_sigil(sigil: &str) -> Option<Op> {
        match sigil {
            "=" => Some(Ex),
            ">" => Some(Gt),
            ">=" => Some(GtEq),
            "<" => Some(Lt),
            "<=" => Some(LtEq),
            _ => None
        }
    }
}

fn parse_version_part(s: &str) -> Result<u32, String> {
    let mut ret = 0;

    for c in s.chars() {
        let n = (c as u32) - ('0' as u32);

        if n > 9 {
            return Err("version components must be numeric".to_string());
        }

        ret *= 10;
        ret +=  n;
    }

    Ok(ret)
}

fn is_sigil(c: char) -> bool {
    match c {
        '>' | '<' | '=' | '~' | '^' => true,
        _ => false
    }
}

impl fmt::Show for VersionReq {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        if self.predicates.is_empty() {
            try!(write!(fmt, "*"));
        } else {
            for (i, ref pred) in self.predicates.iter().enumerate() {
                if i == 0 {
                    try!(write!(fmt, "{}", pred));
                } else {
                    try!(write!(fmt, ", {}", pred));
                }
            }
        }

        Ok(())
    }
}

impl fmt::Show for Predicate {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(fmt, "{} {}", self.op, self.major));

        match self.minor {
            Some(v) => try!(write!(fmt, ".{}", v)),
            None => ()
        }

        match self.patch {
            Some(v) => try!(write!(fmt, ".{}", v)),
            None => ()
        }

        Ok(())
    }
}

impl fmt::Show for Op {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Ex => try!(write!(fmt, "=")),
            Gt => try!(write!(fmt, ">")),
            GtEq => try!(write!(fmt, ">=")),
            Lt => try!(write!(fmt, "<")),
            LtEq => try!(write!(fmt, "<="))
        }
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::VersionReq;
    use super::super::version::parse;
    use super::super::version::Version;

    fn req(s: &str) -> VersionReq {
        VersionReq::parse(s).unwrap()
    }

    fn version(s: &str) -> Version {
        match parse(s) {
            Ok(v) => v,
            Err(e) => fail!("`{}` is not a valid version. Reason: {}", s, e)
        }
    }

    fn assert_match(req: &VersionReq, vers: &[&str]) {
        for ver in vers.iter() {
            assert!(req.matches(&version(*ver)), "did not match {}", ver);
        }
    }

    fn assert_not_match(req: &VersionReq, vers: &[&str]) {
        for ver in vers.iter() {
            assert!(!req.matches(&version(*ver)), "matched {}", ver);
        }
    }

    #[test]
    pub fn test_parsing_exact() {
        let r = req("1.0.0");

        assert!(r.to_string() == "= 1.0.0".to_string());

        assert_match(&r, ["1.0.0"]);
        assert_not_match(&r, ["1.0.1", "0.9.9", "0.10.0", "0.1.0"]);

        let r = req("0.9.0");

        assert!(r.to_string() == "= 0.9.0".to_string());

        assert_match(&r, ["0.9.0"]);
        assert_not_match(&r, ["0.9.1", "1.9.0", "0.0.9"]);
    }

    #[test]
    pub fn test_parsing_greater_than() {
        let r = req(">= 1.0.0");

        assert!(r.to_string() == ">= 1.0.0".to_string());

        assert_match(&r, ["1.0.0"]);
    }

    /* TODO:
     * - Test parse errors
     * - Handle pre releases
     */
}
<commit_msg>Make more stuff private<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

use std::fmt::Show;
use std::fmt;
use std::str::CharOffsets;

use super::version::Version;

#[deriving(PartialEq,Clone)]
pub struct VersionReq {
    predicates: Vec<Predicate>
}

#[deriving(PartialEq,Clone)]
enum Op {
    Ex,   // Exact
    Gt,   // Greater than
    GtEq, // Greater than or equal to
    Lt,   // Less than
    LtEq  // Less than or equal to
}

#[deriving(PartialEq,Clone)]
struct Predicate {
    op: Op,
    major: u32,
    minor: Option<u32>,
    patch: Option<u32>
}

struct PredBuilder {
    op: Option<Op>,
    major: Option<u32>,
    minor: Option<u32>,
    patch: Option<u32>
}

impl VersionReq {
    pub fn any() -> VersionReq {
        VersionReq { predicates: vec!() }
    }

    pub fn parse(input: &str) -> Result<VersionReq, String> {
        let mut lexer = Lexer::new(input);
        let mut builder = PredBuilder::new();
        let mut predicates = Vec::new();

        for token in lexer {
            match token {
                Sigil(x) => try!(builder.set_sigil(x)),
                AlphaNum(x) => try!(builder.set_version_part(x)),
                Dot => (), // Nothing to do for now
                _ => unimplemented!()
            }
        }

        if lexer.is_error() {
            return Err("invalid version requirement".to_string());
        }

        predicates.push(try!(builder.build()));

        Ok(VersionReq { predicates: predicates })
    }

    pub fn exact(version: &Version) -> VersionReq {
        VersionReq { predicates: vec!(Predicate::exact(version)) }
    }

    pub fn matches(&self, version: &Version) -> bool {
        self.predicates.iter().all(|p| p.matches(version))
    }
}

impl Predicate {
    fn exact(version: &Version) -> Predicate {
        Predicate {
            op: Ex,
            major: version.major,
            minor: Some(version.minor),
            patch: Some(version.patch)
        }
    }

    fn matches(&self, ver: &Version) -> bool {
        match self.op {
            Ex => self.is_exact(ver),
            Gt => self.is_greater(ver),
            GtEq => self.is_exact(ver) || self.is_greater(ver),
            _ => false // not implemented
        }
    }

    fn is_exact(&self, ver: &Version) -> bool {
        if self.major != ver.major {
            return false;
        }

        match self.minor {
            Some(minor) => {
                if minor != ver.minor {
                    return false;
                }
            }
            None => return true
        }

        match self.patch {
            Some(patch) => {
                if patch != ver.patch {
                    return false;
                }
            }
            None => return true
        }

        true
    }

    fn is_greater(self, ver: &Version) -> bool {
        if self.major != ver.major {
            return self.major > ver.major;
        }

        match self.minor {
            Some(minor) => {
                if minor != ver.minor {
                    return minor > ver.minor
                }
            }
            None => return false
        }

        match self.patch {
            Some(patch) => {
                if patch != ver.patch {
                    return patch > ver.patch
                }
            }

            None => return false
        }

        false
    }
}

impl PredBuilder {
    fn new() -> PredBuilder {
        PredBuilder {
            op: None,
            major: None,
            minor: None,
            patch: None
        }
    }

    fn set_sigil(&mut self, sigil: &str) -> Result<(), String> {
        if self.op.is_some() {
            return Err("op already set".to_string());
        }

        match Op::from_sigil(sigil) {
            Some(op) => self.op = Some(op),
            _ => return Err("invalid sigil".to_string())
        }

        Ok(())
    }

    fn set_version_part(&mut self, part: &str) -> Result<(), String> {
        if self.op.is_none() {
            // If no op is specified, then the predicate is an exact match on
            // the version
            self.op = Some(Ex);
        }

        if self.major.is_none() {
            self.major = Some(try!(parse_version_part(part)));
        }
        else if self.minor.is_none() {
            self.minor = Some(try!(parse_version_part(part)));
        }
        else if self.patch.is_none() {
            self.patch = Some(try!(parse_version_part(part)));
        }

        Ok(())
    }

    /// Validates that a version predicate can be created given the present
    /// information.
    fn build(&self) -> Result<Predicate, String> {
        let op = match self.op {
            Some(x) => x,
            None => return Err("op required".to_string())
        };

        let major = match self.major {
            Some(x) => x,
            None => return Err("major version required".to_string())
        };

        Ok(Predicate {
            op: op,
            major: major,
            minor: self.minor,
            patch: self.patch
        })
    }
}

struct Lexer<'a> {
    c: char,
    idx: uint,
    iter: CharOffsets<'a>,
    mark: Option<uint>,
    input: &'a str,
    state: LexState
}

#[deriving(Show,PartialEq)]
enum LexState {
    LexInit,
    LexStart,
    LexAlphaNum,
    LexSigil,
    LexErr,
    LexWin
}

#[deriving(Show)]
enum Token<'a> {
    Sigil(&'a str),
    AlphaNum(&'a str),
    Comma,
    Dot
}

impl<'a> Lexer<'a> {
    fn new(input: &'a str) -> Lexer<'a> {
        Lexer {
            c: '\0',
            idx: 0,
            iter: input.char_indices(),
            mark: None,
            input: input,
            state: LexInit
        }
    }

    fn is_error(&self) -> bool {
        self.state == LexErr
    }

    fn mark(&mut self, at: uint) {
        self.mark = Some(at)
    }

    fn flush(&mut self, to: uint, kind: LexState) -> Option<Token<'a>> {
        match self.mark {
            Some(mark) => {
                if to <= mark {
                    return None;
                }

                let s = self.input.slice(mark, to);

                self.mark = None;

                match kind {
                    LexAlphaNum => Some(AlphaNum(s)),
                    LexSigil => Some(Sigil(s)),
                    _ => None // bug
                }
            }
            None => None
        }
    }
}

impl<'a> Iterator<Token<'a>> for Lexer<'a> {
    fn next(&mut self) -> Option<Token<'a>> {
        let mut c;
        let mut idx = 0;

        macro_rules! next(
            () => (
                match self.iter.next() {
                    Some((n_idx, n_char)) => {
                        c = n_char;
                        idx = n_idx;
                    }
                    _ => {
                      let s = self.state;
                      return self.flush(idx + 1, s)
                    }
                }
            ))

        macro_rules! flush(
            ($s:expr) => ({
                self.c = c;
                self.idx = idx;
                self.flush(idx, $s)
            }))

        if self.state == LexInit {
            self.state = LexStart;
            next!();
        } else {
            c = self.c;
            idx = self.idx;
        }

        loop {
            match self.state {
                LexStart => {
                    if c.is_whitespace() {
                        next!(); // Ignore
                    }
                    else if c.is_alphanumeric() {
                        self.mark(idx);
                        self.state = LexAlphaNum;
                        next!();
                    }
                    else if is_sigil(c) {
                        self.mark(idx);
                        self.state = LexSigil;
                        next!();
                    }
                    else if c == '.' {
                        self.state = LexInit;
                        return Some(Dot);
                    }
                    else if c == ',' {
                        self.state = LexInit;
                        return Some(Comma);
                    } else {
                        self.state = LexErr;
                        return None;
                    }
                }
                LexAlphaNum => {
                    if c.is_alphanumeric() {
                        next!();
                    } else {
                        self.state = LexStart;
                        return flush!(LexAlphaNum);
                    }
                }
                LexSigil => {
                    if is_sigil(c) {
                        next!();
                    } else {
                        self.state = LexStart;
                        return flush!(LexSigil);
                    }
                }
                LexErr | LexWin => return None,
                LexInit => return None // bug
            }
        }
    }
}

impl Op {
    fn from_sigil(sigil: &str) -> Option<Op> {
        match sigil {
            "=" => Some(Ex),
            ">" => Some(Gt),
            ">=" => Some(GtEq),
            "<" => Some(Lt),
            "<=" => Some(LtEq),
            _ => None
        }
    }
}

fn parse_version_part(s: &str) -> Result<u32, String> {
    let mut ret = 0;

    for c in s.chars() {
        let n = (c as u32) - ('0' as u32);

        if n > 9 {
            return Err("version components must be numeric".to_string());
        }

        ret *= 10;
        ret +=  n;
    }

    Ok(ret)
}

fn is_sigil(c: char) -> bool {
    match c {
        '>' | '<' | '=' | '~' | '^' => true,
        _ => false
    }
}

impl fmt::Show for VersionReq {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        if self.predicates.is_empty() {
            try!(write!(fmt, "*"));
        } else {
            for (i, ref pred) in self.predicates.iter().enumerate() {
                if i == 0 {
                    try!(write!(fmt, "{}", pred));
                } else {
                    try!(write!(fmt, ", {}", pred));
                }
            }
        }

        Ok(())
    }
}

impl fmt::Show for Predicate {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(fmt, "{} {}", self.op, self.major));

        match self.minor {
            Some(v) => try!(write!(fmt, ".{}", v)),
            None => ()
        }

        match self.patch {
            Some(v) => try!(write!(fmt, ".{}", v)),
            None => ()
        }

        Ok(())
    }
}

impl fmt::Show for Op {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Ex => try!(write!(fmt, "=")),
            Gt => try!(write!(fmt, ">")),
            GtEq => try!(write!(fmt, ">=")),
            Lt => try!(write!(fmt, "<")),
            LtEq => try!(write!(fmt, "<="))
        }
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::VersionReq;
    use super::super::version::parse;
    use super::super::version::Version;

    fn req(s: &str) -> VersionReq {
        VersionReq::parse(s).unwrap()
    }

    fn version(s: &str) -> Version {
        match parse(s) {
            Ok(v) => v,
            Err(e) => fail!("`{}` is not a valid version. Reason: {}", s, e)
        }
    }

    fn assert_match(req: &VersionReq, vers: &[&str]) {
        for ver in vers.iter() {
            assert!(req.matches(&version(*ver)), "did not match {}", ver);
        }
    }

    fn assert_not_match(req: &VersionReq, vers: &[&str]) {
        for ver in vers.iter() {
            assert!(!req.matches(&version(*ver)), "matched {}", ver);
        }
    }

    #[test]
    pub fn test_parsing_exact() {
        let r = req("1.0.0");

        assert!(r.to_string() == "= 1.0.0".to_string());

        assert_match(&r, ["1.0.0"]);
        assert_not_match(&r, ["1.0.1", "0.9.9", "0.10.0", "0.1.0"]);

        let r = req("0.9.0");

        assert!(r.to_string() == "= 0.9.0".to_string());

        assert_match(&r, ["0.9.0"]);
        assert_not_match(&r, ["0.9.1", "1.9.0", "0.0.9"]);
    }

    #[test]
    pub fn test_parsing_greater_than() {
        let r = req(">= 1.0.0");

        assert!(r.to_string() == ">= 1.0.0".to_string());

        assert_match(&r, ["1.0.0"]);
    }

    /* TODO:
     * - Test parse errors
     * - Handle pre releases
     */
}
<|endoftext|>


<commit_before>pub type c_char = i8;
pub type c_long = i64;
pub type c_ulong = u64;

pub type wchar_t = i16;

pub type off_t = c_long;
pub type mode_t = u16;
pub type time_t = i64;
pub type pid_t = usize;
pub type gid_t = usize;
pub type uid_t = usize;

pub type in_addr_t = u32;
pub type in_port_t = u16;

pub type socklen_t = u32;
pub type sa_family_t = u16;

s! {
    pub struct in_addr {
        pub s_addr: in_addr_t,
    }

    pub struct in6_addr {
        pub s6_addr: [u8; 16],
        __align: [u32; 0],
    }

    pub struct sockaddr {
        pub sa_family: sa_family_t,
        pub sa_data: [::c_char; 14],
    }

    pub struct sockaddr_in {
        pub sin_family: sa_family_t,
        pub sin_port: ::in_port_t,
        pub sin_addr: ::in_addr,
        pub sin_zero: [u8; 8],
    }

    pub struct sockaddr_in6 {
        pub sin6_family: sa_family_t,
        pub sin6_port: in_port_t,
        pub sin6_flowinfo: u32,
        pub sin6_addr: ::in6_addr,
        pub sin6_scope_id: u32,
    }
}

pub const STDIN_FILENO: ::c_int = 0;
pub const STDOUT_FILENO: ::c_int = 1;
pub const STDERR_FILENO: ::c_int = 2;

extern {
    pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void;
    pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t)
                -> ::ssize_t;
    pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::size_t)
                 -> ::ssize_t;
}

#[link(name = "c")]
#[link(name = "m")]
extern {}
<commit_msg>Add some permission and misc (mostly 'mode_t' related) constants to Redox.<commit_after>pub type c_char = i8;
pub type c_long = i64;
pub type c_ulong = u64;

pub type wchar_t = i16;

pub type off_t = c_long;
pub type mode_t = u16;
pub type time_t = i64;
pub type pid_t = usize;
pub type gid_t = usize;
pub type uid_t = usize;

pub type in_addr_t = u32;
pub type in_port_t = u16;

pub type socklen_t = u32;
pub type sa_family_t = u16;

s! {
    pub struct in_addr {
        pub s_addr: in_addr_t,
    }

    pub struct in6_addr {
        pub s6_addr: [u8; 16],
        __align: [u32; 0],
    }

    pub struct sockaddr {
        pub sa_family: sa_family_t,
        pub sa_data: [::c_char; 14],
    }

    pub struct sockaddr_in {
        pub sin_family: sa_family_t,
        pub sin_port: ::in_port_t,
        pub sin_addr: ::in_addr,
        pub sin_zero: [u8; 8],
    }

    pub struct sockaddr_in6 {
        pub sin6_family: sa_family_t,
        pub sin6_port: in_port_t,
        pub sin6_flowinfo: u32,
        pub sin6_addr: ::in6_addr,
        pub sin6_scope_id: u32,
    }
}

pub const STDIN_FILENO: ::c_int = 0;
pub const STDOUT_FILENO: ::c_int = 1;
pub const STDERR_FILENO: ::c_int = 2;

pub const EXIT_FAILURE: ::c_int = 1;
pub const EXIT_SUCCESS: ::c_int = 0;

pub const S_ISUID: ::c_int = 0x800;
pub const S_ISGID: ::c_int = 0x400;
pub const S_ISVTX: ::c_int = 0x200;

pub const S_IFIFO: mode_t = 4096;
pub const S_IFCHR: mode_t = 8192;
pub const S_IFBLK: mode_t = 24576;
pub const S_IFDIR: mode_t = 16384;
pub const S_IFREG: mode_t = 32768;
pub const S_IFLNK: mode_t = 40960;
pub const S_IFSOCK: mode_t = 49152;
pub const S_IFMT: mode_t = 61440;
pub const S_IEXEC: mode_t = 64;
pub const S_IWRITE: mode_t = 128;
pub const S_IREAD: mode_t = 256;
pub const S_IRWXU: mode_t = 448;
pub const S_IXUSR: mode_t = 64;
pub const S_IWUSR: mode_t = 128;
pub const S_IRUSR: mode_t = 256;
pub const S_IRWXG: mode_t = 56;
pub const S_IXGRP: mode_t = 8;
pub const S_IWGRP: mode_t = 16;
pub const S_IRGRP: mode_t = 32;
pub const S_IRWXO: mode_t = 7;
pub const S_IXOTH: mode_t = 1;
pub const S_IWOTH: mode_t = 2;
pub const S_IROTH: mode_t = 4;

extern {
    pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void;
    pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t)
                -> ::ssize_t;
    pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::size_t)
                 -> ::ssize_t;
}

#[link(name = "c")]
#[link(name = "m")]
extern {}
<|endoftext|>


<commit_before>use slack_hook::{Attachment, AttachmentBuilder, Field, PayloadBuilder, Slack, SlackText, SlackLink};
use slack_hook::SlackTextContent::{Text, Link};

use taste::{BenchmarkResult, TastingResult};

pub struct SlackNotifier {
    conn: Slack,
    channel: String,
    github_repo: String,
}

impl SlackNotifier {
    pub fn new(hook_url: &str, channel: &str, repo_url: &str) -> SlackNotifier {
        SlackNotifier {
            conn: Slack::new(hook_url).unwrap(),
            channel: String::from(channel),
            github_repo: String::from(repo_url),
        }
    }

    pub fn notify(&self, res: &TastingResult) -> Result<(), String> {
        let payload = PayloadBuilder::new()
            .text(vec![Text("I've tasted commit _".into()),
                       Text(format!("\"{}\"_ -- ", res.commit_msg.lines().next().unwrap())
                           .into()),
                       Link(SlackLink::new(&res.commit_url, &res.commit_id[0..6]))]
                .as_slice())
            .attachments(result_to_attachments(&res))
            .channel(self.channel.clone())
            .username("taster")
            .icon_emoji(":tea:")
            .build()
            .unwrap();

        match self.conn.send(&payload) {
            Ok(_) => Ok(()),
            Err(e) => Err(format!("{:?}", e)),
        }
    }
}

fn result_to_attachments(res: &TastingResult) -> Vec<Attachment> {
    let color = if !res.build || !res.bench {
        "danger"
    } else {
        "good"
    };

    let title = if !res.build {
        "Build failure!"
    } else if !res.bench {
        "Benchmark failure!"
    } else {
        "Performance results:"
    };

    let taste = if !res.build || !res.bench {
        "was inedible"
    } else {
        "tasted nice"
    };

    let mut attachments = Vec::new();
    let build_att = AttachmentBuilder::new("")
        .title(format!("It {}.", taste))
        .fields(vec![Field {
                         title: "".into(),
                         value: SlackText::new(if res.build {
                             "Build: :white_check_mark:"
                         } else {
                             "Build: :x:"
                         }),
                         short: Some(true),
                     },
                     Field {
                         title: "".into(),
                         value: SlackText::new(if res.test {
                             "Tests: :white_check_mark:"
                         } else {
                             "Tests: :x:"
                         }),
                         short: Some(true),
                     },
                     Field {
                         title: "".into(),
                         value: SlackText::new(if res.bench {
                             "Benchmark: :white_check_mark:"
                         } else {
                             "Benchmark: :x:"
                         }),
                         short: Some(true),
                     }])
        .color(color)
        .build()
        .unwrap();
    attachments.push(build_att);

    match res.results {
        None => (),
        Some(ref r) => {
            for res in r {
                let mut nv = res.iter()
                    .map(|(k, v)| {
                        let val = match v {
                            &BenchmarkResult::Neutral(ref s, _) => s,
                            _ => unimplemented!(),
                        };
                        Field {
                            title: k.clone(),
                            value: SlackText::new(val.clone()),
                            short: Some(true),
                        }
                    })
                    .collect::<Vec<_>>();
                nv.sort_by(|a, b| b.title.cmp(&a.title));
                let att = AttachmentBuilder::new("")
                    .color(color)
                    .fields(nv)
                    .build()
                    .unwrap();
                attachments.push(att);
            }
        }
    }
    attachments
}
<commit_msg>Slack: improve build/test/bench line formatting<commit_after>use slack_hook::{Attachment, AttachmentBuilder, Field, PayloadBuilder, Slack, SlackText, SlackLink};
use slack_hook::SlackTextContent::{Text, Link};

use taste::{BenchmarkResult, TastingResult};

pub struct SlackNotifier {
    conn: Slack,
    channel: String,
    github_repo: String,
}

impl SlackNotifier {
    pub fn new(hook_url: &str, channel: &str, repo_url: &str) -> SlackNotifier {
        SlackNotifier {
            conn: Slack::new(hook_url).unwrap(),
            channel: String::from(channel),
            github_repo: String::from(repo_url),
        }
    }

    pub fn notify(&self, res: &TastingResult) -> Result<(), String> {
        let payload = PayloadBuilder::new()
            .text(vec![Text("I've tasted commit _".into()),
                       Text(format!("\"{}\"_ -- ", res.commit_msg.lines().next().unwrap())
                           .into()),
                       Link(SlackLink::new(&res.commit_url, &res.commit_id[0..6]))]
                .as_slice())
            .attachments(result_to_attachments(&res))
            .channel(self.channel.clone())
            .username("taster")
            .icon_emoji(":tea:")
            .build()
            .unwrap();

        match self.conn.send(&payload) {
            Ok(_) => Ok(()),
            Err(e) => Err(format!("{:?}", e)),
        }
    }
}

fn result_to_attachments(res: &TastingResult) -> Vec<Attachment> {
    let color = if !res.build || !res.bench {
        "danger"
    } else {
        "good"
    };

    let title = if !res.build {
        "Build failure!"
    } else if !res.bench {
        "Benchmark failure!"
    } else {
        "Performance results:"
    };

    let taste = if !res.build || !res.bench {
        "was inedible"
    } else {
        "tasted nice"
    };

    let check = |title: &str, result: bool| {
        let mut out = format!("{}: ", title);
        if result {
            out.push_str(":white_check_mark:");
        } else {
            out.push_str(":x:");
        }
        out
    };

    let mut attachments = Vec::new();
    let build_att = AttachmentBuilder::new("")
        .title(format!("It {}.", taste))
        .text(format!("{} {} {}",
                      check("Build", res.build),
                      check("Tests", res.test),
                      check("Benchmark", res.bench)))
        .color(color)
        .build()
        .unwrap();
    attachments.push(build_att);

    match res.results {
        None => (),
        Some(ref r) => {
            for res in r {
                let mut nv = res.iter()
                    .map(|(k, v)| {
                        let val = match v {
                            &BenchmarkResult::Neutral(ref s, _) => s,
                            _ => unimplemented!(),
                        };
                        Field {
                            title: k.clone(),
                            value: SlackText::new(val.clone()),
                            short: Some(true),
                        }
                    })
                    .collect::<Vec<_>>();
                nv.sort_by(|a, b| b.title.cmp(&a.title));
                let att = AttachmentBuilder::new("")
                    .color(color)
                    .fields(nv)
                    .build()
                    .unwrap();
                attachments.push(att);
            }
        }
    }
    attachments
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use scope::Scope;
use ast::{Expr, EvalResult};
use ast::EvalError::*;

pub struct State<'s> {
    default_ns: String,
    namespaces: HashMap<String, Scope<'s>>,
    parent: Option<&'s State<'s>>,
}

impl<'s> State<'s> {
    pub fn new(default: String) -> State<'s> {
        State {
            default_ns: default,
            namespaces: HashMap::new(),
            parent: None,
        }
    }

    pub fn insert(&mut self, ns: Option<String>, name: String, expr: Expr) -> Option<Expr> {
        if let Some(ns) = ns {
            if let Some(ns) = self.namespaces.get_mut(&ns) {
                return ns.insert(name, expr)
            }
        } else {
            if let Some(ns) = self.namespaces.get_mut(&self.default_ns) {
                return ns.insert(name, expr)
            }
        }
        None
    }

    pub fn eval(&self, expr: &Expr) -> EvalResult {
        match try!(self.expand(expr)) {
            ref sym_expr @ Expr::Symbol { .. } => {
                self.eval_symbol(sym_expr)
            },
            ref def_expr @ Expr::Def { .. } => {
                self.eval_def(def_expr)
            },
            ref call_expr @ Expr::Call { .. } => {
                self.eval_call(call_expr)
            },
            ref let_expr @ Expr::Let { .. } => {
                self.eval_let(let_expr)
            },
            other_expr => {
                Ok(other_expr)
            },
        }
    }

    fn eval_symbol(&self, expr: &Expr) -> EvalResult {
        if let Expr::Symbol { ref ns, ref name , .. } = *expr {
            let ns_name = ns.as_ref().unwrap_or(&self.default_ns);
            match self.namespaces.get(ns_name) {
                Some(scope) => {
                    scope.get(name)
                         .map_or(Err(ResolveError(name.clone())), |e| Ok(e.clone()))
                },
                None => {
                    Err(ResolveError(ns_name.clone()))
                }
            }
        } else {
            Err(DispatchError(expr.clone()))
        }
    }

    fn eval_def(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

    fn eval_call(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

    fn eval_let(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

    fn expand(&self, expr: &Expr) -> EvalResult {
        if let Expr::List(ref l) = *expr {
            if l.len() > 0 {
                if let Expr::Symbol { ref name, .. } = l[0] {
                    match &name[..] {
                        "def" => {
                            return self.expand_def(expr)
                        },
                        "fn" => {
                            return self.expand_fn(expr)
                        },
                        "macro" => {
                            return self.expand_macro(expr)
                        },
                        "quote" => {
                            return self.expand_quote(expr)
                        },
                        "unquote" => {
                            return self.expand_unquote(expr)
                        },
                        "unquote-splicing" => {
                            return self.expand_unquote_splicing(expr)
                        },
                        "let" => {
                            return self.expand_let(expr)
                        },
                        _ => {
                            return self.expand_call(expr)
                        }
                    }
                } else {
                    return Err(DispatchError(l[0].clone()))
                }
            }
        }
        Ok(expr.clone())
    }

    fn expand_def(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

    fn expand_fn(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

    fn expand_macro(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

    fn expand_quote(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

    fn expand_unquote(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

    fn expand_unquote_splicing(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

    fn expand_let(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

    fn expand_call(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

}
<commit_msg>Make refactoring of insert implementation<commit_after>use std::collections::HashMap;
use scope::Scope;
use ast::{Expr, EvalResult};
use ast::EvalError::*;

pub struct State<'s> {
    default_ns: String,
    namespaces: HashMap<String, Scope<'s>>,
    parent: Option<&'s State<'s>>,
}

impl<'s> State<'s> {
    pub fn new(default: String) -> State<'s> {
        State {
            default_ns: default,
            namespaces: HashMap::new(),
            parent: None,
        }
    }

    pub fn insert(&mut self, ns: Option<String>, name: String, expr: Expr) -> Option<Expr> {
        let ns = ns.as_ref().unwrap_or(&self.default_ns);
        if let Some(scope) = self.namespaces.get_mut(ns) {
            return scope.insert(name, expr)
        }
        None
    }

    pub fn eval(&self, expr: &Expr) -> EvalResult {
        match try!(self.expand(expr)) {
            ref sym_expr @ Expr::Symbol { .. } => {
                self.eval_symbol(sym_expr)
            },
            ref def_expr @ Expr::Def { .. } => {
                self.eval_def(def_expr)
            },
            ref call_expr @ Expr::Call { .. } => {
                self.eval_call(call_expr)
            },
            ref let_expr @ Expr::Let { .. } => {
                self.eval_let(let_expr)
            },
            other_expr => {
                Ok(other_expr)
            },
        }
    }

    fn eval_symbol(&self, expr: &Expr) -> EvalResult {
        if let Expr::Symbol { ref ns, ref name , .. } = *expr {
            let ns_name = ns.as_ref().unwrap_or(&self.default_ns);
            match self.namespaces.get(ns_name) {
                Some(scope) => {
                    scope.get(name)
                         .map_or(Err(ResolveError(name.clone())), |e| Ok(e.clone()))
                },
                None => {
                    Err(ResolveError(ns_name.clone()))
                }
            }
        } else {
            Err(DispatchError(expr.clone()))
        }
    }

    fn eval_def(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

    fn eval_call(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

    fn eval_let(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

    fn expand(&self, expr: &Expr) -> EvalResult {
        if let Expr::List(ref l) = *expr {
            if l.len() > 0 {
                if let Expr::Symbol { ref name, .. } = l[0] {
                    match &name[..] {
                        "def" => {
                            return self.expand_def(expr)
                        },
                        "fn" => {
                            return self.expand_fn(expr)
                        },
                        "macro" => {
                            return self.expand_macro(expr)
                        },
                        "quote" => {
                            return self.expand_quote(expr)
                        },
                        "unquote" => {
                            return self.expand_unquote(expr)
                        },
                        "unquote-splicing" => {
                            return self.expand_unquote_splicing(expr)
                        },
                        "let" => {
                            return self.expand_let(expr)
                        },
                        _ => {
                            return self.expand_call(expr)
                        }
                    }
                } else {
                    return Err(DispatchError(l[0].clone()))
                }
            }
        }
        Ok(expr.clone())
    }

    fn expand_def(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

    fn expand_fn(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

    fn expand_macro(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

    fn expand_quote(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

    fn expand_unquote(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

    fn expand_unquote_splicing(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

    fn expand_let(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

    fn expand_call(&self, expr: &Expr) -> EvalResult {
        Ok(expr.clone())
    }

}
<|endoftext|>


<commit_before>// Copyright (c) 2019, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use crate::partition::BlockSize;
use crate::predict::PREDICTION_MODES;
use crate::transform::TX_TYPES;
use std::ops::{Add, AddAssign};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EncoderStats {
  /// Stores count of pixels belonging to each block size in this frame
  pub block_size_counts: [usize; BlockSize::BLOCK_SIZES],
  /// Stores count of pixels belonging to skip blocks in this frame
  pub skip_block_count: usize,
  /// Stores count of pixels belonging to each transform type in this frame
  pub tx_type_counts: [usize; TX_TYPES],
  /// Stores count of pixels belonging to each luma prediction mode in this frame
  pub luma_pred_mode_counts: [usize; PREDICTION_MODES],
  /// Stores count of pixels belonging to each chroma prediction mode in this frame
  pub chroma_pred_mode_counts: [usize; PREDICTION_MODES],
}

impl Default for EncoderStats {
  fn default() -> Self {
    EncoderStats {
      block_size_counts: [0; BlockSize::BLOCK_SIZES],
      skip_block_count: 0,
      tx_type_counts: [0; TX_TYPES],
      luma_pred_mode_counts: [0; PREDICTION_MODES],
      chroma_pred_mode_counts: [0; PREDICTION_MODES],
    }
  }
}

impl Add<&Self> for EncoderStats {
  type Output = Self;

  fn add(self, rhs: &EncoderStats) -> Self::Output {
    let mut lhs = self;
    lhs += rhs;
    lhs
  }
}

impl AddAssign<&Self> for EncoderStats {
  fn add_assign(&mut self, rhs: &EncoderStats) {
    for (s, v) in
      self.block_size_counts.iter_mut().zip(rhs.block_size_counts.iter())
    {
      *s += v;
    }
    for (s, v) in self
      .chroma_pred_mode_counts
      .iter_mut()
      .zip(rhs.chroma_pred_mode_counts.iter())
    {
      *s += v;
    }
    for (s, v) in self
      .luma_pred_mode_counts
      .iter_mut()
      .zip(rhs.luma_pred_mode_counts.iter())
    {
      *s += v;
    }
    for (s, v) in self.tx_type_counts.iter_mut().zip(rhs.tx_type_counts.iter())
    {
      *s += v;
    }
    self.skip_block_count += rhs.skip_block_count;
  }
}
<commit_msg>Fix the block_size_counts size<commit_after>// Copyright (c) 2019, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use crate::partition::BlockSize;
use crate::predict::PREDICTION_MODES;
use crate::transform::TX_TYPES;
use std::ops::{Add, AddAssign};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EncoderStats {
  /// Stores count of pixels belonging to each block size in this frame
  pub block_size_counts: [usize; BlockSize::BLOCK_SIZES_ALL],
  /// Stores count of pixels belonging to skip blocks in this frame
  pub skip_block_count: usize,
  /// Stores count of pixels belonging to each transform type in this frame
  pub tx_type_counts: [usize; TX_TYPES],
  /// Stores count of pixels belonging to each luma prediction mode in this frame
  pub luma_pred_mode_counts: [usize; PREDICTION_MODES],
  /// Stores count of pixels belonging to each chroma prediction mode in this frame
  pub chroma_pred_mode_counts: [usize; PREDICTION_MODES],
}

impl Default for EncoderStats {
  fn default() -> Self {
    EncoderStats {
      block_size_counts: [0; BlockSize::BLOCK_SIZES_ALL],
      skip_block_count: 0,
      tx_type_counts: [0; TX_TYPES],
      luma_pred_mode_counts: [0; PREDICTION_MODES],
      chroma_pred_mode_counts: [0; PREDICTION_MODES],
    }
  }
}

impl Add<&Self> for EncoderStats {
  type Output = Self;

  fn add(self, rhs: &EncoderStats) -> Self::Output {
    let mut lhs = self;
    lhs += rhs;
    lhs
  }
}

impl AddAssign<&Self> for EncoderStats {
  fn add_assign(&mut self, rhs: &EncoderStats) {
    for (s, v) in
      self.block_size_counts.iter_mut().zip(rhs.block_size_counts.iter())
    {
      *s += v;
    }
    for (s, v) in self
      .chroma_pred_mode_counts
      .iter_mut()
      .zip(rhs.chroma_pred_mode_counts.iter())
    {
      *s += v;
    }
    for (s, v) in self
      .luma_pred_mode_counts
      .iter_mut()
      .zip(rhs.luma_pred_mode_counts.iter())
    {
      *s += v;
    }
    for (s, v) in self.tx_type_counts.iter_mut().zip(rhs.tx_type_counts.iter())
    {
      *s += v;
    }
    self.skip_block_count += rhs.skip_block_count;
  }
}
<|endoftext|>


<commit_before>//! Code for applying CSS styles to the DOM.
//!
//! This is not very interesting at the moment.  It will get much more
//! complicated if I add support for compound selectors.

use dom::{Node, NodeType, ElementData};
use css::{Stylesheet, Rule, Selector, SimpleSelector, Value, Specificity};
use std::collections::HashMap;

/// Map from CSS property names to values.
pub type PropertyMap =  HashMap<String, Value>;

/// A node with associated style data.
pub struct StyledNode<'a> {
    pub node: &'a Node,
    pub specified_values: PropertyMap,
    pub children: Vec<StyledNode<'a>>,
}

#[derive(PartialEq)]
pub enum Display {
    Inline,
    Block,
    None,
}

impl<'a> StyledNode<'a> {
    /// Return the specified value of a property if it exists, otherwise `None`.
    pub fn value(&self, name: &str) -> Option<Value> {
        self.specified_values.get(name).cloned()
    }

    /// Return the specified value of property `name`, or property `fallback_name` if that doesn't
    /// exist. or value `default` if neither does.
    pub fn lookup(&self, name: &str, fallback_name: &str, default: &Value) -> Value {
        self.value(name).unwrap_or_else(|| self.value(fallback_name)
                        .unwrap_or_else(|| default.clone()))
    }

    /// The value of the `display` property (defaults to inline).
    pub fn display(&self) -> Display {
        match self.value("display") {
            Some(Value::Keyword(s)) => match &*s {
                "block" => Display::Block,
                "none" => Display::None,
                _ => Display::Inline
            },
            _ => Display::Inline
        }
    }
}

/// Apply a stylesheet to an entire DOM tree, returning a StyledNode tree.
///
/// This finds only the specified values at the moment. Eventually it should be extended to find the
/// computed values too, including inherited values.
pub fn style_tree<'a>(root: &'a Node, stylesheet: &'a Stylesheet) -> StyledNode<'a> {
    StyledNode {
        node: root,
        specified_values: match root.node_type {
            NodeType::Element(ref elem) => specified_values(elem, stylesheet),
            NodeType::Text(_) => HashMap::new()
        },
        children: root.children.iter().map(|child| style_tree(child, stylesheet)).collect(),
    }
}

/// Apply styles to a single element, returning the specified styles.
///
/// To do: Allow multiple UA/author/user stylesheets, and implement the cascade.
fn specified_values(elem: &ElementData, stylesheet: &Stylesheet) -> PropertyMap {
    let mut values = HashMap::new();
    let mut rules = matching_rules(elem, stylesheet);

    // Go through the rules from lowest to highest specificity.
    rules.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
    for (_, rule) in rules {
        for declaration in &rule.declarations {
            values.insert(declaration.name.clone(), declaration.value.clone());
        }
    }
    values
}

/// A single CSS rule and the specificity of its most specific matching selector.
type MatchedRule<'a> = (Specificity, &'a Rule);

/// Find all CSS rules that match the given element.
fn matching_rules<'a>(elem: &ElementData, stylesheet: &'a Stylesheet) -> Vec<MatchedRule<'a>> {
    // For now, we just do a linear scan of all the rules.  For large
    // documents, it would be more efficient to store the rules in hash tables
    // based on tag name, id, class, etc.
    stylesheet.rules.iter().filter_map(|rule| match_rule(elem, rule)).collect()
}

/// If `rule` matches `elem`, return a `MatchedRule`. Otherwise return `None`.
fn match_rule<'a>(elem: &ElementData, rule: &'a Rule) -> Option<MatchedRule<'a>> {
    // Find the first (most specific) matching selector.
    rule.selectors.iter().find(|selector| matches(elem, *selector))
        .map(|selector| (selector.specificity(), rule))
}

/// Selector matching:
fn matches(elem: &ElementData, selector: &Selector) -> bool {
    match *selector {
        Selector::Simple(ref simple_selector) => matches_simple_selector(elem, simple_selector)
    }
}

fn matches_simple_selector(elem: &ElementData, selector: &SimpleSelector) -> bool {
    // Check type selector
    if selector.tag_name.iter().any(|name| elem.tag_name != *name) {
        return false
    }

    // Check ID selector
    if selector.id.iter().any(|id| elem.id() != Some(id)) {
        return false;
    }

    // Check class selectors
    let elem_classes = elem.classes();
    if selector.class.iter().any(|class| !elem_classes.contains(&**class)) {
        return false;
    }

    // We didn't find any non-matching selector components.
    return true;
}
<commit_msg>Remove unneeded return statement<commit_after>//! Code for applying CSS styles to the DOM.
//!
//! This is not very interesting at the moment.  It will get much more
//! complicated if I add support for compound selectors.

use dom::{Node, NodeType, ElementData};
use css::{Stylesheet, Rule, Selector, SimpleSelector, Value, Specificity};
use std::collections::HashMap;

/// Map from CSS property names to values.
pub type PropertyMap =  HashMap<String, Value>;

/// A node with associated style data.
pub struct StyledNode<'a> {
    pub node: &'a Node,
    pub specified_values: PropertyMap,
    pub children: Vec<StyledNode<'a>>,
}

#[derive(PartialEq)]
pub enum Display {
    Inline,
    Block,
    None,
}

impl<'a> StyledNode<'a> {
    /// Return the specified value of a property if it exists, otherwise `None`.
    pub fn value(&self, name: &str) -> Option<Value> {
        self.specified_values.get(name).cloned()
    }

    /// Return the specified value of property `name`, or property `fallback_name` if that doesn't
    /// exist. or value `default` if neither does.
    pub fn lookup(&self, name: &str, fallback_name: &str, default: &Value) -> Value {
        self.value(name).unwrap_or_else(|| self.value(fallback_name)
                        .unwrap_or_else(|| default.clone()))
    }

    /// The value of the `display` property (defaults to inline).
    pub fn display(&self) -> Display {
        match self.value("display") {
            Some(Value::Keyword(s)) => match &*s {
                "block" => Display::Block,
                "none" => Display::None,
                _ => Display::Inline
            },
            _ => Display::Inline
        }
    }
}

/// Apply a stylesheet to an entire DOM tree, returning a StyledNode tree.
///
/// This finds only the specified values at the moment. Eventually it should be extended to find the
/// computed values too, including inherited values.
pub fn style_tree<'a>(root: &'a Node, stylesheet: &'a Stylesheet) -> StyledNode<'a> {
    StyledNode {
        node: root,
        specified_values: match root.node_type {
            NodeType::Element(ref elem) => specified_values(elem, stylesheet),
            NodeType::Text(_) => HashMap::new()
        },
        children: root.children.iter().map(|child| style_tree(child, stylesheet)).collect(),
    }
}

/// Apply styles to a single element, returning the specified styles.
///
/// To do: Allow multiple UA/author/user stylesheets, and implement the cascade.
fn specified_values(elem: &ElementData, stylesheet: &Stylesheet) -> PropertyMap {
    let mut values = HashMap::new();
    let mut rules = matching_rules(elem, stylesheet);

    // Go through the rules from lowest to highest specificity.
    rules.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
    for (_, rule) in rules {
        for declaration in &rule.declarations {
            values.insert(declaration.name.clone(), declaration.value.clone());
        }
    }
    values
}

/// A single CSS rule and the specificity of its most specific matching selector.
type MatchedRule<'a> = (Specificity, &'a Rule);

/// Find all CSS rules that match the given element.
fn matching_rules<'a>(elem: &ElementData, stylesheet: &'a Stylesheet) -> Vec<MatchedRule<'a>> {
    // For now, we just do a linear scan of all the rules.  For large
    // documents, it would be more efficient to store the rules in hash tables
    // based on tag name, id, class, etc.
    stylesheet.rules.iter().filter_map(|rule| match_rule(elem, rule)).collect()
}

/// If `rule` matches `elem`, return a `MatchedRule`. Otherwise return `None`.
fn match_rule<'a>(elem: &ElementData, rule: &'a Rule) -> Option<MatchedRule<'a>> {
    // Find the first (most specific) matching selector.
    rule.selectors.iter().find(|selector| matches(elem, *selector))
        .map(|selector| (selector.specificity(), rule))
}

/// Selector matching:
fn matches(elem: &ElementData, selector: &Selector) -> bool {
    match *selector {
        Selector::Simple(ref simple_selector) => matches_simple_selector(elem, simple_selector)
    }
}

fn matches_simple_selector(elem: &ElementData, selector: &SimpleSelector) -> bool {
    // Check type selector
    if selector.tag_name.iter().any(|name| elem.tag_name != *name) {
        return false
    }

    // Check ID selector
    if selector.id.iter().any(|id| elem.id() != Some(id)) {
        return false;
    }

    // Check class selectors
    let elem_classes = elem.classes();
    if selector.class.iter().any(|class| !elem_classes.contains(&**class)) {
        return false;
    }

    // We didn't find any non-matching selector components.
    true
}
<|endoftext|>


<commit_before>use crate::errors;
use std::{
    convert::{TryFrom, TryInto},
    error,
    fmt::{self, Display},
    iter::FromIterator,
    result,
    time::{Duration, SystemTime, UNIX_EPOCH},
};

/// A time tag in OSC message consists of two 32-bit integers where the first one denotes the number of seconds since 1900-01-01 and the second the fractions of a second.
/// For details on its semantics see http://opensoundcontrol.org/node/3/#timetags
///
/// # Examples
///
/// ```
/// use rosc::OscTime;
/// use std::{convert::TryFrom, time::SystemTime};
///
/// assert_eq!(
///     OscTime::try_from(SystemTime::UNIX_EPOCH).unwrap(),
///     OscTime::from((2_208_988_800, 0))
/// );
/// ```
///
/// # Conversions between `(u32, u32)`
///
/// Prior to version `0.5.0` of this crate, `OscTime` was defined as a type alias to `(u32, u32)`.
/// If you are upgrading from one of these older versions, you can use [`.into()`](Into::into) to
/// convert between `(u32, u32)` and `OscTime` in either direction.
///
/// # Conversions between [`std::time::SystemTime`]
///
/// The traits in `std::convert` are implemented for converting between
/// [`SystemTime`](std::time::SystemTime) and `OscTime` in both directions. An `OscTime` can be
/// converted into a `SystemTime` using [`From`](std::convert::From)/[`Into`](std::convert::Into).
/// A `SystemTime` can be converted into an `OscTime` using
/// [`TryFrom`](std::convert::TryFrom)/[`TryInto`](std::convert::TryInto). The fallible variants of
/// the conversion traits are used this case because not every `SystemTime` can be represented as
/// an `OscTime`.
///
/// **These conversions are lossy**, but are tested to have a deviation within
/// 5 nanoseconds when converted back and forth in either direction.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct OscTime {
    pub seconds: u32,
    pub fractional: u32,
}

impl OscTime {
    const UNIX_OFFSET: u64 = 2_208_988_800; // From RFC 5905
    const TWO_POW_32: f64 = (u32::MAX as f64) + 1.0; // Number of bits in a `u32`
    const ONE_OVER_TWO_POW_32: f64 = 1.0 / OscTime::TWO_POW_32;
    const NANOS_PER_SECOND: f64 = 1.0e9;
    const SECONDS_PER_NANO: f64 = 1.0 / OscTime::NANOS_PER_SECOND;

    fn epoch() -> SystemTime {
        UNIX_EPOCH - Duration::from_secs(OscTime::UNIX_OFFSET)
    }
}

impl TryFrom<SystemTime> for OscTime {
    type Error = OscTimeError;

    fn try_from(time: SystemTime) -> std::result::Result<OscTime, OscTimeError> {
        let duration_since_epoch = time
            .duration_since(OscTime::epoch())
            .map_err(|_| OscTimeError(OscTimeErrorKind::BeforeEpoch))?;
        let seconds = u32::try_from(duration_since_epoch.as_secs())
            .map_err(|_| OscTimeError(OscTimeErrorKind::Overflow))?;
        let nanos = duration_since_epoch.subsec_nanos() as f64;
        let fractional = (nanos * OscTime::SECONDS_PER_NANO * OscTime::TWO_POW_32).round() as u32;
        Ok(OscTime {
            seconds,
            fractional,
        })
    }
}

impl From<OscTime> for SystemTime {
    fn from(time: OscTime) -> SystemTime {
        let nanos =
            (time.fractional as f64) * OscTime::ONE_OVER_TWO_POW_32 * OscTime::NANOS_PER_SECOND;
        let duration_since_osc_epoch = Duration::new(time.seconds as u64, nanos as u32);
        OscTime::epoch() + duration_since_osc_epoch
    }
}

impl From<(u32, u32)> for OscTime {
    fn from(time: (u32, u32)) -> OscTime {
        let (seconds, fractional) = time;
        OscTime {
            seconds,
            fractional,
        }
    }
}

impl From<OscTime> for (u32, u32) {
    fn from(time: OscTime) -> (u32, u32) {
        (time.seconds, time.fractional)
    }
}

/// An error returned by conversions involving [`OscTime`].
#[derive(Debug)]
pub struct OscTimeError(OscTimeErrorKind);

#[derive(Debug)]
enum OscTimeErrorKind {
    BeforeEpoch,
    Overflow,
}

impl Display for OscTimeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.0 {
            OscTimeErrorKind::BeforeEpoch => {
                write!(f, "time is before the OSC epoch and cannot be stored")
            }
            OscTimeErrorKind::Overflow => {
                write!(f, "time overflows what OSC time can store")
            }
        }
    }
}

impl error::Error for OscTimeError {}

/// see OSC Type Tag String: [OSC Spec. 1.0](http://opensoundcontrol.org/spec-1_0)
/// padding: zero bytes (n*4)
#[derive(Clone, Debug, PartialEq)]
pub enum OscType {
    Int(i32),
    Float(f32),
    String(String),
    Blob(Vec<u8>),
    // use struct for time tag to avoid destructuring
    Time(OscTime),
    Long(i64),
    Double(f64),
    Char(char),
    Color(OscColor),
    Midi(OscMidiMessage),
    Bool(bool),
    Array(OscArray),
    Nil,
    Inf,
}
macro_rules! value_impl {
    ($(($name:ident, $variant:ident, $ty:ty)),*) => {
        $(
        impl OscType {
            #[allow(dead_code)]
            pub fn $name(self) -> Option<$ty> {
                match self {
                    OscType::$variant(v) => Some(v),
                    _ => None
                }
            }
        }
        impl From<$ty> for OscType {
            fn from(v: $ty) -> Self {
                OscType::$variant(v)
            }
        }
        )*
    }
}
value_impl! {
    (int, Int, i32),
    (float, Float, f32),
    (string, String, String),
    (blob, Blob, Vec<u8>),
    (array, Array, OscArray),
    (long, Long, i64),
    (double, Double, f64),
    (char, Char, char),
    (color, Color, OscColor),
    (midi, Midi, OscMidiMessage),
    (bool, Bool, bool)
}
impl From<(u32, u32)> for OscType {
    fn from(time: (u32, u32)) -> Self {
        OscType::Time(time.into())
    }
}
impl TryFrom<SystemTime> for OscType {
    type Error = OscTimeError;

    fn try_from(time: SystemTime) -> std::result::Result<OscType, OscTimeError> {
        time.try_into().map(OscType::Time)
    }
}
impl OscType {
    pub fn time(self) -> Option<OscTime> {
        match self {
            OscType::Time(time) => Some(time),
            _ => None,
        }
    }
}
impl<'a> From<&'a str> for OscType {
    fn from(string: &'a str) -> Self {
        OscType::String(string.to_string())
    }
}
/// Represents the parts of a Midi message. Mainly used for
/// tunneling midi over a network using the OSC protocol.
#[derive(Clone, Debug, PartialEq)]
pub struct OscMidiMessage {
    pub port: u8,
    pub status: u8,
    pub data1: u8, // maybe use an enum for data?
    pub data2: u8,
}

/// An *osc packet* can contain an *osc message* or a bundle of nested messages
/// which is called *osc bundle*.
#[derive(Clone, Debug, PartialEq)]
pub enum OscPacket {
    Message(OscMessage),
    Bundle(OscBundle),
}

/// An OSC message consists of an address and
/// zero or more arguments. The address should
/// specify an element of your Instrument (or whatever
/// you want to control with OSC) and the arguments
/// are used to set properties of the element to the
/// respective values.
#[derive(Clone, Debug, PartialEq)]
pub struct OscMessage {
    pub addr: String,
    pub args: Vec<OscType>,
}

/// An OSC bundle contains zero or more OSC packets
/// and a time tag. The contained packets *should* be
/// applied at the given time tag.
#[derive(Clone, Debug, PartialEq)]
pub struct OscBundle {
    pub timetag: OscTime,
    pub content: Vec<OscPacket>,
}

/// An RGBA color.
#[derive(Clone, Debug, PartialEq)]
pub struct OscColor {
    pub red: u8,
    pub green: u8,
    pub blue: u8,
    pub alpha: u8,
}

/// An OscArray color.
#[derive(Clone, Debug, PartialEq)]
pub struct OscArray {
    pub content: Vec<OscType>,
}

impl<T: Into<OscType>> FromIterator<T> for OscArray {
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> OscArray {
        OscArray {
            content: iter.into_iter().map(T::into).collect(),
        }
    }
}

pub type Result<T> = result::Result<T, errors::OscError>;

impl From<String> for OscMessage {
    fn from(s: String) -> OscMessage {
        OscMessage {
            addr: s,
            args: vec![],
        }
    }
}
impl<'a> From<&'a str> for OscMessage {
    fn from(s: &str) -> OscMessage {
        OscMessage {
            addr: s.to_string(),
            args: vec![],
        }
    }
}

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

    const TOLERANCE_NANOS: u64 = 5;

    #[test]
    fn system_times_can_be_converted_to_and_from_osc() {
        let times = vec![UNIX_EPOCH, OscTime::epoch(), UNIX_EPOCH];
        for time in times {
            for i in 0..1000 {
                let time = time + Duration::from_nanos(1) * i;
                assert_eq_system_times(time, SystemTime::from(OscTime::try_from(time).unwrap()));
            }
        }
    }

    #[test]
    fn osc_times_can_be_converted_to_and_from_system_times() {
        let mut times = vec![];

        // Sweep across a few numbers to check for tolerance
        for seconds in vec![0, 1, 2, 3, u32::MAX - 1, u32::MAX] {
            let fractional_max = 100;
            for fractional in 0..fractional_max {
                times.push((seconds, fractional));
                times.push((seconds, fractional_max - fractional));
            }
        }

        for osc_time in times.into_iter().map(OscTime::from) {
            assert_eq_osc_times(
                osc_time,
                OscTime::try_from(SystemTime::from(osc_time)).unwrap(),
            );
        }
    }

    #[test]
    fn osc_time_cannot_represent_times_before_1900_01_01() {
        assert!(OscTime::try_from(OscTime::epoch() - Duration::from_secs(1)).is_err())
    }

    fn assert_eq_system_times(a: SystemTime, b: SystemTime) {
        let difference = if a < b {
            b.duration_since(a).unwrap()
        } else {
            a.duration_since(b).unwrap()
        };

        let tolerance = Duration::from_nanos(TOLERANCE_NANOS);

        if difference > tolerance {
            panic!(
                "the fractional seconds components of {:?} and {:?} vary more than the required tolerance of {:?}",
                a, b, tolerance,
            );
        }
    }

    fn assert_eq_osc_times(a: OscTime, b: OscTime) {
        // I did not want to implement subtraction with carrying in order to implement this in the
        // same way as the alternative for system times. Intsead we are compare each part of the
        // OSC times separately.
        let tolerance_fractional_seconds = ((TOLERANCE_NANOS as f64 * OscTime::TWO_POW_32)
            / OscTime::NANOS_PER_SECOND)
            .round() as i64;
        assert_eq!(
            a.seconds, b.seconds,
            "the seconds components of {:?} and {:?} are different",
            a, b
        );
        if (a.fractional as i64 - b.fractional as i64).abs() > tolerance_fractional_seconds {
            panic!(
                "the fractional seconds components of {:?} and {:?} vary more than the required tolerance of {} fractional seconds",
                a, b, tolerance_fractional_seconds,
            );
        }
    }
}
<commit_msg>Base OscTime/SystemTime conversions on UNIX_EPOCH<commit_after>use crate::errors;
use std::{
    convert::{TryFrom, TryInto},
    error,
    fmt::{self, Display},
    iter::FromIterator,
    result,
    time::{Duration, SystemTime, UNIX_EPOCH},
};

/// A time tag in OSC message consists of two 32-bit integers where the first one denotes the number of seconds since 1900-01-01 and the second the fractions of a second.
/// For details on its semantics see http://opensoundcontrol.org/node/3/#timetags
///
/// # Examples
///
/// ```
/// use rosc::OscTime;
/// use std::{convert::TryFrom, time::UNIX_EPOCH};
///
/// assert_eq!(
///     OscTime::try_from(UNIX_EPOCH).unwrap(),
///     OscTime::from((2_208_988_800, 0))
/// );
/// ```
///
/// # Conversions between `(u32, u32)`
///
/// Prior to version `0.5.0` of this crate, `OscTime` was defined as a type alias to `(u32, u32)`.
/// If you are upgrading from one of these older versions, you can use [`.into()`](Into::into) to
/// convert between `(u32, u32)` and `OscTime` in either direction.
///
/// # Conversions between [`std::time::SystemTime`]
///
/// The traits in `std::convert` are implemented for converting between
/// [`SystemTime`](std::time::SystemTime) and `OscTime` in both directions. An `OscTime` can be
/// converted into a `SystemTime` using [`From`](std::convert::From)/[`Into`](std::convert::Into).
/// A `SystemTime` can be converted into an `OscTime` using
/// [`TryFrom`](std::convert::TryFrom)/[`TryInto`](std::convert::TryInto). The fallible variants of
/// the conversion traits are used this case because not every `SystemTime` can be represented as
/// an `OscTime`.
///
/// **These conversions are lossy**, but are tested to have a deviation within
/// 5 nanoseconds when converted back and forth in either direction.
///
/// Although any time since the OSC epoch (`1900-01-01 00:00:00 UTC`) can be represented using the
/// OSC timestamp format, this crate only allows conversions between times greater than or equal to
/// the [`UNIX_EPOCH`](std::time::UNIX_EPOCH). This allows the math used in the conversions to work
/// on 32-bit systems which cannot represent times that far back.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct OscTime {
    pub seconds: u32,
    pub fractional: u32,
}

impl OscTime {
    const UNIX_OFFSET: u64 = 2_208_988_800; // From RFC 5905
    const TWO_POW_32: f64 = (u32::MAX as f64) + 1.0; // Number of bits in a `u32`
    const ONE_OVER_TWO_POW_32: f64 = 1.0 / OscTime::TWO_POW_32;
    const NANOS_PER_SECOND: f64 = 1.0e9;
    const SECONDS_PER_NANO: f64 = 1.0 / OscTime::NANOS_PER_SECOND;
}

impl TryFrom<SystemTime> for OscTime {
    type Error = OscTimeError;

    fn try_from(time: SystemTime) -> std::result::Result<OscTime, OscTimeError> {
        let duration_since_epoch = time
            .duration_since(UNIX_EPOCH)
            .map_err(|_| OscTimeError(OscTimeErrorKind::BeforeEpoch))?
            + Duration::new(OscTime::UNIX_OFFSET, 0);
        let seconds = u32::try_from(duration_since_epoch.as_secs())
            .map_err(|_| OscTimeError(OscTimeErrorKind::Overflow))?;
        let nanos = duration_since_epoch.subsec_nanos() as f64;
        let fractional = (nanos * OscTime::SECONDS_PER_NANO * OscTime::TWO_POW_32).round() as u32;
        Ok(OscTime {
            seconds,
            fractional,
        })
    }
}

impl From<OscTime> for SystemTime {
    fn from(time: OscTime) -> SystemTime {
        let nanos =
            (time.fractional as f64) * OscTime::ONE_OVER_TWO_POW_32 * OscTime::NANOS_PER_SECOND;
        let duration_since_osc_epoch = Duration::new(time.seconds as u64, nanos as u32);
        let duration_since_unix_epoch =
            duration_since_osc_epoch - Duration::new(OscTime::UNIX_OFFSET, 0);
        UNIX_EPOCH + duration_since_unix_epoch
    }
}

impl From<(u32, u32)> for OscTime {
    fn from(time: (u32, u32)) -> OscTime {
        let (seconds, fractional) = time;
        OscTime {
            seconds,
            fractional,
        }
    }
}

impl From<OscTime> for (u32, u32) {
    fn from(time: OscTime) -> (u32, u32) {
        (time.seconds, time.fractional)
    }
}

/// An error returned by conversions involving [`OscTime`].
#[derive(Debug)]
pub struct OscTimeError(OscTimeErrorKind);

#[derive(Debug)]
enum OscTimeErrorKind {
    BeforeEpoch,
    Overflow,
}

impl Display for OscTimeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.0 {
            OscTimeErrorKind::BeforeEpoch => {
                write!(f, "time is before the unix epoch and cannot be stored")
            }
            OscTimeErrorKind::Overflow => {
                write!(f, "time overflows what OSC time can store")
            }
        }
    }
}

impl error::Error for OscTimeError {}

/// see OSC Type Tag String: [OSC Spec. 1.0](http://opensoundcontrol.org/spec-1_0)
/// padding: zero bytes (n*4)
#[derive(Clone, Debug, PartialEq)]
pub enum OscType {
    Int(i32),
    Float(f32),
    String(String),
    Blob(Vec<u8>),
    // use struct for time tag to avoid destructuring
    Time(OscTime),
    Long(i64),
    Double(f64),
    Char(char),
    Color(OscColor),
    Midi(OscMidiMessage),
    Bool(bool),
    Array(OscArray),
    Nil,
    Inf,
}
macro_rules! value_impl {
    ($(($name:ident, $variant:ident, $ty:ty)),*) => {
        $(
        impl OscType {
            #[allow(dead_code)]
            pub fn $name(self) -> Option<$ty> {
                match self {
                    OscType::$variant(v) => Some(v),
                    _ => None
                }
            }
        }
        impl From<$ty> for OscType {
            fn from(v: $ty) -> Self {
                OscType::$variant(v)
            }
        }
        )*
    }
}
value_impl! {
    (int, Int, i32),
    (float, Float, f32),
    (string, String, String),
    (blob, Blob, Vec<u8>),
    (array, Array, OscArray),
    (long, Long, i64),
    (double, Double, f64),
    (char, Char, char),
    (color, Color, OscColor),
    (midi, Midi, OscMidiMessage),
    (bool, Bool, bool)
}
impl From<(u32, u32)> for OscType {
    fn from(time: (u32, u32)) -> Self {
        OscType::Time(time.into())
    }
}
impl TryFrom<SystemTime> for OscType {
    type Error = OscTimeError;

    fn try_from(time: SystemTime) -> std::result::Result<OscType, OscTimeError> {
        time.try_into().map(OscType::Time)
    }
}
impl OscType {
    pub fn time(self) -> Option<OscTime> {
        match self {
            OscType::Time(time) => Some(time),
            _ => None,
        }
    }
}
impl<'a> From<&'a str> for OscType {
    fn from(string: &'a str) -> Self {
        OscType::String(string.to_string())
    }
}
/// Represents the parts of a Midi message. Mainly used for
/// tunneling midi over a network using the OSC protocol.
#[derive(Clone, Debug, PartialEq)]
pub struct OscMidiMessage {
    pub port: u8,
    pub status: u8,
    pub data1: u8, // maybe use an enum for data?
    pub data2: u8,
}

/// An *osc packet* can contain an *osc message* or a bundle of nested messages
/// which is called *osc bundle*.
#[derive(Clone, Debug, PartialEq)]
pub enum OscPacket {
    Message(OscMessage),
    Bundle(OscBundle),
}

/// An OSC message consists of an address and
/// zero or more arguments. The address should
/// specify an element of your Instrument (or whatever
/// you want to control with OSC) and the arguments
/// are used to set properties of the element to the
/// respective values.
#[derive(Clone, Debug, PartialEq)]
pub struct OscMessage {
    pub addr: String,
    pub args: Vec<OscType>,
}

/// An OSC bundle contains zero or more OSC packets
/// and a time tag. The contained packets *should* be
/// applied at the given time tag.
#[derive(Clone, Debug, PartialEq)]
pub struct OscBundle {
    pub timetag: OscTime,
    pub content: Vec<OscPacket>,
}

/// An RGBA color.
#[derive(Clone, Debug, PartialEq)]
pub struct OscColor {
    pub red: u8,
    pub green: u8,
    pub blue: u8,
    pub alpha: u8,
}

/// An OscArray color.
#[derive(Clone, Debug, PartialEq)]
pub struct OscArray {
    pub content: Vec<OscType>,
}

impl<T: Into<OscType>> FromIterator<T> for OscArray {
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> OscArray {
        OscArray {
            content: iter.into_iter().map(T::into).collect(),
        }
    }
}

pub type Result<T> = result::Result<T, errors::OscError>;

impl From<String> for OscMessage {
    fn from(s: String) -> OscMessage {
        OscMessage {
            addr: s,
            args: vec![],
        }
    }
}
impl<'a> From<&'a str> for OscMessage {
    fn from(s: &str) -> OscMessage {
        OscMessage {
            addr: s.to_string(),
            args: vec![],
        }
    }
}

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

    const TOLERANCE_NANOS: u64 = 5;

    #[test]
    fn system_times_can_be_converted_to_and_from_osc() {
        let times = vec![UNIX_EPOCH, SystemTime::now()];
        for time in times {
            for i in 0..1000 {
                let time = time + Duration::from_nanos(1) * i;
                assert_eq_system_times(time, SystemTime::from(OscTime::try_from(time).unwrap()));
            }
        }
    }

    #[test]
    fn osc_times_can_be_converted_to_and_from_system_times() {
        let mut times = vec![];
        // Sweep across a few numbers to check for tolerance
        for seconds in vec![
            // We don't start at zero because times before the UNIX_EPOCH cannot be converted to
            // OscTime.
            OscTime::UNIX_OFFSET as u32,
            OscTime::UNIX_OFFSET as u32 + 1,
            OscTime::UNIX_OFFSET as u32 + 2,
            OscTime::UNIX_OFFSET as u32 + 3,
            u32::MAX - 1,
            u32::MAX,
        ] {
            let fractional_max = 100;
            for fractional in 0..fractional_max {
                times.push((seconds, fractional));
                times.push((seconds, fractional_max - fractional));
            }
        }

        for osc_time in times.into_iter().map(OscTime::from) {
            assert_eq_osc_times(
                osc_time,
                OscTime::try_from(SystemTime::from(osc_time)).unwrap(),
            );
        }
    }

    #[test]
    fn osc_time_cannot_represent_times_before_1970_01_01() {
        assert!(OscTime::try_from(UNIX_EPOCH - Duration::from_secs(1)).is_err())
    }

    fn assert_eq_system_times(a: SystemTime, b: SystemTime) {
        let difference = if a < b {
            b.duration_since(a).unwrap()
        } else {
            a.duration_since(b).unwrap()
        };

        let tolerance = Duration::from_nanos(TOLERANCE_NANOS);

        if difference > tolerance {
            panic!(
                "the fractional seconds components of {:?} and {:?} vary more than the required tolerance of {:?}",
                a, b, tolerance,
            );
        }
    }

    fn assert_eq_osc_times(a: OscTime, b: OscTime) {
        // I did not want to implement subtraction with carrying in order to implement this in the
        // same way as the alternative for system times. Intsead we are compare each part of the
        // OSC times separately.
        let tolerance_fractional_seconds = ((TOLERANCE_NANOS as f64 * OscTime::TWO_POW_32)
            / OscTime::NANOS_PER_SECOND)
            .round() as i64;
        assert_eq!(
            a.seconds, b.seconds,
            "the seconds components of {:?} and {:?} are different",
            a, b
        );
        if (a.fractional as i64 - b.fractional as i64).abs() > tolerance_fractional_seconds {
            panic!(
                "the fractional seconds components of {:?} and {:?} vary more than the required tolerance of {} fractional seconds",
                a, b, tolerance_fractional_seconds,
            );
        }
    }
}
<|endoftext|>