<commit_before>#[macro_use]
extern crate nom;

pub mod parser;

use std::result;

/// A SemVer Version
#[derive(PartialEq,Debug)]
pub struct Version {
    major: u32,
    minor: u32,
    patch: u32,
    pre: Option<String>,
    build: Option<String>,
}

/// An error type for this crate
///
/// Currently, just a generic error. Will make this nicer later.
#[derive(Debug)]
enum SemVerError {
    GenericError,
}

/// A Result type for errors
pub type Result<T> = result::Result<T, SemVerError>;

impl From<()> for SemVerError {
    fn from(_: ()) -> SemVerError {
        SemVerError::GenericError
    }
}

impl Version {
    /// Create a Version from a string
    ///
    /// Currently supported: x, x.y, and x.y.z versions.
    pub fn parse(version: &str) -> Result<Version> {
        Ok(try!(parser::try_parse(version.as_bytes())))
    }
}

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

    #[test]
    fn parse_major_version() {
        let version = "10";
        let version = Version::parse(version).unwrap();

        assert_eq!(version,
                   Version {
                       major: 10,
                       minor: 0,
                       patch: 0,
                       pre: None,
                       build: None,
                   });
    }

    #[test]
    fn parse_minor_version() {
        let version = "10.11";
        let version = Version::parse(version).unwrap();

        assert_eq!(version,
                   Version {
                       major: 10,
                       minor: 11,
                       patch: 0,
                       pre: None,
                       build: None,
                   });
    }

    #[test]
    fn parse_version() {
        let version = "10.11.12";
        let version = Version::parse(version).unwrap();

        assert_eq!(version,
                   Version {
                       major: 10,
                       minor: 11,
                       patch: 12,
                       pre: None,
                       build: None,
                   });
    }

    #[test]
    fn parse_pre_basic() {
        let version = "1.0.0-alpha";
        let version = Version::parse(version).unwrap();
        assert_eq!(version,
                   Version {
                       major: 1,
                       minor: 0,
                       patch: 0,
                       pre: Some(String::from("alpha")),
                       build: None,
                   });
    }

    #[test]
    fn parse_pre_dot() {
        let version = "1.0.0-alpha.1";
        let version = Version::parse(version).unwrap();

        assert_eq!(version,
                   Version {
                       major: 1,
                       minor: 0,
                       patch: 0,
                       pre: Some(String::from("alpha.1")),
                       build: None,
                   });
    }

    #[test]
    fn parse_build() {
        let version = "1.0.0-alpha+100";
        let version = Version::parse(version).unwrap();

        assert_eq!(version,
                   Version {
                       major: 1,
                       minor: 0,
                       patch: 0,
                       pre: Some(String::from("alpha")),
                       build: Some(String::from("100")),
                   });
    }

    #[test]
    fn parse_build_no_pre() {
        let version = "1.0.0+100";
        let version = Version::parse(version).unwrap();

        assert_eq!(version,
                   Version {
                       major: 1,
                       minor: 0,
                       patch: 0,
                       pre: None,
                       build: Some(String::from("100")),
                   });
    }
}
<commit_msg>Import tests from master<commit_after>#[macro_use]
extern crate nom;

pub mod parser;

use std::result;

/// A SemVer Version
#[derive(PartialEq,Debug)]
pub struct Version {
    major: u32,
    minor: u32,
    patch: u32,
    pre: Option<String>,
    build: Option<String>,
}

/// An error type for this crate
///
/// Currently, just a generic error. Will make this nicer later.
#[derive(PartialEq,Debug)]
enum SemVerError {
    GenericError,
}

/// A Result type for errors
pub type Result<T> = result::Result<T, SemVerError>;

impl From<()> for SemVerError {
    fn from(_: ()) -> SemVerError {
        SemVerError::GenericError
    }
}

impl Version {
    /// Create a Version from a string
    ///
    /// Currently supported: x, x.y, and x.y.z versions.
    pub fn parse(version: &str) -> Result<Version> {
        Ok(try!(parser::try_parse(version.trim().as_bytes())))
    }
}

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

    #[test]
    fn test_parse() {
        assert_eq!(Version::parse(""), Err(SemVerError::GenericError));
        assert_eq!(Version::parse("  "), Err(SemVerError::GenericError));
        //assert_eq!(Version::parse("1"), Err(SemVerError::GenericError));
        //assert_eq!(Version::parse("1.2"), Err(SemVerError::GenericError));
        //assert_eq!(Version::parse("1.2.3-"), Err(SemVerError::GenericError));
        assert_eq!(Version::parse("a.b.c"), Err(SemVerError::GenericError));

        //assert_eq!(Version::parse("1.2.3 abc"), Err(SemVerError::GenericError));

        assert!(Version::parse("1.2.3") == Ok(Version {
            major: 1,
            minor: 2,
            patch: 3,
            pre: None,
            build: None,
        }));
        assert!(Version::parse("  1.2.3  ") == Ok(Version {
            major: 1,
            minor: 2,
            patch: 3,
            pre: None,
            build: None,
        }));
        assert!(Version::parse("1.2.3-alpha1") == Ok(Version {
            major: 1,
            minor: 2,
            patch: 3,
            pre: Some(String::from("alpha1")),
            build: None,
        }));
        assert!(Version::parse("  1.2.3-alpha1  ") == Ok(Version {
            major: 1,
            minor: 2,
            patch: 3,
            pre: Some(String::from("alpha1")),
            build: None
        }));
        assert!(Version::parse("1.2.3+build5") == Ok(Version {
            major: 1,
            minor: 2,
            patch: 3,
            pre: None,
            build: Some(String::from("build5")),
        }));
        assert!(Version::parse("  1.2.3+build5  ") == Ok(Version {
            major: 1,
            minor: 2,
            patch: 3,
            pre: None,
            build: Some(String::from("build5")),
        }));
        assert!(Version::parse("1.2.3-alpha1+build5") == Ok(Version {
            major: 1,
            minor: 2,
            patch: 3,
            pre: Some(String::from("alpha1")),
            build: Some(String::from("build5")),
        }));
        assert!(Version::parse("  1.2.3-alpha1+build5  ") == Ok(Version {
            major: 1,
            minor: 2,
            patch: 3,
            pre: Some(String::from("alpha1")),
            build: Some(String::from("build5")),
        }));
        assert!(Version::parse("1.2.3-1.alpha1.9+build5.7.3aedf  ") == Ok(Version {
            major: 1,
            minor: 2,
            patch: 3,
            pre: Some(String::from("1.alpha1.9")),
            build: Some(String::from("build5.7.3aedf")),
        }));
        assert_eq!(Version::parse("0.4.0-beta.1+0851523"), Ok(Version {
            major: 0,
            minor: 4,
            patch: 0,
            pre: Some(String::from("beta.1")),
            build: Some(String::from("0851523")),
        }));

    }

    /*
    #[test]
    fn test_increment_patch() {
        let mut buggy_release = Version::parse("0.1.0").unwrap();
        buggy_release.increment_patch();
        assert_eq!(buggy_release, Version::parse("0.1.1").unwrap());
    }

    #[test]
    fn test_increment_minor() {
        let mut feature_release = Version::parse("1.4.6").unwrap();
        feature_release.increment_minor();
        assert_eq!(feature_release, Version::parse("1.5.0").unwrap());
    }

    #[test]
    fn test_increment_major() {
        let mut chrome_release = Version::parse("46.1.246773").unwrap();
        chrome_release.increment_major();
        assert_eq!(chrome_release, Version::parse("47.0.0").unwrap());
    }

    #[test]
    fn test_increment_keep_prerelease() {
        let mut release = Version::parse("1.0.0-alpha").unwrap();
        release.increment_patch();

        assert_eq!(release, Version::parse("1.0.1").unwrap());

        release.increment_minor();

        assert_eq!(release, Version::parse("1.1.0").unwrap());

        release.increment_major();

        assert_eq!(release, Version::parse("2.0.0").unwrap());
    }

    #[test]
    fn test_increment_clear_metadata() {
        let mut release = Version::parse("1.0.0+4442").unwrap();
        release.increment_patch();

        assert_eq!(release, Version::parse("1.0.1").unwrap());
        release = Version::parse("1.0.1+hello").unwrap();

        release.increment_minor();

        assert_eq!(release, Version::parse("1.1.0").unwrap());
        release = Version::parse("1.1.3747+hello").unwrap();

        release.increment_major();

        assert_eq!(release, Version::parse("2.0.0").unwrap());
    }

    #[test]
    fn test_eq() {
        assert_eq!(Version::parse("1.2.3"), Version::parse("1.2.3"));
        assert_eq!(Version::parse("1.2.3-alpha1"), Version::parse("1.2.3-alpha1"));
        assert_eq!(Version::parse("1.2.3+build.42"), Version::parse("1.2.3+build.42"));
        assert_eq!(Version::parse("1.2.3-alpha1+42"), Version::parse("1.2.3-alpha1+42"));
        assert_eq!(Version::parse("1.2.3+23"), Version::parse("1.2.3+42"));
    }

    #[test]
    fn test_ne() {
        assert!(Version::parse("0.0.0")       != Version::parse("0.0.1"));
        assert!(Version::parse("0.0.0")       != Version::parse("0.1.0"));
        assert!(Version::parse("0.0.0")       != Version::parse("1.0.0"));
        assert!(Version::parse("1.2.3-alpha") != Version::parse("1.2.3-beta"));
    }

    #[test]
    fn test_show() {
        assert_eq!(format!("{}", Version::parse("1.2.3").unwrap()),
                   "1.2.3".to_string());
        assert_eq!(format!("{}", Version::parse("1.2.3-alpha1").unwrap()),
                   "1.2.3-alpha1".to_string());
        assert_eq!(format!("{}", Version::parse("1.2.3+build.42").unwrap()),
                   "1.2.3+build.42".to_string());
        assert_eq!(format!("{}", Version::parse("1.2.3-alpha1+42").unwrap()),
                   "1.2.3-alpha1+42".to_string());
    }

    #[test]
    fn test_to_string() {
        assert_eq!(Version::parse("1.2.3").unwrap().to_string(), "1.2.3".to_string());
        assert_eq!(Version::parse("1.2.3-alpha1").unwrap().to_string(), "1.2.3-alpha1".to_string());
        assert_eq!(Version::parse("1.2.3+build.42").unwrap().to_string(), "1.2.3+build.42".to_string());
        assert_eq!(Version::parse("1.2.3-alpha1+42").unwrap().to_string(), "1.2.3-alpha1+42".to_string());
    }

    #[test]
    fn test_lt() {
        assert!(Version::parse("0.0.0")          < Version::parse("1.2.3-alpha2"));
        assert!(Version::parse("1.0.0")          < Version::parse("1.2.3-alpha2"));
        assert!(Version::parse("1.2.0")          < Version::parse("1.2.3-alpha2"));
        assert!(Version::parse("1.2.3-alpha1")   < Version::parse("1.2.3"));
        assert!(Version::parse("1.2.3-alpha1")   < Version::parse("1.2.3-alpha2"));
        assert!(!(Version::parse("1.2.3-alpha2") < Version::parse("1.2.3-alpha2")));
        assert!(!(Version::parse("1.2.3+23")     < Version::parse("1.2.3+42")));
    }

    #[test]
    fn test_le() {
        assert!(Version::parse("0.0.0")        <= Version::parse("1.2.3-alpha2"));
        assert!(Version::parse("1.0.0")        <= Version::parse("1.2.3-alpha2"));
        assert!(Version::parse("1.2.0")        <= Version::parse("1.2.3-alpha2"));
        assert!(Version::parse("1.2.3-alpha1") <= Version::parse("1.2.3-alpha2"));
        assert!(Version::parse("1.2.3-alpha2") <= Version::parse("1.2.3-alpha2"));
        assert!(Version::parse("1.2.3+23")     <= Version::parse("1.2.3+42"));
    }

    #[test]
    fn test_gt() {
        assert!(Version::parse("1.2.3-alpha2")   > Version::parse("0.0.0"));
        assert!(Version::parse("1.2.3-alpha2")   > Version::parse("1.0.0"));
        assert!(Version::parse("1.2.3-alpha2")   > Version::parse("1.2.0"));
        assert!(Version::parse("1.2.3-alpha2")   > Version::parse("1.2.3-alpha1"));
        assert!(Version::parse("1.2.3")          > Version::parse("1.2.3-alpha2"));
        assert!(!(Version::parse("1.2.3-alpha2") > Version::parse("1.2.3-alpha2")));
        assert!(!(Version::parse("1.2.3+23")     > Version::parse("1.2.3+42")));
    }

    #[test]
    fn test_ge() {
        assert!(Version::parse("1.2.3-alpha2") >= Version::parse("0.0.0"));
        assert!(Version::parse("1.2.3-alpha2") >= Version::parse("1.0.0"));
        assert!(Version::parse("1.2.3-alpha2") >= Version::parse("1.2.0"));
        assert!(Version::parse("1.2.3-alpha2") >= Version::parse("1.2.3-alpha1"));
        assert!(Version::parse("1.2.3-alpha2") >= Version::parse("1.2.3-alpha2"));
        assert!(Version::parse("1.2.3+23")     >= Version::parse("1.2.3+42"));
    }

    #[test]
    fn test_prerelease_check() {
        assert!(Version::parse("1.0.0").unwrap().is_prerelease() == false);
        assert!(Version::parse("0.0.1").unwrap().is_prerelease() == false);
        assert!(Version::parse("4.1.4-alpha").unwrap().is_prerelease());
        assert!(Version::parse("1.0.0-beta294296").unwrap().is_prerelease());
    }

    #[test]
    fn test_spec_order() {
        let vs = ["1.0.0-alpha",
                  "1.0.0-alpha.1",
                  "1.0.0-alpha.beta",
                  "1.0.0-beta",
                  "1.0.0-beta.2",
                  "1.0.0-beta.11",
                  "1.0.0-rc.1",
                  "1.0.0"];
        let mut i = 1;
        while i < vs.len() {
            let a = Version::parse(vs[i-1]).unwrap();
            let b = Version::parse(vs[i]).unwrap();
            assert!(a < b);
            i += 1;
        }
    }
    */
}
<|endoftext|>


<commit_before>// Copyright 2015 Dawid Ciężarkiewicz
// See LICENSE-MPL
//! Simple Map with default for missing values and compacting (removal of
//! elements with default value from underlying map).
//!
//! So you can just:
//!
//! ```
//! use simplemap::SimpleMap;
//!
//! let mut map = SimpleMap::new();
//!
//! assert_eq!(map[0u32], 0u32);
//! map[1] = 3;
//! assert_eq!(map[1], 3);
//! ```

#![feature(hashmap_hasher)]

#![cfg_attr(all(test, feature="bench"), feature(test))]

#[cfg(all(test, feature="bench"))]
extern crate test;
extern crate fnv;

#[cfg(test)]
extern crate rand;

use std::ops::{Index, IndexMut};
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::collections::hash_state::{DefaultState, HashState};
use std::iter::Chain;
use std::hash::Hash;
use fnv::FnvHasher;
use std::fmt;

/// SimpleMap
///
/// Simple Map with default for missing values and compacting (removal of
/// elements with default value from underlying map).
#[derive(Clone)]
pub struct SimpleMap<K, V, S = DefaultState<FnvHasher>> {
    map : HashMap<K, V, S>,
    default : V,
    pending : Option<(K, V)>
}

impl<K, V> SimpleMap<K, V>
where K : Ord+Clone+Hash,
      V : Clone+Eq+Default,
{
    /// Create a `SimpleMap`.
    ///
    /// `Default::default()` will be used as a default value.
    pub fn new() -> SimpleMap<K, V, DefaultState<FnvHasher>> {
        SimpleMap {
            map : Default::default(),
            default: Default::default(),
            pending: None,
        }
    }
}

impl<K, V, S> SimpleMap<K, V, S>
where K : Ord+Clone+Hash,
      V : Clone+Eq+Default,
      S : HashState+Default
{
    /// Create a `SimpleMap`.
    ///
    /// `Default::default()` will be used as a default value.
    pub fn with_hash_state(hash_state : S) -> SimpleMap<K, V, S> {
        SimpleMap {
            map : HashMap::with_hash_state(hash_state),
            default: Default::default(),
            pending: None,
        }
    }
}

impl<K, V> SimpleMap<K, V>
where K : Ord+Clone+Hash,
      V : Clone+Eq,
{
    /// Create a `SimpleMap` with custom default value.
    pub fn new_with_default(default : V) -> SimpleMap<K, V, DefaultState<FnvHasher>> {
        SimpleMap {
            map : Default::default(),
            default: default,
            pending: None,
        }
    }
}

impl<K, V, S> SimpleMap<K, V, S>
where K : Ord+Clone+Hash,
      S : HashState+Default,
      V : Clone+Eq,
{
    pub fn with_default_with_hash_state(default : V, hash_state: S) -> SimpleMap<K, V, S> {
        SimpleMap {
            map : HashMap::with_hash_state(hash_state),
            default: default,
            pending: None,
        }
    }
}

impl<K, V, S> SimpleMap<K, V, S>
where K : Ord+Clone+Hash,
      V : Clone+Eq,
      S: HashState,
{
    fn apply_pending(&mut self) {
       match self.pending {
           Some(ref pending) => {
               let &(ref idx , ref val) = pending;
               if *val == self.default {
                   self.map.remove(idx);
               } else {
                   self.map.insert(idx.clone(), val.clone());
               }
           },
           None => {}
       }
       self.pending = None;
    }

    /// Make sure to remove all elements with default value.
    pub fn compact(&mut self) {
        self.apply_pending();
    }

    /// Iterator over map elements with non-default values.
    ///
    /// Note: It might return elements with default value, unless `compact`
    /// is called before `iter()`.
    pub fn iter<'a>(&'a self) -> Chain<std::collections::hash_map::Iter<'a, K, V>, std::iter::Map<std::option::Iter<'a, (K, V)>, fn(&'a (K, V)) -> (&'a K, &'a V)>> {
        let SimpleMap {
            ref map,
            ref pending,
            ..
        } = *self;

        let f: fn(&'a (K, V)) -> (&'a K, &'a V) = ref_to_tuple_to_tuple_of_refs;

        map.iter().chain(pending.iter().map(f))
    }
}

impl<K, V, S> SimpleMap<K, V, S>
where K : Ord+Clone+Hash,
      S: HashState,
      V : Clone+Eq,
{
    /// Iterator yielding (K, V) instead of (&K, &V)
    pub fn iter_cloned<'a>(&'a self) ->
        Chain<
            std::iter::Map<std::collections::hash_map::Iter<'a, K, V>, fn((&'a K, &'a V)) -> (K, V)>,
            std::iter::Cloned<std::option::Iter<'a, (K, V)>>
        >
    {
        let SimpleMap {
            ref map,
            ref pending,
            ..
        } = *self;

        let f: fn((&'a K, &'a V)) -> (K, V) = tuple_of_refs_to_tuple;

        map.iter().map(f).chain(pending.iter().cloned())
    }

}

fn ref_to_tuple_to_tuple_of_refs<'a, K, V>(t : &'a(K, V)) -> (&'a K, &'a V) {
    let &(ref i, ref t) = t;
    (i, t)
}

fn tuple_of_refs_to_tuple<'a, K : Clone, V : Clone>(t : (&'a K, &'a V)) -> (K, V) {
    let (i, t) = t;
    (i.clone(), t.clone())
}

use std::iter::FromIterator;
use std::iter::IntoIterator;

impl<K, V, S> FromIterator<(K, V)> for SimpleMap<K, V, S>
where K: Ord+Hash, V: Default,
      S: HashState+Default {
    fn from_iter<I>(iterator: I) -> SimpleMap<K, V, S>
        where I: IntoIterator<Item=(K, V)> {
            SimpleMap {
                default: Default::default(),
                map: FromIterator::from_iter(iterator),
                pending: None,
            }
    }
}

/// ```
/// use simplemap::SimpleMap;
///
/// let mut map = SimpleMap::new();
///
/// let val : u32 = map[0u32];
/// assert_eq!(val, 0);
/// ```
impl<K, V, S> Index<K> for SimpleMap<K, V, S>
where K : Ord+Hash,
      S : HashState+Default,
{
    type Output = V;
    fn index<'a>(&'a self, index: K) -> &'a V {
        match self.pending {
            Some(ref pending) => {
               let &(ref i, ref val) = pending;
               if *i == index {
                   return val
               }
            }
            None => {},
        }

        match self.map.get(&index) {
            Some(entry) => entry,
            None => &self.default,
        }
    }
}

/// ```
/// use simplemap::SimpleMap;
///
/// let mut map = SimpleMap::new();
///
/// map[1u32] = 3i32;
/// assert_eq!(map[1], 3);
/// ```
impl<K, V, S> IndexMut<K> for SimpleMap<K, V, S>
where
K : Ord+Clone+Hash,
V : Clone+Eq,
      S : HashState+Default,
{
    fn index_mut<'a>(&'a mut self, index: K) -> &'a mut V {
        self.apply_pending();

        match self.map.entry(index.clone()) {
            Entry::Occupied(entry) => {
                self.pending = Some((index, entry.get().clone()));
                let &mut (_, ref mut val) = self.pending.as_mut().unwrap();
                val
            },
            Entry::Vacant(_) => {
                self.pending = Some((index, self.default.clone()));
                let &mut (_, ref mut val) = self.pending.as_mut().unwrap();
                val
            }
        }
    }
}

impl<K, V, S> fmt::Debug for SimpleMap<K, V, S>
where K : Ord+Eq+Clone+Hash+fmt::Debug,
      V : Clone+Eq+fmt::Debug,
      S: HashState,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_map().entries(self.iter()).finish()
    }
}

impl<K, V> Default for SimpleMap<K, V>
where K : Ord+Clone+Hash,
      V : Clone+Eq+Default,
{
     fn default() -> Self {
         SimpleMap::with_default_with_hash_state(Default::default(), Default::default())
     }
}

#[cfg(test)]
mod tests {
    pub use super::*;
    use std::collections::HashMap;
    use std::collections::hash_state::{DefaultState};
    use fnv::FnvHasher;
    use rand::Rng;

    #[test]
    fn default() {
        let map = SimpleMap::new_with_default(5u32);
        assert_eq!(map[1u32], 5u32);
    }

    #[test]
    fn iter() {
        let mut map = SimpleMap::new();

        map[0u32] = 3i32; // counts
        map[1u32] = 0i32; // default, doesn't count
        map[2u32] = 2i32; // counts
        map[0u32] = 2i32; // replaces the existing one
        let _ = map[0u32]; // shouldn't change anything

        map.compact();
        assert_eq!(map.iter().count(), 2);
    }

    #[test]
    fn random() {
        let mut bmap : HashMap<_, _, DefaultState<FnvHasher>> = Default::default();
        let mut smap = SimpleMap::new();

        let mut rng = rand::thread_rng();

        for val in 0u32..10000 {
            let idx = rng.gen_range(-5i32, 5);
            let bval = *bmap.get(&idx).unwrap_or(&Default::default());
            let sval = smap[idx];
            assert_eq!(bval, sval);
            bmap.insert(idx, val);
            smap[idx] = val;
        }
    }

    #[test]
    fn strings() {
        let mut smap = SimpleMap::new();

        smap["one"] = 1u32;
        smap["two"] = 2u32;

        assert_eq!(smap["zero"], 0u32);
    }

#[cfg(feature="bench")]
    mod bench {
        use std::collections::BTreeMap;
        use std::collections::HashMap;
        use std::collections::hash_state::{DefaultState};
        use fnv::FnvHasher;
        use super::*;
        use test::Bencher;
        use test;
#[bench]
        fn normal_btreemap_insert(b : &mut Bencher) {
            let mut map = BTreeMap::new();

            let mut i = 0u32;
            b.iter(|| {
                map.insert(i, i);
                i = i.wrapping_add(i);
            });
        }

#[bench]
        fn normal_btreemap_get(b : &mut Bencher) {
            let mut map = BTreeMap::new();

            for i in 0u32..10000 {
                map.insert(i, i);
            }

            let mut i = 0u32;
            b.iter(|| {
                test::black_box(map.get(&i));
                i = i.wrapping_add(i);
            });
        }

#[bench]
        fn normal_hashmap_insert(b : &mut Bencher) {
            let mut map : HashMap<_, _, DefaultState<FnvHasher>> = Default::default();

            let mut i = 0u32;
            b.iter(|| {
                map.insert(i, i);
                i = i.wrapping_add(i);
            });
        }

#[bench]
        fn normal_hashmap_get(b : &mut Bencher) {
            let mut map : HashMap<_, _, DefaultState<FnvHasher>> = Default::default();

            for i in 0u32..10000 {
                map.insert(i, i);
            }

            let mut i = 0u32;
            b.iter(|| {
                test::black_box(map.get(&i));
                i = i.wrapping_add(i);
            });
        }

#[bench]
        fn compact_map_idx_assign(b : &mut Bencher) {
            let mut map = SimpleMap::new();

            let mut i = 0u32;
            b.iter(|| {
                map[i] = i;
                i = i.wrapping_add(i);
            });
        }

#[bench]
        fn compact_map_idx_get(b : &mut Bencher) {
            let mut map = SimpleMap::new();

            for i in 0u32..10000 {
                map[i] = i;
            }

            let mut i = 0u32;
            b.iter(|| {
                test::black_box(map[i]);
                i = i.wrapping_add(i);
            });
        }
    }
}
<commit_msg>tests: Fix compilation.<commit_after>// Copyright 2015 Dawid Ciężarkiewicz
// See LICENSE-MPL
//! Simple Map with default for missing values and compacting (removal of
//! elements with default value from underlying map).
//!
//! So you can just:
//!
//! ```
//! use simplemap::SimpleMap;
//!
//! let mut map = SimpleMap::new();
//!
//! assert_eq!(map[0u32], 0u32);
//! map[1] = 3;
//! assert_eq!(map[1], 3);
//! ```

#![feature(hashmap_hasher)]

#![cfg_attr(all(test, feature="bench"), feature(test))]

#[cfg(all(test, feature="bench"))]
extern crate test;
extern crate fnv;

#[cfg(test)]
extern crate rand;

use std::ops::{Index, IndexMut};
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::collections::hash_state::{DefaultState, HashState};
use std::iter::Chain;
use std::hash::Hash;
use fnv::FnvHasher;
use std::fmt;

/// SimpleMap
///
/// Simple Map with default for missing values and compacting (removal of
/// elements with default value from underlying map).
#[derive(Clone)]
pub struct SimpleMap<K, V, S = DefaultState<FnvHasher>> {
    map : HashMap<K, V, S>,
    default : V,
    pending : Option<(K, V)>
}

impl<K, V> SimpleMap<K, V>
where K : Ord+Clone+Hash,
      V : Clone+Eq+Default,
{
    /// Create a `SimpleMap`.
    ///
    /// `Default::default()` will be used as a default value.
    pub fn new() -> SimpleMap<K, V, DefaultState<FnvHasher>> {
        SimpleMap {
            map : Default::default(),
            default: Default::default(),
            pending: None,
        }
    }
}

impl<K, V, S> SimpleMap<K, V, S>
where K : Ord+Clone+Hash,
      V : Clone+Eq+Default,
      S : HashState+Default
{
    /// Create a `SimpleMap`.
    ///
    /// `Default::default()` will be used as a default value.
    pub fn with_hash_state(hash_state : S) -> SimpleMap<K, V, S> {
        SimpleMap {
            map : HashMap::with_hash_state(hash_state),
            default: Default::default(),
            pending: None,
        }
    }
}

impl<K, V> SimpleMap<K, V>
where K : Ord+Clone+Hash,
      V : Clone+Eq,
{
    /// Create a `SimpleMap` with custom default value.
    pub fn new_with_default(default : V) -> SimpleMap<K, V, DefaultState<FnvHasher>> {
        SimpleMap {
            map : Default::default(),
            default: default,
            pending: None,
        }
    }
}

impl<K, V, S> SimpleMap<K, V, S>
where K : Ord+Clone+Hash,
      S : HashState+Default,
      V : Clone+Eq,
{
    pub fn with_default_with_hash_state(default : V, hash_state: S) -> SimpleMap<K, V, S> {
        SimpleMap {
            map : HashMap::with_hash_state(hash_state),
            default: default,
            pending: None,
        }
    }
}

impl<K, V, S> SimpleMap<K, V, S>
where K : Ord+Clone+Hash,
      V : Clone+Eq,
      S: HashState,
{
    fn apply_pending(&mut self) {
       match self.pending {
           Some(ref pending) => {
               let &(ref idx , ref val) = pending;
               if *val == self.default {
                   self.map.remove(idx);
               } else {
                   self.map.insert(idx.clone(), val.clone());
               }
           },
           None => {}
       }
       self.pending = None;
    }

    /// Make sure to remove all elements with default value.
    pub fn compact(&mut self) {
        self.apply_pending();
    }

    /// Iterator over map elements with non-default values.
    ///
    /// Note: It might return elements with default value, unless `compact`
    /// is called before `iter()`.
    pub fn iter<'a>(&'a self) -> Chain<std::collections::hash_map::Iter<'a, K, V>, std::iter::Map<std::option::Iter<'a, (K, V)>, fn(&'a (K, V)) -> (&'a K, &'a V)>> {
        let SimpleMap {
            ref map,
            ref pending,
            ..
        } = *self;

        let f: fn(&'a (K, V)) -> (&'a K, &'a V) = ref_to_tuple_to_tuple_of_refs;

        map.iter().chain(pending.iter().map(f))
    }
}

impl<K, V, S> SimpleMap<K, V, S>
where K : Ord+Clone+Hash,
      S: HashState,
      V : Clone+Eq,
{
    /// Iterator yielding (K, V) instead of (&K, &V)
    pub fn iter_cloned<'a>(&'a self) ->
        Chain<
            std::iter::Map<std::collections::hash_map::Iter<'a, K, V>, fn((&'a K, &'a V)) -> (K, V)>,
            std::iter::Cloned<std::option::Iter<'a, (K, V)>>
        >
    {
        let SimpleMap {
            ref map,
            ref pending,
            ..
        } = *self;

        let f: fn((&'a K, &'a V)) -> (K, V) = tuple_of_refs_to_tuple;

        map.iter().map(f).chain(pending.iter().cloned())
    }

}

fn ref_to_tuple_to_tuple_of_refs<'a, K, V>(t : &'a(K, V)) -> (&'a K, &'a V) {
    let &(ref i, ref t) = t;
    (i, t)
}

fn tuple_of_refs_to_tuple<'a, K : Clone, V : Clone>(t : (&'a K, &'a V)) -> (K, V) {
    let (i, t) = t;
    (i.clone(), t.clone())
}

use std::iter::FromIterator;
use std::iter::IntoIterator;

impl<K, V, S> FromIterator<(K, V)> for SimpleMap<K, V, S>
where K: Ord+Hash, V: Default,
      S: HashState+Default {
    fn from_iter<I>(iterator: I) -> SimpleMap<K, V, S>
        where I: IntoIterator<Item=(K, V)> {
            SimpleMap {
                default: Default::default(),
                map: FromIterator::from_iter(iterator),
                pending: None,
            }
    }
}

/// ```
/// use simplemap::SimpleMap;
///
/// let mut map = SimpleMap::new();
///
/// let val : u32 = map[0u32];
/// assert_eq!(val, 0);
/// ```
impl<K, V, S> Index<K> for SimpleMap<K, V, S>
where K : Ord+Hash,
      S : HashState+Default,
{
    type Output = V;
    fn index<'a>(&'a self, index: K) -> &'a V {
        match self.pending {
            Some(ref pending) => {
               let &(ref i, ref val) = pending;
               if *i == index {
                   return val
               }
            }
            None => {},
        }

        match self.map.get(&index) {
            Some(entry) => entry,
            None => &self.default,
        }
    }
}

/// ```
/// use simplemap::SimpleMap;
///
/// let mut map = SimpleMap::new();
///
/// map[1u32] = 3i32;
/// assert_eq!(map[1], 3);
/// ```
impl<K, V, S> IndexMut<K> for SimpleMap<K, V, S>
where
K : Ord+Clone+Hash,
V : Clone+Eq,
      S : HashState+Default,
{
    fn index_mut<'a>(&'a mut self, index: K) -> &'a mut V {
        self.apply_pending();

        match self.map.entry(index.clone()) {
            Entry::Occupied(entry) => {
                self.pending = Some((index, entry.get().clone()));
                let &mut (_, ref mut val) = self.pending.as_mut().unwrap();
                val
            },
            Entry::Vacant(_) => {
                self.pending = Some((index, self.default.clone()));
                let &mut (_, ref mut val) = self.pending.as_mut().unwrap();
                val
            }
        }
    }
}

impl<K, V, S> fmt::Debug for SimpleMap<K, V, S>
where K : Ord+Eq+Clone+Hash+fmt::Debug,
      V : Clone+Eq+fmt::Debug,
      S: HashState,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_map().entries(self.iter()).finish()
    }
}

impl<K, V> Default for SimpleMap<K, V>
where K : Ord+Clone+Hash,
      V : Clone+Eq+Default,
{
     fn default() -> Self {
         SimpleMap::with_default_with_hash_state(Default::default(), Default::default())
     }
}

#[cfg(test)]
mod tests {
    pub use super::*;
    use std::collections::HashMap;
    use std::collections::hash_state::{DefaultState};
    use fnv::FnvHasher;
    use rand::Rng;
    use rand;

    #[test]
    fn default() {
        let map = SimpleMap::new_with_default(5u32);
        assert_eq!(map[1u32], 5u32);
    }

    #[test]
    fn iter() {
        let mut map = SimpleMap::new();

        map[0u32] = 3i32; // counts
        map[1u32] = 0i32; // default, doesn't count
        map[2u32] = 2i32; // counts
        map[0u32] = 2i32; // replaces the existing one
        let _ = map[0u32]; // shouldn't change anything

        map.compact();
        assert_eq!(map.iter().count(), 2);
    }

    #[test]
    fn random() {
        let mut bmap : HashMap<_, _, DefaultState<FnvHasher>> = Default::default();
        let mut smap = SimpleMap::new();

        let mut rng = rand::thread_rng();

        for val in 0u32..10000 {
            let idx = rng.gen_range(-5i32, 5);
            let bval = *bmap.get(&idx).unwrap_or(&Default::default());
            let sval = smap[idx];
            assert_eq!(bval, sval);
            bmap.insert(idx, val);
            smap[idx] = val;
        }
    }

    #[test]
    fn strings() {
        let mut smap = SimpleMap::new();

        smap["one"] = 1u32;
        smap["two"] = 2u32;

        assert_eq!(smap["zero"], 0u32);
    }

#[cfg(feature="bench")]
    mod bench {
        use std::collections::BTreeMap;
        use std::collections::HashMap;
        use std::collections::hash_state::{DefaultState};
        use fnv::FnvHasher;
        use super::*;
        use test::Bencher;
        use test;
#[bench]
        fn normal_btreemap_insert(b : &mut Bencher) {
            let mut map = BTreeMap::new();

            let mut i = 0u32;
            b.iter(|| {
                map.insert(i, i);
                i = i.wrapping_add(i);
            });
        }

#[bench]
        fn normal_btreemap_get(b : &mut Bencher) {
            let mut map = BTreeMap::new();

            for i in 0u32..10000 {
                map.insert(i, i);
            }

            let mut i = 0u32;
            b.iter(|| {
                test::black_box(map.get(&i));
                i = i.wrapping_add(i);
            });
        }

#[bench]
        fn normal_hashmap_insert(b : &mut Bencher) {
            let mut map : HashMap<_, _, DefaultState<FnvHasher>> = Default::default();

            let mut i = 0u32;
            b.iter(|| {
                map.insert(i, i);
                i = i.wrapping_add(i);
            });
        }

#[bench]
        fn normal_hashmap_get(b : &mut Bencher) {
            let mut map : HashMap<_, _, DefaultState<FnvHasher>> = Default::default();

            for i in 0u32..10000 {
                map.insert(i, i);
            }

            let mut i = 0u32;
            b.iter(|| {
                test::black_box(map.get(&i));
                i = i.wrapping_add(i);
            });
        }

#[bench]
        fn compact_map_idx_assign(b : &mut Bencher) {
            let mut map = SimpleMap::new();

            let mut i = 0u32;
            b.iter(|| {
                map[i] = i;
                i = i.wrapping_add(i);
            });
        }

#[bench]
        fn compact_map_idx_get(b : &mut Bencher) {
            let mut map = SimpleMap::new();

            for i in 0u32..10000 {
                map[i] = i;
            }

            let mut i = 0u32;
            b.iter(|| {
                test::black_box(map[i]);
                i = i.wrapping_add(i);
            });
        }
    }
}
<|endoftext|>


<commit_before>/*!

This crate provides some macros for quickly parsing values out of text.  Roughly speaking, it does the inverse of the `print!`/`format!` macros; or, in other words, a similar job to `scanf` from C.

The macros of interest are:

* [`readln!`](macro.readln!.html) - reads and scans a line from standard input.
* [`try_readln!`](macro.try_readln!.html) - like `readln!`, except it returns a `Result` instead of panicking.
* [`scan!`](macro.scan!.html) - scans the provided string.

If you are interesting in implementing support for your own types, see the [`ScanFromStr`](scanner/trait.ScanFromStr.html) trait.

## Features

The following optional features are available:

* `arrays-32`: implement scanning for arrays of up to 32 elements.  The default is up to 8 elements.

* `tuples-16`: implement scanning for tuples of up to 16 elements.  The default is up to 4 elements.

## Quick Examples

Here is a simple CLI program that asks the user their name and age.  You can run this using `cargo run --example ask_age`.

```ignore
#[macro_use] extern crate scan_rules;

use scan_rules::scanner::Word;

fn main() {
    print!("What's your name? ");
    let name: String = readln! { (let name: Word<String>) => name };
    //                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ rule
    //                                                       ^~~^ body
    //                           ^~~~~~~~~~~~~~~~~~~~~~~^ pattern
    //                            ^~~~~~~~~~~~~~~~~~~~~^ variable binding

    print!("Hi, {}.  How old are you? ", name);
    readln! {
        (let age) => {
    //   ^~~~~~^ implicitly typed variable binding
            let age: i32 = age;
            println!("{} years old, huh?  Neat.", age);
        },
        (..other) => println!("`{}` doesn't *look* like a number...", other),
    //   ^~~~~~^ bind to any input "left over"
    }
}
```

This example shows how to parse one of several different syntaxes.  You can run this using `cargo run --example scan_data`.

```ignore
#[macro_use] extern crate scan_rules;

use std::collections::BTreeSet;
use scan_rules::scanner::Word;

#[derive(Debug)]
enum Data {
    Vector(i32, i32, i32),
    Truthy(bool),
    Words(Vec<String>),
    Lucky(BTreeSet<i32>),
    Other(String),
}

fn main() {
    print!("Enter some data: ");
    let data = readln! {
        ("<", let x, ",", let y, ",", let z, ">") => Data::Vector(x, y, z),
    //      ^ pattern terms are comma-separated
    //   ^~^ literal text match

        // Rules are tried top-to-bottom, stopping as soon as one matches.
        (let b) => Data::Truthy(b),
        ("yes") => Data::Truthy(true),
        ("no") => Data::Truthy(false),

        ("words:", [ let words: Word<String> ],+) => Data::Words(words),
    //             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~^ repetition pattern
    //                                         ^ one or more matches
    //                                        ^ matches must be comma-separated

        ("lucky numbers:", [ let ns: i32 ]*: BTreeSet<_>) => Data::Lucky(ns),
    //          collect into specific type ^~~~~~~~~~~~^
    //                                    ^ zero or more (you might be unlucky!)
    //                                      (no separator this time)

        // Rather than scanning a sequence of values and collecting them into
        // a `BTreeSet`, we can instead scan the `BTreeSet` *directly*.  This
        // scans the syntax `BTreeSet` uses when printed using `{:?}`:
        // `{1, 5, 13, ...}`.
        ("lucky numbers:", let ns) => Data::Lucky(ns),

        (..other) => Data::Other(String::from(other))
    };
    println!("data: {:?}", data);
}
```

## Pattern Syntax

A scanning pattern is made up of one or more pattern terms, separated by commas.  The following terms are supported:

* *strings* - any expression that evaluates to a string will be used as a literal match on the input.  Exactly *how* this match is done depends on the kind of input, but the default is to do a case-sensitive match of whole words, individual non-letter characters, and to ignore all whitespace.

  *E.g.* `"Two words"`, `"..."` (counts as three "words"), `&format!("{} {}", "Two", "words")`.

* `let` *name* \[ `:` *type* ] - scans a value out of the input text, and binds it to *name*.  If *type* is omitted, it will be inferred.

  *E.g.* `let x`, `let n: i32`, `let words: Vec<_>`, `let _: &str` (scans and discards a value).

* `..` *name* - binds the remaining, unscanned input as a string to *name*.  This can *only* appear as the final term in a top-level pattern.

* `[` *pattern* `]` \[ *(nothing)* | `,` | `(` *seperator pattern* `)` ] ( `?` | `*` | `+` | `{` *range* `}` ) \[ ":" *collection type* ] - scans *pattern* repeatedly.

  The first (mandatory) part of the term specifies the *pattern* that should be repeatedly scanned.

  The second (optional) part of the term controls if (and what) repeats are separated by.  `,` is provided as a short-cut to an obvious common case; it is equivalent to writing `(",")`.  Otherwise, you may write any arbitrary *separator pattern* as the separator, including variable bindings and more repetitions.

  The third (mandatory) part of the term specifies how many times *pattern* should be scanned.  The available options are:

  * `?` - match zero or one times.
  * `*` - match zero or more times.
  * `+` - match one or more times.
  * `{n}` - match exactly *n* times.
  * `{a,}` - match at least *a* times.
  * `{,b}` - match at most *b* times.
  * `{a, b}` - match at least *a* times, and at most *b* times.

  The fourth (optional) part of the term specifies what type of collection scanned values should be added to.  Note that the type specified here applies to *all* values captured by this repetition.  As such, you typically want to use a partially inferred type such as `BTreeSet<_>`.  If omitted, it defaults to `Vec<_>`.

  *E.g.* `[ let nums: i32 ],+`, `[ "pretty" ]*, "please"`.

## Things What Need Mentioning

* *Rule* syntax.
* Scanners and things like `Word` being abstract.
* Cursor(s).
* More examples.
* `#![recursion_limit]`

*/
#![forbid(missing_docs)]
#![recursion_limit="128"]
#[macro_use] extern crate lazy_static;
extern crate itertools;
extern crate regex;
extern crate strcursor;

#[macro_use] mod macros;

pub use error::{ScanError, ScanErrorKind};

mod error;
pub mod input;
pub mod scanner;

/**
Remove a single trailing line terminator from `s`.

This is publicly exposed for the sake of macros and **is not** considered a stable part of the public API.
*/
#[doc(hidden)]
pub fn strip_line_term(s: &str) -> &str {
    if s.ends_with("\r\n") {
        &s[0..s.len()-2]
    } else if s.ends_with("\n") {
        &s[0..s.len()-1]
    } else if s.ends_with("\r") {
        &s[0..s.len()-1]
    } else {
        s
    }
}

/**
Compute the offset of `b`, which must be a subslice of `a`.

This is publicly exposed for the sake of macros and **is not** considered a stable part of the public API.
*/
#[doc(hidden)]
pub fn subslice_offset(a: &str, b: &str) -> Option<usize> {
    use scanner::util::StrUtil;
    a.subslice_offset(b)
}
<commit_msg>Added link block to crate docs.<commit_after>/*!

This crate provides some macros for quickly parsing values out of text.  Roughly speaking, it does the inverse of the `print!`/`format!` macros; or, in other words, a similar job to `scanf` from C.

The macros of interest are:

* [`readln!`](macro.readln!.html) - reads and scans a line from standard input.
* [`try_readln!`](macro.try_readln!.html) - like `readln!`, except it returns a `Result` instead of panicking.
* [`scan!`](macro.scan!.html) - scans the provided string.

If you are interesting in implementing support for your own types, see the [`ScanFromStr`](scanner/trait.ScanFromStr.html) trait.

**Links**

* [Latest Release](https://crates.io/crates/scan-rules/)
* [Latest Docs](https://danielkeep.github.io/rust-scan-rules/doc/scan_rules/index.html)
* [Repository](https://github.com/DanielKeep/rust-scan-rules)

## Features

The following optional features are available:

* `arrays-32`: implement scanning for arrays of up to 32 elements.  The default is up to 8 elements.

* `tuples-16`: implement scanning for tuples of up to 16 elements.  The default is up to 4 elements.

## Quick Examples

Here is a simple CLI program that asks the user their name and age.  You can run this using `cargo run --example ask_age`.

```ignore
#[macro_use] extern crate scan_rules;

use scan_rules::scanner::Word;

fn main() {
    print!("What's your name? ");
    let name: String = readln! { (let name: Word<String>) => name };
    //                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ rule
    //                                                       ^~~^ body
    //                           ^~~~~~~~~~~~~~~~~~~~~~~^ pattern
    //                            ^~~~~~~~~~~~~~~~~~~~~^ variable binding

    print!("Hi, {}.  How old are you? ", name);
    readln! {
        (let age) => {
    //   ^~~~~~^ implicitly typed variable binding
            let age: i32 = age;
            println!("{} years old, huh?  Neat.", age);
        },
        (..other) => println!("`{}` doesn't *look* like a number...", other),
    //   ^~~~~~^ bind to any input "left over"
    }
}
```

This example shows how to parse one of several different syntaxes.  You can run this using `cargo run --example scan_data`.

```ignore
#[macro_use] extern crate scan_rules;

use std::collections::BTreeSet;
use scan_rules::scanner::Word;

#[derive(Debug)]
enum Data {
    Vector(i32, i32, i32),
    Truthy(bool),
    Words(Vec<String>),
    Lucky(BTreeSet<i32>),
    Other(String),
}

fn main() {
    print!("Enter some data: ");
    let data = readln! {
        ("<", let x, ",", let y, ",", let z, ">") => Data::Vector(x, y, z),
    //      ^ pattern terms are comma-separated
    //   ^~^ literal text match

        // Rules are tried top-to-bottom, stopping as soon as one matches.
        (let b) => Data::Truthy(b),
        ("yes") => Data::Truthy(true),
        ("no") => Data::Truthy(false),

        ("words:", [ let words: Word<String> ],+) => Data::Words(words),
    //             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~^ repetition pattern
    //                                         ^ one or more matches
    //                                        ^ matches must be comma-separated

        ("lucky numbers:", [ let ns: i32 ]*: BTreeSet<_>) => Data::Lucky(ns),
    //          collect into specific type ^~~~~~~~~~~~^
    //                                    ^ zero or more (you might be unlucky!)
    //                                      (no separator this time)

        // Rather than scanning a sequence of values and collecting them into
        // a `BTreeSet`, we can instead scan the `BTreeSet` *directly*.  This
        // scans the syntax `BTreeSet` uses when printed using `{:?}`:
        // `{1, 5, 13, ...}`.
        ("lucky numbers:", let ns) => Data::Lucky(ns),

        (..other) => Data::Other(String::from(other))
    };
    println!("data: {:?}", data);
}
```

## Pattern Syntax

A scanning pattern is made up of one or more pattern terms, separated by commas.  The following terms are supported:

* *strings* - any expression that evaluates to a string will be used as a literal match on the input.  Exactly *how* this match is done depends on the kind of input, but the default is to do a case-sensitive match of whole words, individual non-letter characters, and to ignore all whitespace.

  *E.g.* `"Two words"`, `"..."` (counts as three "words"), `&format!("{} {}", "Two", "words")`.

* `let` *name* \[ `:` *type* ] - scans a value out of the input text, and binds it to *name*.  If *type* is omitted, it will be inferred.

  *E.g.* `let x`, `let n: i32`, `let words: Vec<_>`, `let _: &str` (scans and discards a value).

* `..` *name* - binds the remaining, unscanned input as a string to *name*.  This can *only* appear as the final term in a top-level pattern.

* `[` *pattern* `]` \[ *(nothing)* | `,` | `(` *seperator pattern* `)` ] ( `?` | `*` | `+` | `{` *range* `}` ) \[ ":" *collection type* ] - scans *pattern* repeatedly.

  The first (mandatory) part of the term specifies the *pattern* that should be repeatedly scanned.

  The second (optional) part of the term controls if (and what) repeats are separated by.  `,` is provided as a short-cut to an obvious common case; it is equivalent to writing `(",")`.  Otherwise, you may write any arbitrary *separator pattern* as the separator, including variable bindings and more repetitions.

  The third (mandatory) part of the term specifies how many times *pattern* should be scanned.  The available options are:

  * `?` - match zero or one times.
  * `*` - match zero or more times.
  * `+` - match one or more times.
  * `{n}` - match exactly *n* times.
  * `{a,}` - match at least *a* times.
  * `{,b}` - match at most *b* times.
  * `{a, b}` - match at least *a* times, and at most *b* times.

  The fourth (optional) part of the term specifies what type of collection scanned values should be added to.  Note that the type specified here applies to *all* values captured by this repetition.  As such, you typically want to use a partially inferred type such as `BTreeSet<_>`.  If omitted, it defaults to `Vec<_>`.

  *E.g.* `[ let nums: i32 ],+`, `[ "pretty" ]*, "please"`.

## Things What Need Mentioning

* *Rule* syntax.
* Scanners and things like `Word` being abstract.
* Cursor(s).
* More examples.
* `#![recursion_limit]`

*/
#![forbid(missing_docs)]
#![recursion_limit="128"]
#[macro_use] extern crate lazy_static;
extern crate itertools;
extern crate regex;
extern crate strcursor;

#[macro_use] mod macros;

pub use error::{ScanError, ScanErrorKind};

mod error;
pub mod input;
pub mod scanner;

/**
Remove a single trailing line terminator from `s`.

This is publicly exposed for the sake of macros and **is not** considered a stable part of the public API.
*/
#[doc(hidden)]
pub fn strip_line_term(s: &str) -> &str {
    if s.ends_with("\r\n") {
        &s[0..s.len()-2]
    } else if s.ends_with("\n") {
        &s[0..s.len()-1]
    } else if s.ends_with("\r") {
        &s[0..s.len()-1]
    } else {
        s
    }
}

/**
Compute the offset of `b`, which must be a subslice of `a`.

This is publicly exposed for the sake of macros and **is not** considered a stable part of the public API.
*/
#[doc(hidden)]
pub fn subslice_offset(a: &str, b: &str) -> Option<usize> {
    use scanner::util::StrUtil;
    a.subslice_offset(b)
}
<|endoftext|>


<commit_before>//! This crate provides x86_64 specific functions and data structures,
//! and access to various system registers.

#![cfg_attr(not(test), no_std)]
#![cfg_attr(feature = "const_fn", feature(const_fn))]
#![cfg_attr(feature = "const_fn", feature(const_in_array_repeat_expressions))]
#![cfg_attr(feature = "inline_asm", feature(llvm_asm))]
#![cfg_attr(feature = "abi_x86_interrupt", feature(abi_x86_interrupt))]
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![cfg_attr(feature = "deny-warnings", deny(missing_docs))]
#![cfg_attr(not(feature = "deny-warnings"), warn(missing_docs))]
#![deny(missing_debug_implementations)]

pub use crate::addr::{align_down, align_up, PhysAddr, VirtAddr};

/// Makes a function const only when `feature = "const_fn"` is enabled.
///
/// This is needed for const functions with bounds on their generic parameters,
/// such as those in `Page` and `PhysFrame` and many more.
macro_rules! const_fn {
    (
        $(#[$attr:meta])*
        pub $($fn:tt)*
    ) => {
        $(#[$attr])*
        #[cfg(feature = "const_fn")]
        pub const $($fn)*

        $(#[$attr])*
        #[cfg(not(feature = "const_fn"))]
        pub $($fn)*
    }
}

#[cfg(all(feature = "instructions", feature = "external_asm"))]
pub(crate) mod asm;

pub mod addr;
pub mod instructions;
pub mod registers;
pub mod structures;

/// Represents a protection ring level.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum PrivilegeLevel {
    /// Privilege-level 0 (most privilege): This level is used by critical system-software
    /// components that require direct access to, and control over, all processor and system
    /// resources. This can include BIOS, memory-management functions, and interrupt handlers.
    Ring0 = 0,

    /// Privilege-level 1 (moderate privilege): This level is used by less-critical system-
    /// software services that can access and control a limited scope of processor and system
    /// resources. Software running at these privilege levels might include some device drivers
    /// and library routines. The actual privileges of this level are defined by the
    /// operating system.
    Ring1 = 1,

    /// Privilege-level 2 (moderate privilege): Like level 1, this level is used by
    /// less-critical system-software services that can access and control a limited scope of
    /// processor and system resources. The actual privileges of this level are defined by the
    /// operating system.
    Ring2 = 2,

    /// Privilege-level 3 (least privilege): This level is used by application software.
    /// Software running at privilege-level 3 is normally prevented from directly accessing
    /// most processor and system resources. Instead, applications request access to the
    /// protected processor and system resources by calling more-privileged service routines
    /// to perform the accesses.
    Ring3 = 3,
}

impl PrivilegeLevel {
    /// Creates a `PrivilegeLevel` from a numeric value. The value must be in the range 0..4.
    ///
    /// This function panics if the passed value is >3.
    #[inline]
    pub fn from_u16(value: u16) -> PrivilegeLevel {
        match value {
            0 => PrivilegeLevel::Ring0,
            1 => PrivilegeLevel::Ring1,
            2 => PrivilegeLevel::Ring2,
            3 => PrivilegeLevel::Ring3,
            i => panic!("{} is not a valid privilege level", i),
        }
    }
}
<commit_msg>Fix build error on latest nightly (#182)<commit_after>//! This crate provides x86_64 specific functions and data structures,
//! and access to various system registers.

#![cfg_attr(not(test), no_std)]
#![cfg_attr(feature = "const_fn", feature(const_fn))]
#![cfg_attr(feature = "const_fn", feature(const_mut_refs))]
#![cfg_attr(feature = "const_fn", feature(const_in_array_repeat_expressions))]
#![cfg_attr(feature = "inline_asm", feature(llvm_asm))]
#![cfg_attr(feature = "abi_x86_interrupt", feature(abi_x86_interrupt))]
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![cfg_attr(feature = "deny-warnings", deny(missing_docs))]
#![cfg_attr(not(feature = "deny-warnings"), warn(missing_docs))]
#![deny(missing_debug_implementations)]

pub use crate::addr::{align_down, align_up, PhysAddr, VirtAddr};

/// Makes a function const only when `feature = "const_fn"` is enabled.
///
/// This is needed for const functions with bounds on their generic parameters,
/// such as those in `Page` and `PhysFrame` and many more.
macro_rules! const_fn {
    (
        $(#[$attr:meta])*
        pub $($fn:tt)*
    ) => {
        $(#[$attr])*
        #[cfg(feature = "const_fn")]
        pub const $($fn)*

        $(#[$attr])*
        #[cfg(not(feature = "const_fn"))]
        pub $($fn)*
    }
}

#[cfg(all(feature = "instructions", feature = "external_asm"))]
pub(crate) mod asm;

pub mod addr;
pub mod instructions;
pub mod registers;
pub mod structures;

/// Represents a protection ring level.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum PrivilegeLevel {
    /// Privilege-level 0 (most privilege): This level is used by critical system-software
    /// components that require direct access to, and control over, all processor and system
    /// resources. This can include BIOS, memory-management functions, and interrupt handlers.
    Ring0 = 0,

    /// Privilege-level 1 (moderate privilege): This level is used by less-critical system-
    /// software services that can access and control a limited scope of processor and system
    /// resources. Software running at these privilege levels might include some device drivers
    /// and library routines. The actual privileges of this level are defined by the
    /// operating system.
    Ring1 = 1,

    /// Privilege-level 2 (moderate privilege): Like level 1, this level is used by
    /// less-critical system-software services that can access and control a limited scope of
    /// processor and system resources. The actual privileges of this level are defined by the
    /// operating system.
    Ring2 = 2,

    /// Privilege-level 3 (least privilege): This level is used by application software.
    /// Software running at privilege-level 3 is normally prevented from directly accessing
    /// most processor and system resources. Instead, applications request access to the
    /// protected processor and system resources by calling more-privileged service routines
    /// to perform the accesses.
    Ring3 = 3,
}

impl PrivilegeLevel {
    /// Creates a `PrivilegeLevel` from a numeric value. The value must be in the range 0..4.
    ///
    /// This function panics if the passed value is >3.
    #[inline]
    pub fn from_u16(value: u16) -> PrivilegeLevel {
        match value {
            0 => PrivilegeLevel::Ring0,
            1 => PrivilegeLevel::Ring1,
            2 => PrivilegeLevel::Ring2,
            3 => PrivilegeLevel::Ring3,
            i => panic!("{} is not a valid privilege level", i),
        }
    }
}
<|endoftext|>


<commit_before>//! **Leaf is a open, fast and a well-designed, modular Framework for distributed Deep Learning on
//! {C, G}PUs.**
//!
//! ## Overview
//!
//! To build a Deep Neural Network you create a [Network][network] which is a container for all
//! different types of [Layers][layers]. These layers are grouped in different types such as
//! [Activation Layers][activation], [Loss Layers][loss] which states the characteristics of the
//! layer.
//!
//! Now to train your network you will use one of the [Solvers][solvers]. The Solver defines the
//! [Optimization Method][optimization] and keeps track on the learning progress.
//!
//! The operations can run on different Backends {CPU, GPU} and must not be defined at compile
//! time, which allows for easy backend swapping.
//!
//! ## Examples
//!
//! ```
//! # extern crate leaf;
//! # use leaf::network::{NetworkConfig};
//! # fn main() {
//! # }
//! ```
//!
//! ## Development
//!
//! The implementation of various Layers is pretty scarce at the moment.
//! There are around a dozen layers, which are really important and would increase the value and
//! functionality of Leaf tremendously.
//! Progress get tracked at
//! - [Issue #18 for Loss Layers][issue-loss]
//! - [Issue #19 for Activation Layers][issue-activation]
//! - [Issue #20 for Common Layers][issue-common]
//!
//! To better structure these different layer types and state their functionality and behavior more
//! clearly, we will give them their own mod. [Issue #21][issue-mod]
//!
//! [network]: ./network/index.html
//! [layers]: ./layers/index.html
//! [activation]: #
//! [loss]: #
//! [solvers]: ./solvers/index.html
//! [optimization]: https://en.wikipedia.org/wiki/Stochastic_optimization
//!
//! [issue-loss]: https://github.com/autumnai/leaf/issues/18
//! [issue-activation]: https://github.com/autumnai/leaf/issues/19
//! [issue-common]: https://github.com/autumnai/leaf/issues/20
//! [issue-mod]: https://github.com/autumnai/leaf/issues/21
#![feature(plugin)]
#![feature(augmented_assignments)]
#![plugin(clippy)]
#![allow(dead_code)]
#![allow(unused_variables)]
#![deny(missing_docs,
        missing_debug_implementations, missing_copy_implementations,
        trivial_casts, trivial_numeric_casts,
        unsafe_code,
        unused_import_braces, unused_qualifications)]

#[macro_use]
extern crate log;
extern crate rblas;
extern crate phloem;
pub mod shared_memory;
mod math;
/// The Layer and Layer Interface
pub mod layer;
pub mod layers;
/// The Solver
pub mod solver;
/// The specific Solvers
pub mod solvers;
pub mod network;
<commit_msg>docs(lib): add project philosophie<commit_after>//! Leaf is a open, fast and a well-designed, modular Framework for distributed Deep Learning on
//! {C, G}PUs.
//!
//! ## Overview
//!
//! To build a Deep Neural Network you create a [Network][network] which is a container for all
//! different types of [Layers][layers]. These layers are grouped in different types such as
//! [Activation Layers][activation] and [Loss Layers][loss] which states the characteristics of the
//! layer.
//!
//! Now to train your network you will use one of the [Solvers][solvers]. The Solver defines the
//! [Optimization Method][optimization] and keeps track on the learning progress.
//!
//! The operations can run on different Backends {CPU, GPU} and must not be defined at compile
//! time, which allows for easy backend swapping.
//!
//! ## Philosophie
//!
//! We are strong believers in the technology of Machine Learning. We put our experience in
//! software engineering into Leaf, to solve our own need for a modern, performant and easy-to-use
//! Deep Learning Framework. These principles direct our decisions on Leaf and related projects.
//!
//! * __Performance__: For research and industry speed and efficency are curcial for
//! state-of-the-art machine learning over massive data and networks.
//! * __Architecture__: Designing an open architecture that follows best practices and concepts in
//! Engineering such as modularity, flexibility and expressiveness is critical to stimulate future
//! innovation.
//! * __Documentation__: A well-written documentation that addresses both concepts and
//! implementations, empowers developers and researchers to contribute their unique experience to
//! the project for the benefit of everyone.
//!
//! ## Examples
//!
//! ```
//! # extern crate leaf;
//! # use leaf::network::{NetworkConfig};
//! # fn main() {
//! # }
//! ```
//!
//! ## Development
//!
//! The implementation of various Layers is pretty scarce at the moment.

//! There are around a dozen layers, which are really important and would increase the value and
//! functionality of Leaf tremendously.

//! Progress get tracked at

//!
//! - [Issue #18 for Loss Layers][issue-loss]
//! - [Issue #19 for Activation Layers][issue-activation]
//! - [Issue #20 for Common Layers][issue-common]
//!
//! [network]: ./network/index.html
//! [layers]: ./layers/index.html
//! [activation]: ./layers/activation/index.html
//! [loss]: ./layers/loss/index.html
//! [solvers]: ./solvers/index.html
//! [optimization]: https://en.wikipedia.org/wiki/Stochastic_optimization
//!
//! [issue-loss]: https://github.com/autumnai/leaf/issues/18
//! [issue-activation]: https://github.com/autumnai/leaf/issues/19
//! [issue-common]: https://github.com/autumnai/leaf/issues/20
#![feature(plugin)]
#![feature(augmented_assignments)]
#![plugin(clippy)]
#![allow(dead_code)]
#![allow(unused_variables)]
#![deny(missing_docs,
        missing_debug_implementations, missing_copy_implementations,
        trivial_casts, trivial_numeric_casts,
        unsafe_code,
        unused_import_braces, unused_qualifications)]

#[macro_use]
extern crate log;
extern crate rblas;
extern crate phloem;
pub mod shared_memory;
mod math;
/// The Layer and Layer Interface
pub mod layer;
pub mod layers;
/// The Solver
pub mod solver;
/// The specific Solvers
pub mod solvers;
pub mod network;
<|endoftext|>


<commit_before>use std::io::Read;
use std::sync::mpsc::channel;
use std::sync::mpsc::Receiver;
use std::thread;

const LF: u8 = 10;
const CR: u8 = 13;
const QUOTE: u8 = 34;
const COMMA: u8 = 44;

// Error messages
pub const UNEXPECTED_EOL: &'static str = "Unexpected end of line";
pub const UNEXPECTED_CHAR: &'static str = "Unexpected character after quote";
pub const EXPECTED_LF: &'static str = "Expected linefeed after carriage return";

enum CSVState {
    Start,
    NonQuotedValue,
    QuotedValue,
    QuoteQuote,
    ExpectLF,
    Error,
}

type CSVResult = Result<CSVState, &'static str>;

#[derive(Debug, PartialEq, Eq)]
pub struct CSVError {
    pub line: i32,
    pub col: i32,
    pub text: &'static str,
}

fn parse_start(byte: u8) -> CSVResult {
    match byte {
        QUOTE => Ok(CSVState::QuotedValue),
        COMMA => Ok(CSVState::Start),
        _ => Ok(CSVState::NonQuotedValue),
    }
}

fn parse_non_quoted(byte: u8) -> CSVResult {
    match byte {
        COMMA | LF => Ok(CSVState::Start),
        CR => Ok(CSVState::ExpectLF),
        _ => Ok(CSVState::NonQuotedValue),
    }
}

fn parse_quoted(byte: u8) -> CSVResult {
    match byte {
        QUOTE => Ok(CSVState::QuoteQuote),
        CR | LF => Err(UNEXPECTED_EOL),
        _ => Ok(CSVState::QuotedValue),
    }
}

fn parse_quote_quote(byte: u8) -> CSVResult {
    match byte {
        QUOTE => Ok(CSVState::QuotedValue),
        COMMA | LF => Ok(CSVState::Start),
        CR => Ok(CSVState::ExpectLF),
        _ => Err(UNEXPECTED_CHAR),
    }
}

fn parse_cr(byte: u8) -> CSVResult {
    match byte {
        LF => Ok(CSVState::Start),
        _ => Err(EXPECTED_LF),
    }
}

fn parse_err(byte: u8) -> CSVResult {
    match byte {
        LF => Ok(CSVState::Start),
        _ => Ok(CSVState::Error),
    }
}

fn next_state(state: CSVState, byte: u8) -> CSVResult {
    match state {
        CSVState::Start => parse_start(byte),
        CSVState::NonQuotedValue => parse_non_quoted(byte),
        CSVState::QuotedValue => parse_quoted(byte),
        CSVState::QuoteQuote => parse_quote_quote(byte),
        CSVState::ExpectLF => parse_cr(byte),
        CSVState::Error => parse_err(byte),
    }
}

pub fn publish_errors_for_csv<T: Read + Send + 'static>(reader: T) -> Receiver<CSVError> {
    let (sender, receiver) = channel();

    thread::spawn(move || {
        let mut state = CSVState::Start;
        let mut line = 1;
        let mut col = 0;

        for b in reader.bytes() {
            let byte = b.unwrap();

            state = match next_state(state, byte) {
                Ok(new_state) => new_state,
                Err(error) => {
                    sender.send(CSVError {
                        line: line,
                        col: col,
                        text: error,
                    }).unwrap();
                    match error {
                        UNEXPECTED_EOL => CSVState::Start,
                        _ => CSVState::Error
                    }
                }
            };

            if byte == LF {
                line += 1;
                col = 0;
            } else {
                col += 1;
            }
        }
    });

    receiver
}
<commit_msg>No more ASCII magic numbers<commit_after>use std::io::Read;
use std::sync::mpsc::channel;
use std::sync::mpsc::Receiver;
use std::thread;

const LF: u8 = b'\n';
const CR: u8 = b'\r';
const QUOTE: u8 = b'"';
const COMMA: u8 = b',';

// Error messages
pub const UNEXPECTED_EOL: &'static str = "Unexpected end of line";
pub const UNEXPECTED_CHAR: &'static str = "Unexpected character after quote";
pub const EXPECTED_LF: &'static str = "Expected linefeed after carriage return";

enum CSVState {
    Start,
    NonQuotedValue,
    QuotedValue,
    QuoteQuote,
    ExpectLF,
    Error,
}

type CSVResult = Result<CSVState, &'static str>;

#[derive(Debug, PartialEq, Eq)]
pub struct CSVError {
    pub line: i32,
    pub col: i32,
    pub text: &'static str,
}

fn parse_start(byte: u8) -> CSVResult {
    match byte {
        QUOTE => Ok(CSVState::QuotedValue),
        COMMA => Ok(CSVState::Start),
        _ => Ok(CSVState::NonQuotedValue),
    }
}

fn parse_non_quoted(byte: u8) -> CSVResult {
    match byte {
        COMMA | LF => Ok(CSVState::Start),
        CR => Ok(CSVState::ExpectLF),
        _ => Ok(CSVState::NonQuotedValue),
    }
}

fn parse_quoted(byte: u8) -> CSVResult {
    match byte {
        QUOTE => Ok(CSVState::QuoteQuote),
        CR | LF => Err(UNEXPECTED_EOL),
        _ => Ok(CSVState::QuotedValue),
    }
}

fn parse_quote_quote(byte: u8) -> CSVResult {
    match byte {
        QUOTE => Ok(CSVState::QuotedValue),
        COMMA | LF => Ok(CSVState::Start),
        CR => Ok(CSVState::ExpectLF),
        _ => Err(UNEXPECTED_CHAR),
    }
}

fn parse_cr(byte: u8) -> CSVResult {
    match byte {
        LF => Ok(CSVState::Start),
        _ => Err(EXPECTED_LF),
    }
}

fn parse_err(byte: u8) -> CSVResult {
    match byte {
        LF => Ok(CSVState::Start),
        _ => Ok(CSVState::Error),
    }
}

fn next_state(state: CSVState, byte: u8) -> CSVResult {
    match state {
        CSVState::Start => parse_start(byte),
        CSVState::NonQuotedValue => parse_non_quoted(byte),
        CSVState::QuotedValue => parse_quoted(byte),
        CSVState::QuoteQuote => parse_quote_quote(byte),
        CSVState::ExpectLF => parse_cr(byte),
        CSVState::Error => parse_err(byte),
    }
}

pub fn publish_errors_for_csv<T: Read + Send + 'static>(reader: T) -> Receiver<CSVError> {
    let (sender, receiver) = channel();

    thread::spawn(move || {
        let mut state = CSVState::Start;
        let mut line = 1;
        let mut col = 0;

        for b in reader.bytes() {
            let byte = b.unwrap();

            state = match next_state(state, byte) {
                Ok(new_state) => new_state,
                Err(error) => {
                    sender.send(CSVError {
                        line: line,
                        col: col,
                        text: error,
                    }).unwrap();
                    match error {
                        UNEXPECTED_EOL => CSVState::Start,
                        _ => CSVState::Error
                    }
                }
            };

            if byte == LF {
                line += 1;
                col = 0;
            } else {
                col += 1;
            }
        }
    });

    receiver
}
<|endoftext|>


<commit_before>extern crate petgraph;

use std::str::FromStr;
use std::fmt::Debug;
use std::io::BufRead;

use petgraph::graph::NodeIndex;
use petgraph::{Directed, Graph};

pub trait Visitor<NodeWt, EdgeWt> {
    fn init(&mut self, num_nodes: usize, num_edges: usize);
    fn node(&mut self, node_id: usize, node_weight: Option<NodeWt>);
    fn endnode(&mut self, _node_id: usize) {
    }
    fn edge(&mut self, src_id: usize, dst_id: usize, edge_weight: Option<EdgeWt>);
}

pub fn read_sgf<R, V, NodeWt, EdgeWt, I>(rd: &mut R, visitor: &mut V)
    where R: BufRead,
          V: Visitor<NodeWt, EdgeWt>,
          NodeWt: FromStr<Err = I>,
          EdgeWt: FromStr<Err = I>,
          I: Debug
{
    let mut meta: Option<(usize, usize)> = None;

    for line in rd.lines() {
        let line = line.unwrap();
        let line = line.trim();

        if line.starts_with("#") {
            // skip comment
            continue;
        }

        if meta.is_none() {
            // First non-comment line is expected to be meta
            let mut m = line.split_whitespace();
            let _version = match m.next() {
                Some("SGF/1") => {
                    1
                }
                _ => {
                    panic!("Invalid format");
                }
            };
            let num_nodes: usize = match m.next() {
                Some(ns) => {
                    ns.parse().unwrap()
                }
                _ => {
                    panic!("Invalid format");
                }
            };
            let num_edges: usize = match m.next() {
                Some(ns) => {
                    ns.parse().unwrap()
                }
                _ => {
                    panic!("Invalid format");
                }
            };

            meta = Some((num_nodes, num_edges));

            visitor.init(num_nodes, num_edges);
        } else {
            let mut i = line.splitn(2, '|');
            let (node_id, node_weight) = match i.next() {
                Some(ns) => {
                    let mut it = ns.splitn(2, ":");
                    let node_id: usize = it.next().unwrap().parse().unwrap();
                    let node_weight: Option<NodeWt> = it.next().map(|s| s.parse().unwrap());
                    (node_id, node_weight)
                }
                _ => {
                    panic!("Invalid format");
                }
            };
            visitor.node(node_id, node_weight);

            let edge_s = i.next().unwrap();
            for es in edge_s.split(',') {
                let mut it = es.splitn(2, ":");
                let target_id: usize = it.next()
                                         .unwrap()
                                         .parse()
                                         .unwrap();

                let edge_weight: Option<EdgeWt> = it.next()
                                                    .map(|s| s.parse::<EdgeWt>().unwrap());

                visitor.edge(node_id, target_id, edge_weight);
            }

            visitor.endnode(node_id);
        }
    }
}

pub struct PetgraphReader<NodeWt: Default, EdgeWt: Default> {
    graph: Graph<NodeWt, EdgeWt, Directed>,
}

impl<NodeWt, EdgeWt, I> PetgraphReader<NodeWt, EdgeWt>
where NodeWt: Default+FromStr<Err = I>,
      EdgeWt: Default+FromStr<Err = I>,
      I:Debug
{
    pub fn new() -> PetgraphReader<NodeWt, EdgeWt> {
        PetgraphReader { graph: Graph::new() }
    }

    pub fn from_sgf<R: BufRead>(rd: &mut R) -> Graph<NodeWt, EdgeWt, Directed> {
        let mut visitor = Self::new();
        read_sgf(rd, &mut visitor);
        return visitor.graph;
    }
}

impl<NodeWt:Default, EdgeWt:Default> Visitor<NodeWt, EdgeWt> for PetgraphReader<NodeWt, EdgeWt> {
    fn init(&mut self, num_nodes: usize, _num_edges: usize) {
        for _ in 0..num_nodes {
            self.graph.add_node(NodeWt::default());
        }
    }

    fn node(&mut self, node_id: usize, node_weight: Option<NodeWt>) {
        *self.graph.node_weight_mut(NodeIndex::new(node_id)).unwrap() =
            node_weight.unwrap_or(NodeWt::default());
    }

    fn edge(&mut self, src_id: usize, dst_id: usize, edge_weight: Option<EdgeWt>) {
        let _ = self.graph.add_edge(NodeIndex::new(src_id),
                                    NodeIndex::new(dst_id),
                                    edge_weight.unwrap_or(EdgeWt::default()));
    }
}
<commit_msg>Add Unweighted for parsing unweighted graphs<commit_after>extern crate petgraph;

use std::str::FromStr;
use std::fmt::Debug;
use std::io::BufRead;

use petgraph::graph::NodeIndex;
use petgraph::{Directed, Graph};

#[derive(Debug, Default, Clone, Copy)]
pub struct Unweighted;
impl FromStr for Unweighted {
type Err = &'static str;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.is_empty() {
            Ok(Unweighted)
        } else {
            Err("Invalid Unweighted string")
        }
    }
}

pub trait Visitor<NodeWt, EdgeWt> {
    fn init(&mut self, num_nodes: usize, num_edges: usize);
    fn node(&mut self, node_id: usize, node_weight: Option<NodeWt>);
    fn endnode(&mut self, _node_id: usize) {
    }
    fn edge(&mut self, src_id: usize, dst_id: usize, edge_weight: Option<EdgeWt>);
}

pub fn read_sgf<R, V, NodeWt, EdgeWt, I>(rd: &mut R, visitor: &mut V)
    where R: BufRead,
          V: Visitor<NodeWt, EdgeWt>,
          NodeWt: FromStr<Err = I>,
          EdgeWt: FromStr<Err = I>,
          I: Debug
{
    let mut meta: Option<(usize, usize)> = None;

    for line in rd.lines() {
        let line = line.unwrap();
        let line = line.trim();

        if line.starts_with("#") {
            // skip comment
            continue;
        }

        if meta.is_none() {
            // First non-comment line is expected to be meta
            let mut m = line.split_whitespace();
            let _version = match m.next() {
                Some("SGF/1") => {
                    1
                }
                _ => {
                    panic!("Invalid format");
                }
            };
            let num_nodes: usize = match m.next() {
                Some(ns) => {
                    ns.parse().unwrap()
                }
                _ => {
                    panic!("Invalid format");
                }
            };
            let num_edges: usize = match m.next() {
                Some(ns) => {
                    ns.parse().unwrap()
                }
                _ => {
                    panic!("Invalid format");
                }
            };

            meta = Some((num_nodes, num_edges));

            visitor.init(num_nodes, num_edges);
        } else {
            let mut i = line.splitn(2, '|');
            let (node_id, node_weight) = match i.next() {
                Some(ns) => {
                    let mut it = ns.splitn(2, ":");
                    let node_id: usize = it.next().unwrap().parse().unwrap();
                    let node_weight: Option<NodeWt> = it.next().map(|s| s.parse().unwrap());
                    (node_id, node_weight)
                }
                _ => {
                    panic!("Invalid format");
                }
            };
            visitor.node(node_id, node_weight);

            let edge_s = i.next().unwrap();
            for es in edge_s.split(',') {
                let mut it = es.splitn(2, ":");
                let target_id: usize = it.next()
                                         .unwrap()
                                         .parse()
                                         .unwrap();

                let edge_weight: Option<EdgeWt> = it.next()
                                                    .map(|s| s.parse::<EdgeWt>().unwrap());

                visitor.edge(node_id, target_id, edge_weight);
            }

            visitor.endnode(node_id);
        }
    }
}

pub struct PetgraphReader<NodeWt: Default, EdgeWt: Default> {
    graph: Graph<NodeWt, EdgeWt, Directed>,
}

impl<NodeWt, EdgeWt, I> PetgraphReader<NodeWt, EdgeWt>
where NodeWt: Default+FromStr<Err = I>,
      EdgeWt: Default+FromStr<Err = I>,
      I:Debug
{
    pub fn new() -> PetgraphReader<NodeWt, EdgeWt> {
        PetgraphReader { graph: Graph::new() }
    }

    pub fn from_sgf<R: BufRead>(rd: &mut R) -> Graph<NodeWt, EdgeWt, Directed> {
        let mut visitor = Self::new();
        read_sgf(rd, &mut visitor);
        return visitor.graph;
    }
}

impl<NodeWt:Default, EdgeWt:Default> Visitor<NodeWt, EdgeWt> for PetgraphReader<NodeWt, EdgeWt> {
    fn init(&mut self, num_nodes: usize, _num_edges: usize) {
        for _ in 0..num_nodes {
            self.graph.add_node(NodeWt::default());
        }
    }

    fn node(&mut self, node_id: usize, node_weight: Option<NodeWt>) {
        *self.graph.node_weight_mut(NodeIndex::new(node_id)).unwrap() =
            node_weight.unwrap_or(NodeWt::default());
    }

    fn edge(&mut self, src_id: usize, dst_id: usize, edge_weight: Option<EdgeWt>) {
        let _ = self.graph.add_edge(NodeIndex::new(src_id),
                                    NodeIndex::new(dst_id),
                                    edge_weight.unwrap_or(EdgeWt::default()));
    }
}
<|endoftext|>