<commit_before>// Copyright 2016 Mozilla
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

use std::collections::{BTreeSet, BTreeMap, LinkedList};
use std::cmp::{Ordering, Ord, PartialOrd};
use std::fmt::{Display, Formatter};

use symbols;
use num::BigInt;
use ordered_float::OrderedFloat;

/// Value represents one of the allowed values in an EDN string.
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum Value {
    Nil,
    Boolean(bool),
    Integer(i64),
    BigInteger(BigInt),
    // https://users.rust-lang.org/t/hashmap-key-cant-be-float-number-type-why/7892
    Float(OrderedFloat<f64>),
    Text(String),
    PlainSymbol(symbols::PlainSymbol),
    NamespacedSymbol(symbols::NamespacedSymbol),
    Keyword(symbols::Keyword),
    NamespacedKeyword(symbols::NamespacedKeyword),
    Vector(Vec<Value>),
    // We're using a LinkedList here instead of a Vec or VecDeque because the
    // LinkedList is faster for appending (which we do a lot of).
    // See https://github.com/mozilla/mentat/issues/231
    List(LinkedList<Value>),
    // We're using BTree{Set, Map} rather than Hash{Set, Map} because the BTree variants
    // implement Hash. The Hash variants don't in order to preserve O(n) hashing
    // time, which is hard given recursive data structures.
    // See https://internals.rust-lang.org/t/implementing-hash-for-hashset-hashmap/3817/1
    Set(BTreeSet<Value>),
    Map(BTreeMap<Value, Value>),
}

use self::Value::*;

impl Display for Value {
    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
        match *self {
            Keyword(ref v) => v.fmt(f),
            NamespacedKeyword(ref v) => v.fmt(f),
            PlainSymbol(ref v) => v.fmt(f),
            NamespacedSymbol(ref v) => v.fmt(f),

            Integer(v) => write!(f, "{}", v),
            BigInteger(ref v) => write!(f, "{}N", v),
            Float(OrderedFloat(v)) => write!(f, "{}", v),       // TODO: make sure float syntax is correct.
                                                                // TODO: NaN.
            Text(ref v) => write!(f, "{}", v),                  // TODO: EDN escaping.
            Vector(ref v) => {
                try!(write!(f, "["));
                for x in v {
                    try!(write!(f, " {}", x));
                }
                write!(f, " ]")
            }
            _ =>
                write!(f, "{}",
                       match *self {
                           Nil => "null",
                           Boolean(b) => if b { "true" } else { "false" },
                           _ => unimplemented!(),
                       }),
        }
    }
}

/// Creates `is_$TYPE` helper functions for Value, like
/// `is_big_integer()` or `is_text()`.
macro_rules! def_is {
    ($name: ident, $pat: pat) => {
        pub fn $name(&self) -> bool {
            match *self { $pat => true, _ => false }
        }
    }
}

/// Creates `as_$TYPE` helper functions for Value, like `as_big_integer()`,
/// which returns the underlying value representing this Value wrapped
/// in an Option, like `<Option<&BigInt>`.
macro_rules! def_as {
    ($name: ident, $kind: path, $t: ty) => {
        pub fn $name(&self) -> Option<&$t> {
            match *self { $kind(ref v) => Some(v), _ => None }
        }
    }
}

impl Value {
    def_is!(is_nil, Nil);
    def_is!(is_boolean, Boolean(_));
    def_is!(is_integer, Integer(_));
    def_is!(is_big_integer, BigInteger(_));
    def_is!(is_float, Float(_));
    def_is!(is_text, Text(_));
    def_is!(is_symbol, PlainSymbol(_));
    def_is!(is_namespaced_symbol, NamespacedSymbol(_));
    def_is!(is_keyword, Keyword(_));
    def_is!(is_namespaced_keyword, NamespacedKeyword(_));
    def_is!(is_vector, Vector(_));
    def_is!(is_list, List(_));
    def_is!(is_set, Set(_));
    def_is!(is_map, Map(_));

    /// `as_nil` does not use the macro as it does not have an underlying
    /// value, and returns `Option<()>`.
    pub fn as_nil(&self) -> Option<()> {
        match *self { Nil => Some(()), _ => None }
    }

    def_as!(as_boolean, Boolean, bool);
    def_as!(as_integer, Integer, i64);
    def_as!(as_big_integer, BigInteger, BigInt);
    def_as!(as_float, Float, OrderedFloat<f64>);
    def_as!(as_text, Text, String);
    def_as!(as_symbol, PlainSymbol, symbols::PlainSymbol);
    def_as!(as_namespaced_symbol, NamespacedSymbol, symbols::NamespacedSymbol);
    def_as!(as_keyword, Keyword, symbols::Keyword);
    def_as!(as_namespaced_keyword, NamespacedKeyword, symbols::NamespacedKeyword);
    def_as!(as_vector, Vector, Vec<Value>);
    def_as!(as_list, List, LinkedList<Value>);
    def_as!(as_set, Set, BTreeSet<Value>);
    def_as!(as_map, Map, BTreeMap<Value, Value>);

    pub fn from_bigint(src: &str) -> Option<Value> {
        src.parse::<BigInt>().map(Value::BigInteger).ok()
    }
}

impl From<f64> for Value {
    fn from(src: f64) -> Value {
        Value::Float(OrderedFloat::from(src))
    }
}

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

// TODO: Check we follow the equality rules at the bottom of https://github.com/edn-format/edn
impl Ord for Value {
    fn cmp(&self, other: &Value) -> Ordering {

        let ord_order = to_ord(self).cmp(&to_ord(other));
        match *self {
            Nil             => match *other { Nil             => Ordering::Equal, _ => ord_order },
            Boolean(bs)     => match *other { Boolean(bo)     => bo.cmp(&bs), _ => ord_order },
            BigInteger(ref bs) => match *other { BigInteger(ref bo) => bo.cmp(&bs), _ => ord_order },
            Integer(is)     => match *other { Integer(io)     => io.cmp(&is), _ => ord_order },
            Float(ref fs)   => match *other { Float(ref fo)   => fo.cmp(&fs), _ => ord_order },
            Text(ref ts)    => match *other { Text(ref to)    => to.cmp(&ts), _ => ord_order },
            PlainSymbol(ref ss)  => match *other { PlainSymbol(ref so)  => so.cmp(&ss), _ => ord_order },
            NamespacedSymbol(ref ss)
                => match *other { NamespacedSymbol(ref so)    => so.cmp(&ss), _ => ord_order },
            Keyword(ref ks) => match *other { Keyword(ref ko) => ko.cmp(&ks), _ => ord_order },
            NamespacedKeyword(ref ks)
                => match *other { NamespacedKeyword(ref ko)   => ko.cmp(&ks), _ => ord_order },
            Vector(ref vs)  => match *other { Vector(ref vo)  => vo.cmp(&vs), _ => ord_order },
            List(ref ls)    => match *other { List(ref lo)    => lo.cmp(&ls), _ => ord_order },
            Set(ref ss)     => match *other { Set(ref so)     => so.cmp(&ss), _ => ord_order },
            Map(ref ms)     => match *other { Map(ref mo)     => mo.cmp(&ms), _ => ord_order },
        }
    }
}

fn to_ord(value: &Value) -> i32 {
    match *value {
        Nil => 0,
        Boolean(_) => 1,
        Integer(_) => 2,
        BigInteger(_) => 3,
        Float(_) => 4,
        Text(_) => 5,
        PlainSymbol(_) => 6,
        NamespacedSymbol(_) => 7,
        Keyword(_) => 8,
        NamespacedKeyword(_) => 9,
        Vector(_) => 10,
        List(_) => 11,
        Set(_) => 12,
        Map(_) => 13,
    }
}

/// Converts `name` into a plain or namespaced value symbol, depending on
/// whether or not `namespace` is given.
///
/// # Examples
///
/// ```
/// # use edn::types::to_symbol;
/// # use edn::types::Value;
/// # use edn::symbols;
/// let value = to_symbol("foo", "bar");
/// assert_eq!(value, Value::NamespacedSymbol(symbols::NamespacedSymbol::new("foo", "bar")));
///
/// let value = to_symbol(None, "baz");
/// assert_eq!(value, Value::PlainSymbol(symbols::PlainSymbol::new("baz")));
/// ```
pub fn to_symbol<'a, T: Into<Option<&'a str>>>(namespace: T, name: &str) -> Value {
    namespace.into().map_or_else(
        || Value::PlainSymbol(symbols::PlainSymbol::new(name)),
        |ns| Value::NamespacedSymbol(symbols::NamespacedSymbol::new(ns, name)))
}

/// Converts `name` into a plain or namespaced value keyword, depending on
/// whether or not `namespace` is given.
///
/// # Examples
///
/// ```
/// # use edn::types::to_keyword;
/// # use edn::types::Value;
/// # use edn::symbols;
/// let value = to_keyword("foo", "bar");
/// assert_eq!(value, Value::NamespacedKeyword(symbols::NamespacedKeyword::new("foo", "bar")));
///
/// let value = to_keyword(None, "baz");
/// assert_eq!(value, Value::Keyword(symbols::Keyword::new("baz")));
/// ```
pub fn to_keyword<'a, T: Into<Option<&'a str>>>(namespace: T, name: &str) -> Value {
    namespace.into().map_or_else(
        || Value::Keyword(symbols::Keyword::new(name)),
        |ns| Value::NamespacedKeyword(symbols::NamespacedKeyword::new(ns, name)))
}

#[cfg(test)]
mod test {
    extern crate ordered_float;
    extern crate num;

    use super::*;

    use std::collections::{BTreeSet, BTreeMap, LinkedList};
    use std::cmp::{Ordering};

    use symbols;
    use num::BigInt;
    use ordered_float::OrderedFloat;
    use std::iter::FromIterator;

    #[test]
    fn test_value_from() {
        assert_eq!(Value::from(42f64), Value::Float(OrderedFloat::from(42f64)));
        assert_eq!(Value::from_bigint("42").unwrap(), Value::BigInteger(BigInt::from(42)));
    }

    #[test]
    fn test_print_edn() {
        assert_eq!("[ 1 2 [ 3.14 ] [ ] :five :six/seven eight nine/ten true ]",
            Value::Vector(vec!(Value::Integer(1),
            Value::Integer(2),
            Value::Vector(vec!(Value::Float(OrderedFloat(3.14)))),
            Value::Vector(vec!()),
            Value::Keyword(symbols::Keyword::new("five")),
            Value::NamespacedKeyword(symbols::NamespacedKeyword::new("six", "seven")),
            Value::PlainSymbol(symbols::PlainSymbol::new("eight")),
            Value::NamespacedSymbol(symbols::NamespacedSymbol::new("nine", "ten")),
            Value::Boolean(true))).to_string());
    }
}<commit_msg>Avoid needless reborrows and simplify `Ord` implementation for edn::Value<commit_after>// Copyright 2016 Mozilla
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

use std::collections::{BTreeSet, BTreeMap, LinkedList};
use std::cmp::{Ordering, Ord, PartialOrd};
use std::fmt::{Display, Formatter};

use symbols;
use num::BigInt;
use ordered_float::OrderedFloat;

/// Value represents one of the allowed values in an EDN string.
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum Value {
    Nil,
    Boolean(bool),
    Integer(i64),
    BigInteger(BigInt),
    // https://users.rust-lang.org/t/hashmap-key-cant-be-float-number-type-why/7892
    Float(OrderedFloat<f64>),
    Text(String),
    PlainSymbol(symbols::PlainSymbol),
    NamespacedSymbol(symbols::NamespacedSymbol),
    Keyword(symbols::Keyword),
    NamespacedKeyword(symbols::NamespacedKeyword),
    Vector(Vec<Value>),
    // We're using a LinkedList here instead of a Vec or VecDeque because the
    // LinkedList is faster for appending (which we do a lot of).
    // See https://github.com/mozilla/mentat/issues/231
    List(LinkedList<Value>),
    // We're using BTree{Set, Map} rather than Hash{Set, Map} because the BTree variants
    // implement Hash. The Hash variants don't in order to preserve O(n) hashing
    // time, which is hard given recursive data structures.
    // See https://internals.rust-lang.org/t/implementing-hash-for-hashset-hashmap/3817/1
    Set(BTreeSet<Value>),
    Map(BTreeMap<Value, Value>),
}

use self::Value::*;

impl Display for Value {
    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
        match *self {
            Keyword(ref v) => v.fmt(f),
            NamespacedKeyword(ref v) => v.fmt(f),
            PlainSymbol(ref v) => v.fmt(f),
            NamespacedSymbol(ref v) => v.fmt(f),

            Integer(v) => write!(f, "{}", v),
            BigInteger(ref v) => write!(f, "{}N", v),
            Float(OrderedFloat(v)) => write!(f, "{}", v),       // TODO: make sure float syntax is correct.
                                                                // TODO: NaN.
            Text(ref v) => write!(f, "{}", v),                  // TODO: EDN escaping.
            Vector(ref v) => {
                try!(write!(f, "["));
                for x in v {
                    try!(write!(f, " {}", x));
                }
                write!(f, " ]")
            }
            _ =>
                write!(f, "{}",
                       match *self {
                           Nil => "null",
                           Boolean(b) => if b { "true" } else { "false" },
                           _ => unimplemented!(),
                       }),
        }
    }
}

/// Creates `is_$TYPE` helper functions for Value, like
/// `is_big_integer()` or `is_text()`.
macro_rules! def_is {
    ($name: ident, $pat: pat) => {
        pub fn $name(&self) -> bool {
            match *self { $pat => true, _ => false }
        }
    }
}

/// Creates `as_$TYPE` helper functions for Value, like `as_big_integer()`,
/// which returns the underlying value representing this Value wrapped
/// in an Option, like `<Option<&BigInt>`.
macro_rules! def_as {
    ($name: ident, $kind: path, $t: ty) => {
        pub fn $name(&self) -> Option<&$t> {
            match *self { $kind(ref v) => Some(v), _ => None }
        }
    }
}

impl Value {
    def_is!(is_nil, Nil);
    def_is!(is_boolean, Boolean(_));
    def_is!(is_integer, Integer(_));
    def_is!(is_big_integer, BigInteger(_));
    def_is!(is_float, Float(_));
    def_is!(is_text, Text(_));
    def_is!(is_symbol, PlainSymbol(_));
    def_is!(is_namespaced_symbol, NamespacedSymbol(_));
    def_is!(is_keyword, Keyword(_));
    def_is!(is_namespaced_keyword, NamespacedKeyword(_));
    def_is!(is_vector, Vector(_));
    def_is!(is_list, List(_));
    def_is!(is_set, Set(_));
    def_is!(is_map, Map(_));

    /// `as_nil` does not use the macro as it does not have an underlying
    /// value, and returns `Option<()>`.
    pub fn as_nil(&self) -> Option<()> {
        match *self { Nil => Some(()), _ => None }
    }

    def_as!(as_boolean, Boolean, bool);
    def_as!(as_integer, Integer, i64);
    def_as!(as_big_integer, BigInteger, BigInt);
    def_as!(as_float, Float, OrderedFloat<f64>);
    def_as!(as_text, Text, String);
    def_as!(as_symbol, PlainSymbol, symbols::PlainSymbol);
    def_as!(as_namespaced_symbol, NamespacedSymbol, symbols::NamespacedSymbol);
    def_as!(as_keyword, Keyword, symbols::Keyword);
    def_as!(as_namespaced_keyword, NamespacedKeyword, symbols::NamespacedKeyword);
    def_as!(as_vector, Vector, Vec<Value>);
    def_as!(as_list, List, LinkedList<Value>);
    def_as!(as_set, Set, BTreeSet<Value>);
    def_as!(as_map, Map, BTreeMap<Value, Value>);

    pub fn from_bigint(src: &str) -> Option<Value> {
        src.parse::<BigInt>().map(Value::BigInteger).ok()
    }

    pub fn from_symbol<'a, T: Into<Option<&'a str>>>(namespace: T, name: &str) -> Value {
        to_symbol(namespace, name)
    }

    pub fn from_keyword<'a, T: Into<Option<&'a str>>>(namespace: T, name: &str) -> Value {
        to_keyword(namespace, name)
    }
}

impl From<f64> for Value {
    fn from(src: f64) -> Value {
        Value::Float(OrderedFloat::from(src))
    }
}

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

impl Ord for Value {
    fn cmp(&self, other: &Value) -> Ordering {
        match (self, other) {
            (&Nil, &Nil) => Ordering::Equal,
            (&Boolean(a), &Boolean(b)) => b.cmp(&a),
            (&Integer(a), &Integer(b)) => b.cmp(&a),
            (&BigInteger(ref a), &BigInteger(ref b)) => b.cmp(a),
            (&Float(ref a), &Float(ref b)) => b.cmp(a),
            (&Text(ref a), &Text(ref b)) => b.cmp(a),
            (&PlainSymbol(ref a), &PlainSymbol(ref b)) => b.cmp(a),
            (&NamespacedSymbol(ref a), &NamespacedSymbol(ref b)) => b.cmp(a),
            (&Keyword(ref a), &Keyword(ref b)) => b.cmp(a),
            (&NamespacedKeyword(ref a), &NamespacedKeyword(ref b)) => b.cmp(a),
            (&Vector(ref a), &Vector(ref b)) => b.cmp(a),
            (&List(ref a), &List(ref b)) => b.cmp(a),
            (&Set(ref a), &Set(ref b)) => b.cmp(a),
            (&Map(ref a), &Map(ref b)) => b.cmp(a),
            _ => to_ord(self).cmp(&to_ord(other))
        }
    }
}

fn to_ord(value: &Value) -> i32 {
    match *value {
        Nil => 0,
        Boolean(_) => 1,
        Integer(_) => 2,
        BigInteger(_) => 3,
        Float(_) => 4,
        Text(_) => 5,
        PlainSymbol(_) => 6,
        NamespacedSymbol(_) => 7,
        Keyword(_) => 8,
        NamespacedKeyword(_) => 9,
        Vector(_) => 10,
        List(_) => 11,
        Set(_) => 12,
        Map(_) => 13,
    }
}

/// Converts `name` into a plain or namespaced value symbol, depending on
/// whether or not `namespace` is given.
///
/// # Examples
///
/// ```
/// # use edn::types::to_symbol;
/// # use edn::types::Value;
/// # use edn::symbols;
/// let value = to_symbol("foo", "bar");
/// assert_eq!(value, Value::NamespacedSymbol(symbols::NamespacedSymbol::new("foo", "bar")));
///
/// let value = to_symbol(None, "baz");
/// assert_eq!(value, Value::PlainSymbol(symbols::PlainSymbol::new("baz")));
/// ```
pub fn to_symbol<'a, T: Into<Option<&'a str>>>(namespace: T, name: &str) -> Value {
    namespace.into().map_or_else(
        || Value::PlainSymbol(symbols::PlainSymbol::new(name)),
        |ns| Value::NamespacedSymbol(symbols::NamespacedSymbol::new(ns, name)))
}

/// Converts `name` into a plain or namespaced value keyword, depending on
/// whether or not `namespace` is given.
///
/// # Examples
///
/// ```
/// # use edn::types::to_keyword;
/// # use edn::types::Value;
/// # use edn::symbols;
/// let value = to_keyword("foo", "bar");
/// assert_eq!(value, Value::NamespacedKeyword(symbols::NamespacedKeyword::new("foo", "bar")));
///
/// let value = to_keyword(None, "baz");
/// assert_eq!(value, Value::Keyword(symbols::Keyword::new("baz")));
/// ```
pub fn to_keyword<'a, T: Into<Option<&'a str>>>(namespace: T, name: &str) -> Value {
    namespace.into().map_or_else(
        || Value::Keyword(symbols::Keyword::new(name)),
        |ns| Value::NamespacedKeyword(symbols::NamespacedKeyword::new(ns, name)))
}

#[cfg(test)]
mod test {
    extern crate ordered_float;
    extern crate num;

    use super::*;

    use std::collections::{BTreeSet, BTreeMap, LinkedList};
    use std::cmp::{Ordering};

    use symbols;
    use num::BigInt;
    use ordered_float::OrderedFloat;
    use std::iter::FromIterator;

    #[test]
    fn test_value_from() {
        assert_eq!(Value::from(42f64), Value::Float(OrderedFloat::from(42f64)));
        assert_eq!(Value::from_bigint("42").unwrap(), Value::BigInteger(BigInt::from(42)));
    }

    #[test]
    fn test_print_edn() {
        assert_eq!("[ 1 2 [ 3.14 ] [ ] :five :six/seven eight nine/ten true ]",
            Value::Vector(vec!(Value::Integer(1),
            Value::Integer(2),
            Value::Vector(vec!(Value::Float(OrderedFloat(3.14)))),
            Value::Vector(vec!()),
            Value::Keyword(symbols::Keyword::new("five")),
            Value::NamespacedKeyword(symbols::NamespacedKeyword::new("six", "seven")),
            Value::PlainSymbol(symbols::PlainSymbol::new("eight")),
            Value::NamespacedSymbol(symbols::NamespacedSymbol::new("nine", "ten")),
            Value::Boolean(true))).to_string());
    }

    #[test]
    fn test_ord() {
        // TODO: Check we follow the equality rules at the bottom of https://github.com/edn-format/edn
        assert_eq!(Value::Nil.cmp(&Value::Nil), Ordering::Equal);
        assert_eq!(Value::Boolean(false).cmp(&Value::Boolean(true)), Ordering::Greater);
        assert_eq!(Value::Integer(1).cmp(&Value::Integer(2)), Ordering::Greater);
        assert_eq!(Value::from_bigint("1").cmp(&Value::from_bigint("2")), Ordering::Greater);
        assert_eq!(Value::from(1f64).cmp(&Value::from(2f64)), Ordering::Greater);
        assert_eq!(Value::Text("1".to_string()).cmp(&Value::Text("2".to_string())), Ordering::Greater);
        assert_eq!(Value::from_symbol("a", "b").cmp(&Value::from_symbol("c", "d")), Ordering::Greater);
        assert_eq!(Value::from_symbol(None, "a").cmp(&Value::from_symbol(None, "b")), Ordering::Greater);
        assert_eq!(Value::from_keyword(":a", ":b").cmp(&Value::from_keyword(":c", ":d")), Ordering::Greater);
        assert_eq!(Value::from_keyword(None, ":a").cmp(&Value::from_keyword(None, ":b")), Ordering::Greater);
        assert_eq!(Value::Vector(vec![]).cmp(&Value::Vector(vec![])), Ordering::Equal);
        assert_eq!(Value::List(LinkedList::new()).cmp(&Value::List(LinkedList::new())), Ordering::Equal);
        assert_eq!(Value::Set(BTreeSet::new()).cmp(&Value::Set(BTreeSet::new())), Ordering::Equal);
        assert_eq!(Value::Map(BTreeMap::new()).cmp(&Value::Map(BTreeMap::new())), Ordering::Equal);
    }
}<|endoftext|>


<commit_before>pub mod responses {

    use std::fmt;

    use serde;
    use serde_json as json;

    #[derive(Deserialize, Debug)]
    pub struct AuthResponse {
        pub session: SessionResponse,
    }

    #[derive(Deserialize, Debug, Clone)]
    pub struct SessionResponse {
        pub key: String,
        pub subscriber: i64,
        pub name: String,
    }

    #[derive(Deserialize)]
    pub struct NowPlayingResponseWrapper {
        pub nowplaying: NowPlayingResponse,
    }

    #[derive(Deserialize, Debug)]
    pub struct NowPlayingResponse {
        pub artist: CorrectableString,
        pub album: CorrectableString,
        #[serde(rename="albumArtist")]
        pub album_artist: CorrectableString,
        pub track: CorrectableString,
    }

    #[derive(Deserialize)]
    pub struct ScrobbleResponseWrapper {
        pub scrobbles: Scrobbles,
    }

    #[derive(Deserialize)]
    pub struct Scrobbles {
        pub scrobble: ScrobbleResponse,
    }

    #[derive(Deserialize, Debug)]
    pub struct ScrobbleResponse {
        pub artist: CorrectableString,
        pub album: CorrectableString,
        #[serde(rename="albumArtist")]
        pub album_artist: CorrectableString,
        pub track: CorrectableString,
        pub timestamp: String,
    }

    #[derive(Deserialize, Debug)]
    pub struct CorrectableString {
        #[serde(deserialize_with="CorrectableString::deserialize_corrected_field")]
        pub corrected: bool,
        #[serde(rename="#text", default)]
        pub text: String,
    }

    impl CorrectableString {
        fn deserialize_corrected_field<'de, D>(de: D) -> Result<bool, D::Error>
            where D: serde::Deserializer<'de>
        {
            let deser_result: json::Value = try!(serde::Deserialize::deserialize(de));
            match deser_result {
                json::Value::String(ref s) if &*s == "1" => Ok(true),
                json::Value::String(ref s) if &*s == "0" => Ok(false),
                _ => Err(serde::de::Error::custom("Unexpected value")),
            }
        }
    }

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

}

pub mod metadata {

    use std::collections::HashMap;

    /// Repesents a single track play (aka a "scrobble")
    #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
    pub struct Scrobble {
        artist: String,
        track: String,
        album: String
    }

    impl Scrobble {

        /// Constructs a new Scrobble instance, representing a music track
        /// played in the past.
        pub fn new(artist: String, track: String, album: String) -> Scrobble {
            Scrobble{ artist: artist, track: track, album: album }
        }

        /// Converts the Scrobble metadata (track name, artist & album name)
        /// into a HashMap. Map keys are `"track"`, `"artist"` and `"album"`,
        /// respectively.
        pub fn as_map(&self) -> HashMap<&str, String> {
            let mut params = HashMap::new();
            params.insert("track", self.track.clone());
            params.insert("artist", self.artist.clone());
            params.insert("album", self.album.clone());

            params
        }

    }

}<commit_msg>Add timestamp to Scrobble model (issue #2)<commit_after>pub mod responses {

    use std::fmt;

    use serde;
    use serde_json as json;

    #[derive(Deserialize, Debug)]
    pub struct AuthResponse {
        pub session: SessionResponse,
    }

    #[derive(Deserialize, Debug, Clone)]
    pub struct SessionResponse {
        pub key: String,
        pub subscriber: i64,
        pub name: String,
    }

    #[derive(Deserialize)]
    pub struct NowPlayingResponseWrapper {
        pub nowplaying: NowPlayingResponse,
    }

    #[derive(Deserialize, Debug)]
    pub struct NowPlayingResponse {
        pub artist: CorrectableString,
        pub album: CorrectableString,
        #[serde(rename="albumArtist")]
        pub album_artist: CorrectableString,
        pub track: CorrectableString,
    }

    #[derive(Deserialize)]
    pub struct ScrobbleResponseWrapper {
        pub scrobbles: Scrobbles,
    }

    #[derive(Deserialize)]
    pub struct Scrobbles {
        pub scrobble: ScrobbleResponse,
    }

    #[derive(Deserialize, Debug)]
    pub struct ScrobbleResponse {
        pub artist: CorrectableString,
        pub album: CorrectableString,
        #[serde(rename="albumArtist")]
        pub album_artist: CorrectableString,
        pub track: CorrectableString,
        pub timestamp: String,
    }

    #[derive(Deserialize, Debug)]
    pub struct CorrectableString {
        #[serde(deserialize_with="CorrectableString::deserialize_corrected_field")]
        pub corrected: bool,
        #[serde(rename="#text", default)]
        pub text: String,
    }

    impl CorrectableString {
        fn deserialize_corrected_field<'de, D>(de: D) -> Result<bool, D::Error>
            where D: serde::Deserializer<'de>
        {
            let deser_result: json::Value = try!(serde::Deserialize::deserialize(de));
            match deser_result {
                json::Value::String(ref s) if &*s == "1" => Ok(true),
                json::Value::String(ref s) if &*s == "0" => Ok(false),
                _ => Err(serde::de::Error::custom("Unexpected value")),
            }
        }
    }

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

}

pub mod metadata {

    use std::collections::HashMap;

    /// Repesents a single track play (aka a "scrobble")
    #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
    pub struct Scrobble {
        artist: String,
        track: String,
        album: String,

        timestamp: Option<u64>
    }

    impl Scrobble {

        /// Constructs a new Scrobble instance, representing a music track
        /// played in the past.
        pub fn new(artist: String, track: String, album: String) -> Scrobble {
            Scrobble{ artist: artist, track: track, album: album, timestamp: None }
        }

        pub fn with_timestamp(&mut self, timestamp: u64) -> &mut Scrobble {
            self.timestamp = Some(timestamp);
            self
        }

        /// Converts the Scrobble metadata (track name, artist & album name)
        /// into a HashMap. Map keys are `"track"`, `"artist"` and `"album"`,
        /// respectively.
        pub fn as_map(&self) -> HashMap<&str, String> {
            let mut params = HashMap::new();
            params.insert("track", self.track.clone());
            params.insert("artist", self.artist.clone());
            params.insert("album", self.album.clone());

            if let Some(timestamp) = self.timestamp {
                params.insert("timestamp", timestamp.to_string());
            }

            params
        }

    }

}<|endoftext|>


<commit_before>use cudnn::{Cudnn, Tensor};
use cublas::{Cublas};
use cudart::{Memory};

pub struct Nn {
    pub cudnn: Cudnn,
    pub cublas: Cublas
}

impl Nn {
    pub fn new() -> Result<Nn, &'static str> {
        let cudnn = try!(Cudnn::new());
        let cublas = try!(Cublas::new());

        Ok(Nn{ cudnn: cudnn, cublas: cublas })
    }

    pub fn fcn_forward(&self,
                       m: usize,
                       n: usize,
                       src: &Memory<f32>,
                       dst: &mut Memory<f32>,
                       params: &Memory<f32>)
                       -> Result<(), &'static str> {
        self.cublas.s_gemv(m as i32,
                           n as i32,
                           params,
                           src,
                           dst)
    }
}
<commit_msg>implemented backward - fcn<commit_after>use cudnn::{Cudnn, Tensor};
use cublas::{Cublas};
use cudart::{Memory};

pub struct Nn {
    pub cudnn: Cudnn,
    pub cublas: Cublas
}

impl Nn {
    pub fn new() -> Result<Nn, &'static str> {
        let cudnn = try!(Cudnn::new());
        let cublas = try!(Cublas::new());

        Ok(Nn{ cudnn: cudnn, cublas: cublas })
    }

    pub fn fcn_forward(&self,
                       m: usize,
                       n: usize,
                       src: &Memory<f32>,
                       dst: &mut Memory<f32>,
                       params: &Memory<f32>)
                       -> Result<(), &'static str> {
        self.cublas.s_gemv(m as i32,
                           n as i32,
                           params,
                           src,
                           dst)
    }

    pub fn fcn_backward(&self,
                        scale: f32,
                        m: usize,
                        n: usize,
                        x: &Memory<f32>,
                        dy: &Memory<f32>,
                        params: &mut Memory<f32>)
                        -> Result<(), &'static str> {
        self.cublas.s_ger(m as i32,
                          n as i32,
                          scale,
                          x,
                          dy,
                          params)
    }
}
<|endoftext|>


<commit_before>use ffi::types::hid_t;
use ffi::h5i::{H5I_type_t, H5Iget_type, H5Iis_valid, H5Iinc_ref, H5Idec_ref, H5Iget_ref,
               H5I_INVALID_HID};
use ffi::h5i::H5I_type_t::*;

use std::collections::HashMap;
use std::sync::{Arc, Mutex, RwLock};

fn get_id_type(id: hid_t) -> H5I_type_t {
    let tp = h5lock!(H5Iget_type(id));
    let valid = id > 0 && tp > H5I_BADID && tp < H5I_NTYPES;
    if valid { tp } else { H5I_BADID }
}

fn is_valid_id(id: hid_t) -> bool {
    let tp = get_id_type(id);
    tp > H5I_BADID && tp < H5I_NTYPES
}

fn is_valid_user_id(id: hid_t) -> bool {
    h5lock!(H5Iis_valid(id)) == 1
}

pub struct Handle {
    id: Arc<RwLock<hid_t>>,
}

impl Handle {
    pub fn new(id: hid_t) -> Handle {
        lazy_static! {
            static ref REGISTRY: Registry = Registry::new();
        }
        Handle {
            // if the id is not registered with the library, do not share it
            id: match is_valid_user_id(id) {
                false => Arc::new(RwLock::new(id)),
                true  => REGISTRY.new_handle(id),
            }
        }
    }

    pub fn id(&self) -> hid_t {
        *self.id.read().unwrap()
    }

    pub fn invalidate(&self) {
        *self.id.write().unwrap() = H5I_INVALID_HID;
    }

    fn incref(&self) {
        if self.is_valid() {
            h5lock!(H5Iinc_ref(self.id()));
        }
    }

    fn decref(&self) {
        if self.is_valid() {
            h5lock!(H5Idec_ref(self.id()));
        }
        // must invalidate all linked IDs because the library reuses them internally
        if !self.is_valid() && !is_valid_id(self.id()) {
            self.invalidate();
        }
    }
}

impl Clone for Handle {
    fn clone(&self) -> Handle {
        self.incref();
        Handle::new(self.id())
    }
}

impl Drop for Handle {
    fn drop(&mut self) {
        self.decref();
    }
}

struct Registry {
    registry: Mutex<HashMap<hid_t, Arc<RwLock<hid_t>>>>,
}

impl Registry {
    pub fn new() -> Registry {
        Registry { registry: Mutex::new(HashMap::new()) }
    }

    pub fn new_handle(&self, id: hid_t) -> Arc<RwLock<hid_t>> {
        let mut registry = self.registry.lock().unwrap();
        let handle = registry.entry(id).or_insert(Arc::new(RwLock::new(id)));
        if *handle.read().unwrap() != id {
            // an id may be left dangling by previous invalidation of a linked handle
            *handle = Arc::new(RwLock::new(id));
        }
        handle.clone()
    }
}

pub trait Object {
    fn id(&self) -> hid_t;

    /// Returns reference count if the handle is valid, 0 otherwise.
    fn refcount(&self) -> u32 {
        if self.is_valid() {
            match h5call!(H5Iget_ref(self.id())) {
                Ok(count) if count >= 0 => count as u32,
                _                       => 0,
            }
        } else {
            0
        }
    }

    fn is_valid(&self) -> bool {
        is_valid_user_id(self.id())
    }

    fn id_type(&self) -> H5I_type_t {
        get_id_type(self.id())
    }

    fn is_file(&self) -> bool          { self.id_type() == H5I_FILE }
    fn is_group(&self) -> bool         { self.id_type() == H5I_GROUP }
    fn is_datatype(&self) -> bool      { self.id_type() == H5I_DATATYPE }
    fn is_dataspace(&self) -> bool     { self.id_type() == H5I_DATASPACE }
    fn is_dataset(&self) -> bool       { self.id_type() == H5I_DATASET }
    fn is_attribute(&self) -> bool     { self.id_type() == H5I_ATTR }
    fn is_reference(&self) -> bool     { self.id_type() == H5I_REFERENCE }
    fn is_vfl(&self) -> bool           { self.id_type() == H5I_VFL }
    fn is_plist_class(&self) -> bool   { self.id_type() == H5I_GENPROP_CLS }
    fn is_plist(&self) -> bool         { self.id_type() == H5I_GENPROP_LST }
    fn is_error_class(&self) -> bool   { self.id_type() == H5I_ERROR_CLASS }
    fn is_error_message(&self) -> bool { self.id_type() == H5I_ERROR_MSG }
    fn is_error_stack(&self) -> bool   { self.id_type() == H5I_ERROR_STACK }
}

impl Object for Handle {
    fn id(&self) -> hid_t {
        self.id()
    }
}

#[test]
fn test_handle() {
    use ffi::h5p::{H5P_ROOT, H5P_FILE_ACCESS, H5Pcreate};
    use ffi::h5i::H5I_INVALID_HID;

    #[derive(Clone)]
    struct TestObject {
        handle: Handle,
    }

    impl TestObject {
        fn new(id: hid_t) -> TestObject {
            TestObject { handle: Handle::new(id) }
        }

        fn incref(&self) {
            self.handle.incref()
        }

        fn decref(&self) {
            self.handle.decref()
        }
    }

    impl Object for TestObject {
        fn id(&self) -> hid_t {
            self.handle.id()
        }
    }

    // invalid id
    let mut obj = TestObject::new(H5I_INVALID_HID);
    assert_eq!(obj.id(), H5I_INVALID_HID);
    assert!(!obj.is_valid());
    assert!(!is_valid_id(obj.id()));
    assert!(!is_valid_user_id(obj.id()));
    assert_eq!(obj.id_type(), H5I_BADID);
    assert_eq!(obj.refcount(), 0);

    // existing generic id
    obj = TestObject::new(*H5P_ROOT);
    assert_eq!(obj.id(), *H5P_ROOT);
    assert!(is_valid_id(obj.id()));
    assert!(!is_valid_user_id(obj.id()));
    assert!(!obj.is_valid());
    assert!(obj.is_plist_class());
    assert_eq!(obj.refcount(), 0);
    obj.decref();
    assert!(is_valid_id(obj.id()));

    // new user id
    obj = TestObject::new(h5call!(H5Pcreate(*H5P_FILE_ACCESS)).unwrap());
    assert!(obj.id() > 0);
    assert!(obj.is_valid());
    assert!(is_valid_id(obj.id()));
    assert!(is_valid_user_id(obj.id()));

    assert!(!obj.is_file());
    assert!(!obj.is_group());
    assert!(!obj.is_datatype());
    assert!(!obj.is_dataspace());
    assert!(!obj.is_dataset());
    assert!(!obj.is_attribute());
    assert!(!obj.is_reference());
    assert!(!obj.is_vfl());
    assert!(!obj.is_plist_class());
    assert!(obj.is_plist());
    assert!(!obj.is_error_class());
    assert!(!obj.is_error_message());
    assert!(!obj.is_error_stack());

    assert_eq!(obj.refcount(), 1);
    obj.incref();
    assert_eq!(obj.refcount(), 2);
    obj.decref();
    assert_eq!(obj.refcount(), 1);
    obj.decref();
    obj.decref();
    assert_eq!(obj.refcount(), 0);
    assert!(!obj.is_valid());
    assert!(!is_valid_user_id(obj.id()));
    assert!(!is_valid_id(obj.id()));

    // cloning and dropping
    obj = TestObject::new(h5call!(H5Pcreate(*H5P_FILE_ACCESS)).unwrap());
    let obj_id = obj.id();
    obj = TestObject::new(h5call!(H5Pcreate(*H5P_FILE_ACCESS)).unwrap());
    assert!(!is_valid_id(obj_id));
    assert!(!is_valid_user_id(obj_id));
    assert!(obj.id() > 0);
    assert!(obj.is_valid());
    assert!(is_valid_id(obj.id()));
    assert!(is_valid_user_id(obj.id()));
    assert_eq!(obj.refcount(), 1);
    let mut obj2 = obj.clone();
    assert_eq!(obj.refcount(), 2);
    assert_eq!(obj2.refcount(), 2);
    drop(obj2);
    assert!(obj.is_valid());
    assert_eq!(obj.refcount(), 1);
    obj2 = obj.clone();
    obj.decref();
    obj.decref();
    assert_eq!(obj.id(), H5I_INVALID_HID);
    assert_eq!(obj2.id(), H5I_INVALID_HID);
}
<commit_msg>Add Object::from_id trait method<commit_after>use ffi::types::hid_t;
use ffi::h5i::{H5I_type_t, H5Iget_type, H5Iis_valid, H5Iinc_ref, H5Idec_ref, H5Iget_ref,
               H5I_INVALID_HID};
use ffi::h5i::H5I_type_t::*;

use std::collections::HashMap;
use std::sync::{Arc, Mutex, RwLock};

fn get_id_type(id: hid_t) -> H5I_type_t {
    let tp = h5lock!(H5Iget_type(id));
    let valid = id > 0 && tp > H5I_BADID && tp < H5I_NTYPES;
    if valid { tp } else { H5I_BADID }
}

fn is_valid_id(id: hid_t) -> bool {
    let tp = get_id_type(id);
    tp > H5I_BADID && tp < H5I_NTYPES
}

fn is_valid_user_id(id: hid_t) -> bool {
    h5lock!(H5Iis_valid(id)) == 1
}

pub struct Handle {
    id: Arc<RwLock<hid_t>>,
}

impl Handle {
    pub fn new(id: hid_t) -> Handle {
        lazy_static! {
            static ref REGISTRY: Registry = Registry::new();
        }
        Handle {
            // if the id is not registered with the library, do not share it
            id: match is_valid_user_id(id) {
                false => Arc::new(RwLock::new(id)),
                true  => REGISTRY.new_handle(id),
            }
        }
    }

    pub fn id(&self) -> hid_t {
        *self.id.read().unwrap()
    }

    pub fn invalidate(&self) {
        *self.id.write().unwrap() = H5I_INVALID_HID;
    }

    fn incref(&self) {
        if self.is_valid() {
            h5lock!(H5Iinc_ref(self.id()));
        }
    }

    fn decref(&self) {
        if self.is_valid() {
            h5lock!(H5Idec_ref(self.id()));
        }
        // must invalidate all linked IDs because the library reuses them internally
        if !self.is_valid() && !is_valid_id(self.id()) {
            self.invalidate();
        }
    }
}

impl Clone for Handle {
    fn clone(&self) -> Handle {
        self.incref();
        Handle::new(self.id())
    }
}

impl Drop for Handle {
    fn drop(&mut self) {
        self.decref();
    }
}

struct Registry {
    registry: Mutex<HashMap<hid_t, Arc<RwLock<hid_t>>>>,
}

impl Registry {
    pub fn new() -> Registry {
        Registry { registry: Mutex::new(HashMap::new()) }
    }

    pub fn new_handle(&self, id: hid_t) -> Arc<RwLock<hid_t>> {
        let mut registry = self.registry.lock().unwrap();
        let handle = registry.entry(id).or_insert(Arc::new(RwLock::new(id)));
        if *handle.read().unwrap() != id {
            // an id may be left dangling by previous invalidation of a linked handle
            *handle = Arc::new(RwLock::new(id));
        }
        handle.clone()
    }
}

pub trait Object {
    fn id(&self) -> hid_t;
    fn from_id(id: hid_t) -> Self;

    /// Returns reference count if the handle is valid, 0 otherwise.
    fn refcount(&self) -> u32 {
        if self.is_valid() {
            match h5call!(H5Iget_ref(self.id())) {
                Ok(count) if count >= 0 => count as u32,
                _                       => 0,
            }
        } else {
            0
        }
    }

    fn is_valid(&self) -> bool {
        is_valid_user_id(self.id())
    }

    fn id_type(&self) -> H5I_type_t {
        get_id_type(self.id())
    }

    fn is_file(&self) -> bool          { self.id_type() == H5I_FILE }
    fn is_group(&self) -> bool         { self.id_type() == H5I_GROUP }
    fn is_datatype(&self) -> bool      { self.id_type() == H5I_DATATYPE }
    fn is_dataspace(&self) -> bool     { self.id_type() == H5I_DATASPACE }
    fn is_dataset(&self) -> bool       { self.id_type() == H5I_DATASET }
    fn is_attribute(&self) -> bool     { self.id_type() == H5I_ATTR }
    fn is_reference(&self) -> bool     { self.id_type() == H5I_REFERENCE }
    fn is_vfl(&self) -> bool           { self.id_type() == H5I_VFL }
    fn is_plist_class(&self) -> bool   { self.id_type() == H5I_GENPROP_CLS }
    fn is_plist(&self) -> bool         { self.id_type() == H5I_GENPROP_LST }
    fn is_error_class(&self) -> bool   { self.id_type() == H5I_ERROR_CLASS }
    fn is_error_message(&self) -> bool { self.id_type() == H5I_ERROR_MSG }
    fn is_error_stack(&self) -> bool   { self.id_type() == H5I_ERROR_STACK }
}

impl Object for Handle {
    fn id(&self) -> hid_t {
        self.id()
    }

    fn from_id(id: hid_t) -> Handle {
        Handle::new(id)
    }
}

#[test]
fn test_handle() {
    use ffi::h5p::{H5P_ROOT, H5P_FILE_ACCESS, H5Pcreate};
    use ffi::h5i::H5I_INVALID_HID;

    #[derive(Clone)]
    struct TestObject {
        handle: Handle,
    }

    impl TestObject {
        fn incref(&self) {
            self.handle.incref()
        }

        fn decref(&self) {
            self.handle.decref()
        }
    }

    impl Object for TestObject {
        fn id(&self) -> hid_t {
            self.handle.id()
        }

        fn from_id(id: hid_t) -> TestObject {
            TestObject { handle: Handle::new(id) }
        }
    }

    // invalid id
    let mut obj = TestObject::from_id(H5I_INVALID_HID);
    assert_eq!(obj.id(), H5I_INVALID_HID);
    assert!(!obj.is_valid());
    assert!(!is_valid_id(obj.id()));
    assert!(!is_valid_user_id(obj.id()));
    assert_eq!(obj.id_type(), H5I_BADID);
    assert_eq!(obj.refcount(), 0);

    // existing generic id
    obj = TestObject::from_id(*H5P_ROOT);
    assert_eq!(obj.id(), *H5P_ROOT);
    assert!(is_valid_id(obj.id()));
    assert!(!is_valid_user_id(obj.id()));
    assert!(!obj.is_valid());
    assert!(obj.is_plist_class());
    assert_eq!(obj.refcount(), 0);
    obj.decref();
    assert!(is_valid_id(obj.id()));

    // new user id
    obj = TestObject::from_id(h5call!(H5Pcreate(*H5P_FILE_ACCESS)).unwrap());
    assert!(obj.id() > 0);
    assert!(obj.is_valid());
    assert!(is_valid_id(obj.id()));
    assert!(is_valid_user_id(obj.id()));

    assert!(!obj.is_file());
    assert!(!obj.is_group());
    assert!(!obj.is_datatype());
    assert!(!obj.is_dataspace());
    assert!(!obj.is_dataset());
    assert!(!obj.is_attribute());
    assert!(!obj.is_reference());
    assert!(!obj.is_vfl());
    assert!(!obj.is_plist_class());
    assert!(obj.is_plist());
    assert!(!obj.is_error_class());
    assert!(!obj.is_error_message());
    assert!(!obj.is_error_stack());

    assert_eq!(obj.refcount(), 1);
    obj.incref();
    assert_eq!(obj.refcount(), 2);
    obj.decref();
    assert_eq!(obj.refcount(), 1);
    obj.decref();
    obj.decref();
    assert_eq!(obj.refcount(), 0);
    assert!(!obj.is_valid());
    assert!(!is_valid_user_id(obj.id()));
    assert!(!is_valid_id(obj.id()));

    // cloning and dropping
    obj = TestObject::from_id(h5call!(H5Pcreate(*H5P_FILE_ACCESS)).unwrap());
    let obj_id = obj.id();
    obj = TestObject::from_id(h5call!(H5Pcreate(*H5P_FILE_ACCESS)).unwrap());
    assert!(!is_valid_id(obj_id));
    assert!(!is_valid_user_id(obj_id));
    assert!(obj.id() > 0);
    assert!(obj.is_valid());
    assert!(is_valid_id(obj.id()));
    assert!(is_valid_user_id(obj.id()));
    assert_eq!(obj.refcount(), 1);
    let mut obj2 = obj.clone();
    assert_eq!(obj.refcount(), 2);
    assert_eq!(obj2.refcount(), 2);
    drop(obj2);
    assert!(obj.is_valid());
    assert_eq!(obj.refcount(), 1);
    obj2 = obj.clone();
    obj.decref();
    obj.decref();
    assert_eq!(obj.id(), H5I_INVALID_HID);
    assert_eq!(obj2.id(), H5I_INVALID_HID);
}
<|endoftext|>


<commit_before>use cpu::Cpu;

pub enum Opcode {
    Nop,
}

impl Opcode {
	pub fn execute(&self, cpu: &mut Cpu, byte1: i8, byte2: i8, byte3: i8) {
	    match *self {
		    Nop => {},
		}
	}
}<commit_msg>Opcode enum done<commit_after>use cpu::Cpu;

pub enum Opcode {
    Nop = 0,
	Cls,
	Vblnk,
	Bgc,
	Spr,
	Drw,
	Drw2,
	Rnd,
	Flip,
	Snd0,
	Snd1,
	Snd2,
	Snd3,
	Snp,
	Sng,
	Jmp = 0x10,
	Jx = 0x12,
	Jme,
	Call,
	Ret,
	Jmp2,
	Cx,
	Call2,
	Ldi = 0x20,
	Ldi2,
	Ldm,
	Ldm2,
	Mov,
	Stm = 0x30,
	Stm2,
	Addi = 0x40,
	Add,
	Add2,
	Subi = 0x50,
	Sub,
	Sub2,
	Cmpi,
	Cmp,
	Andi = 0x60,
	And,
	Tsti,
	Tst,
	Ori = 0x70,
	Or,
	Or2,
	Xori = 0x80,
	Xor,
	Xor2,
	Muli = 0x90,
	Mul,
	Mul2,
	Divi = 0xA0,
	Div,
	Div2,
	Modi,
	Mod,
	Mod2,
	Remi,
	Rem,
	Rem2,
	Shl = 0xB0,
	Shr,
	Sar,
	Shl2,
	Shr2,
	Sar2,
	Push = 0xC0,
	Pop,
	Pushall,
	Popall,
	Pushf,
	Popf,
	Pal = 0xD0,
	Pal2,
	Noti = 0xE0,
	Not,
	Not2,
	Negi,
	Neg,
	Neg2,
}

impl Opcode {
	pub fn execute(&self, cpu: &mut Cpu, byte1: i8, byte2: i8, byte3: i8) {
	    match *self {
		    Nop => {},
			_ => fail!("Yeah"),
		}
	}
}<|endoftext|>


<commit_before>extern crate bf_lib;

use bf_lib::traits::*;
use bf_lib::bf_lexer::BFLexer;
use bf_lib::bf_vm::BFVM;
use std::process;

use std::fs::File;
use std::io::prelude::*;

#[derive(Debug)]
enum ArgumentMode {
    Skip,
    Start,
    Str,
    File,
}

fn read_file(in_str : String, mut out_str : &mut String ) {
    let mut file = File::open(in_str).expect("Unable to open file.");
    file.read_to_string(&mut out_str).expect("Unable to read file.");
}

fn print_help() {
    println!("
Rustfuck

Usage:
    bf-cli <file>
    bf-cli ( -f | --file ) <file>
    bf-cli ( -s | --str ) <bfstring>

Options:
    -h --help   Shows this screen.
");
}

fn main() {
    /* ---------------------------------------------------.
    |     Load Arguments                                  |
    '---------------------------------------------------- */
    let mut mode = ArgumentMode::Skip;
    let mut input = String::new();
    for argument in std::env::args() {
        match mode {
            ArgumentMode::Skip => mode = ArgumentMode::Start,
            ArgumentMode::Start => {
                match argument.as_ref() {
                    "-s" | "--str" => mode = ArgumentMode::Str,
                    "-f" | "--file" => mode = ArgumentMode::File,
                    "-h" | "--help" => {
                        print_help();
                        process::exit(1);
                    }
                    _ => read_file(argument, &mut input)
                };
            },
            ArgumentMode::Str => input = argument,
            ArgumentMode::File => read_file(argument, &mut input)
        }
    }

    /* ---------------------------------------------------.
    |    Interpret and Run Input                          |
    '---------------------------------------------------- */
    let tokens = BFLexer::parse(String::from(input));
    let mut bfvm = BFVM::new();

    let result = match tokens {
        LexResult::Success(t) => bfvm.run(t),
        _ =>  {
            println!("Error !");
            VMResult::Error { message : String::from("Uh oh") }
        }
    };
    println!();

    /* ---------------------------------------------------.
    |    Output Result                                    |
    '---------------------------------------------------- */
    let return_code = if result == VMResult::Success { 0 } else { 1 };
    process::exit(return_code);
}
<commit_msg>Updated help string<commit_after>extern crate bf_lib;

use bf_lib::traits::*;
use bf_lib::bf_lexer::BFLexer;
use bf_lib::bf_vm::BFVM;
use std::process;

use std::fs::File;
use std::io::prelude::*;

#[derive(Debug)]
enum ArgumentMode {
    Skip,
    Start,
    Str,
    File,
}

fn read_file(in_str : String, mut out_str : &mut String ) {
    let mut file = File::open(in_str).expect("Unable to open file.");
    file.read_to_string(&mut out_str).expect("Unable to read file.");
}

fn print_help() {
    println!("
Rust BrainFuck Interpreter

Usage:
    bf-cli <file>
    bf-cli ( -f | --file ) <file>
    bf-cli ( -s | --str ) <bfstring>

Options:
    -h --help   Shows this screen.
");
}

fn main() {
    /* ---------------------------------------------------.
    |     Load Arguments                                  |
    '---------------------------------------------------- */
    let mut mode = ArgumentMode::Skip;
    let mut input = String::new();
    for argument in std::env::args() {
        match mode {
            ArgumentMode::Skip => mode = ArgumentMode::Start,
            ArgumentMode::Start => {
                match argument.as_ref() {
                    "-s" | "--str" => mode = ArgumentMode::Str,
                    "-f" | "--file" => mode = ArgumentMode::File,
                    "-h" | "--help" => {
                        print_help();
                        process::exit(1);
                    }
                    _ => read_file(argument, &mut input)
                };
            },
            ArgumentMode::Str => input = argument,
            ArgumentMode::File => read_file(argument, &mut input)
        }
    }

    /* ---------------------------------------------------.
    |    Interpret and Run Input                          |
    '---------------------------------------------------- */
    let tokens = BFLexer::parse(String::from(input));
    let mut bfvm = BFVM::new();

    let result = match tokens {
        LexResult::Success(t) => bfvm.run(t),
        _ =>  {
            println!("Error !");
            VMResult::Error { message : String::from("Uh oh") }
        }
    };
    println!();

    /* ---------------------------------------------------.
    |    Output Result                                    |
    '---------------------------------------------------- */
    let return_code = if result == VMResult::Success { 0 } else { 1 };
    process::exit(return_code);
}
<|endoftext|>


<commit_before>//! XML-RPC response parser.

use {Value, Response, Fault};
use error::ParseError;

use base64;
use xml::reader::{XmlEvent, EventReader};
use xml::name::OwnedName;
use xml::common::Position;
use xml::ParserConfig;
use iso8601::datetime;
use std::io::{self, ErrorKind, Read};
use std::collections::BTreeMap;

pub type ParseResult<T> = Result<T, ParseError>;

pub struct Parser<'a, R: Read + 'a> {
    reader: EventReader<&'a mut R>,
}

impl<'a, R: Read> Parser<'a, R> {
    pub fn new(reader: &'a mut R) -> Self {
        Parser {
            reader: EventReader::new_with_config(reader, ParserConfig {
                cdata_to_characters: true,
                ..Default::default()
            }),
        }
    }

    /// Reads an `XmlEvent` from a reader, disposing events we want to ignore.
    fn pull_event(&mut self) -> ParseResult<XmlEvent> {
        loop {
            let event = try!(self.reader.next());
            match event {
                XmlEvent::StartDocument { .. }
                | XmlEvent::Comment(_)
                | XmlEvent::Whitespace(_)
                | XmlEvent::ProcessingInstruction { .. } => {},
                XmlEvent::StartElement { .. }
                | XmlEvent::EndElement { .. }
                | XmlEvent::EndDocument
                | XmlEvent::CData(_)
                | XmlEvent::Characters(_) => {
                    return Ok(event);
                }
            }
        }
    }

    /// Expects an opening tag like `<tag>` without attributes (and a local name without namespaces).
    fn expect_open(&mut self, tag: &str) -> ParseResult<()> {
        match try!(self.pull_event()) {
            XmlEvent::StartElement { ref name, ref attributes, .. }
            if name == &OwnedName::local(tag) => {
                if !attributes.is_empty() {
                    return self.unexpected(format!("unexpected attributes in <{}>", tag));
                }

                Ok(())
            }
            _ => return self.unexpected(format!("expected <{}>", tag)),
        }
    }

    /// Expects a closing tag like `</tag>` with a local name without namespaces.
    fn expect_close(&mut self, tag: &str) -> ParseResult<()> {
        match try!(self.pull_event()) {
            XmlEvent::EndElement { ref name } if name == &OwnedName::local(tag) => {
                Ok(())
            }
            _ => self.unexpected(format!("expected </{}>", tag)),
        }
    }

    /// Builds and returns an `Err(UnexpectedXml)`.
    fn unexpected<T, E: ToString>(&self, expected: E) -> ParseResult<T> {
        let expected = expected.to_string();
        let position = self.reader.position();

        Err(ParseError::UnexpectedXml {
            expected: expected,
            position: position,
        })
    }

    fn parse_response(&mut self) -> ParseResult<Response> {
        let response: Response;

        // <methodResponse>
        try!(self.expect_open("methodResponse"));

        // <fault> / <params>
        match try!(self.pull_event()) {
            XmlEvent::StartElement { ref name, ref attributes, .. } => {
                if !attributes.is_empty() {
                    return self.unexpected("unexpected attributes");
                }

                if name == &OwnedName::local("fault") {
                    let value = try!(self.parse_value());
                    let fault = try!(Fault::from_value(&value).ok_or_else(|| {
                        io::Error::new(ErrorKind::Other, "malformed <fault>")
                    }));
                    response = Err(fault);
                } else if name == &OwnedName::local("params") {
                    // <param>
                    try!(self.expect_open("param"));

                    let value = try!(self.parse_value());
                    response = Ok(value);

                    // </param>
                    try!(self.expect_close("param"));
                } else {
                    return self.unexpected(format!("expected <fault> or <params>, got {}", name));
                }
            }
            _ => return self.unexpected("expected <fault> or <params>"),
        }

        Ok(response)
    }

    pub fn parse_value(&mut self) -> ParseResult<Value> {
        // <value>
        try!(self.expect_open("value"));

        let value = try!(self.parse_value_inner());

        // </value>
        try!(self.expect_close("value"));

        Ok(value)
    }

    fn parse_value_inner(&mut self) -> ParseResult<Value> {
        let value: Value;

        // Raw string or specific type tag
        value = match try!(self.pull_event()) {
            XmlEvent::StartElement { ref name, ref attributes, .. } => {
                if !attributes.is_empty() {
                    return self.unexpected(format!("unexpected attributes in <{}>", name));
                }

                if name == &OwnedName::local("struct") {
                    let mut members = BTreeMap::new();
                    loop {
                        match try!(self.pull_event()) {
                            XmlEvent::EndElement { ref name } if name == &OwnedName::local("struct") => break,
                            XmlEvent::StartElement { ref name, ref attributes, .. } if name == &OwnedName::local("member") => {
                                // <member>
                                if !attributes.is_empty() {
                                    return self.unexpected(format!("unexpected attributes in <{}>", name));
                                }

                                // <name>NAME</name>
                                try!(self.expect_open("name"));
                                let name = match try!(self.pull_event()) {
                                    XmlEvent::Characters(string) => string,
                                    _ => return self.unexpected("expected CDATA"),
                                };
                                try!(self.expect_close("name"));

                                // Value
                                let value = try!(self.parse_value());

                                // </member>
                                try!(self.expect_close("member"));

                                members.insert(name, value);
                            }
                            _ => return self.unexpected("expected </struct> or <member>"),
                        }
                    }

                    Value::Struct(members)
                } else if name == &OwnedName::local("array") {
                    let mut elements: Vec<Value> = Vec::new();
                    try!(self.expect_open("data"));
                    loop {
                        match try!(self.pull_event()) {
                            XmlEvent::EndElement { ref name } if name == &OwnedName::local("data") => break,
                            XmlEvent::StartElement { ref name, .. } if name == &OwnedName::local("value") => {
                                elements.push(try!(self.parse_value_inner()));
                                try!(self.expect_close("value"));
                            }
                            _event => return self.unexpected("expected </data> or <value>")
                        }
                    }
                    try!(self.expect_close("array"));
                    Value::Array(elements)
                } else if name == &OwnedName::local("nil") {
                    try!(self.expect_close("nil"));
                    Value::Nil
                } else {
                    // All other types expect raw characters...
                    let data = match try!(self.pull_event()) {
                        XmlEvent::Characters(string) => string,
                        _ => return self.unexpected("expected characters"),
                    };

                    // ...and a corresponding close tag
                    try!(self.expect_close(&name.local_name));

                    if name == &OwnedName::local("i4") || name == &OwnedName::local("int") {
                        Value::Int(try!(data.parse::<i32>().map_err(|_| {
                            io::Error::new(ErrorKind::Other, format!("invalid value for integer: {}", data))
                        })))
                    } else if name == &OwnedName::local("i8") {
                        Value::Int64(try!(data.parse::<i64>().map_err(|_| {
                            io::Error::new(ErrorKind::Other, format!("invalid value for 64-bit integer: {}", data))
                        })))
                    } else if name == &OwnedName::local("boolean") {
                        let val = match data.trim() {
                            "0" => false,
                            "1" => true,
                            _ => return Err(io::Error::new(ErrorKind::Other, format!("invalid value for <boolean>: {}", data)).into())
                        };

                        Value::Bool(val)
                    } else if name == &OwnedName::local("string") {
                        Value::String(data.clone())
                    } else if name == &OwnedName::local("double") {
                        Value::Double(try!(data.parse::<f64>().map_err(|_| {
                            io::Error::new(ErrorKind::Other, format!("invalid value for double: {}", data))
                        })))
                    } else if name == &OwnedName::local("dateTime.iso8601") {
                        Value::DateTime(try!(datetime(&data).map_err(|e| {
                            io::Error::new(ErrorKind::Other, format!("invalid value for dateTime.iso8601: {} ({})", data, e))
                        })))
                    } else if name == &OwnedName::local("base64") {
                        Value::Base64(try!(base64::decode(&data).map_err(|_| {
                            io::Error::new(ErrorKind::Other, format!("invalid value for base64: {}", data))
                        })))
                    } else {
                        return self.unexpected("invalid <value> content");
                    }
                }
            }
            XmlEvent::Characters(string) => {
                Value::String(string)
            }
            _ => return self.unexpected("invalid <value> content"),
        };

        Ok(value)
    }
}

/// Parses a response from an XML reader.
pub fn parse_response<R: Read>(reader: &mut R) -> ParseResult<Response> {
    Parser::new(reader).parse_response()
}

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

    use {Response, Value};
    use error::Fault;
    use std::fmt::Debug;

    fn read_response(xml: &str) -> ParseResult<Response> {
        parse_response(&mut xml.as_bytes())
    }

    fn read_value(xml: &str) -> ParseResult<Value> {
        Parser::new(&mut xml.as_bytes()).parse_value()
    }

    fn assert_ok<T: Debug, E: Debug>(result: Result<T, E>) {
        match result {
            Ok(t) => println!("assert_ok successful on Ok: {:?}", t),
            Err(e) => panic!("assert_ok called on Err value: {:?}", e),
        }
    }

    fn assert_err<T: Debug, E: Debug>(result: Result<T, E>) {
        match result {
            Ok(t) => panic!("assert_err called on Ok value: {:?}", t),
            Err(e) => println!("assert_err successful on Err: {:?}", e),
        }
    }

    #[test]
    fn parses_fault() {
        assert_eq!(read_response(r##"
<?xml version="1.0"?>
<methodResponse>
   <fault>
      <value>
         <struct>
            <member>
               <name>faultCode</name>
               <value><int>4</int></value>
               </member>
            <member>
               <name>faultString</name>
               <value><string>Too many parameters.</string></value>
               </member>
            </struct>
         </value>
      </fault>
   </methodResponse>"##),
        Ok(Err(Fault {
            fault_code: 4,
            fault_string: "Too many parameters.".into(),
        })));
    }

    #[test]
    fn ignores_additional_fault_fields() {
        assert_eq!(read_response(r##"
<?xml version="1.0"?>
<methodResponse>
   <fault>
      <value>
         <struct>
            <member>
               <name>faultCode</name>
               <value><int>4</int></value>
               </member>
            <member>
               <name>faultString</name>
               <value><string>Too many parameters.</string></value>
               </member>
            <member>
               <name>unnecessaryParameter</name>
               <value><string>Too many parameters.</string></value>
               </member>
            </struct>
         </value>
      </fault>
   </methodResponse>"##),
        Ok(Err(Fault {
            fault_code: 4,
            fault_string: "Too many parameters.".into(),
        })));
    }

    #[test]
    fn rejects_invalid_faults() {
        // Make sure to reject type errors in <fault>s - They're specified to contain specifically
        // typed fields.
        assert!(read_response(r##"
<?xml version="1.0"?>
<methodResponse>
   <fault>
      <value>
         <struct>
            <member>
               <name>faultCode</name>
               <value><string>I'm not an int!</string></value>
               </member>
            <member>
               <name>faultString</name>
               <value><string>Too many parameters.</string></value>
               </member>
            </struct>
         </value>
      </fault>
   </methodResponse>"##).is_err());
    }

    #[test]
    fn parses_string_value_with_whitespace() {
        assert_eq!(read_value("<value><string>  I'm a string!  </string></value>"),
            Ok(Value::String("  I'm a string!  ".into())));
    }

    #[test]
    fn parses_64bit_int() {
        assert_eq!(read_value("<value><i8>12345</i8></value>"),
            Ok(Value::Int64(12345)));
        assert_eq!(read_value("<value><i8>-100100100100</i8></value>"),
            Ok(Value::Int64(-100100100100)));
    }

    #[test]
    fn parses_date_values() {
        assert_ok(read_value("<value><dateTime.iso8601>2015-02-18T23:16:09Z</dateTime.iso8601></value>"));
        assert_ok(read_value("<value><dateTime.iso8601>19980717T14:08:55</dateTime.iso8601></value>"));
    }

    #[test]
    fn parses_array_values() {
      assert_eq!(read_value("<value><array><data><value><i4>5</i4></value><value><string>a</string></value></data></array></value>"), Ok(Value::Array(vec![Value::Int(5), Value::String("a".into())])));
    }

    #[test]
    fn parses_raw_value_as_string() {
        assert_eq!(read_value("<value>\t  I'm a string!  </value>"),
            Ok(Value::String("\t  I'm a string!  ".into())));
    }

    #[test]
    fn parses_nil_values() {
        assert_eq!(read_value("<value><nil/></value>"), Ok(Value::Nil));
        assert_eq!(read_value("<value><nil></nil></value>"), Ok(Value::Nil));
    }

    #[test]
    fn unescapes_values() {
        assert_eq!(read_value("<value><string>abc<abc&abc</string></value>"),
            Ok(Value::String("abc<abc&abc".into())));
    }

    #[test]
    fn rejects_value_with_attributes() {
        // XXX we *should* reject everything with attributes
        assert_err(read_value(r#"<value name="ble">\t  I'm a string!  </value>"#));
    }
}
<commit_msg>Format test<commit_after>//! XML-RPC response parser.

use {Value, Response, Fault};
use error::ParseError;

use base64;
use xml::reader::{XmlEvent, EventReader};
use xml::name::OwnedName;
use xml::common::Position;
use xml::ParserConfig;
use iso8601::datetime;
use std::io::{self, ErrorKind, Read};
use std::collections::BTreeMap;

pub type ParseResult<T> = Result<T, ParseError>;

pub struct Parser<'a, R: Read + 'a> {
    reader: EventReader<&'a mut R>,
}

impl<'a, R: Read> Parser<'a, R> {
    pub fn new(reader: &'a mut R) -> Self {
        Parser {
            reader: EventReader::new_with_config(reader, ParserConfig {
                cdata_to_characters: true,
                ..Default::default()
            }),
        }
    }

    /// Reads an `XmlEvent` from a reader, disposing events we want to ignore.
    fn pull_event(&mut self) -> ParseResult<XmlEvent> {
        loop {
            let event = try!(self.reader.next());
            match event {
                XmlEvent::StartDocument { .. }
                | XmlEvent::Comment(_)
                | XmlEvent::Whitespace(_)
                | XmlEvent::ProcessingInstruction { .. } => {},
                XmlEvent::StartElement { .. }
                | XmlEvent::EndElement { .. }
                | XmlEvent::EndDocument
                | XmlEvent::CData(_)
                | XmlEvent::Characters(_) => {
                    return Ok(event);
                }
            }
        }
    }

    /// Expects an opening tag like `<tag>` without attributes (and a local name without namespaces).
    fn expect_open(&mut self, tag: &str) -> ParseResult<()> {
        match try!(self.pull_event()) {
            XmlEvent::StartElement { ref name, ref attributes, .. }
            if name == &OwnedName::local(tag) => {
                if !attributes.is_empty() {
                    return self.unexpected(format!("unexpected attributes in <{}>", tag));
                }

                Ok(())
            }
            _ => return self.unexpected(format!("expected <{}>", tag)),
        }
    }

    /// Expects a closing tag like `</tag>` with a local name without namespaces.
    fn expect_close(&mut self, tag: &str) -> ParseResult<()> {
        match try!(self.pull_event()) {
            XmlEvent::EndElement { ref name } if name == &OwnedName::local(tag) => {
                Ok(())
            }
            _ => self.unexpected(format!("expected </{}>", tag)),
        }
    }

    /// Builds and returns an `Err(UnexpectedXml)`.
    fn unexpected<T, E: ToString>(&self, expected: E) -> ParseResult<T> {
        let expected = expected.to_string();
        let position = self.reader.position();

        Err(ParseError::UnexpectedXml {
            expected: expected,
            position: position,
        })
    }

    fn parse_response(&mut self) -> ParseResult<Response> {
        let response: Response;

        // <methodResponse>
        try!(self.expect_open("methodResponse"));

        // <fault> / <params>
        match try!(self.pull_event()) {
            XmlEvent::StartElement { ref name, ref attributes, .. } => {
                if !attributes.is_empty() {
                    return self.unexpected("unexpected attributes");
                }

                if name == &OwnedName::local("fault") {
                    let value = try!(self.parse_value());
                    let fault = try!(Fault::from_value(&value).ok_or_else(|| {
                        io::Error::new(ErrorKind::Other, "malformed <fault>")
                    }));
                    response = Err(fault);
                } else if name == &OwnedName::local("params") {
                    // <param>
                    try!(self.expect_open("param"));

                    let value = try!(self.parse_value());
                    response = Ok(value);

                    // </param>
                    try!(self.expect_close("param"));
                } else {
                    return self.unexpected(format!("expected <fault> or <params>, got {}", name));
                }
            }
            _ => return self.unexpected("expected <fault> or <params>"),
        }

        Ok(response)
    }

    pub fn parse_value(&mut self) -> ParseResult<Value> {
        // <value>
        try!(self.expect_open("value"));

        let value = try!(self.parse_value_inner());

        // </value>
        try!(self.expect_close("value"));

        Ok(value)
    }

    fn parse_value_inner(&mut self) -> ParseResult<Value> {
        let value: Value;

        // Raw string or specific type tag
        value = match try!(self.pull_event()) {
            XmlEvent::StartElement { ref name, ref attributes, .. } => {
                if !attributes.is_empty() {
                    return self.unexpected(format!("unexpected attributes in <{}>", name));
                }

                if name == &OwnedName::local("struct") {
                    let mut members = BTreeMap::new();
                    loop {
                        match try!(self.pull_event()) {
                            XmlEvent::EndElement { ref name } if name == &OwnedName::local("struct") => break,
                            XmlEvent::StartElement { ref name, ref attributes, .. } if name == &OwnedName::local("member") => {
                                // <member>
                                if !attributes.is_empty() {
                                    return self.unexpected(format!("unexpected attributes in <{}>", name));
                                }

                                // <name>NAME</name>
                                try!(self.expect_open("name"));
                                let name = match try!(self.pull_event()) {
                                    XmlEvent::Characters(string) => string,
                                    _ => return self.unexpected("expected CDATA"),
                                };
                                try!(self.expect_close("name"));

                                // Value
                                let value = try!(self.parse_value());

                                // </member>
                                try!(self.expect_close("member"));

                                members.insert(name, value);
                            }
                            _ => return self.unexpected("expected </struct> or <member>"),
                        }
                    }

                    Value::Struct(members)
                } else if name == &OwnedName::local("array") {
                    let mut elements: Vec<Value> = Vec::new();
                    try!(self.expect_open("data"));
                    loop {
                        match try!(self.pull_event()) {
                            XmlEvent::EndElement { ref name } if name == &OwnedName::local("data") => break,
                            XmlEvent::StartElement { ref name, .. } if name == &OwnedName::local("value") => {
                                elements.push(try!(self.parse_value_inner()));
                                try!(self.expect_close("value"));
                            }
                            _event => return self.unexpected("expected </data> or <value>")
                        }
                    }
                    try!(self.expect_close("array"));
                    Value::Array(elements)
                } else if name == &OwnedName::local("nil") {
                    try!(self.expect_close("nil"));
                    Value::Nil
                } else {
                    // All other types expect raw characters...
                    let data = match try!(self.pull_event()) {
                        XmlEvent::Characters(string) => string,
                        _ => return self.unexpected("expected characters"),
                    };

                    // ...and a corresponding close tag
                    try!(self.expect_close(&name.local_name));

                    if name == &OwnedName::local("i4") || name == &OwnedName::local("int") {
                        Value::Int(try!(data.parse::<i32>().map_err(|_| {
                            io::Error::new(ErrorKind::Other, format!("invalid value for integer: {}", data))
                        })))
                    } else if name == &OwnedName::local("i8") {
                        Value::Int64(try!(data.parse::<i64>().map_err(|_| {
                            io::Error::new(ErrorKind::Other, format!("invalid value for 64-bit integer: {}", data))
                        })))
                    } else if name == &OwnedName::local("boolean") {
                        let val = match data.trim() {
                            "0" => false,
                            "1" => true,
                            _ => return Err(io::Error::new(ErrorKind::Other, format!("invalid value for <boolean>: {}", data)).into())
                        };

                        Value::Bool(val)
                    } else if name == &OwnedName::local("string") {
                        Value::String(data.clone())
                    } else if name == &OwnedName::local("double") {
                        Value::Double(try!(data.parse::<f64>().map_err(|_| {
                            io::Error::new(ErrorKind::Other, format!("invalid value for double: {}", data))
                        })))
                    } else if name == &OwnedName::local("dateTime.iso8601") {
                        Value::DateTime(try!(datetime(&data).map_err(|e| {
                            io::Error::new(ErrorKind::Other, format!("invalid value for dateTime.iso8601: {} ({})", data, e))
                        })))
                    } else if name == &OwnedName::local("base64") {
                        Value::Base64(try!(base64::decode(&data).map_err(|_| {
                            io::Error::new(ErrorKind::Other, format!("invalid value for base64: {}", data))
                        })))
                    } else {
                        return self.unexpected("invalid <value> content");
                    }
                }
            }
            XmlEvent::Characters(string) => {
                Value::String(string)
            }
            _ => return self.unexpected("invalid <value> content"),
        };

        Ok(value)
    }
}

/// Parses a response from an XML reader.
pub fn parse_response<R: Read>(reader: &mut R) -> ParseResult<Response> {
    Parser::new(reader).parse_response()
}

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

    use {Response, Value};
    use error::Fault;
    use std::fmt::Debug;

    fn read_response(xml: &str) -> ParseResult<Response> {
        parse_response(&mut xml.as_bytes())
    }

    fn read_value(xml: &str) -> ParseResult<Value> {
        Parser::new(&mut xml.as_bytes()).parse_value()
    }

    fn assert_ok<T: Debug, E: Debug>(result: Result<T, E>) {
        match result {
            Ok(t) => println!("assert_ok successful on Ok: {:?}", t),
            Err(e) => panic!("assert_ok called on Err value: {:?}", e),
        }
    }

    fn assert_err<T: Debug, E: Debug>(result: Result<T, E>) {
        match result {
            Ok(t) => panic!("assert_err called on Ok value: {:?}", t),
            Err(e) => println!("assert_err successful on Err: {:?}", e),
        }
    }

    #[test]
    fn parses_fault() {
        assert_eq!(read_response(r##"
<?xml version="1.0"?>
<methodResponse>
   <fault>
      <value>
         <struct>
            <member>
               <name>faultCode</name>
               <value><int>4</int></value>
               </member>
            <member>
               <name>faultString</name>
               <value><string>Too many parameters.</string></value>
               </member>
            </struct>
         </value>
      </fault>
   </methodResponse>"##),
        Ok(Err(Fault {
            fault_code: 4,
            fault_string: "Too many parameters.".into(),
        })));
    }

    #[test]
    fn ignores_additional_fault_fields() {
        assert_eq!(read_response(r##"
<?xml version="1.0"?>
<methodResponse>
   <fault>
      <value>
         <struct>
            <member>
               <name>faultCode</name>
               <value><int>4</int></value>
               </member>
            <member>
               <name>faultString</name>
               <value><string>Too many parameters.</string></value>
               </member>
            <member>
               <name>unnecessaryParameter</name>
               <value><string>Too many parameters.</string></value>
               </member>
            </struct>
         </value>
      </fault>
   </methodResponse>"##),
        Ok(Err(Fault {
            fault_code: 4,
            fault_string: "Too many parameters.".into(),
        })));
    }

    #[test]
    fn rejects_invalid_faults() {
        // Make sure to reject type errors in <fault>s - They're specified to contain specifically
        // typed fields.
        assert!(read_response(r##"
<?xml version="1.0"?>
<methodResponse>
   <fault>
      <value>
         <struct>
            <member>
               <name>faultCode</name>
               <value><string>I'm not an int!</string></value>
               </member>
            <member>
               <name>faultString</name>
               <value><string>Too many parameters.</string></value>
               </member>
            </struct>
         </value>
      </fault>
   </methodResponse>"##).is_err());
    }

    #[test]
    fn parses_string_value_with_whitespace() {
        assert_eq!(read_value("<value><string>  I'm a string!  </string></value>"),
            Ok(Value::String("  I'm a string!  ".into())));
    }

    #[test]
    fn parses_64bit_int() {
        assert_eq!(read_value("<value><i8>12345</i8></value>"),
            Ok(Value::Int64(12345)));
        assert_eq!(read_value("<value><i8>-100100100100</i8></value>"),
            Ok(Value::Int64(-100100100100)));
    }

    #[test]
    fn parses_date_values() {
        assert_ok(read_value("<value><dateTime.iso8601>2015-02-18T23:16:09Z</dateTime.iso8601></value>"));
        assert_ok(read_value("<value><dateTime.iso8601>19980717T14:08:55</dateTime.iso8601></value>"));
    }

    #[test]
    fn parses_array_values() {
        assert_eq!(read_value(r#"
                <value><array><data>
                    <value><i4>5</i4></value>
                    <value><string>a</string></value>
                </data></array></value>"#),
            Ok(Value::Array(vec![Value::Int(5), Value::String("a".into())])));
    }

    #[test]
    fn parses_raw_value_as_string() {
        assert_eq!(read_value("<value>\t  I'm a string!  </value>"),
            Ok(Value::String("\t  I'm a string!  ".into())));
    }

    #[test]
    fn parses_nil_values() {
        assert_eq!(read_value("<value><nil/></value>"), Ok(Value::Nil));
        assert_eq!(read_value("<value><nil></nil></value>"), Ok(Value::Nil));
    }

    #[test]
    fn unescapes_values() {
        assert_eq!(read_value("<value><string>abc<abc&abc</string></value>"),
            Ok(Value::String("abc<abc&abc".into())));
    }

    #[test]
    fn rejects_value_with_attributes() {
        // XXX we *should* reject everything with attributes
        assert_err(read_value(r#"<value name="ble">\t  I'm a string!  </value>"#));
    }
}
<|endoftext|>


<commit_before>//! The parser module implements a nock syntax parser.

use std::str::FromStr;
use std::fmt;
use std::fmt::{Display, Formatter};
use std::error::Error;

use tokenizer::{Tokenizer, Token, TokenizerError, ExpressionReader};

#[derive(Debug,PartialEq)]
pub enum Noun {
    Atom(u64),
    Cell(Box<Noun>, Vec<Noun>),
}

#[derive(Debug)]
pub struct ParseError {
    msg: String,
    cause: Option<Box<Error>>,
}

impl ParseError {
    pub fn new<S: Into<String>>(msg: S) -> Self {
        ParseError {
            msg: msg.into(),
            cause: None,
        }
    }

    pub fn new_with_cause<S: Into<String>>(msg: S, err: Box<Error>) -> Self {
        ParseError {
            msg: msg.into(),
            cause: Some(err),
        }
    }
}

impl Display for ParseError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "ParseError: {}\n", self.msg));
        if let Some(ref cause) = self.cause {
            try!(write!(f, "Cause:\n\t{}", cause));
        }
        return Ok(());
    }
}

impl Error for ParseError {
    fn description(&self) -> &str {
        &self.msg
    }

    fn cause(&self) -> Option<&Error> {
        if let Some(ref cause) = self.cause {
            return Some(cause.as_ref());
        }
        return None;
    }
}

impl From<TokenizerError> for ParseError {
    fn from(err: TokenizerError) -> Self {
        Self::new_with_cause("Tokenizer Error", Box::new(err))
    }
}

pub struct Parser {
    toker: Tokenizer,
}

impl Parser {
    pub fn new(reader: Box<ExpressionReader>) -> Self {
        Parser { toker: Tokenizer::new(reader) }
    }

    fn parse_atom(&mut self, tok: &Token) -> Result<Noun, ParseError> {
        let atom = u64::from_str(&tok.val);
        return match atom {
            Ok(atom) => Ok(Noun::Atom(atom)),
            Err(e) => Err(ParseError::new_with_cause("Atom ParseError", Box::new(e))),
        };
    }

    fn flatten(&self, mut nouns: Vec<Noun>) -> Vec<Noun> {
        if nouns.len() == 1 {
            let noun = nouns.pop();
            if let Some(Noun::Cell(head, tail)) = noun {
                nouns.push(*head);
                let mut new_tail = self.flatten(tail);
                nouns.append(&mut new_tail);
            } else if let Some(noun) = noun {
                nouns.push(noun);
            }
        }
        return nouns;
    }

    fn parse_cell(&mut self) -> Result<Noun, ParseError> {
        let head = try!(self.parse());
        let mut tail = Vec::<Noun>::new();
        loop {
            let tok = try!(self.toker.next());
            if tok.is_atom() {
                tail.push(try!(self.parse_atom(&tok)))
            } else if tok.is_cell_start() {
                tail.push(try!(self.parse_cell()))
            } else if tok.is_cell_end() {
                tail = self.flatten(tail);
                break;
            }
        }
        Ok(Noun::Cell(Box::new(head), tail))
    }

    pub fn parse(&mut self) -> Result<Noun, ParseError> {
        let tok = try!(self.toker.next());
        if tok.is_atom() {
            return self.parse_atom(&tok);
        } else if tok.is_cell_start() {
            return self.parse_cell();
        }
        Err(ParseError::new("Unhandled Token!"))
    }
}

#[cfg(test)]
mod parser_tests {
    use parser::{Parser, Noun};
    use tokenizer::tokenizer_tests::MockReader;

    #[test]
    fn test_parse_simple_atom() {
        let reader = MockReader::new(vec![
            "1".to_string(),
        ]);
        let mut parser = Parser::new(Box::new(reader));
        let noun = parser.parse();
        assert!(noun.is_ok());
        let noun = noun.unwrap();
        assert_eq!(noun, Noun::Atom(1));
    }

    #[test]
    fn test_parse_simple_cell() {
        let reader = MockReader::new(vec![
            "[1 2]".to_string(),
        ]);
        let mut parser = Parser::new(Box::new(reader));
        let noun = parser.parse();
        assert!(noun.is_ok());
        let noun = noun.unwrap();
        assert_eq!(noun,
                   Noun::Cell(Box::new(Noun::Atom(1)), vec![Noun::Atom(2)]));
    }

    #[test]
    fn test_parse_autoconsed_cell() {
        let reader = MockReader::new(vec![
            "[1 2 3]".to_string(),
        ]);
        let mut parser = Parser::new(Box::new(reader));
        let noun = parser.parse();
        assert!(noun.is_ok());
        let noun = noun.unwrap();
        assert_eq!(noun,
                   Noun::Cell(Box::new(Noun::Atom(1)), vec![Noun::Atom(2), Noun::Atom(3)]));
    }

    #[test]
    fn test_parse_consed_cell() {
        let reader = MockReader::new(vec![
            "[1 [2 3]]".to_string(),
        ]);
        let mut parser = Parser::new(Box::new(reader));
        let noun = parser.parse();
        assert!(noun.is_ok());
        let noun = noun.unwrap();
        assert_eq!(noun,
                   Noun::Cell(Box::new(Noun::Atom(1)), vec![Noun::Atom(2), Noun::Atom(3)]));
    }

    #[test]
    fn test_parse_nested_cell() {
        let reader = MockReader::new(vec![
            "[1 [2 3] 4]".to_string(),
        ]);
        let mut parser = Parser::new(Box::new(reader));
        let noun = parser.parse();
        assert!(noun.is_ok());
        let noun = noun.unwrap();
        assert_eq!(noun,
                   Noun::Cell(Box::new(Noun::Atom(1)),
                              vec![Noun::Cell(Box::new(Noun::Atom(2)), vec![Noun::Atom(3)]),
                                   Noun::Atom(4)]));
    }
}
<commit_msg>Add a Display Implementation for Nouns.<commit_after>//! The parser module implements a nock syntax parser.

use std::str::FromStr;
use std::fmt;
use std::fmt::{Display, Formatter};
use std::error::Error;

use tokenizer::{Tokenizer, Token, TokenizerError, ExpressionReader};

#[derive(Debug,PartialEq)]
pub enum Noun {
    Atom(u64),
    Cell(Box<Noun>, Vec<Noun>),
}

impl Display for Noun {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        match self {
            &Noun::Atom(ref u) => try!(write!(fmt, "{}", u)),
            &Noun::Cell(ref head, ref tail) => {
                try!(write!(fmt, "[{}", head));
                for n in tail {
                    try!(write!(fmt, " {}", n));
                }
                try!(write!(fmt, "]"))
            },
        }
        return Ok(())
    }
}

#[derive(Debug)]
pub struct ParseError {
    msg: String,
    cause: Option<Box<Error>>,
}

impl ParseError {
    pub fn new<S: Into<String>>(msg: S) -> Self {
        ParseError {
            msg: msg.into(),
            cause: None,
        }
    }

    pub fn new_with_cause<S: Into<String>>(msg: S, err: Box<Error>) -> Self {
        ParseError {
            msg: msg.into(),
            cause: Some(err),
        }
    }
}

impl Display for ParseError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "ParseError: {}\n", self.msg));
        if let Some(ref cause) = self.cause {
            try!(write!(f, "Cause:\n\t{}", cause));
        }
        return Ok(());
    }
}

impl Error for ParseError {
    fn description(&self) -> &str {
        &self.msg
    }

    fn cause(&self) -> Option<&Error> {
        if let Some(ref cause) = self.cause {
            return Some(cause.as_ref());
        }
        return None;
    }
}

impl From<TokenizerError> for ParseError {
    fn from(err: TokenizerError) -> Self {
        Self::new_with_cause("Tokenizer Error", Box::new(err))
    }
}

pub struct Parser {
    toker: Tokenizer,
}

impl Parser {
    pub fn new(reader: Box<ExpressionReader>) -> Self {
        Parser { toker: Tokenizer::new(reader) }
    }

    fn parse_atom(&mut self, tok: &Token) -> Result<Noun, ParseError> {
        let atom = u64::from_str(&tok.val);
        return match atom {
            Ok(atom) => Ok(Noun::Atom(atom)),
            Err(e) => Err(ParseError::new_with_cause("Atom ParseError", Box::new(e))),
        };
    }

    fn flatten(&self, mut nouns: Vec<Noun>) -> Vec<Noun> {
        if nouns.len() == 1 {
            let noun = nouns.pop();
            if let Some(Noun::Cell(head, tail)) = noun {
                nouns.push(*head);
                let mut new_tail = self.flatten(tail);
                nouns.append(&mut new_tail);
            } else if let Some(noun) = noun {
                nouns.push(noun);
            }
        }
        return nouns;
    }

    fn parse_cell(&mut self) -> Result<Noun, ParseError> {
        let head = try!(self.parse());
        let mut tail = Vec::<Noun>::new();
        loop {
            let tok = try!(self.toker.next());
            if tok.is_atom() {
                tail.push(try!(self.parse_atom(&tok)))
            } else if tok.is_cell_start() {
                tail.push(try!(self.parse_cell()))
            } else if tok.is_cell_end() {
                tail = self.flatten(tail);
                break;
            }
        }
        Ok(Noun::Cell(Box::new(head), tail))
    }

    pub fn parse(&mut self) -> Result<Noun, ParseError> {
        let tok = try!(self.toker.next());
        if tok.is_atom() {
            return self.parse_atom(&tok);
        } else if tok.is_cell_start() {
            return self.parse_cell();
        }
        Err(ParseError::new("Unhandled Token!"))
    }
}

#[cfg(test)]
mod parser_tests {
    use parser::{Parser, Noun};
    use tokenizer::tokenizer_tests::MockReader;

    #[test]
    fn test_parse_simple_atom() {
        let reader = MockReader::new(vec![
            "1".to_string(),
        ]);
        let mut parser = Parser::new(Box::new(reader));
        let noun = parser.parse();
        assert!(noun.is_ok());
        let noun = noun.unwrap();
        assert_eq!(noun, Noun::Atom(1));
    }

    #[test]
    fn test_parse_simple_cell() {
        let reader = MockReader::new(vec![
            "[1 2]".to_string(),
        ]);
        let mut parser = Parser::new(Box::new(reader));
        let noun = parser.parse();
        assert!(noun.is_ok());
        let noun = noun.unwrap();
        assert_eq!(noun,
                   Noun::Cell(Box::new(Noun::Atom(1)), vec![Noun::Atom(2)]));
    }

    #[test]
    fn test_parse_autoconsed_cell() {
        let reader = MockReader::new(vec![
            "[1 2 3]".to_string(),
        ]);
        let mut parser = Parser::new(Box::new(reader));
        let noun = parser.parse();
        assert!(noun.is_ok());
        let noun = noun.unwrap();
        assert_eq!(noun,
                   Noun::Cell(Box::new(Noun::Atom(1)), vec![Noun::Atom(2), Noun::Atom(3)]));
    }

    #[test]
    fn test_parse_consed_cell() {
        let reader = MockReader::new(vec![
            "[1 [2 3]]".to_string(),
        ]);
        let mut parser = Parser::new(Box::new(reader));
        let noun = parser.parse();
        assert!(noun.is_ok());
        let noun = noun.unwrap();
        assert_eq!(noun,
                   Noun::Cell(Box::new(Noun::Atom(1)), vec![Noun::Atom(2), Noun::Atom(3)]));
    }

    #[test]
    fn test_parse_nested_cell() {
        let reader = MockReader::new(vec![
            "[1 [2 3] 4]".to_string(),
        ]);
        let mut parser = Parser::new(Box::new(reader));
        let noun = parser.parse();
        assert!(noun.is_ok());
        let noun = noun.unwrap();
        assert_eq!(noun,
                   Noun::Cell(Box::new(Noun::Atom(1)),
                              vec![Noun::Cell(Box::new(Noun::Atom(2)), vec![Noun::Atom(3)]),
                                   Noun::Atom(4)]));
    }
}
<|endoftext|>