<commit_before>#![feature(zero_one)]
#![feature(const_fn)]
#![no_std]

#[cfg(test)]
mod tests;

use core::mem::size_of;

#[derive(Debug, Clone, Copy)]
pub struct BitField<T: Number>(T);

impl<T> BitField<T>
    where T: Number
{
    pub const fn new(value: T) -> BitField<T> {
        BitField(value)
    }

    pub fn get_bit(&self, bit: u8) -> bool {
        assert!(bit < self.length());
        self.get_range(bit..(bit + 1)) == T::one()
    }

    pub fn get_range(&self, range: Range<u8>) -> T {
        assert!(range.start < self.length());
        assert!(range.end <= self.length());
        assert!(range.start < range.end);

        // shift away high bits
        let bits = self.0 << (self.length() - range.end) >> (self.length() - range.end);

        // shift away low bits
        bits >> range.start
    }

    pub fn set_bit(&mut self, bit: u8, value: bool) -> Self {
        assert!(bit < self.length());
        if value {
            self.0 |= T::one() << bit;
        } else {
            self.0 &= !(T::one() << bit);
        }
        *self
    }

    pub fn set_range(&mut self, range: Range<u8>, value: T) -> Self {
        assert!(range.start < self.length());
        assert!(range.end <= self.length());
        assert!(range.start < range.end);
        assert!(value << (self.length() - (range.end - range.start)) >>
                (self.length() - (range.end - range.start)) == value,
                "value too big");

        let bitmask: T = !(!T::zero() << (self.length() - range.end) >>
                           (self.length() - range.end) >>
                           range.start << range.start);

        let bits = self.0 & bitmask;
        // set bits
        self.0 = bits | (value << range.start);

        *self
    }

    fn length(&self) -> u8 {
        size_of::<T>() as u8 * 8
    }
}

use core::ops::{Range, Shl, Shr, BitAnd, BitOr, BitOrAssign, BitAndAssign, Not};
use core::num::{Zero, One};
use core::fmt::Debug;

pub trait Number: Debug + Copy + Eq + Zero + One +
    Not<Output=Self> + Shl<u8, Output=Self> + Shr<u8, Output=Self> +
    BitAnd<Self, Output=Self> + BitOr<Self, Output=Self>  + BitAndAssign + BitOrAssign {}

impl Number for u8 {}
impl Number for u16 {}
impl Number for u32 {}
impl Number for u64 {}
impl Number for usize {}
<commit_msg>Return &mut Self from set_* methods (instead of Self)<commit_after>#![feature(zero_one)]
#![feature(const_fn)]
#![no_std]

#[cfg(test)]
mod tests;

use core::mem::size_of;

#[derive(Debug, Clone, Copy)]
pub struct BitField<T: Number>(T);

impl<T> BitField<T>
    where T: Number
{
    pub const fn new(value: T) -> BitField<T> {
        BitField(value)
    }

    pub fn get_bit(&self, bit: u8) -> bool {
        assert!(bit < self.length());
        self.get_range(bit..(bit + 1)) == T::one()
    }

    pub fn get_range(&self, range: Range<u8>) -> T {
        assert!(range.start < self.length());
        assert!(range.end <= self.length());
        assert!(range.start < range.end);

        // shift away high bits
        let bits = self.0 << (self.length() - range.end) >> (self.length() - range.end);

        // shift away low bits
        bits >> range.start
    }

    pub fn set_bit(&mut self, bit: u8, value: bool) -> &mut Self {
        assert!(bit < self.length());
        if value {
            self.0 |= T::one() << bit;
        } else {
            self.0 &= !(T::one() << bit);
        }
        self
    }

    pub fn set_range(&mut self, range: Range<u8>, value: T) -> &mut Self {
        assert!(range.start < self.length());
        assert!(range.end <= self.length());
        assert!(range.start < range.end);
        assert!(value << (self.length() - (range.end - range.start)) >>
                (self.length() - (range.end - range.start)) == value,
                "value too big");

        let bitmask: T = !(!T::zero() << (self.length() - range.end) >>
                           (self.length() - range.end) >>
                           range.start << range.start);

        let bits = self.0 & bitmask;
        // set bits
        self.0 = bits | (value << range.start);

        self
    }

    fn length(&self) -> u8 {
        size_of::<T>() as u8 * 8
    }
}

use core::ops::{Range, Shl, Shr, BitAnd, BitOr, BitOrAssign, BitAndAssign, Not};
use core::num::{Zero, One};
use core::fmt::Debug;

pub trait Number: Debug + Copy + Eq + Zero + One +
    Not<Output=Self> + Shl<u8, Output=Self> + Shr<u8, Output=Self> +
    BitAnd<Self, Output=Self> + BitOr<Self, Output=Self>  + BitAndAssign + BitOrAssign {}

impl Number for u8 {}
impl Number for u16 {}
impl Number for u32 {}
impl Number for u64 {}
impl Number for usize {}
<|endoftext|>


<commit_before>#![deny(missing_docs)]
#![cfg_attr(test, feature(test, alloc))]

//! A table object type for dynamical data

use std::collections::HashMap;
use std::sync::Arc;
use std::ops::{ Deref, DerefMut, Index, IndexMut };
use std::hash::{ Hash, Hasher };
use std::borrow::Borrow;

/// Represents a dynamical typed value
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Value {
    /// An empty value.
    Null,
    /// A boolean value.
    Bool(bool),
    /// A pointer sized integer.
    Usize(usize),
    /// A 64 bit unsigned integer.
    U64(u64),
    /// A 64 bit signed integer.
    I64(i64),
    /// A 64 bit floating number.
    F64(F64),
    /// A string.
    String(Arc<String>),
    /// A table.
    Table(Arc<Table>),
}

impl Value {
    /// Creates a new f64 value.
    pub fn f64(val: f64) -> Value {
        Value::F64(F64(val))
    }

    /// Creates a new string value.
    pub fn str(val: &str) -> Value {
        use std::borrow::ToOwned;

        Value::String(Arc::new(val.to_owned()))
    }

    /// Creates a new table value.
    pub fn table(val: Table) -> Value {
        Value::Table(Arc::new(val))
    }
}

impl Hash for Value {
    fn hash<S>(&self, state: &mut S) where S: Hasher {
        match self {
            &Value::String(ref text) => text.hash(state),
            &Value::Null => 0.hash(state),
            &Value::Bool(val) => val.hash(state),
            &Value::Usize(val) => val.hash(state),
            &Value::U64(val) => val.hash(state),
            &Value::I64(val) => val.hash(state),
            &Value::F64(val) => val.hash(state),
            &Value::Table(ref val) => val.hash(state),
        }
    }
}

impl Borrow<str> for Value {
    fn borrow(&self) -> &str {
        match self {
            &Value::String(ref text) => {
                &text
            }
            _ => ""
        }
    }
}

/// Wrapper for f64
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct F64(pub f64);

impl Eq for F64 {}

impl Hash for F64 {
    fn hash<S>(&self, state: &mut S) where S: Hasher {
        let val = self.0 as u64;
        val.hash(state)
    }
}

impl Deref for F64 {
    type Target = f64;

    fn deref<'a>(&'a self) -> &'a f64 {
        &self.0
    }
}

impl DerefMut for F64 {
    fn deref_mut<'a>(&'a mut self) -> &'a mut f64 {
        &mut self.0
    }
}

/// The table object
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Table(pub HashMap<Value, Value>);

impl Hash for Table {
    fn hash<S>(&self, state: &mut S) where S: Hasher {
        for (key, val) in self.0.iter() {
            key.hash(state);
            val.hash(state);
        }
    }
}

impl Deref for Table {
    type Target = HashMap<Value, Value>;

    fn deref<'a>(&'a self) -> &'a HashMap<Value, Value> {
        &self.0
    }
}

impl DerefMut for Table {
    fn deref_mut<'a>(&'a mut self) -> &'a mut HashMap<Value, Value> {
        &mut self.0
    }
}

impl Index<Value> for Table {
    type Output = Value;

    fn index<'a>(&'a self, index: Value) -> &'a Value {
        self.0.get(&index).unwrap()
    }
}

impl Index<usize> for Table {
    type Output = Value;

    fn index<'a>(&'a self, index: usize) -> &'a Value {
        self.0.get(&Value::Usize(index)).unwrap()
    }
}

impl<'b> Index<&'b str> for Table {
    type Output = Value;

    fn index<'a>(&'a self, index: &'b str) -> &'a Value {
        self.0.get(index).unwrap()
    }
}

impl IndexMut<Value> for Table {
    fn index_mut<'a>(&'a mut self, index: Value) -> &'a mut Value {
        use std::collections::hash_map::Entry;

        match self.0.entry(index.clone()) {
            Entry::Occupied(_) => {},
            Entry::Vacant(x) => {x.insert(Value::Null);}
        };
        self.0.get_mut(&index).unwrap()
    }
}

impl IndexMut<usize> for Table {
    fn index_mut<'a>(&'a mut self, index: usize) -> &'a mut Value {
        use std::collections::hash_map::Entry;

        match self.0.entry(Value::Usize(index)) {
            Entry::Occupied(_) => {},
            Entry::Vacant(x) => {x.insert(Value::Null);}
        };
        self.0.get_mut(&Value::Usize(index)).unwrap()
    }
}

impl<'b> IndexMut<&'b str> for Table {
    fn index_mut<'a>(&'a mut self, index: &'b str) -> &'a mut Value {
        use std::borrow::ToOwned;

        if !self.0.contains_key(index) {
            self.insert(Value::String(Arc::new((*index).to_owned())),
                Value::Null);
        }
        self.0.get_mut(index).unwrap()
    }
}

impl Table {
    /// Creates new table.
    pub fn new() -> Table {
        Table(HashMap::new())
    }

    /// Creates new table with capacity.
    pub fn with_capacity(capacity: usize) -> Table {
        Table(HashMap::with_capacity(capacity))
    }
}

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

    use super::*;
    use self::test::Bencher;
    use std::sync::Arc;

    #[test]
    fn test_size() {
        use std::mem::size_of;

        // Make sure `Value` is not exceeding 128 bits on 64 bit systems.
        // This is for performance reasons.
        if size_of::<usize>() == 8 {
            assert_eq!(size_of::<Value>(), 16);
        }
    }

    #[test]
    fn test_sync() {
        fn foo<T: Sync>() {}

        // Make sure `Value` can be shared among tasks.
        foo::<Value>();
        foo::<Table>();
    }

    #[test]
    fn test_vec3() {
        let mut vec3 = Table::with_capacity(3);
        vec3[0] = Value::f64(1.0);
        vec3[1] = Value::f64(2.0);
        vec3[2] = Value::f64(3.0);
        assert_eq!(vec3[0], Value::f64(1.0));
        assert_eq!(vec3[1], Value::f64(2.0));
        assert_eq!(vec3[2], Value::f64(3.0));
        vec3.clear();
        assert_eq!(vec3.len(), 0);
    }

    #[test]
    fn test_table_as_key() {
        use std::borrow::ToOwned;

        let a = Value::Table(Arc::new(Table::new()));
        let mut b = Table::new();
        b[a] = Value::String(Arc::new("hello".to_owned()));
    }

    #[test]
    fn test_str_as_key() {
        use std::borrow::ToOwned;

        let mut a = Table::new();
        a.insert(Value::String(Arc::new("hello".to_owned())),
            Value::String(Arc::new("world".to_owned())));
        assert!(
            if let Some(&Value::String(_)) = a.get("hello") { true }
            else { false }
        );
        assert_eq!(a["hello"], Value::String(Arc::new("world".to_owned())));
        a["hello2"] = Value::String(Arc::new("world".to_owned()));
        assert_eq!(a["hello"], a["hello2"]);
    }

    #[bench]
    fn bench_create_empty(bencher: &mut Bencher) {
        bencher.iter(|| {
            let _ = Table::new();
        });
    }

    #[bench]
    fn bench_create_empty_arc(bencher: &mut Bencher) {
        use std::sync::Arc;

        bencher.iter(|| {
            let _ = Arc::new(Table::new());
        });
    }

    #[bench]
    fn bench_overwrite(bencher: &mut Bencher) {
        let mut a = Table::new();
        bencher.iter(|| {
            a[0] = Value::f64(1.0);
        });
    }

    #[bench]
    fn bench_overwrite_arc(bencher: &mut Bencher) {
        use std::sync::Arc;

        let mut a = Arc::new(Table::new());
        bencher.iter(|| {
            a.make_unique()[0] = Value::f64(1.0);
        });
    }
}

<commit_msg>Updated to latest Rust<commit_after>#![deny(missing_docs)]
#![cfg_attr(test, feature(test))]

//! A table object type for dynamical data

use std::collections::HashMap;
use std::sync::Arc;
use std::ops::{ Deref, DerefMut, Index, IndexMut };
use std::hash::{ Hash, Hasher };
use std::borrow::Borrow;

/// Represents a dynamical typed value
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Value {
    /// An empty value.
    Null,
    /// A boolean value.
    Bool(bool),
    /// A pointer sized integer.
    Usize(usize),
    /// A 64 bit unsigned integer.
    U64(u64),
    /// A 64 bit signed integer.
    I64(i64),
    /// A 64 bit floating number.
    F64(F64),
    /// A string.
    String(Arc<String>),
    /// A table.
    Table(Arc<Table>),
}

impl Value {
    /// Creates a new f64 value.
    pub fn f64(val: f64) -> Value {
        Value::F64(F64(val))
    }

    /// Creates a new string value.
    pub fn str(val: &str) -> Value {
        use std::borrow::ToOwned;

        Value::String(Arc::new(val.to_owned()))
    }

    /// Creates a new table value.
    pub fn table(val: Table) -> Value {
        Value::Table(Arc::new(val))
    }
}

impl Hash for Value {
    fn hash<S>(&self, state: &mut S) where S: Hasher {
        match self {
            &Value::String(ref text) => text.hash(state),
            &Value::Null => 0.hash(state),
            &Value::Bool(val) => val.hash(state),
            &Value::Usize(val) => val.hash(state),
            &Value::U64(val) => val.hash(state),
            &Value::I64(val) => val.hash(state),
            &Value::F64(val) => val.hash(state),
            &Value::Table(ref val) => val.hash(state),
        }
    }
}

impl Borrow<str> for Value {
    fn borrow(&self) -> &str {
        match self {
            &Value::String(ref text) => {
                &text
            }
            _ => ""
        }
    }
}

/// Wrapper for f64
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct F64(pub f64);

impl Eq for F64 {}

impl Hash for F64 {
    fn hash<S>(&self, state: &mut S) where S: Hasher {
        let val = self.0 as u64;
        val.hash(state)
    }
}

impl Deref for F64 {
    type Target = f64;

    fn deref<'a>(&'a self) -> &'a f64 {
        &self.0
    }
}

impl DerefMut for F64 {
    fn deref_mut<'a>(&'a mut self) -> &'a mut f64 {
        &mut self.0
    }
}

/// The table object
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Table(pub HashMap<Value, Value>);

impl Hash for Table {
    fn hash<S>(&self, state: &mut S) where S: Hasher {
        for (key, val) in self.0.iter() {
            key.hash(state);
            val.hash(state);
        }
    }
}

impl Deref for Table {
    type Target = HashMap<Value, Value>;

    fn deref<'a>(&'a self) -> &'a HashMap<Value, Value> {
        &self.0
    }
}

impl DerefMut for Table {
    fn deref_mut<'a>(&'a mut self) -> &'a mut HashMap<Value, Value> {
        &mut self.0
    }
}

impl Index<Value> for Table {
    type Output = Value;

    fn index<'a>(&'a self, index: Value) -> &'a Value {
        self.0.get(&index).unwrap()
    }
}

impl Index<usize> for Table {
    type Output = Value;

    fn index<'a>(&'a self, index: usize) -> &'a Value {
        self.0.get(&Value::Usize(index)).unwrap()
    }
}

impl<'b> Index<&'b str> for Table {
    type Output = Value;

    fn index<'a>(&'a self, index: &'b str) -> &'a Value {
        self.0.get(index).unwrap()
    }
}

impl IndexMut<Value> for Table {
    fn index_mut<'a>(&'a mut self, index: Value) -> &'a mut Value {
        use std::collections::hash_map::Entry;

        match self.0.entry(index.clone()) {
            Entry::Occupied(_) => {},
            Entry::Vacant(x) => {x.insert(Value::Null);}
        };
        self.0.get_mut(&index).unwrap()
    }
}

impl IndexMut<usize> for Table {
    fn index_mut<'a>(&'a mut self, index: usize) -> &'a mut Value {
        use std::collections::hash_map::Entry;

        match self.0.entry(Value::Usize(index)) {
            Entry::Occupied(_) => {},
            Entry::Vacant(x) => {x.insert(Value::Null);}
        };
        self.0.get_mut(&Value::Usize(index)).unwrap()
    }
}

impl<'b> IndexMut<&'b str> for Table {
    fn index_mut<'a>(&'a mut self, index: &'b str) -> &'a mut Value {
        use std::borrow::ToOwned;

        if !self.0.contains_key(index) {
            self.insert(Value::String(Arc::new((*index).to_owned())),
                Value::Null);
        }
        self.0.get_mut(index).unwrap()
    }
}

impl Table {
    /// Creates new table.
    pub fn new() -> Table {
        Table(HashMap::new())
    }

    /// Creates new table with capacity.
    pub fn with_capacity(capacity: usize) -> Table {
        Table(HashMap::with_capacity(capacity))
    }
}

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

    use super::*;
    use self::test::Bencher;
    use std::sync::Arc;

    #[test]
    fn test_size() {
        use std::mem::size_of;

        // Make sure `Value` is not exceeding 128 bits on 64 bit systems.
        // This is for performance reasons.
        if size_of::<usize>() == 8 {
            assert_eq!(size_of::<Value>(), 16);
        }
    }

    #[test]
    fn test_sync() {
        fn foo<T: Sync>() {}

        // Make sure `Value` can be shared among tasks.
        foo::<Value>();
        foo::<Table>();
    }

    #[test]
    fn test_vec3() {
        let mut vec3 = Table::with_capacity(3);
        vec3[0] = Value::f64(1.0);
        vec3[1] = Value::f64(2.0);
        vec3[2] = Value::f64(3.0);
        assert_eq!(vec3[0], Value::f64(1.0));
        assert_eq!(vec3[1], Value::f64(2.0));
        assert_eq!(vec3[2], Value::f64(3.0));
        vec3.clear();
        assert_eq!(vec3.len(), 0);
    }

    #[test]
    fn test_table_as_key() {
        use std::borrow::ToOwned;

        let a = Value::Table(Arc::new(Table::new()));
        let mut b = Table::new();
        b[a] = Value::String(Arc::new("hello".to_owned()));
    }

    #[test]
    fn test_str_as_key() {
        use std::borrow::ToOwned;

        let mut a = Table::new();
        a.insert(Value::String(Arc::new("hello".to_owned())),
            Value::String(Arc::new("world".to_owned())));
        assert!(
            if let Some(&Value::String(_)) = a.get("hello") { true }
            else { false }
        );
        assert_eq!(a["hello"], Value::String(Arc::new("world".to_owned())));
        a["hello2"] = Value::String(Arc::new("world".to_owned()));
        assert_eq!(a["hello"], a["hello2"]);
    }

    #[bench]
    fn bench_create_empty(bencher: &mut Bencher) {
        bencher.iter(|| {
            let _ = Table::new();
        });
    }

    #[bench]
    fn bench_create_empty_arc(bencher: &mut Bencher) {
        use std::sync::Arc;

        bencher.iter(|| {
            let _ = Arc::new(Table::new());
        });
    }

    #[bench]
    fn bench_overwrite(bencher: &mut Bencher) {
        let mut a = Table::new();
        bencher.iter(|| {
            a[0] = Value::f64(1.0);
        });
    }

    #[bench]
    fn bench_overwrite_arc(bencher: &mut Bencher) {
        fn is_copy<T: Clone>() {}

        use std::sync::Arc;

        is_copy::<Arc<Table>>();
        let mut a = Arc::new(Table::new());
        bencher.iter(|| {
            Arc::make_mut(&mut a)[0] = Value::f64(1.0);
        });
    }
}

<|endoftext|>


<commit_before>#![feature(catch_panic)]
#[macro_use]
extern crate lazy_static;
use std::string::ToString;
use std::thread::{JoinHandle, spawn, catch_panic};
use std::sync::*;
use std::any::{Any};

pub struct ExampleGroup {
    description: String,
    running_examples: Vec<JoinHandle<Result<(), Box<Any + Send>>>>,
}

pub struct ExampleGroupAndBlock {
    group: ExampleGroup,
    block: Box<Fn(&mut ExampleGroup) + Sync + Send + 'static>,
}

pub struct Example {
    description: String,
}

impl ExampleGroup {
    pub fn it<F>(&mut self, description: &'static str, example_definition_block: F) where F: Fn() + Sync + Send + 'static {
        self.running_examples.push(spawn(move || {
            let result = catch_panic(move || {
                example_definition_block();
            });

            let c = WORLD.clone();
            let world = c.lock().unwrap();
            if result.is_err() {
                world.reporter.example_failed();
            } else {
                world.reporter.example_passed();
            }

            return result;
        }));
    }

    fn block_on_all_examples(self) -> Result<(), ()> {
        let mut failed = false;
        for jh in self.running_examples.into_iter() {
            if jh.join().unwrap().is_err() {
                failed = true;
            }
        }

        if failed {
            return Err(());
        } else {
            return Ok(());
        }
    }

    fn run(mut self, block: Box<Fn(&mut ExampleGroup) + Send + Sync + 'static>) -> bool {
        block(&mut self);

        let result = self.block_on_all_examples();
        return result.is_ok();
    }
}

pub struct Reporter;

impl Reporter {
    pub fn example_failed(&self) {
        print!("F");
    }

    pub fn example_passed(&self) {
        print!(".");
    }
}

struct World {
    reporter: Reporter,
    failed: bool,
    example_groups: Vec<ExampleGroupAndBlock>,
}

lazy_static! {
    static ref WORLD: Arc<Mutex<World>> = Arc::new(Mutex::new(World { failed: false, reporter: Reporter, example_groups: Vec::new() }));
}

pub fn describe<F>(description: &str, example_group_definition_block: F) where F: Fn(&mut ExampleGroup) + Sync + Send + 'static {
    let c = WORLD.clone();
    let mut world = c.lock().unwrap();

    world.example_groups.push(
        ExampleGroupAndBlock {
            group: ExampleGroup {
                description: description.to_string(),
                running_examples: Vec::new(),
            },
            block: Box::new(example_group_definition_block)
        }
    );
}

pub fn get_examples_from_world() -> Vec<ExampleGroupAndBlock> {
    let world_mutex = WORLD.clone();
    let mut world = world_mutex.lock().unwrap();
    let mut result = Vec::new();
    while !world.example_groups.is_empty() {
        result.push(world.example_groups.remove(0));
    }

    return result;

}

pub fn descriptor_main() {
    let mut example_groups = get_examples_from_world();
    let mut join_handles = Vec::new();

    while !example_groups.is_empty() {
        let example_group_and_block = example_groups.remove(0);
        let example_group = example_group_and_block.group;
        let block = example_group_and_block.block;
        join_handles.push(spawn(|| -> Result<(), ()> {
            if example_group.run(block) {
                return Ok(());
            } else {
                return Err(());
            }
        }));
    }

    for join_handle in join_handles.into_iter() {
        let result = join_handle.join().unwrap();
        if result.is_err() {
            let world_mutex = WORLD.clone();
            let mut world = world_mutex.lock().unwrap();
            world.failed = true;
        }
    }
    let world_mutex = WORLD.clone();
    let mut world = world_mutex.lock().unwrap();
    println!("{}", world.failed);
}
<commit_msg>Create with_world abstraction.<commit_after>#![feature(catch_panic)]
#[macro_use]
extern crate lazy_static;
use std::string::ToString;
use std::thread::{JoinHandle, spawn, catch_panic};
use std::sync::*;
use std::any::{Any};

pub struct ExampleGroup {
    description: String,
    running_examples: Vec<JoinHandle<Result<(), Box<Any + Send>>>>,
}

pub struct ExampleGroupAndBlock {
    group: ExampleGroup,
    block: Box<Fn(&mut ExampleGroup) + Sync + Send + 'static>,
}

pub struct Example {
    description: String,
}

impl ExampleGroup {
    pub fn it<F>(&mut self, description: &'static str, example_definition_block: F) where F: Fn() + Sync + Send + 'static {
        self.running_examples.push(spawn(move || {
            let result = catch_panic(move || {
                example_definition_block();
            });

            with_world(|world| {
                if result.is_err() {
                    world.reporter.example_failed();
                } else {
                    world.reporter.example_passed();
                }
            });

            return result;
        }));
    }

    fn block_on_all_examples(self) -> Result<(), ()> {
        let mut failed = false;
        for jh in self.running_examples.into_iter() {
            if jh.join().unwrap().is_err() {
                failed = true;
            }
        }

        if failed {
            return Err(());
        } else {
            return Ok(());
        }
    }

    fn run(mut self, block: Box<Fn(&mut ExampleGroup) + Send + Sync + 'static>) -> bool {
        block(&mut self);

        let result = self.block_on_all_examples();
        return result.is_ok();
    }
}

pub struct Reporter;

impl Reporter {
    pub fn example_failed(&self) {
        print!("F");
    }

    pub fn example_passed(&self) {
        print!(".");
    }
}

struct World {
    reporter: Reporter,
    failed: bool,
    example_groups: Vec<ExampleGroupAndBlock>,
}

fn with_world<F>(blk: F) where F: FnOnce(&mut World) -> () {
    let c = WORLD.clone();
    let mut guard = c.lock().unwrap();
    blk(&mut guard);
}

impl World {
}

lazy_static! {
    static ref WORLD: Arc<Mutex<World>> = Arc::new(Mutex::new(World { failed: false, reporter: Reporter, example_groups: Vec::new() }));
}

pub fn describe<F>(description: &str, example_group_definition_block: F) where F: Fn(&mut ExampleGroup) + Sync + Send + 'static {
    with_world(|world| {
        world.example_groups.push(
            ExampleGroupAndBlock {
                group: ExampleGroup {
                    description: description.to_string(),
                    running_examples: Vec::new(),
                },
                block: Box::new(example_group_definition_block)
            }
        );
    });
}

pub fn get_examples_from_world() -> Vec<ExampleGroupAndBlock> {
    let world_mutex = WORLD.clone();
    let mut world = world_mutex.lock().unwrap();
    let mut result = Vec::new();

    with_world(|world| {
        while !world.example_groups.is_empty() {
            result.push(world.example_groups.remove(0));
        }
    });

    return result;

}

pub fn descriptor_main() {
    let mut example_groups = get_examples_from_world();
    let mut join_handles = Vec::new();

    while !example_groups.is_empty() {
        let example_group_and_block = example_groups.remove(0);
        let example_group = example_group_and_block.group;
        let block = example_group_and_block.block;
        join_handles.push(spawn(|| -> Result<(), ()> {
            if example_group.run(block) {
                return Ok(());
            } else {
                return Err(());
            }
        }));
    }

    for join_handle in join_handles.into_iter() {
        let result = join_handle.join().unwrap();
        if result.is_err() {
            with_world(|world| {
                world.failed = true;
            });
        }
    }
    with_world(|world| {
        println!("{}", world.failed);
    });
}
<|endoftext|>


<commit_before>//! RethinkDB protocol implementation in Rust

extern crate protobuf;
extern crate serde_json;

pub mod proto;

use serde_json::value::{Value, ToJson};
use protobuf::repeated::RepeatedField;
use proto::{
    Term, Datum,
    Datum_DatumType as DT,
    Term_TermType as TT,
};

pub trait ToTerm {
    fn to_term(&self) -> Term;
}

impl<T: ToJson> ToTerm for T {
    fn to_term(&self) -> Term {
        // Datum
        let mut datum = Datum::new();
        match self.to_json() {
            Value::String(val) => {
                datum.set_field_type(DT::R_STR);
                datum.set_r_str(val);
            },
            Value::Bool(val) => {
                datum.set_field_type(DT::R_BOOL);
                datum.set_r_bool(val);
            },
            Value::I64(val) => {
                datum.set_field_type(DT::R_NUM);
                datum.set_r_num(val as f64);
            },
            Value::U64(val) => {
                datum.set_field_type(DT::R_NUM);
                datum.set_r_num(val as f64);
            },
            Value::F64(val) => {
                datum.set_field_type(DT::R_NUM);
                datum.set_r_num(val);
            },
            Value::Array(_val) => {
                unimplemented!();
            },
            Value::Object(_val) => {
                unimplemented!();
            },
            Value::Null => {
                datum.set_field_type(DT::R_NULL);
            },
        }
        // Term
        let mut term = Term::new();
        term.set_field_type(TT::DATUM);
        term.set_datum(datum);
        term
    }
}

impl ToTerm for Term {
    fn to_term(&self) -> Term {
        self.clone()
    }
}

macro_rules! command {
    ($T:expr, $args:expr) => {{
        let mut term = Term::new();
        term.set_field_type($T);
        if !$args.is_empty() {
            let args = RepeatedField::from_vec($args);
            term.set_args(args);
        }
        From::from(term)
    }}
}

pub trait Command
    where Self: Sized + From<Term> + Into<Term>
{
    fn db<T: ToTerm>(self, arg: T) -> Self {
        let args = vec![
            arg.to_term(),
            ];
        command!(TT::DB, args)
    }

    fn table<T: ToTerm>(self, arg: T) -> Self {
        let args = vec![
            self.into(),
            arg.to_term(),
            ];
        command!(TT::TABLE, args)
    }

    fn object(self, arg: Vec<&ToTerm>) -> Self {
        let args: Vec<Term> = arg.iter()
            .map(|a| a.to_term())
            .collect();
        command!(TT::OBJECT, args)
    }
}

#[test]
fn test_commands_can_be_chained() {
    impl Command for Term { }
    let r = Term::new();
    r.db("heroes").table("marvel");
}
<commit_msg>Refactor commands<commit_after>//! RethinkDB protocol implementation in Rust

extern crate protobuf;
extern crate serde_json;

pub mod proto;

use serde_json::value::{Value, ToJson};
use protobuf::repeated::RepeatedField;
use proto::{
    Term, Datum,
    Datum_DatumType as DT,
    Term_TermType as TT,
};

impl Term {
    fn is_empty(&self) -> bool {
        *self == Term::new()
    }
}

pub trait ToTerm {
    fn to_term(&self) -> Term;
}

impl<T: ToJson> ToTerm for T {
    fn to_term(&self) -> Term {
        // Datum
        let mut datum = Datum::new();
        match self.to_json() {
            Value::String(val) => {
                datum.set_field_type(DT::R_STR);
                datum.set_r_str(val);
            },
            Value::Bool(val) => {
                datum.set_field_type(DT::R_BOOL);
                datum.set_r_bool(val);
            },
            Value::I64(val) => {
                datum.set_field_type(DT::R_NUM);
                datum.set_r_num(val as f64);
            },
            Value::U64(val) => {
                datum.set_field_type(DT::R_NUM);
                datum.set_r_num(val as f64);
            },
            Value::F64(val) => {
                datum.set_field_type(DT::R_NUM);
                datum.set_r_num(val);
            },
            Value::Array(_val) => {
                unimplemented!();
            },
            Value::Object(_val) => {
                unimplemented!();
            },
            Value::Null => {
                datum.set_field_type(DT::R_NULL);
            },
        }
        // Term
        let mut term = Term::new();
        term.set_field_type(TT::DATUM);
        term.set_datum(datum);
        term
    }
}

impl ToTerm for Term {
    fn to_term(&self) -> Term {
        self.clone()
    }
}

macro_rules! command {
    ($T:expr, $cmd:expr, $args:expr, $opts:expr) => {{
        let mut term = Term::new();
        term.set_field_type($T);
        let mut args = Vec::new();
        if !$cmd.is_empty() {
            args.push($cmd);
        }
        if let Some(list) = $args {
            args.extend(list);
        }
        /*
        if let Some(_opt) = $opts {
            unimplemented!();
        }
        */
        if !args.is_empty() {
            let args = RepeatedField::from_vec(args);
            term.set_args(args);
        }
        From::from(term)
    }}
}

macro_rules! closure_par {
    () => {{
        // ID
        let mut id = Datum::new();
        id.set_field_type(DT::R_NUM);
        id.set_r_num(1.0);
        // DATUM
        let mut datum = Term::new();
        datum.set_field_type(TT::DATUM);
        datum.set_datum(id);
        // VAR
        let mut var = Term::new();
        var.set_field_type(TT::VAR);
        let args = RepeatedField::from_vec(vec![datum]);
        var.set_args(args);
        From::from(var)
    }}
}

macro_rules! closure_arg {
    ($res:expr) => {{
        // ID
        let mut id = Datum::new();
        id.set_field_type(DT::R_NUM);
        id.set_r_num(1.0);
        // ARRAY
        let mut array = Datum::new();
        array.set_field_type(DT::R_ARRAY);
        let args = RepeatedField::from_vec(vec![id]);
        array.set_r_array(args);
        // DATUM
        let mut datum = Term::new();
        datum.set_field_type(TT::DATUM);
        datum.set_datum(array);
        // FUNC
        let mut func = Term::new();
        func.set_field_type(TT::FUNC);
        let args = RepeatedField::from_vec(vec![datum, $res]);
        func.set_args(args);
        func
    }}
}

pub trait Command
    where Self: Sized + From<Term> + Into<Term>
{
    fn db<T: ToTerm>(self, arg: T) -> Self {
        let cmd = self.into();
        let arg = arg.to_term();
        command!(TT::DB, cmd, Some(vec![arg]), None)
    }

    fn table<T: ToTerm>(self, arg: T) -> Self {
        let cmd = self.into();
        let arg = arg.to_term();
        command!(TT::TABLE, cmd, Some(vec![arg]), None)
    }

    fn map<F>(self, func: F) -> Self
        where F: Fn(Self) -> Self
    {
        let cmd = self.into();
        let arg = func(closure_par!()).into();
        command!(TT::MAP, cmd, Some(vec![arg]), None)
    }

    fn array(self, arg: Vec<&ToTerm>) -> Self {
        let cmd = self.into();
        let args: Vec<Term> = arg.iter()
            .map(|a| a.to_term())
            .collect();
        command!(TT::MAKE_ARRAY, cmd, Some(args), None)
    }
}

#[test]
fn test_commands_can_be_chained() {
    impl Command for Term { }
    let r = Term::new();
    let term = r.map(|row| row.db("heroes").table("marvel"));
    panic!(format!("{:?}", term));
}
<|endoftext|>


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

#![crate_name = "fontconfig"]
#![crate_type = "lib"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]

#![feature(globs)]

extern crate libc;
extern crate std;

pub mod fontconfig;
<commit_msg>Rust upgrade<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![crate_name = "fontconfig"]
#![crate_type = "lib"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]

#![feature(globs)]

extern crate libc;

pub mod fontconfig;
<|endoftext|>


<commit_before>mod parser;

use std::path::Path;
use std::collections::HashMap;
use std::io::{BufReader, Read};
use std::fs::File;
use std::str::FromStr;

use parser::{parse_line, Parsed};

type IniParsed = HashMap<String, HashMap<String, String>>;

#[derive(Debug)]
pub struct Ini(IniParsed);

impl<'a> Ini {
    fn new() -> Ini {
        Ini(HashMap::new())
    }
    fn from_string<S: Into<String>>(string: S) -> Ini {
        let mut result = Ini::new();
        let mut section_name = String::new();
        let mut entry_list = HashMap::new();
        for (i, line) in string.into().lines().enumerate() {
            match parse_line(&line) {
                Parsed::Section(name) => {
                    if section_name.len() != 0 {
                        result.0.insert(section_name, entry_list.clone());
                        entry_list.clear();
                    }
                    section_name = name;
                }
                Parsed::Value(name, value) => {
                    entry_list.insert(name, value);
                }
                Parsed::Error(msg) => println!("line {}: error: {}", i, msg),
                _ => (),
            };
        }
        // add last section
        if section_name.len() != 0 {
            result.0.insert(section_name, entry_list.clone());
            entry_list.clear();
        }
        result
    }

    pub fn from_file<S: AsRef<Path> + ?Sized>(path: &S) -> Ini {
        let file = File::open(path)
                       .expect(&format!("Can't open `{}`!", path.as_ref().display()));
        let mut reader = BufReader::new(file);
        let mut buffer = String::new();
        let _ = reader.read_to_string(&mut buffer)
                      .expect(&format!("Can't read `{}`!", path.as_ref().display()));
        Ini::from_string(buffer)
    }
    pub fn from_buffer<S: Into<String>>(buf: S) -> Ini {
        Ini::from_string(buf.into())
    }
    fn get_raw<S>(&'a self, section: S, key: S) -> Option<&String>
        where S: Into<String>
    {
        let s = self.0.get(&section.into());
        match s {
            Some(hm) => hm.get(&key.into()),
            None => None,
        }
    }
    pub fn get<T, S>(&'a self, section: S, key: S) -> Option<T>
        where T: FromStr, S: Into<String>
    {
        let data = self.get_raw(section.into(), key.into());
        match data {
            Some(x) => x.parse().ok(),
            None => None
        }
    }
    pub fn get_def<T: FromStr>(&'a self, section: &str, key: &str, default: T) -> T {
        let s = self.get_raw(section, key);
        match s {
            Some(x) => x.parse().unwrap_or(default),
            None => default,
        }
    }
    pub fn get_vec<T>(&'a self, section: &str, key: &str, default: &[T]) -> Vec<T>
        where T: FromStr + Copy + Clone
    {
        let s = self.get_raw(section, key);
        match s {
            Some(x) => {
                x.split(',')
                 .zip(default)
                 .map(|(s, &d)| s.trim().parse().unwrap_or(d))
                 .collect()
            }
            None => default.to_vec(),
        }
    }
}

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

    #[test]
    fn test_int() {
        let input: String = "[string]\nabc = 10".to_owned();
        let ini = Ini::from_string(input);
        let abc: Option<u32> = ini.get("string", "abc");
        assert_eq!(abc, Some(10));
    }

    #[test]
    fn test_float_def() {
        let ini = Ini::from_string("[section]\nname=10.5");
        let name: f64 = ini.get_def("section", "name", 0.0);
        assert_eq!(name, 10.5);
    }

    #[test]
    fn test_float_vec() {
        let ini = Ini::from_string("[section]\nname=1.2, 3.4, 5.6");
        let name: Vec<f64> = ini.get_vec("section", "name", &[0.0, 0.0, 0.0]);
        assert_eq!(name, [1.2, 3.4, 5.6]);
    }
}
<commit_msg>[upd] revert to &str<commit_after>mod parser;

use std::path::Path;
use std::collections::HashMap;
use std::io::{BufReader, Read};
use std::fs::File;
use std::str::FromStr;

use parser::{parse_line, Parsed};

type IniParsed = HashMap<String, HashMap<String, String>>;

#[derive(Debug)]
pub struct Ini(IniParsed);

impl<'a> Ini {
    fn new() -> Ini {
        Ini(HashMap::new())
    }
    fn from_string(string: &str) -> Ini {
        let mut result = Ini::new();
        let mut section_name = String::new();
        let mut entry_list = HashMap::new();
        for (i, line) in string.lines().enumerate() {
            match parse_line(&line) {
                Parsed::Section(name) => {
                    if section_name.len() != 0 {
                        result.0.insert(section_name, entry_list.clone());
                        entry_list.clear();
                    }
                    section_name = name;
                }
                Parsed::Value(name, value) => {
                    entry_list.insert(name, value);
                }
                Parsed::Error(msg) => println!("line {}: error: {}", i, msg),
                _ => (),
            };
        }
        // add last section
        if section_name.len() != 0 {
            result.0.insert(section_name, entry_list.clone());
            entry_list.clear();
        }
        result
    }

    pub fn from_file<S: AsRef<Path> + ?Sized>(path: &S) -> Ini {
        let file = File::open(path)
                       .expect(&format!("Can't open `{}`!", path.as_ref().display()));
        let mut reader = BufReader::new(file);
        let mut buffer = String::new();
        let _ = reader.read_to_string(&mut buffer)
                      .expect(&format!("Can't read `{}`!", path.as_ref().display()));
        Ini::from_string(&buffer)
    }
    pub fn from_buffer<S: Into<String>>(buf: S) -> Ini {
        Ini::from_string(&buf.into())
    }
    fn get_raw(&'a self, section: &str, key: &str) -> Option<&String> {
        let s = self.0.get(section);
        match s {
            Some(hm) => hm.get(key),
            None => None,
        }
    }
    pub fn get<T: FromStr>(&'a self, section: &str, key: &str) -> Option<T> {
        let data = self.get_raw(section, key);
        match data {
            Some(x) => x.parse().ok(),
            None => None
        }
    }
    pub fn get_def<T: FromStr>(&'a self, section: &str, key: &str, default: T) -> T {
        let s = self.get_raw(section, key);
        match s {
            Some(x) => x.parse().unwrap_or(default),
            None => default,
        }
    }
    pub fn get_vec<T>(&'a self, section: &str, key: &str, default: &[T]) -> Vec<T>
        where T: FromStr + Copy + Clone
    {
        let s = self.get_raw(section, key);
        match s {
            Some(x) => {
                x.split(',')
                 .zip(default)
                 .map(|(s, &d)| s.trim().parse().unwrap_or(d))
                 .collect()
            }
            None => default.to_vec(),
        }
    }
}

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

    #[test]
    fn test_int() {
        let input: String = "[string]\nabc = 10".to_owned();
        let ini = Ini::from_buffer(input);
        let abc: Option<u32> = ini.get("string", "abc");
        assert_eq!(abc, Some(10));
    }

    #[test]
    fn test_float_def() {
        let ini = Ini::from_string("[section]\nname=10.5");
        let name: f64 = ini.get_def("section", "name", 0.0);
        assert_eq!(name, 10.5);
    }

    #[test]
    fn test_float_vec() {
        let ini = Ini::from_string("[section]\nname=1.2, 3.4, 5.6");
        let name: Vec<f64> = ini.get_vec("section", "name", &[0.0, 0.0, 0.0]);
        assert_eq!(name, [1.2, 3.4, 5.6]);
    }
}
<|endoftext|>


<commit_before>use connection::Connection;
use libproto::blockchain::{Block, Status};
use libproto::router::{MsgType, RoutingKey, SubModules};
use libproto::{Message, OperateType, SyncRequest, SyncResponse};
use rand::{thread_rng, Rng, ThreadRng};
use std::collections::{BTreeMap, HashSet, VecDeque};
use std::convert::{Into, TryFrom, TryInto};
use std::sync::{mpsc, Arc};
use std::time::{Duration, Instant};
use std::u8;
use Source;

const SYNC_STEP: u64 = 20;
const SYNC_TIME_OUT: u64 = 60;

/// Get messages and determine if need to synchronize or broadcast the current node status
pub struct Synchronizer {
    tx_pub: mpsc::Sender<(String, Vec<u8>)>,
    con: Arc<Connection>,
    current_status: Status,
    global_status: Status,
    sync_end_height: u64, //current_status <= sync_end_status
    is_synchronizing: bool,
    latest_status_lists: BTreeMap<u64, VecDeque<u32>>,
    block_lists: BTreeMap<u64, Block>,
    rand: ThreadRng,
    // Timer for each height processing
    remote_sync_time_out: Instant,
    /// local sync error
    local_sync_count: u8,
}

unsafe impl Sync for Synchronizer {}
unsafe impl Send for Synchronizer {}

impl Synchronizer {
    pub fn new(tx_pub: mpsc::Sender<(String, Vec<u8>)>, con: Arc<Connection>) -> Self {
        Synchronizer {
            tx_pub: tx_pub,
            con: con,
            current_status: Status::new(),
            global_status: Status::new(),
            latest_status_lists: BTreeMap::new(),
            sync_end_height: 0,
            is_synchronizing: true,
            block_lists: BTreeMap::new(),
            rand: thread_rng(),
            remote_sync_time_out: (Instant::now() - Duration::from_secs(SYNC_TIME_OUT)),
            local_sync_count: 0,
        }
    }

    /// After receiving the `Chain >> Status`, it is processed as follows:
    /// 1. The chain height suddenly becomes lower than the original,
    ///    which means that the library is deleted, that is,
    ///    the synchronization is restarted from the received height.
    /// 2. The height of the chain is greater than or equal to the original height,
    ///    less than or equal to the height that the network has synchronized
    ///        - It is equal to the original height more than 2 times, indicating that
    ///          the data in the chain or executor is lost, and the block information is
    ///          sent again from the buffer. If no buffer exists, the data is requested again from other nodes.
    /// 3. The height is greater than or equal to the global height, indicating that the synchronization
    ///     has been completed and the synchronization status is exited.
    /// 4. The height is less than the global height, indicating that synchronization needs to be continued
    /// 5. Other unknown state
    pub fn update_current_status(&mut self, latest_status: Status) {
        debug!(
            "sync: update_current_status: current height = {}, \
             before height = {}, \
             sync_end_height = {}",
            latest_status.get_height(),
            self.current_status.get_height(),
            self.sync_end_height
        );
        let old_height = self.current_status.get_height();
        let new_height = latest_status.get_height();

        if new_height == old_height && self.local_sync_count < u8::MAX {
            // Chain height does not increase
            self.local_sync_count += 1;
        } else {
            self.local_sync_count = 0;
            self.remote_sync_time_out = Instant::now();
        }

        self.latest_status_lists = self
            .latest_status_lists
            .split_off(&(latest_status.get_height() + 1));
        self.current_status = latest_status;
        self.broadcast_status();
        self.prune_block_list_cache(new_height + 1);

        info!(
            "current: {}, sync_end: {}, global: {}, sync: {}",
            new_height,
            self.sync_end_height,
            self.global_status.get_height(),
            self.is_synchronizing
        );

        if new_height < old_height {
            // Chain error, may be a problem with the database, such as the database was deleted
            let start_height = new_height + 1;

            if self.block_lists.contains_key(&start_height) && !self.block_lists.is_empty() {
                self.submit_blocks();
            } else {
                self.start_sync_req(start_height);
            }
        } else if new_height < self.sync_end_height {
            // In synchronization, or loss of sync data, need to resend
            debug!(
                "Syncing: update_current_status: height = {}, block_lists len = {}",
                new_height,
                self.block_lists.len()
            );

            if !self.block_lists.is_empty() && new_height < self.sync_end_height {
                if self.local_sync_count >= 3 {
                    // Chain height does not increase, loss data or data is invalid,
                    // send cache to executor and chain, and clear cache
                    self.local_sync_count = 0;
                    self.block_lists.clear();
                    self.start_sync_req(new_height + 1);
                    info!("More than 3 times, clear the cache");
                }
            }

            self.is_synchronizing = true;
        } else if new_height >= self.global_status.get_height() {
            if self.is_synchronizing {
                self.is_synchronizing = false;
                self.sync_end_height = 0;
            }
        } else if new_height < self.global_status.get_height() {
            // If the block height is equal to the maximum height that has already been synchronized,
            // perform the synchronization operation first to see if it is the latest in the chain
            if self.is_synchronizing {
                self.start_sync_req(new_height + 1);
            }
        } else {
            info!("...Can't reach this");
        }
    }

    /// 1. Global height is less than current height + 1, no action
    /// 2. Global height is equal to current height + 1
    ///     - The global height continues to increase, and if the current state is not synchronized,
    ///       the synchronization request is initiated immediately.
    ///     - If the global height is no longer growing, after the predetermined time has elapsed,
    ///       the synchronization request is also initiated.
    /// 3. Global height is greater than current height + 1, Timeout or not in sync, initiate synchronization
    pub fn update_global_status(&mut self, status: &Status, origin: u32) {
        debug!(
            "sync: update_global_status: current height = {}, from node = {}, height = {}",
            self.current_status.get_height(),
            origin,
            status.get_height()
        );
        let current_height = self.current_status.get_height();
        let old_global_status = self.global_status.clone();
        if self.global_status.get_height() < status.get_height() {
            self.global_status = status.clone();
        }

        if status.get_height() < current_height + 1 {
            // The current node is the latest height and does not need to be synchronized
        } else if status.get_height() == current_height + 1 {
            // A node on the chain blocks out, synchronizing the latest block
            self.add_latest_sync_lists(status.get_height(), origin);

            if self.global_status.get_height() > old_global_status.get_height()
                && !self.is_synchronizing
            {
                self.start_sync_req(status.get_height());
            } else if self.global_status.get_height() == old_global_status.get_height()
                && !self.is_synchronizing
            {
                if self.remote_sync_time_out.elapsed().as_secs() > SYNC_TIME_OUT {
                    self.start_sync_req(current_height + 1);
                }
            }
        } else {
            // The node is far behind the data on the chain and initiates a synchronization request
            self.add_latest_sync_lists(status.get_height(), origin);

            if self.remote_sync_time_out.elapsed().as_secs() > SYNC_TIME_OUT
                || !self.is_synchronizing
            {
                self.start_sync_req(current_height + 1);
            }
        }
    }

    pub fn is_synchronizing(&self) -> bool {
        self.is_synchronizing
    }

    pub fn process_sync(&mut self, mut blocks: SyncResponse) {
        let blocks = blocks.take_blocks();
        debug!("sync: process_sync: blocks len = {}", blocks.len());

        let mut heights = vec![];
        for block in blocks.into_iter() {
            heights.push(block.get_header().get_height());
            self.block_lists
                .insert(block.get_header().get_height(), block);
        }

        debug!("sync: process_sync: heights = {:?}", heights);
        self.submit_blocks();
    }

    pub fn receive(&mut self, _from: Source, payload: (String, Vec<u8>)) {
        let (key, body) = payload;
        let mut msg = Message::try_from(&body).unwrap();
        let origin = msg.get_origin();
        match RoutingKey::from(&key) {
            routing_key!(Chain >> Status) => {
                if let Some(status) = msg.take_status() {
                    self.update_current_status(status);
                };
            }
            routing_key!(Synchronizer >> Status) => {
                if let Some(status) = msg.take_status() {
                    self.update_global_status(&status, origin);
                };
            }
            routing_key!(Synchronizer >> SyncResponse) => {
                if let Some(blocks) = msg.take_sync_response() {
                    self.process_sync(blocks);
                };
            }
            _ => {
                error!("receive: unexpected data key = {:?}", key);
            }
        }
    }

    // Initiate a sync request
    fn start_sync_req(&mut self, start_height: u64) {
        debug!(
            "sync: start_sync_req: start_height = {}, current height = {}",
            start_height,
            self.current_status.get_height()
        );
        let mut origin = 0;
        let mut end_height = start_height;
        let mut is_send = false;
        let current_height = self.current_status.get_height();

        if let Some((height, origins)) = self
            .latest_status_lists
            .iter()
            .rfind(|&(_, origins)| origins.len() > 0)
        {
            debug!(
                "sync: start_sync_req: height = {}, origins = {:?}",
                height, origins
            );
            if let Some(origins) = self.latest_status_lists.get(height) {
                if *height > current_height {
                    origin = origins[self.rand.gen_range(0, origins.len())];
                    end_height = if *height + 1 > current_height + SYNC_STEP {
                        current_height + SYNC_STEP
                    } else {
                        *height + 1
                    };
                    is_send = true;
                }
            }
        }

        if is_send {
            self.sync_strategy(start_height, end_height, origin);
        }
    }

    fn sync_strategy(&self, start_height: u64, end_height: u64, origin: u32) {
        //current height = 155,start_height = 156, end height = 160, to origin = 1
        debug!(
            "sync: sync_strategy: current height = {}, \
             start_height = {}, \
             end height = {}, \
             to origin = {}",
            self.current_status.get_height(),
            start_height,
            end_height,
            origin
        );
        if start_height >= self.current_status.get_height() && start_height <= end_height {
            let mut start_height = start_height;
            let mut step_sum = SYNC_STEP;
            let mut heights = vec![];

            while start_height <= end_height {
                if step_sum == 0 {
                    step_sum = SYNC_STEP;
                    self.send_sync_req(heights, origin);
                    heights = vec![];
                }
                heights.push(start_height);

                step_sum -= 1;
                start_height += 1;
            }
            self.send_sync_req(heights, origin);
        }
    }

    fn send_sync_req(&self, heights: Vec<u64>, origin: u32) {
        if !heights.is_empty() {
            debug!(
                "sync: send_sync_req:current height = {}, \
                 heights = {:?}, \
                 origin {:?}, \
                 chain.sync: OperateType {:?}",
                self.current_status.get_height(),
                heights,
                origin,
                OperateType::Single
            );
            let mut sync_req = SyncRequest::new();
            sync_req.set_heights(heights);
            let msg = Message::init(OperateType::Single, origin, sync_req.into());
            self.con
                .broadcast(routing_key!(Synchronizer >> SyncRequest).into(), msg);
        }
    }

    fn broadcast_status(&mut self) {
        debug!(
            "sync: broadcast status {:?}, {:?} to other nodes",
            self.current_status.get_height(),
            self.current_status.get_hash()
        );
        let msg: Message = self.current_status.clone().into();
        self.con
            .broadcast(routing_key!(Synchronizer >> Status).into(), msg);
    }

    // Submit synchronization information
    fn submit_blocks(&mut self) {
        let mut height = self.current_status.get_height() + 1;
        debug!(
            "sync: submit_blocks:submit_height = {},\
             current height = {},\
             sync_end_height = {},\
             block_lists = {}",
            height,
            self.current_status.get_height(),
            self.sync_end_height,
            self.block_lists.len()
        );
        let mut blocks = vec![];
        let end_height = height + SYNC_STEP;

        loop {
            if height <= end_height {
                if let Some(block) = self.block_lists.get(&height) {
                    blocks.push(block.to_owned());
                } else {
                    break;
                }
            } else {
                break;
            }
            height += 1;
        }

        match blocks.last() {
            Some(block) => {
                if let Some(header) = block.header.as_ref() {
                    let height = header.get_height() - 1;

                    if height > self.sync_end_height {
                        self.sync_end_height = height;
                    }
                }
            }
            None => {}
        }

        if self.block_lists.contains_key(&::std::u64::MAX) {
            blocks.push(self.block_lists.remove(&::std::u64::MAX).unwrap());
        }

        self.pub_blocks(blocks);
        self.is_synchronizing = true;
        self.remote_sync_time_out = Instant::now();
    }

    fn pub_blocks(&mut self, blocks: Vec<Block>) {
        if !blocks.is_empty() {
            debug!(
                "sync: pub_blocks: current height = {}, \
                 sync_end_height = {}, \
                 len = {}, ",
                self.current_status.get_height(),
                self.sync_end_height,
                blocks.len()
            );
            let mut sync_res = SyncResponse::new();
            sync_res.set_blocks(blocks.into());
            let msg: Message = sync_res.into();
            self.tx_pub.send((
                routing_key!(Net >> SyncResponse).into(),
                msg.try_into().unwrap(),
            ));
        }
    }

    fn add_latest_sync_lists(&mut self, height: u64, origin: u32) {
        debug!(
            "sync: add_sync_lists: current height = {}, \
             from node = {}, \
             height = {}",
            self.current_status.get_height(),
            origin,
            height
        );
        if self
            .latest_status_lists
            .entry(height)
            .or_insert_with(VecDeque::new)
            .iter()
            .fold(HashSet::new(), |mut set, item| {
                set.insert(item);
                set
            })
            .insert(&origin)
        {
            self.latest_status_lists
                .entry(height)
                .or_insert_with(VecDeque::new)
                .push_back(origin);
        }
    }

    /// Prune block on btreemap
    fn prune_block_list_cache(&mut self, height: u64) {
        self.block_lists = self.block_lists.split_off(&height);
    }
}
<commit_msg>:bug: fix sync init<commit_after>use connection::Connection;
use libproto::blockchain::{Block, Status};
use libproto::router::{MsgType, RoutingKey, SubModules};
use libproto::{Message, OperateType, SyncRequest, SyncResponse};
use rand::{thread_rng, Rng, ThreadRng};
use std::collections::{BTreeMap, HashSet, VecDeque};
use std::convert::{Into, TryFrom, TryInto};
use std::sync::{mpsc, Arc};
use std::time::{Duration, Instant};
use std::u8;
use Source;

const SYNC_STEP: u64 = 20;
const SYNC_TIME_OUT: u64 = 9;

/// Get messages and determine if need to synchronize or broadcast the current node status
pub struct Synchronizer {
    tx_pub: mpsc::Sender<(String, Vec<u8>)>,
    con: Arc<Connection>,
    current_status: Status,
    global_status: Status,
    sync_end_height: u64, //current_status <= sync_end_status
    is_synchronizing: bool,
    latest_status_lists: BTreeMap<u64, VecDeque<u32>>,
    block_lists: BTreeMap<u64, Block>,
    rand: ThreadRng,
    // Timer for each height processing
    remote_sync_time_out: Instant,
    /// local sync error
    local_sync_count: u8,
}

unsafe impl Sync for Synchronizer {}
unsafe impl Send for Synchronizer {}

impl Synchronizer {
    pub fn new(tx_pub: mpsc::Sender<(String, Vec<u8>)>, con: Arc<Connection>) -> Self {
        Synchronizer {
            tx_pub: tx_pub,
            con: con,
            current_status: Status::new(),
            global_status: Status::new(),
            latest_status_lists: BTreeMap::new(),
            sync_end_height: 0,
            is_synchronizing: false,
            block_lists: BTreeMap::new(),
            rand: thread_rng(),
            remote_sync_time_out: (Instant::now() - Duration::from_secs(SYNC_TIME_OUT)),
            local_sync_count: 0,
        }
    }

    /// After receiving the `Chain >> Status`, it is processed as follows:
    /// 1. The chain height suddenly becomes lower than the original,
    ///    which means that the library is deleted, that is,
    ///    the synchronization is restarted from the received height.
    /// 2. The height of the chain is greater than or equal to the original height,
    ///    less than or equal to the height that the network has synchronized
    ///        - It is equal to the original height more than 2 times, indicating that
    ///          the data in the chain or executor is lost, and the block information is
    ///          sent again from the buffer. If no buffer exists, the data is requested again from other nodes.
    /// 3. The height is greater than or equal to the global height, indicating that the synchronization
    ///     has been completed and the synchronization status is exited.
    /// 4. The height is less than the global height, indicating that synchronization needs to be continued
    /// 5. Other unknown state
    pub fn update_current_status(&mut self, latest_status: Status) {
        debug!(
            "sync: update_current_status: current height = {}, \
             before height = {}, \
             sync_end_height = {}",
            latest_status.get_height(),
            self.current_status.get_height(),
            self.sync_end_height
        );
        let old_height = self.current_status.get_height();
        let new_height = latest_status.get_height();

        if new_height == old_height {
            if self.local_sync_count < u8::MAX {
                // Chain height does not increase
                self.local_sync_count += 1;
            }
        } else {
            self.local_sync_count = 0;
            self.remote_sync_time_out = Instant::now();
        }

        self.latest_status_lists = self
            .latest_status_lists
            .split_off(&(latest_status.get_height() + 1));
        self.current_status = latest_status;
        self.broadcast_status();
        self.prune_block_list_cache(new_height + 1);

        info!(
            "current: {}, sync_end: {}, global: {}, sync: {}",
            new_height,
            self.sync_end_height,
            self.global_status.get_height(),
            self.is_synchronizing
        );

        if new_height < old_height {
            // Chain error, may be a problem with the database, such as the database was deleted
            let start_height = new_height + 1;

            if self.block_lists.contains_key(&start_height) && !self.block_lists.is_empty() {
                self.submit_blocks();
            } else {
                self.start_sync_req(start_height);
            }
        } else if new_height < self.sync_end_height {
            // In synchronization, or loss of sync data, need to resend
            debug!(
                "Syncing: update_current_status: height = {}, block_lists len = {}",
                new_height,
                self.block_lists.len()
            );

            if !self.block_lists.is_empty() && new_height < self.sync_end_height {
                if self.local_sync_count >= 3 {
                    // Chain height does not increase, loss data or data is invalid,
                    // send cache to executor and chain, and clear cache
                    self.local_sync_count = 0;
                    self.block_lists.clear();
                    self.start_sync_req(new_height + 1);
                    info!("More than 3 times, clear the cache");
                }
            }

            self.is_synchronizing = true;
        } else if new_height >= self.global_status.get_height() {
            if self.is_synchronizing {
                self.is_synchronizing = false;
                self.sync_end_height = 0;
            }
        } else if new_height < self.global_status.get_height() {
            // If the block height is equal to the maximum height that has already been synchronized,
            // perform the synchronization operation first to see if it is the latest in the chain
            if self.is_synchronizing {
                self.start_sync_req(new_height + 1);
            }
        } else {
            info!("...Can't reach this");
        }
    }

    /// 1. Global height is less than current height + 1, no action
    /// 2. Global height is equal to current height + 1
    ///     - The global height continues to increase, and if the current state is not synchronized,
    ///       the synchronization request is initiated immediately.
    ///     - If the global height is no longer growing, after the predetermined time has elapsed,
    ///       the synchronization request is also initiated.
    /// 3. Global height is greater than current height + 1, Timeout or not in sync, initiate synchronization
    pub fn update_global_status(&mut self, status: &Status, origin: u32) {
        debug!(
            "sync: update_global_status: current height = {}, from node = {}, height = {}",
            self.current_status.get_height(),
            origin,
            status.get_height()
        );
        let current_height = self.current_status.get_height();
        if self.global_status.get_height() < status.get_height() {
            self.global_status = status.clone();
        }

        if status.get_height() < current_height + 1 {
            // The current node is the latest height and does not need to be synchronized
        } else if status.get_height() == current_height + 1 {
            // A node on the chain blocks out, synchronizing the latest block
            self.add_latest_sync_lists(status.get_height(), origin);

            if self.remote_sync_time_out.elapsed().as_secs() > SYNC_TIME_OUT
                && !self.is_synchronizing
            {
                self.start_sync_req(current_height + 1);
            }
        } else {
            // The node is far behind the data on the chain and initiates a synchronization request
            self.add_latest_sync_lists(status.get_height(), origin);

            if self.remote_sync_time_out.elapsed().as_secs() > SYNC_TIME_OUT
                || !self.is_synchronizing
            {
                self.start_sync_req(current_height + 1);
            }
        }
    }

    pub fn is_synchronizing(&self) -> bool {
        self.is_synchronizing
    }

    pub fn process_sync(&mut self, mut blocks: SyncResponse) {
        let blocks = blocks.take_blocks();
        debug!("sync: process_sync: blocks len = {}", blocks.len());

        let mut heights = vec![];
        for block in blocks.into_iter() {
            heights.push(block.get_header().get_height());
            self.block_lists
                .insert(block.get_header().get_height(), block);
        }

        debug!("sync: process_sync: heights = {:?}", heights);
        self.submit_blocks();
    }

    pub fn receive(&mut self, _from: Source, payload: (String, Vec<u8>)) {
        let (key, body) = payload;
        let mut msg = Message::try_from(&body).unwrap();
        let origin = msg.get_origin();
        match RoutingKey::from(&key) {
            routing_key!(Chain >> Status) => {
                if let Some(status) = msg.take_status() {
                    self.update_current_status(status);
                };
            }
            routing_key!(Synchronizer >> Status) => {
                if let Some(status) = msg.take_status() {
                    self.update_global_status(&status, origin);
                };
            }
            routing_key!(Synchronizer >> SyncResponse) => {
                if let Some(blocks) = msg.take_sync_response() {
                    self.process_sync(blocks);
                };
            }
            _ => {
                error!("receive: unexpected data key = {:?}", key);
            }
        }
    }

    // Initiate a sync request
    fn start_sync_req(&mut self, start_height: u64) {
        debug!(
            "sync: start_sync_req: start_height = {}, current height = {}",
            start_height,
            self.current_status.get_height()
        );
        let mut origin = 0;
        let mut end_height = start_height;
        let mut is_send = false;
        let current_height = self.current_status.get_height();

        if let Some((height, origins)) = self
            .latest_status_lists
            .iter()
            .rfind(|&(_, origins)| origins.len() > 0)
        {
            debug!(
                "sync: start_sync_req: height = {}, origins = {:?}",
                height, origins
            );
            if let Some(origins) = self.latest_status_lists.get(height) {
                if *height > current_height {
                    origin = origins[self.rand.gen_range(0, origins.len())];
                    end_height = if *height + 1 > current_height + SYNC_STEP {
                        current_height + SYNC_STEP
                    } else {
                        *height + 1
                    };
                    is_send = true;
                }
            }
        }

        if is_send {
            self.sync_strategy(start_height, end_height, origin);
        }
    }

    fn sync_strategy(&self, start_height: u64, end_height: u64, origin: u32) {
        //current height = 155,start_height = 156, end height = 160, to origin = 1
        debug!(
            "sync: sync_strategy: current height = {}, \
             start_height = {}, \
             end height = {}, \
             to origin = {}",
            self.current_status.get_height(),
            start_height,
            end_height,
            origin
        );
        if start_height >= self.current_status.get_height() && start_height <= end_height {
            let mut start_height = start_height;
            let mut step_sum = SYNC_STEP;
            let mut heights = vec![];

            while start_height <= end_height {
                if step_sum == 0 {
                    step_sum = SYNC_STEP;
                    self.send_sync_req(heights, origin);
                    heights = vec![];
                }
                heights.push(start_height);

                step_sum -= 1;
                start_height += 1;
            }
            self.send_sync_req(heights, origin);
        }
    }

    fn send_sync_req(&self, heights: Vec<u64>, origin: u32) {
        if !heights.is_empty() {
            debug!(
                "sync: send_sync_req:current height = {}, \
                 heights = {:?}, \
                 origin {:?}, \
                 chain.sync: OperateType {:?}",
                self.current_status.get_height(),
                heights,
                origin,
                OperateType::Single
            );
            let mut sync_req = SyncRequest::new();
            sync_req.set_heights(heights);
            let msg = Message::init(OperateType::Single, origin, sync_req.into());
            self.con
                .broadcast(routing_key!(Synchronizer >> SyncRequest).into(), msg);
        }
    }

    fn broadcast_status(&mut self) {
        debug!(
            "sync: broadcast status {:?}, {:?} to other nodes",
            self.current_status.get_height(),
            self.current_status.get_hash()
        );
        let msg: Message = self.current_status.clone().into();
        self.con
            .broadcast(routing_key!(Synchronizer >> Status).into(), msg);
    }

    // Submit synchronization information
    fn submit_blocks(&mut self) {
        let mut height = self.current_status.get_height() + 1;
        debug!(
            "sync: submit_blocks:submit_height = {},\
             current height = {},\
             sync_end_height = {},\
             block_lists = {}",
            height,
            self.current_status.get_height(),
            self.sync_end_height,
            self.block_lists.len()
        );
        let mut blocks = vec![];
        let end_height = height + SYNC_STEP;

        loop {
            if height <= end_height {
                if let Some(block) = self.block_lists.get(&height) {
                    blocks.push(block.to_owned());
                } else {
                    break;
                }
            } else {
                break;
            }
            height += 1;
        }

        match blocks.last() {
            Some(block) => {
                if let Some(header) = block.header.as_ref() {
                    let height = header.get_height() - 1;

                    if height > self.sync_end_height {
                        self.sync_end_height = height;
                    }
                }
            }
            None => {}
        }

        if self.block_lists.contains_key(&::std::u64::MAX) {
            blocks.push(self.block_lists.remove(&::std::u64::MAX).unwrap());
        }

        self.pub_blocks(blocks);
        self.is_synchronizing = true;
        self.remote_sync_time_out = Instant::now();
    }

    fn pub_blocks(&mut self, blocks: Vec<Block>) {
        if !blocks.is_empty() {
            debug!(
                "sync: pub_blocks: current height = {}, \
                 sync_end_height = {}, \
                 len = {}, ",
                self.current_status.get_height(),
                self.sync_end_height,
                blocks.len()
            );
            let mut sync_res = SyncResponse::new();
            sync_res.set_blocks(blocks.into());
            let msg: Message = sync_res.into();
            self.tx_pub.send((
                routing_key!(Net >> SyncResponse).into(),
                msg.try_into().unwrap(),
            ));
        }
    }

    fn add_latest_sync_lists(&mut self, height: u64, origin: u32) {
        debug!(
            "sync: add_sync_lists: current height = {}, \
             from node = {}, \
             height = {}",
            self.current_status.get_height(),
            origin,
            height
        );
        if self
            .latest_status_lists
            .entry(height)
            .or_insert_with(VecDeque::new)
            .iter()
            .fold(HashSet::new(), |mut set, item| {
                set.insert(item);
                set
            })
            .insert(&origin)
        {
            self.latest_status_lists
                .entry(height)
                .or_insert_with(VecDeque::new)
                .push_back(origin);
        }
    }

    /// Prune block on btreemap
    fn prune_block_list_cache(&mut self, height: u64) {
        self.block_lists = self.block_lists.split_off(&height);
    }
}
<|endoftext|>


<commit_before>extern crate robin_core;

extern crate nom;

#[cfg(test)]
mod parser_tests {
    use nom::IResult;

    use robin_core::parser::identifier;

    #[test]
    fn parse_a_left_brace() {
        assert_eq!(identifier::symbol_identifier(b"{"),
                   IResult::Done(&b""[..], "{".to_string()));
    }

    #[test]
    fn parse_a_right_brace() {
        assert_eq!(identifier::symbol_identifier(b"}"),
                   IResult::Done(&b""[..], "}".to_string()));
    }

    #[test]
    fn parse_a_left_bracket() {
        assert_eq!(identifier::symbol_identifier(b"("),
                   IResult::Done(&b""[..], "(".to_string()));
    }

    #[test]
    fn parse_a_right_bracket() {
        assert_eq!(identifier::symbol_identifier(b")"),
                   IResult::Done(&b""[..], ")".to_string()));
    }

    #[test]
    fn parse_a_left_square_bracket() {
        assert_eq!(identifier::symbol_identifier(b"["),
                   IResult::Done(&b""[..], "[".to_string()));
    }

    #[test]
    fn parse_a_right_square_bracket() {
        assert_eq!(identifier::symbol_identifier(b"]"),
                   IResult::Done(&b""[..], "]".to_string()));
    }

    #[test]
    fn parse_a_fullstop() {
        assert_eq!(identifier::symbol_identifier(b"."),
                   IResult::Done(&b""[..], ".".to_string()));
    }

    #[test]
    fn parse_a_semicolon() {
        assert_eq!(identifier::symbol_identifier(b";"),
                   IResult::Done(&b""[..], ";".to_string()));
    }

    #[test]
    fn parse_a_comma() {
        assert_eq!(identifier::symbol_identifier(b","),
                   IResult::Done(&b""[..], ",".to_string()));
    }

    #[test]
    fn parse_less_than() {
        assert_eq!(identifier::symbol_identifier(b"<"),
                   IResult::Done(&b""[..], "<".to_string()));
    }

    #[test]
    fn parse_greater_than() {
        assert_eq!(identifier::symbol_identifier(b">"),
                   IResult::Done(&b""[..], ">".to_string()));
    }

    #[test]
    fn parse_equals() {
        assert_eq!(identifier::symbol_identifier(b"="),
                   IResult::Done(&b""[..], "=".to_string()));
    }

    #[test]
    fn parse_exclamation() {
        assert_eq!(identifier::symbol_identifier(b"!"),
                   IResult::Done(&b""[..], "!".to_string()));
    }

    #[test]
    fn parse_plus() {
        assert_eq!(identifier::symbol_identifier(b"+"),
                   IResult::Done(&b""[..], "+".to_string()));
    }

    #[test]
    fn parse_minus() {
        assert_eq!(identifier::symbol_identifier(b"-"),
                   IResult::Done(&b""[..], "-".to_string()));
    }

    #[test]
    fn parse_times() {
        assert_eq!(identifier::symbol_identifier(b"*"),
                   IResult::Done(&b""[..], "*".to_string()));
    }

    #[test]
    fn parse_divide() {
        assert_eq!(identifier::symbol_identifier(b"/"),
                   IResult::Done(&b""[..], "/".to_string()));
    }

    #[test]
    fn parse_ampersand() {
        assert_eq!(identifier::symbol_identifier(b"&"),
                   IResult::Done(&b""[..], "&".to_string()));
    }

    #[test]
    fn parse_pipe() {
        assert_eq!(identifier::symbol_identifier(b"|"),
                   IResult::Done(&b""[..], "|".to_string()));
    }

    #[test]
    fn parse_power_of() {
        assert_eq!(identifier::symbol_identifier(b"^"),
                   IResult::Done(&b""[..], "^".to_string()));
    }

    #[test]
    fn parse_tilde() {
        assert_eq!(identifier::symbol_identifier(b"~"),
                   IResult::Done(&b""[..], "~".to_string()));
    }

    #[test]
    fn parse_question() {
        assert_eq!(identifier::symbol_identifier(b"?"),
                   IResult::Done(&b""[..], "?".to_string()));
    }

    #[test]
    fn parse_colon() {
        assert_eq!(identifier::symbol_identifier(b":"),
                   IResult::Done(&b""[..], ":".to_string()));
    }
}
/*
                | tag!(":")
*/<commit_msg>Add a test to parse mutliple symbols<commit_after>extern crate robin_core;

extern crate nom;

#[cfg(test)]
mod parser_tests {
    use nom::IResult;

    use robin_core::parser::identifier;

    #[test]
    fn parse_a_left_brace() {
        assert_eq!(identifier::symbol_identifier(b"{"),
                   IResult::Done(&b""[..], "{".to_string()));
    }

    #[test]
    fn parse_a_right_brace() {
        assert_eq!(identifier::symbol_identifier(b"}"),
                   IResult::Done(&b""[..], "}".to_string()));
    }

    #[test]
    fn parse_a_left_bracket() {
        assert_eq!(identifier::symbol_identifier(b"("),
                   IResult::Done(&b""[..], "(".to_string()));
    }

    #[test]
    fn parse_a_right_bracket() {
        assert_eq!(identifier::symbol_identifier(b")"),
                   IResult::Done(&b""[..], ")".to_string()));
    }

    #[test]
    fn parse_a_left_square_bracket() {
        assert_eq!(identifier::symbol_identifier(b"["),
                   IResult::Done(&b""[..], "[".to_string()));
    }

    #[test]
    fn parse_a_right_square_bracket() {
        assert_eq!(identifier::symbol_identifier(b"]"),
                   IResult::Done(&b""[..], "]".to_string()));
    }

    #[test]
    fn parse_a_fullstop() {
        assert_eq!(identifier::symbol_identifier(b"."),
                   IResult::Done(&b""[..], ".".to_string()));
    }

    #[test]
    fn parse_a_semicolon() {
        assert_eq!(identifier::symbol_identifier(b";"),
                   IResult::Done(&b""[..], ";".to_string()));
    }

    #[test]
    fn parse_a_comma() {
        assert_eq!(identifier::symbol_identifier(b","),
                   IResult::Done(&b""[..], ",".to_string()));
    }

    #[test]
    fn parse_less_than() {
        assert_eq!(identifier::symbol_identifier(b"<"),
                   IResult::Done(&b""[..], "<".to_string()));
    }

    #[test]
    fn parse_greater_than() {
        assert_eq!(identifier::symbol_identifier(b">"),
                   IResult::Done(&b""[..], ">".to_string()));
    }

    #[test]
    fn parse_equals() {
        assert_eq!(identifier::symbol_identifier(b"="),
                   IResult::Done(&b""[..], "=".to_string()));
    }

    #[test]
    fn parse_exclamation() {
        assert_eq!(identifier::symbol_identifier(b"!"),
                   IResult::Done(&b""[..], "!".to_string()));
    }

    #[test]
    fn parse_plus() {
        assert_eq!(identifier::symbol_identifier(b"+"),
                   IResult::Done(&b""[..], "+".to_string()));
    }

    #[test]
    fn parse_minus() {
        assert_eq!(identifier::symbol_identifier(b"-"),
                   IResult::Done(&b""[..], "-".to_string()));
    }

    #[test]
    fn parse_times() {
        assert_eq!(identifier::symbol_identifier(b"*"),
                   IResult::Done(&b""[..], "*".to_string()));
    }

    #[test]
    fn parse_divide() {
        assert_eq!(identifier::symbol_identifier(b"/"),
                   IResult::Done(&b""[..], "/".to_string()));
    }

    #[test]
    fn parse_ampersand() {
        assert_eq!(identifier::symbol_identifier(b"&"),
                   IResult::Done(&b""[..], "&".to_string()));
    }

    #[test]
    fn parse_pipe() {
        assert_eq!(identifier::symbol_identifier(b"|"),
                   IResult::Done(&b""[..], "|".to_string()));
    }

    #[test]
    fn parse_power_of() {
        assert_eq!(identifier::symbol_identifier(b"^"),
                   IResult::Done(&b""[..], "^".to_string()));
    }

    #[test]
    fn parse_tilde() {
        assert_eq!(identifier::symbol_identifier(b"~"),
                   IResult::Done(&b""[..], "~".to_string()));
    }

    #[test]
    fn parse_question() {
        assert_eq!(identifier::symbol_identifier(b"?"),
                   IResult::Done(&b""[..], "?".to_string()));
    }

    #[test]
    fn parse_colon() {
        assert_eq!(identifier::symbol_identifier(b":"),
                   IResult::Done(&b""[..], ":".to_string()));
    }

    #[test]
    fn parse_multiple_symbols() {
        assert_eq!(identifier::symbol_identifier(b"|>+"),
                   IResult::Done(&b""[..], "|>+".to_string()));
    }
}<|endoftext|>