<commit_before>use std::collections::HashMap;
use std::hash::BuildHasherDefault;

use fnv::FnvHasher;

use {Entity, Index, Generation};
use bitset::BitSet;

/// Base trait for a component storage that is used as a trait object.
/// Doesn't depend on the actual component type.
pub trait StorageBase {
    /// Deletes a particular `Entity` from the storage.
    fn del(&mut self, Entity);
}

pub struct Storage<T, U> where
    U: UnprotectedStorage<T>
{
    mask: BitSet,
    inner: U,
}

impl<T, U> Storage<T, U> where
    T: Component<Storage=U>,
    U: UnprotectedStorage<T>,
{
    /// Creates a new `Storage`. This is called when you register a new
    /// component type within the world.
    pub fn new() -> Storage<T, U> {
        Storage {
            mask: BitSet::new(),
            data: UnprotectedStorage::new(),
        }
    }
    /// Tries to read the data associated with an `Entity`.
    pub fn get(&self, Entity) -> Option<&T> {
        let id = e.get_id();
        if self.mask.contains(id as u32) {
            let v = unsafe { self.data.get(id) };
            if v.generation == e.get_gen() {
                return Some(&v.data);
            }
        }
        None
    }
    /// Tries to mutate the data associated with an `Entity`.
    fn get_mut(&mut self, Entity) -> Option<&mut T> {
        let id = e.get_id();
        if self.mask.contains(id as u32) {
            let v = unsafe { self.data.get_mut(id) };
            if v.generation == e.get_gen() {
                return Some(&mut v.data);
            }
        }
        None
    }
    /// Inserts new data for a given `Entity`.
    fn insert(&mut self, Entity, T) {
        let id = e.get_id();
        if self.mask.contains(id as u32) {
            let mut data = &mut self.values.0[id];
            data.generation = e.get_gen();
            mem::swap(&mut data.data, &mut v);
            Some(v)
        } else {
            self.set.add(id as u32);
            if self.values.0.len() <= id {
                self.extend(id);
            }
            unsafe {
                ptr::write(
                    &mut self.values.0[id],
                    GenerationData{
                        generation: e.get_gen(),
                        data: v
                    }
                );
            }
            None
        };
    }
    /// Removes the data associated with an `Entity`.
    fn remove(&mut self, Entity) -> Option<T> {

    }
}
/// Typed component storage trait.
pub trait Storage: StorageBase + Sized {
    /// The Component to get or set
    type Component;
    /// Used during iterator
    type UnprotectedStorage: UnprotectedStorage<Component=Self::Component>;
    /// Creates a new `Storage<T>`. This is called when you register a new
    /// component type within the world.
    fn new() -> Self;
    /// Inserts new data for a given `Entity`.
    fn insert(&mut self, Entity, Self::Component);
    /// Tries to read the data associated with an `Entity`.
    fn get(&self, Entity) -> Option<&Self::Component>;
    /// Tries to mutate the data associated with an `Entity`.
    fn get_mut(&mut self, Entity) -> Option<&mut Self::Component>;
    /// Removes the data associated with an `Entity`.
    fn remove(&mut self, Entity) -> Option<Self::Component>;
}

/// Used by the framework to quickly join componets
pub trait UnprotectedStorage<T>: Sized {
    /// Creates a new `Storage<T>`. This is called when you register a new
    /// component type within the world.
    fn new() -> Self;
    /// Tries reading the data associated with an `Entity`.
    /// This is unsafe because the external set used
    /// to protect this storage is absent.
    unsafe fn get(&self, id: Index) -> &T;
    /// Tries mutating the data associated with an `Entity`.
    /// This is unsafe because the external set used
    /// to protect this storage is absent.
    unsafe fn get_mut(&mut self, id: Index) -> &mut T;
    /// Inserts new data for a given `Entity`.
    unsafe fn insert(&mut self, Index, T);
    /// Removes the data associated with an `Entity`.
    unsafe fn remove(&mut self, Index) -> Option<T>;
}

pub struct InnerHashMap<T>(HashMap<Index, GenerationData<T>, BuildHasherDefault<FnvHasher>>);

/// HashMap-based storage. Best suited for rare components.
pub struct HashMapStorage<T>{
    set: BitSet,
    map: InnerHashMap<T>
}

impl<T> StorageBase for HashMapStorage<T> {
    fn del(&mut self, entity: Entity) {
        if self.set.remove(entity.get_id() as u32) {
            self.map.0.remove(&(entity.get_id() as u32));
        }
    }
}

impl<T> Storage for HashMapStorage<T> {
    type Component = T;
    type UnprotectedStorage = InnerHashMap<T>;

    fn new() -> Self {
        let fnv = BuildHasherDefault::<FnvHasher>::default();
        HashMapStorage {
            set: BitSet::new(),
            map: InnerHashMap(HashMap::with_hasher(fnv))
        }
    }
    fn get(&self, entity: Entity) -> Option<&T> {
        self.map.0.get(&(entity.get_id() as u32))
            .and_then(|x| if x.generation == entity.get_gen() { Some(&x.data) } else { None })

    }
    fn get_mut(&mut self, entity: Entity) -> Option<&mut T> {
        self.map.0.get_mut(&(entity.get_id() as u32))
            .and_then(|x| if x.generation == entity.get_gen() { Some(&mut x.data) } else { None })

    }
    fn insert(&mut self, entity: Entity, value: T) {
        let value = GenerationData{
            data: value,
            generation: entity.get_gen()
        };
        if self.map.0.insert(entity.get_id() as u32, value).is_none() {
            self.set.add(entity.get_id() as u32);
        }
    }
    fn remove(&mut self, entity: Entity) -> Option<T> {
        if self.set.remove(entity.get_id() as u32) {
            let value = self.map.0.remove(&(entity.get_id() as u32)).unwrap();
            if value.generation == entity.get_gen() {
                Some(value.data)
            } else {
                // it should be unlikely that the generation mismatch was
                // wrong, so this is a slow path to re-add the value back
                self.insert(entity, value.data);
                None
            }
        } else {
            None
        }
    }
    fn open(&self) -> (&BitSet, &Self::UnprotectedStorage) {
        (&self.set, &self.map)
    }
    fn open_mut(&mut self) -> (&BitSet, &mut Self::UnprotectedStorage) {
        (&self.set, &mut self.map)
    }
}

impl<T> UnprotectedStorage for InnerHashMap<T> {
    type Component = T;
    unsafe fn get(&self, e: Index) -> &T {
        &self.0.get(&e).unwrap().data
    }
    unsafe fn get_mut(&mut self, e: Index) -> &mut T {
        &mut self.0.get_mut(&e).unwrap().data
    }
}

pub struct InnerVec<T>(Vec<GenerationData<T>>);

pub struct GenerationData<T> {
    pub generation: Generation,
    pub data: T
}

/// Vec-based storage, stores the generations of the data in
/// order to match with given entities. Supposed to have maximum
/// performance for the components mostly present in entities.
pub struct VecStorage<T> {
    set: BitSet,
    values: InnerVec<T>,
}

impl<T> VecStorage<T> {
    fn extend(&mut self, id: usize) {
        debug_assert!(id >= self.values.0.len());
        let delta = (id + 1) - self.values.0.len();
        self.values.0.reserve(delta);
        unsafe {
            self.values.0.set_len(id + 1);
        }
    }
}

impl<T> Drop for VecStorage<T> {
    fn drop(&mut self) {
        use std::mem;

        for (i, v) in self.values.0.drain(..).enumerate() {
            // if v was not in the set the data is invalid
            // and we must forget it instead of dropping it
            if !self.set.remove(i as u32) {
                mem::forget(v);
            }
        }
    }
}

impl<T> super::StorageBase for VecStorage<T> {
    fn del(&mut self, e: Entity) {
        self.remove(e);
    }
}

impl<T> super::Storage for VecStorage<T> {
    type Component = T;
    type UnprotectedStorage = InnerVec<T>;

    fn new() -> Self {
        VecStorage {
            set: BitSet::new(),
            values: InnerVec(Vec::new()),
        }
    }
    fn get(&self, e: Entity) -> Option<&T> {
        let id = e.get_id();
        if self.set.contains(id as u32) {
            let v = unsafe { self.values.0.get_unchecked(id) };
            if v.generation == e.get_gen() {
                return Some(&v.data);
            }
        }
        None

    }
    fn get_mut(&mut self, e: Entity) -> Option<&mut T> {
        let id = e.get_id();
        if self.set.contains(id as u32) {
            let v = unsafe { self.values.0.get_unchecked_mut(id) };
            if v.generation == e.get_gen() {
                return Some(&mut v.data);
            }
        }
        None
    }
    fn insert(&mut self, e: Entity, mut v: T) {
        use std::{ptr, mem};

        let id = e.get_id();
        if self.set.contains(id as u32) {
            let mut data = &mut self.values.0[id];
            data.generation = e.get_gen();
            mem::swap(&mut data.data, &mut v);
            Some(v)
        } else {
            self.set.add(id as u32);
            if self.values.0.len() <= id {
                self.extend(id);
            }
            unsafe {
                ptr::write(
                    &mut self.values.0[id],
                    GenerationData{
                        generation: e.get_gen(),
                        data: v
                    }
                );
            }
            None
        };
    }
    fn remove(&mut self, e: Entity) -> Option<T> {
        use std::ptr;

        let (id, gen) = (e.get_id(), e.get_gen());
        let gen_matches = self.values.0.get(id)
            .map(|x| x.generation == gen).unwrap_or(false);

        if gen_matches && self.set.remove(id as u32) {
            let value = unsafe { ptr::read(&self.values.0[id]) };
            Some(value.data)
        } else {
            None
        }
    }
    fn open(&self) -> (&BitSet, &InnerVec<T>) {
        (&self.set, &self.values)
    }
    fn open_mut(&mut self) -> (&BitSet, &mut InnerVec<T>) {
        (&self.set, &mut self.values)
    }
}

impl<T> super::UnprotectedStorage for InnerVec<T> {
    type Component = T;
    unsafe fn get(&self, e: u32) -> &T {
        &self.0.get_unchecked(e as usize).data
    }
    unsafe fn get_mut(&mut self, e: u32) -> &mut T {
        &mut self.0.get_unchecked_mut(e as usize).data
    }
}

#[cfg(test)]
mod map_test {
    use {Storage, Entity, Generation};
    use super::VecStorage;

    #[test]
    fn insert() {
        let mut c = VecStorage::new();
        for i in 0..1_000 {
            c.insert(Entity::new(i, Generation(0)), i);
        }

        for i in 0..1_000 {
            assert_eq!(c.get(Entity::new(i, Generation(0))).unwrap(), &i);
        }
    }

    #[test]
    fn insert_100k() {
        let mut c = VecStorage::new();
        for i in 0..100_000 {
            c.insert(Entity::new(i, Generation(0)), i);
        }

        for i in 0..100_000 {
            assert_eq!(c.get(Entity::new(i, Generation(0))).unwrap(), &i);
        }
    }

    #[test]
    fn remove() {
        let mut c = VecStorage::new();
        for i in 0..1_000 {
            c.insert(Entity::new(i, Generation(0)), i);
        }

        for i in 0..1_000 {
            assert_eq!(c.get(Entity::new(i, Generation(0))).unwrap(), &i);
        }

        for i in 0..1_000 {
            c.remove(Entity::new(i, Generation(0)));
        }

        for i in 0..1_000 {
            assert!(c.get(Entity::new(i, Generation(0))).is_none());
        }
    }

    #[test]
    fn test_gen() {
        let mut c = VecStorage::new();
        for i in 0..1_000i32 {
            c.insert(Entity::new(i as u32, Generation(0)), i);
            c.insert(Entity::new(i as u32, Generation(0)), -i);
        }

        for i in 0..1_000i32 {
            assert_eq!(c.get(Entity::new(i as u32, Generation(0))).unwrap(), &-i);
        }
    }

    #[test]
    fn insert_same_key() {
        let mut c = VecStorage::new();
        for i in 0..10_000 {
            c.insert(Entity::new(i as u32, Generation(0)), i);
            assert_eq!(c.get(Entity::new(i as u32, Generation(0))).unwrap(), &i);
        }
    }

    #[should_panic]
    #[test]
    fn wrap() {
        let mut c = VecStorage::new();
        c.insert(Entity::new(1 << 25, Generation(0)), 7);
    }
}

#[cfg(test)]
mod test {
    use {Entity, Generation, Storage, VecStorage, HashMapStorage};

    fn test_add<S>() where S: Storage<Component=u32> {
        let mut s = S::new();
        for i in 0..1_000 {
            s.insert(Entity::new(i, Generation(1)), i + 2718);
        }

        for i in 0..1_000 {
            assert_eq!(*s.get(Entity::new(i, Generation(1))).unwrap(), i + 2718);
        }
    }

    fn test_sub<S>() where S: Storage<Component=u32> {
        let mut s = S::new();
        for i in 0..1_000 {
            s.insert(Entity::new(i, Generation(1)), i + 2718);
        }

        for i in 0..1_000 {
            assert_eq!(s.remove(Entity::new(i, Generation(1))).unwrap(), i + 2718);
            assert!(s.remove(Entity::new(i, Generation(1))).is_none());
        }
    }

    fn test_get_mut<S>() where S: Storage<Component=u32> {
        let mut s = S::new();
        for i in 0..1_000 {
            s.insert(Entity::new(i, Generation(1)), i + 2718);
        }

        for i in 0..1_000 {
            *s.get_mut(Entity::new(i, Generation(1))).unwrap() -= 718;
        }

        for i in 0..1_000 {
            assert_eq!(*s.get(Entity::new(i, Generation(1))).unwrap(), i + 2000);
        }
    }

    fn test_add_gen<S>() where S: Storage<Component=u32> {
        let mut s = S::new();
        for i in 0..1_000 {
            s.insert(Entity::new(i, Generation(1)), i + 2718);
            s.insert(Entity::new(i, Generation(2)), i + 31415);
        }

        for i in 0..1_000 {
            // this is removed since vec and hashmap disagree
            // on how this behavior should work...
            //assert!(s.get(Entity::new(i, 1)).is_none());
            assert_eq!(*s.get(Entity::new(i, Generation(2))).unwrap(), i + 31415);
        }
    }

    fn test_sub_gen<S>() where S: Storage<Component=u32> {
        let mut s = S::new();
        for i in 0..1_000 {
            s.insert(Entity::new(i, Generation(2)), i + 2718);
        }

        for i in 0..1_000 {
            assert!(s.remove(Entity::new(i, Generation(1))).is_none());
        }
    }

    #[test] fn vec_test_add() { test_add::<VecStorage<u32>>(); }
    #[test] fn vec_test_sub() { test_sub::<VecStorage<u32>>(); }
    #[test] fn vec_test_get_mut() { test_get_mut::<VecStorage<u32>>(); }
    #[test] fn vec_test_add_gen() { test_add_gen::<VecStorage<u32>>(); }
    #[test] fn vec_test_sub_gen() { test_sub_gen::<VecStorage<u32>>(); }

    #[test] fn hash_test_add() { test_add::<HashMapStorage<u32>>(); }
    #[test] fn hash_test_sub() { test_sub::<HashMapStorage<u32>>(); }
    #[test] fn hash_test_get_mut() { test_get_mut::<HashMapStorage<u32>>(); }
    #[test] fn hash_test_add_gen() { test_add_gen::<HashMapStorage<u32>>(); }
    #[test] fn hash_test_sub_gen() { test_sub_gen::<HashMapStorage<u32>>(); }
}

<commit_msg>Rough implementation of the new Storage<commit_after>use std::collections::HashMap;
use std::hash::BuildHasherDefault;
use std::ops::Deref;

use fnv::FnvHasher;

use {Entity, Index, Generation};
use bitset::BitSet;

/// Base trait for a component storage that is used as a trait object.
/// Doesn't depend on the actual component type.
pub trait StorageBase {
    /// Deletes a particular `Index` from the storage.
    unsafe fn del(&mut self, Index);
}

pub struct MaskedStorage<T, U> where
    U: UnprotectedStorage<T>,
{
    mask: BitSet,
    inner: U,
}

impl<T, U> MaskedStorage<T, U> where
    U: UnprotectedStorage<T>,
{
    /// Creates a new `MaskedStorage`. This is called when you register
    /// a new component type within the world.
    pub fn new() -> MaskedStorage<T, U> {
        Storage {
            mask: BitSet::new(),
            data: UnprotectedStorage::new(),
        }
    }
}

impl<T, U> StorageBase for MaskedStorage<T, U> where
    U: UnprotectedStorage<T>,
{
    unsafe fn del(&mut self, index: Index) {
        self.inner.remove(index);
    }
}

pub struct Storage<'a T, U, G> where
    U: UnprotectedStorage<T>,
{
    mask: BitSet,
    inner: U,
    gens: G,
}

impl<T, U, G> Storage<T, U, G> where
    T: Component<Storage=U>,
    U: UnprotectedStorage<T>,
    G: Deref<Target=&'a [Generation]>,
{
    /// Check if an entity has component `T`.
    fn has(&self, e: Entity) -> bool {
        self.mask.contains(e.get_id() as u32) &&
        e.get_gen() == self.gens.get(e.get_id()).unwrap_or(1)
    }
    /// Tries to read the data associated with an `Entity`.
    pub fn get(&self, e: Entity) -> Option<&T> {
        if self.has(e) {
            Some(unsafe { self.inner.get(e.get_id()) })
        }else {None}
    }
    /// Tries to mutate the data associated with an `Entity`.
    fn get_mut(&mut self, e: Entity) -> Option<&mut T> {
        if self.has(e) {
            Some(unsafe { self.inner.get_mut(e.get_id()) })
        }else {None}
    }
    /// Inserts new data for a given `Entity`.
    fn insert(&mut self, e: Entity, v: T) {
        let id = e.get_id();
        if self.mask.contains(id as u32) {
            *unsafe{ self.inner.get_mut(id) } = v;
        } else {
            self.mask.add(id as u32);
            unsafe{ self.inner.insert(id, v) };
        }
    }
    /// Removes the data associated with an `Entity`.
    fn remove(&mut self, e: Entity) -> Option<T> {
        let id = e.get_id();
        if e.get_gen() == self.gens.get(e.get_id()).unwrap_or(1) && self.mask.remove(id as u32) {
            Some(self.inner.remove(id))
        }else { None }
    }
}

/// Used by the framework to quickly join componets
pub trait UnprotectedStorage<T>: Sized {
    /// Creates a new `Storage<T>`. This is called when you register a new
    /// component type within the world.
    fn new() -> Self;
    /// Clean the storage given a check to figure out if an index
    /// is valid or not. Allows us to safely drop the storage.
    unsafe fn clean<F>(&mut self, F) where F: Fn(Index) -> bool;
    /// Tries reading the data associated with an `Index`.
    /// This is unsafe because the external set used
    /// to protect this storage is absent.
    unsafe fn get(&self, id: Index) -> &T;
    /// Tries mutating the data associated with an `Index`.
    /// This is unsafe because the external set used
    /// to protect this storage is absent.
    unsafe fn get_mut(&mut self, id: Index) -> &mut T;
    /// Inserts new data for a given `Index`.
    unsafe fn insert(&mut self, Index, T);
    /// Removes the data associated with an `Index`.
    unsafe fn remove(&mut self, Index) -> T;
}

/// HashMap-based storage. Best suited for rare components.
pub struct HashMapStorage<T>(HashMap<Index, T, BuildHasherDefault<FnvHasher>>);

impl<T> UnprotectedStorage<T> for HashMapStorage<T> {
    fn new() -> Self {
        let fnv = BuildHasherDefault::<FnvHasher>::default();
        HashMapStorage(HashMap::with_hasher(fnv))
    }
    unsafe fn clean<F>(&mut self, has: F) where F: Fn(Index) -> bool {
        use std::mem;
        for (i, v) in self.0.drain() {
            if !has(i) {
                // if v was not in the set the data is invalid
                // and we must forget it instead of dropping it
                mem::forget(v);
            }
        }
    }
    unsafe fn get(&self, id: Index) -> &T {
        self.0.get(&id).unwrap()
    }
    unsafe fn get_mut(&mut self, id: Index) -> &mut T {
        self.0.get_mut(&id).unwrap()
    }
    unsafe fn insert(&mut self, id: Index, v: T) {
        self.0.insert(id, v)
    }
    unsafe fn remove(&mut self, id: Index) -> T {
        self.0.remove(&id).unwrap()
    }
}

/// Vec-based storage, stores the generations of the data in
/// order to match with given entities. Supposed to have maximum
/// performance for the components mostly present in entities.
pub struct VecStorage<T>(Vec<T>);

impl<T> UnprotectedStorage<T> for VecStorage<T> {
    fn new() -> Self {
        VecStorage(Vec::new())
    }
    unsafe fn clean<F>(&mut self, has: F) where F: Fn(Index) -> bool {
        use std::mem;
        for (i, v) in self.0.drain().enumerate() {
            if !has(i) {
                // if v was not in the set the data is invalid
                // and we must forget it instead of dropping it
                mem::forget(v);
            }
        }
    }
    unsafe fn get(&self, id: Index) -> &T {
        self.0.get_unchecked(id)
    }
    unsafe fn get_mut(&mut self, id: Index) -> &mut T {
        self.0.get_unchecked_mut(id)
    }
    unsafe fn insert(&mut self, id: Index, v: T) {
        let id = e.get_id();
        if self.0.len() <= id {
            let delta = id + 1 - self.0.len();
            self.0.reserve(delta);
            self.0.set_len(id + 1);
        }
        self.0[id] = v;
    }
    unsafe fn remove(&mut self, id: Index) -> T {
        use std::ptr;
        ptr::read(self.get(id))
    }
}

#[cfg(test)]
mod map_test {
    use {Storage, Entity, Generation};
    use super::VecStorage;

    #[test]
    fn insert() {
        let mut c = VecStorage::new();
        for i in 0..1_000 {
            c.insert(Entity::new(i, Generation(0)), i);
        }

        for i in 0..1_000 {
            assert_eq!(c.get(Entity::new(i, Generation(0))).unwrap(), &i);
        }
    }

    #[test]
    fn insert_100k() {
        let mut c = VecStorage::new();
        for i in 0..100_000 {
            c.insert(Entity::new(i, Generation(0)), i);
        }

        for i in 0..100_000 {
            assert_eq!(c.get(Entity::new(i, Generation(0))).unwrap(), &i);
        }
    }

    #[test]
    fn remove() {
        let mut c = VecStorage::new();
        for i in 0..1_000 {
            c.insert(Entity::new(i, Generation(0)), i);
        }

        for i in 0..1_000 {
            assert_eq!(c.get(Entity::new(i, Generation(0))).unwrap(), &i);
        }

        for i in 0..1_000 {
            c.remove(Entity::new(i, Generation(0)));
        }

        for i in 0..1_000 {
            assert!(c.get(Entity::new(i, Generation(0))).is_none());
        }
    }

    #[test]
    fn test_gen() {
        let mut c = VecStorage::new();
        for i in 0..1_000i32 {
            c.insert(Entity::new(i as u32, Generation(0)), i);
            c.insert(Entity::new(i as u32, Generation(0)), -i);
        }

        for i in 0..1_000i32 {
            assert_eq!(c.get(Entity::new(i as u32, Generation(0))).unwrap(), &-i);
        }
    }

    #[test]
    fn insert_same_key() {
        let mut c = VecStorage::new();
        for i in 0..10_000 {
            c.insert(Entity::new(i as u32, Generation(0)), i);
            assert_eq!(c.get(Entity::new(i as u32, Generation(0))).unwrap(), &i);
        }
    }

    #[should_panic]
    #[test]
    fn wrap() {
        let mut c = VecStorage::new();
        c.insert(Entity::new(1 << 25, Generation(0)), 7);
    }
}

#[cfg(test)]
mod test {
    use {Entity, Generation, Storage, VecStorage, HashMapStorage};

    fn test_add<S>() where S: Storage<Component=u32> {
        let mut s = S::new();
        for i in 0..1_000 {
            s.insert(Entity::new(i, Generation(1)), i + 2718);
        }

        for i in 0..1_000 {
            assert_eq!(*s.get(Entity::new(i, Generation(1))).unwrap(), i + 2718);
        }
    }

    fn test_sub<S>() where S: Storage<Component=u32> {
        let mut s = S::new();
        for i in 0..1_000 {
            s.insert(Entity::new(i, Generation(1)), i + 2718);
        }

        for i in 0..1_000 {
            assert_eq!(s.remove(Entity::new(i, Generation(1))).unwrap(), i + 2718);
            assert!(s.remove(Entity::new(i, Generation(1))).is_none());
        }
    }

    fn test_get_mut<S>() where S: Storage<Component=u32> {
        let mut s = S::new();
        for i in 0..1_000 {
            s.insert(Entity::new(i, Generation(1)), i + 2718);
        }

        for i in 0..1_000 {
            *s.get_mut(Entity::new(i, Generation(1))).unwrap() -= 718;
        }

        for i in 0..1_000 {
            assert_eq!(*s.get(Entity::new(i, Generation(1))).unwrap(), i + 2000);
        }
    }

    fn test_add_gen<S>() where S: Storage<Component=u32> {
        let mut s = S::new();
        for i in 0..1_000 {
            s.insert(Entity::new(i, Generation(1)), i + 2718);
            s.insert(Entity::new(i, Generation(2)), i + 31415);
        }

        for i in 0..1_000 {
            // this is removed since vec and hashmap disagree
            // on how this behavior should work...
            //assert!(s.get(Entity::new(i, 1)).is_none());
            assert_eq!(*s.get(Entity::new(i, Generation(2))).unwrap(), i + 31415);
        }
    }

    fn test_sub_gen<S>() where S: Storage<Component=u32> {
        let mut s = S::new();
        for i in 0..1_000 {
            s.insert(Entity::new(i, Generation(2)), i + 2718);
        }

        for i in 0..1_000 {
            assert!(s.remove(Entity::new(i, Generation(1))).is_none());
        }
    }

    #[test] fn vec_test_add() { test_add::<VecStorage<u32>>(); }
    #[test] fn vec_test_sub() { test_sub::<VecStorage<u32>>(); }
    #[test] fn vec_test_get_mut() { test_get_mut::<VecStorage<u32>>(); }
    #[test] fn vec_test_add_gen() { test_add_gen::<VecStorage<u32>>(); }
    #[test] fn vec_test_sub_gen() { test_sub_gen::<VecStorage<u32>>(); }

    #[test] fn hash_test_add() { test_add::<HashMapStorage<u32>>(); }
    #[test] fn hash_test_sub() { test_sub::<HashMapStorage<u32>>(); }
    #[test] fn hash_test_get_mut() { test_get_mut::<HashMapStorage<u32>>(); }
    #[test] fn hash_test_add_gen() { test_add_gen::<HashMapStorage<u32>>(); }
    #[test] fn hash_test_sub_gen() { test_sub_gen::<HashMapStorage<u32>>(); }
}

<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::collections::hash_map::DefaultHasher;
use std::fmt::Display;
use std::hash::{Hash, Hasher};
use std::process::Command;
use std::fmt;

use rustc_version::VersionMeta;
use tempdir::TempDir;
use toml::Value;

use cargo::{Root, Rustflags};
use errors::*;
use extensions::CommandExt;
use rustc::{Src, Sysroot, Target};
use util;
use xargo::Home;
use {cargo, xargo};

#[cfg(feature = "dev")]
fn profile() -> &'static str {
    "debug"
}

#[cfg(not(feature = "dev"))]
fn profile() -> &'static str {
    "release"
}

fn build(target: &Target,
         deps: &Dependencies,
         ctoml: &cargo::Toml,
         home: &Home,
         rustflags: &Rustflags,
         hash: u64,
         verbose: bool)
         -> Result<()> {
    const TOML: &'static str = r#"
[package]
authors = ["The Rust Project Developers"]
name = "sysroot"
version = "0.0.0"
"#;

    let td = TempDir::new("xargo")
        .chain_err(|| "couldn't create a temporary directory")?;
    let td = td.path();

    let mut stoml = TOML.to_owned();
    stoml.push_str(&deps.to_string());

    if let Some(profile) = ctoml.profile() {
        stoml.push_str(&profile.to_string())
    }

    util::write(&td.join("Cargo.toml"), &stoml)?;
    util::mkdir(&td.join("src"))?;
    util::write(&td.join("src/lib.rs"), "")?;

    let cargo = || {
        let mut cmd = Command::new("cargo");
        cmd.env("RUSTFLAGS", rustflags.to_string());
        cmd.arg("build");

        match () {
            #[cfg(feature = "dev")]
            () => {}
            #[cfg(not(feature = "dev"))]
            () => {
                cmd.arg("--release");
            }
        }
        cmd.arg("--manifest-path");
        cmd.arg(td.join("Cargo.toml"));
        cmd.args(&["--target", target.triple()]);

        if verbose {
            cmd.arg("-v");
        }

        cmd
    };

    for krate in deps.crates() {
        cargo().arg("-p").arg(krate).run(verbose)?;
    }

    // Copy artifacts to Xargo sysroot
    let rustlib = home.lock_rw(target.triple())?;
    rustlib.remove_siblings()
        .chain_err(|| format!("couldn't clear {}", rustlib.path().display()))?;
    let dst = rustlib.parent().join("lib");
    util::mkdir(&dst)?;
    util::cp_r(&td.join("target")
                   .join(target.triple())
                   .join(profile())
                   .join("deps"),
               &dst)?;

    // Create hash file
    util::write(&rustlib.parent().join(".hash"), &hash.to_string())?;

    Ok(())
}

fn old_hash(target: &str, home: &Home) -> Result<Option<u64>> {
    // FIXME this should be `lock_ro`
    let lock = home.lock_rw(target)?;
    let hfile = lock.parent().join(".hash");

    if hfile.exists() {
        Ok(util::read(&hfile)?.parse().ok())
    } else {
        Ok(None)
    }
}

/// Computes the hash of the would-be target sysroot
///
/// This information is used to compute the hash
///
/// - Dependencies in `Xargo.toml` for a specific target
/// - RUSTFLAGS / build.rustflags / target.*.rustflags
/// - The target specification file, is any
/// - `[profile.release]` in `Cargo.toml`
/// - `rustc` commit hash
fn hash(target: &Target,
        dependencies: &Dependencies,
        rustflags: &Rustflags,
        ctoml: &cargo::Toml,
        meta: &VersionMeta)
        -> Result<u64> {
    let mut hasher = DefaultHasher::new();

    dependencies.hash(&mut hasher);

    rustflags.hash(&mut hasher);

    target.hash(&mut hasher)?;

    if let Some(profile) = ctoml.profile() {
        profile.hash(&mut hasher);
    }

    if let Some(ref hash) = meta.commit_hash {
        hash.hash(&mut hasher);
    }

    Ok(hasher.finish())
}

pub fn update(target: &Target,
              home: &Home,
              root: &Root,
              rustflags: &Rustflags,
              meta: &VersionMeta,
              src: &Src,
              sysroot: &Sysroot,
              verbose: bool)
              -> Result<()> {
    let ctoml = cargo::toml(root)?;
    let xtoml = xargo::toml(root)?;

    let deps = Dependencies::from(xtoml.as_ref(), target.triple(), &src)?;

    let hash = hash(target, &deps, rustflags, &ctoml, meta)?;

    if old_hash(target.triple(), home)? != Some(hash) {
        build(target, &deps, &ctoml, home, rustflags, hash, verbose)?;
    }

    // copy host artifacts into the sysroot, if necessary
    let lock = home.lock_rw(&meta.host)?;
    let hfile = lock.parent().join(".hash");

    let hash = meta.commit_hash.as_ref().map(|s| &**s).unwrap_or("");
    if hfile.exists() {
        if util::read(&hfile)? == hash {
            return Ok(());
        }
    }

    lock.remove_siblings()
        .chain_err(|| format!("couldn't clear {}", lock.path().display()))?;
    let dst = lock.parent().join("lib");
    util::mkdir(&dst)?;
    util::cp_r(&sysroot.path()
                   .join("lib/rustlib")
                   .join(&meta.host)
                   .join("lib"),
               &dst)?;

    util::write(&hfile, hash)?;

    Ok(())
}

/// Sysroot dependencies for a particular target
pub struct Dependencies {
    crates: Vec<String>,
    table: Value,
}

impl Dependencies {
    fn from(toml: Option<&xargo::Toml>,
            target: &str,
            src: &Src)
            -> Result<Self> {
        let mut deps = if let Some(value) =
            toml.and_then(|t| t.dependencies(target)) {
            if let Some(table) = value.as_table() {
                table.clone()
            } else {
                Err(format!("Xargo.toml: target.{}.dependencies must be a \
                             table",
                            target))?
            }
        } else {
            // If no dependencies were listed, we assume `core` as the only
            // dependency
            let mut t = BTreeMap::new();
            t.insert("core".to_owned(), Value::Table(BTreeMap::new()));
            t
        };

        let mut crates = vec![];
        for (k, v) in deps.iter_mut() {
            crates.push(k.clone());

            let path =
                src.path().join(format!("lib{}", k)).display().to_string();

            if let Value::Table(ref mut map) = *v {
                map.insert("path".to_owned(), Value::String(path));
            } else {
                Err(format!("Xargo.toml: target.{}.dependencies.{} must be \
                             a table",
                            target,
                            k))?
            }
        }

        let mut map = BTreeMap::new();
        map.insert("dependencies".to_owned(), Value::Table(deps));

        Ok(Dependencies {
            crates: crates,
            table: Value::Table(map),
        })
    }

    fn crates(&self) -> &[String] {
        &self.crates
    }

    fn hash<H>(&self, hasher: &mut H)
        where H: Hasher
    {
        self.table.to_string().hash(hasher);
    }
}

impl Display for Dependencies {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.table, f)
    }
}
<commit_msg>unset CARGO_TARGET_DIR when building the sysroot<commit_after>use std::collections::BTreeMap;
use std::collections::hash_map::DefaultHasher;
use std::fmt::Display;
use std::hash::{Hash, Hasher};
use std::process::Command;
use std::fmt;

use rustc_version::VersionMeta;
use tempdir::TempDir;
use toml::Value;

use cargo::{Root, Rustflags};
use errors::*;
use extensions::CommandExt;
use rustc::{Src, Sysroot, Target};
use util;
use xargo::Home;
use {cargo, xargo};

#[cfg(feature = "dev")]
fn profile() -> &'static str {
    "debug"
}

#[cfg(not(feature = "dev"))]
fn profile() -> &'static str {
    "release"
}

fn build(target: &Target,
         deps: &Dependencies,
         ctoml: &cargo::Toml,
         home: &Home,
         rustflags: &Rustflags,
         hash: u64,
         verbose: bool)
         -> Result<()> {
    const TOML: &'static str = r#"
[package]
authors = ["The Rust Project Developers"]
name = "sysroot"
version = "0.0.0"
"#;

    let td = TempDir::new("xargo")
        .chain_err(|| "couldn't create a temporary directory")?;
    let td = td.path();

    let mut stoml = TOML.to_owned();
    stoml.push_str(&deps.to_string());

    if let Some(profile) = ctoml.profile() {
        stoml.push_str(&profile.to_string())
    }

    util::write(&td.join("Cargo.toml"), &stoml)?;
    util::mkdir(&td.join("src"))?;
    util::write(&td.join("src/lib.rs"), "")?;

    let cargo = || {
        let mut cmd = Command::new("cargo");
        cmd.env("RUSTFLAGS", rustflags.to_string());
        cmd.env_remove("CARGO_TARGET_DIR");
        cmd.arg("build");

        match () {
            #[cfg(feature = "dev")]
            () => {}
            #[cfg(not(feature = "dev"))]
            () => {
                cmd.arg("--release");
            }
        }
        cmd.arg("--manifest-path");
        cmd.arg(td.join("Cargo.toml"));
        cmd.args(&["--target", target.triple()]);

        if verbose {
            cmd.arg("-v");
        }

        cmd
    };

    for krate in deps.crates() {
        cargo().arg("-p").arg(krate).run(verbose)?;
    }

    // Copy artifacts to Xargo sysroot
    let rustlib = home.lock_rw(target.triple())?;
    rustlib.remove_siblings()
        .chain_err(|| format!("couldn't clear {}", rustlib.path().display()))?;
    let dst = rustlib.parent().join("lib");
    util::mkdir(&dst)?;
    util::cp_r(&td.join("target")
                   .join(target.triple())
                   .join(profile())
                   .join("deps"),
               &dst)?;

    // Create hash file
    util::write(&rustlib.parent().join(".hash"), &hash.to_string())?;

    Ok(())
}

fn old_hash(target: &str, home: &Home) -> Result<Option<u64>> {
    // FIXME this should be `lock_ro`
    let lock = home.lock_rw(target)?;
    let hfile = lock.parent().join(".hash");

    if hfile.exists() {
        Ok(util::read(&hfile)?.parse().ok())
    } else {
        Ok(None)
    }
}

/// Computes the hash of the would-be target sysroot
///
/// This information is used to compute the hash
///
/// - Dependencies in `Xargo.toml` for a specific target
/// - RUSTFLAGS / build.rustflags / target.*.rustflags
/// - The target specification file, is any
/// - `[profile.release]` in `Cargo.toml`
/// - `rustc` commit hash
fn hash(target: &Target,
        dependencies: &Dependencies,
        rustflags: &Rustflags,
        ctoml: &cargo::Toml,
        meta: &VersionMeta)
        -> Result<u64> {
    let mut hasher = DefaultHasher::new();

    dependencies.hash(&mut hasher);

    rustflags.hash(&mut hasher);

    target.hash(&mut hasher)?;

    if let Some(profile) = ctoml.profile() {
        profile.hash(&mut hasher);
    }

    if let Some(ref hash) = meta.commit_hash {
        hash.hash(&mut hasher);
    }

    Ok(hasher.finish())
}

pub fn update(target: &Target,
              home: &Home,
              root: &Root,
              rustflags: &Rustflags,
              meta: &VersionMeta,
              src: &Src,
              sysroot: &Sysroot,
              verbose: bool)
              -> Result<()> {
    let ctoml = cargo::toml(root)?;
    let xtoml = xargo::toml(root)?;

    let deps = Dependencies::from(xtoml.as_ref(), target.triple(), &src)?;

    let hash = hash(target, &deps, rustflags, &ctoml, meta)?;

    if old_hash(target.triple(), home)? != Some(hash) {
        build(target, &deps, &ctoml, home, rustflags, hash, verbose)?;
    }

    // copy host artifacts into the sysroot, if necessary
    let lock = home.lock_rw(&meta.host)?;
    let hfile = lock.parent().join(".hash");

    let hash = meta.commit_hash.as_ref().map(|s| &**s).unwrap_or("");
    if hfile.exists() {
        if util::read(&hfile)? == hash {
            return Ok(());
        }
    }

    lock.remove_siblings()
        .chain_err(|| format!("couldn't clear {}", lock.path().display()))?;
    let dst = lock.parent().join("lib");
    util::mkdir(&dst)?;
    util::cp_r(&sysroot.path()
                   .join("lib/rustlib")
                   .join(&meta.host)
                   .join("lib"),
               &dst)?;

    util::write(&hfile, hash)?;

    Ok(())
}

/// Sysroot dependencies for a particular target
pub struct Dependencies {
    crates: Vec<String>,
    table: Value,
}

impl Dependencies {
    fn from(toml: Option<&xargo::Toml>,
            target: &str,
            src: &Src)
            -> Result<Self> {
        let mut deps = if let Some(value) =
            toml.and_then(|t| t.dependencies(target)) {
            if let Some(table) = value.as_table() {
                table.clone()
            } else {
                Err(format!("Xargo.toml: target.{}.dependencies must be a \
                             table",
                            target))?
            }
        } else {
            // If no dependencies were listed, we assume `core` as the only
            // dependency
            let mut t = BTreeMap::new();
            t.insert("core".to_owned(), Value::Table(BTreeMap::new()));
            t
        };

        let mut crates = vec![];
        for (k, v) in deps.iter_mut() {
            crates.push(k.clone());

            let path =
                src.path().join(format!("lib{}", k)).display().to_string();

            if let Value::Table(ref mut map) = *v {
                map.insert("path".to_owned(), Value::String(path));
            } else {
                Err(format!("Xargo.toml: target.{}.dependencies.{} must be \
                             a table",
                            target,
                            k))?
            }
        }

        let mut map = BTreeMap::new();
        map.insert("dependencies".to_owned(), Value::Table(deps));

        Ok(Dependencies {
            crates: crates,
            table: Value::Table(map),
        })
    }

    fn crates(&self) -> &[String] {
        &self.crates
    }

    fn hash<H>(&self, hasher: &mut H)
        where H: Hasher
    {
        self.table.to_string().hash(hasher);
    }
}

impl Display for Dependencies {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.table, f)
    }
}
<|endoftext|>


<commit_before>pub mod configuration;

#[cfg(target_os = "macos")]
pub mod macos;
#[cfg(target_os = "linux")]
pub mod linux;

use std::net::Ipv4Addr;
use std::io::{Write, Read};

use common::error::*;

pub trait Tun: Read + Write {
    fn name(&self) -> &str;

    fn address(&self) -> Result<Ipv4Addr>;
    fn set_address(&mut self, value: Ipv4Addr) -> Result<()>;

    fn broadcast(&self) -> Result<Ipv4Addr>;
    fn set_broadcast(&mut self, value: Ipv4Addr) -> Result<()>;

    fn destination(&self) -> Result<Ipv4Addr>;
    fn set_destination(&mut self, value: Ipv4Addr) -> Result<()>;

    fn netmask(&self) -> Result<Ipv4Addr>;
    fn set_netmask(&mut self, value: Ipv4Addr) -> Result<()>;

    fn mtu(&self) -> Result<i32>;
    fn set_mtu(&mut self, value: i32) -> Result<()>;

    fn flags(&self) -> Result<i16>;
    fn set_flags(&mut self, value: i16) -> Result<()>;

    fn set_enabled(&mut self, value: bool) -> Result<()>;
}
<commit_msg>pub tun  function<commit_after>#[cfg(target_os = "macos")]
pub mod macos;
#[cfg(target_os = "linux")]
pub mod linux;
pub mod configuration;

#[cfg(target_os = "macos")]
pub use self::macos as os;
#[cfg(target_os = "macos")]
pub use self::macos::create;

#[cfg(target_os = "linux")]
pub use self::linux as os;
#[cfg(target_os = "linux")]
pub use self::linux::create;

pub use self::configuration::Configuration;

use std::net::Ipv4Addr;
use std::io::{Write, Read};

use common::error::*;

pub trait Tun: Read + Write {
    fn name(&self) -> &str;

    fn address(&self) -> Result<Ipv4Addr>;
    fn set_address(&mut self, value: Ipv4Addr) -> Result<()>;

    fn broadcast(&self) -> Result<Ipv4Addr>;
    fn set_broadcast(&mut self, value: Ipv4Addr) -> Result<()>;

    fn destination(&self) -> Result<Ipv4Addr>;
    fn set_destination(&mut self, value: Ipv4Addr) -> Result<()>;

    fn netmask(&self) -> Result<Ipv4Addr>;
    fn set_netmask(&mut self, value: Ipv4Addr) -> Result<()>;

    fn mtu(&self) -> Result<i32>;
    fn set_mtu(&mut self, value: i32) -> Result<()>;

    fn flags(&self) -> Result<i16>;
    fn set_flags(&mut self, value: i16) -> Result<()>;

    fn set_enabled(&mut self, value: bool) -> Result<()>;
}
<|endoftext|>


<commit_before>extern crate kernel32;
extern crate winapi;

use self::kernel32::{ReadProcessMemory, OpenProcess};
use self::winapi::winnt::HANDLE;

use {ReadsMemory, ProvidesSlices};
use slice::MemorySlice;
use error::*;

pub struct MemReader {
  pub pid: u32,
  handle: HANDLE
}

impl MemReader {
  pub fn new(pid: u32) -> Result<MemReader> {
    let handle = unsafe { OpenProcess(0x0010, 0, pid) };
    if handle.is_null() {
      return Err(MemReaderError::Handle(None));
    }
    Ok(MemReader {
      pid: pid,
      handle: handle
    })
  }
}

impl ReadsMemory for MemReader {
  fn read_bytes(&self, address: usize, n: usize) -> Result<Vec<u8>> {
    let mut buffer: Vec<u8> = vec![0; n];
    let mut read: u64 = unsafe { ::std::mem::uninitialized() };
    let res = unsafe {
      ReadProcessMemory(self.handle,
        address as *const _,
        buffer.as_mut_ptr() as *mut _,
        n as u64,
        &mut read as *mut _)
    };
    if res != 1 {
      return Err(MemReaderError::UnsuccessfulRead(Some(1)));
    }
    if read != n as u64 {
      return Err(MemReaderError::FewerBytesRead(read as usize, buffer[..n].to_vec()));
    }
    Ok(buffer)
  }
}

impl ProvidesSlices for MemReader {
  fn address_slice(&self, start: usize, end: usize) -> MemorySlice {
    MemorySlice::new(self, start, end)
  }

  fn address_slice_len(&self, start: usize, n: usize) -> MemorySlice {
    MemorySlice::new(self, start, start + n)
  }
}
<commit_msg>refactor: remove pid from Windows MemReader<commit_after>extern crate kernel32;
extern crate winapi;

use self::kernel32::{ReadProcessMemory, OpenProcess};
use self::winapi::winnt::HANDLE;

use {ReadsMemory, ProvidesSlices};
use slice::MemorySlice;
use error::*;

pub struct MemReader {
  handle: HANDLE
}

impl MemReader {
  pub fn new(pid: u32) -> Result<MemReader> {
    let handle = unsafe { OpenProcess(0x0010, 0, pid) };
    if handle.is_null() {
      return Err(MemReaderError::Handle(None));
    }
    Ok(MemReader {
      handle: handle
    })
  }
}

impl ReadsMemory for MemReader {
  fn read_bytes(&self, address: usize, n: usize) -> Result<Vec<u8>> {
    let mut buffer: Vec<u8> = vec![0; n];
    let mut read: u64 = unsafe { ::std::mem::uninitialized() };
    let res = unsafe {
      ReadProcessMemory(self.handle,
        address as *const _,
        buffer.as_mut_ptr() as *mut _,
        n as u64,
        &mut read as *mut _)
    };
    if res != 1 {
      return Err(MemReaderError::UnsuccessfulRead(Some(1)));
    }
    if read != n as u64 {
      return Err(MemReaderError::FewerBytesRead(read as usize, buffer[..n].to_vec()));
    }
    Ok(buffer)
  }
}

impl ProvidesSlices for MemReader {
  fn address_slice(&self, start: usize, end: usize) -> MemorySlice {
    MemorySlice::new(self, start, end)
  }

  fn address_slice_len(&self, start: usize, n: usize) -> MemorySlice {
    MemorySlice::new(self, start, start + n)
  }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::WorkerBinding;
use dom::bindings::codegen::Bindings::WorkerBinding::WorkerMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::InheritTypes::{EventCast, EventTargetCast};
use dom::bindings::error::{Fallible, ErrorResult};
use dom::bindings::error::Error::Syntax;
use dom::bindings::global::{GlobalRef, GlobalField};
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::refcounted::Trusted;
use dom::bindings::structuredclone::StructuredCloneData;
use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::{Reflectable, reflect_dom_object};
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
use dom::errorevent::ErrorEvent;
use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers};
use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId};
use dom::messageevent::MessageEvent;
use script_task::{ScriptChan, ScriptMsg, Runnable};

use util::str::DOMString;

use js::jsapi::JSContext;
use js::jsval::{JSVal, UndefinedValue};
use url::UrlParser;

use std::borrow::ToOwned;
use std::cell::Cell;
use std::sync::mpsc::{channel, Sender};

pub type TrustedWorkerAddress = Trusted<Worker>;

#[dom_struct]
pub struct Worker {
    eventtarget: EventTarget,
    refcount: Cell<uint>,
    global: GlobalField,
    /// Sender to the Receiver associated with the DedicatedWorkerGlobalScope
    /// this Worker created.
    sender: Sender<(TrustedWorkerAddress, ScriptMsg)>,
}

impl Worker {
    fn new_inherited(global: GlobalRef, sender: Sender<(TrustedWorkerAddress, ScriptMsg)>) -> Worker {
        Worker {
            eventtarget: EventTarget::new_inherited(EventTargetTypeId::Worker),
            refcount: Cell::new(0),
            global: GlobalField::from_rooted(&global),
            sender: sender,
        }
    }

    pub fn new(global: GlobalRef, sender: Sender<(TrustedWorkerAddress, ScriptMsg)>) -> Temporary<Worker> {
        reflect_dom_object(box Worker::new_inherited(global, sender),
                           global,
                           WorkerBinding::Wrap)
    }

    // http://www.whatwg.org/html/#dom-worker
    pub fn Constructor(global: GlobalRef, script_url: DOMString) -> Fallible<Temporary<Worker>> {
        // Step 2-4.
        let worker_url = match UrlParser::new().base_url(&global.get_url())
                .parse(script_url.as_slice()) {
            Ok(url) => url,
            Err(_) => return Err(Syntax),
        };

        let resource_task = global.resource_task();

        let (sender, receiver) = channel();
        let worker = Worker::new(global, sender.clone()).root();
        let worker_ref = Trusted::new(global.get_cx(), worker.r(), global.script_chan());

        DedicatedWorkerGlobalScope::run_worker_scope(
            worker_url, worker_ref, resource_task, global.script_chan(),
            sender, receiver);

        Ok(Temporary::from_rooted(worker.r()))
    }

    pub fn handle_message(address: TrustedWorkerAddress,
                          data: StructuredCloneData) {
        let worker = address.to_temporary().root();

        let global = worker.r().global.root();
        let target: JSRef<EventTarget> = EventTargetCast::from_ref(worker.r());

        let message = data.read(global.r());
        MessageEvent::dispatch_jsval(target, global.r(), message);
    }

    pub fn handle_error_message(address: TrustedWorkerAddress, message: DOMString,
                                filename: DOMString, lineno: u32, colno: u32) {
        let worker = address.to_temporary().root();
        let global = worker.r().global.root();
        let error = UndefinedValue();
        let target: JSRef<EventTarget> = EventTargetCast::from_ref(worker.r());
        let errorevent = ErrorEvent::new(global.r(), "error".to_owned(),
                                         EventBubbles::Bubbles, EventCancelable::Cancelable,
                                         message, filename, lineno, colno, error).root();
        let event: JSRef<Event> = EventCast::from_ref(errorevent.r());
        event.fire(target);
    }
}

impl<'a> WorkerMethods for JSRef<'a, Worker> {
    fn PostMessage(self, cx: *mut JSContext, message: JSVal) -> ErrorResult {
        let data = try!(StructuredCloneData::write(cx, message));
        let address = Trusted::new(cx, self, self.global.root().r().script_chan().clone());
        self.sender.send((address, ScriptMsg::DOMMessage(data))).unwrap();
        Ok(())
    }

    event_handler!(message, GetOnmessage, SetOnmessage);
}

pub struct WorkerMessageHandler {
    addr: TrustedWorkerAddress,
    data: StructuredCloneData,
}

impl WorkerMessageHandler {
    pub fn new(addr: TrustedWorkerAddress, data: StructuredCloneData) -> WorkerMessageHandler {
        WorkerMessageHandler {
            addr: addr,
            data: data,
        }
    }
}

impl Runnable for WorkerMessageHandler {
    fn handler(self: Box<WorkerMessageHandler>) {
        let this = *self;
        Worker::handle_message(this.addr, this.data);
    }
}
<commit_msg>Remove the unused Worker::refcount field.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::WorkerBinding;
use dom::bindings::codegen::Bindings::WorkerBinding::WorkerMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::InheritTypes::{EventCast, EventTargetCast};
use dom::bindings::error::{Fallible, ErrorResult};
use dom::bindings::error::Error::Syntax;
use dom::bindings::global::{GlobalRef, GlobalField};
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::refcounted::Trusted;
use dom::bindings::structuredclone::StructuredCloneData;
use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::{Reflectable, reflect_dom_object};
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
use dom::errorevent::ErrorEvent;
use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers};
use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId};
use dom::messageevent::MessageEvent;
use script_task::{ScriptChan, ScriptMsg, Runnable};

use util::str::DOMString;

use js::jsapi::JSContext;
use js::jsval::{JSVal, UndefinedValue};
use url::UrlParser;

use std::borrow::ToOwned;
use std::sync::mpsc::{channel, Sender};

pub type TrustedWorkerAddress = Trusted<Worker>;

#[dom_struct]
pub struct Worker {
    eventtarget: EventTarget,
    global: GlobalField,
    /// Sender to the Receiver associated with the DedicatedWorkerGlobalScope
    /// this Worker created.
    sender: Sender<(TrustedWorkerAddress, ScriptMsg)>,
}

impl Worker {
    fn new_inherited(global: GlobalRef, sender: Sender<(TrustedWorkerAddress, ScriptMsg)>) -> Worker {
        Worker {
            eventtarget: EventTarget::new_inherited(EventTargetTypeId::Worker),
            global: GlobalField::from_rooted(&global),
            sender: sender,
        }
    }

    pub fn new(global: GlobalRef, sender: Sender<(TrustedWorkerAddress, ScriptMsg)>) -> Temporary<Worker> {
        reflect_dom_object(box Worker::new_inherited(global, sender),
                           global,
                           WorkerBinding::Wrap)
    }

    // http://www.whatwg.org/html/#dom-worker
    pub fn Constructor(global: GlobalRef, script_url: DOMString) -> Fallible<Temporary<Worker>> {
        // Step 2-4.
        let worker_url = match UrlParser::new().base_url(&global.get_url())
                .parse(script_url.as_slice()) {
            Ok(url) => url,
            Err(_) => return Err(Syntax),
        };

        let resource_task = global.resource_task();

        let (sender, receiver) = channel();
        let worker = Worker::new(global, sender.clone()).root();
        let worker_ref = Trusted::new(global.get_cx(), worker.r(), global.script_chan());

        DedicatedWorkerGlobalScope::run_worker_scope(
            worker_url, worker_ref, resource_task, global.script_chan(),
            sender, receiver);

        Ok(Temporary::from_rooted(worker.r()))
    }

    pub fn handle_message(address: TrustedWorkerAddress,
                          data: StructuredCloneData) {
        let worker = address.to_temporary().root();

        let global = worker.r().global.root();
        let target: JSRef<EventTarget> = EventTargetCast::from_ref(worker.r());

        let message = data.read(global.r());
        MessageEvent::dispatch_jsval(target, global.r(), message);
    }

    pub fn handle_error_message(address: TrustedWorkerAddress, message: DOMString,
                                filename: DOMString, lineno: u32, colno: u32) {
        let worker = address.to_temporary().root();
        let global = worker.r().global.root();
        let error = UndefinedValue();
        let target: JSRef<EventTarget> = EventTargetCast::from_ref(worker.r());
        let errorevent = ErrorEvent::new(global.r(), "error".to_owned(),
                                         EventBubbles::Bubbles, EventCancelable::Cancelable,
                                         message, filename, lineno, colno, error).root();
        let event: JSRef<Event> = EventCast::from_ref(errorevent.r());
        event.fire(target);
    }
}

impl<'a> WorkerMethods for JSRef<'a, Worker> {
    fn PostMessage(self, cx: *mut JSContext, message: JSVal) -> ErrorResult {
        let data = try!(StructuredCloneData::write(cx, message));
        let address = Trusted::new(cx, self, self.global.root().r().script_chan().clone());
        self.sender.send((address, ScriptMsg::DOMMessage(data))).unwrap();
        Ok(())
    }

    event_handler!(message, GetOnmessage, SetOnmessage);
}

pub struct WorkerMessageHandler {
    addr: TrustedWorkerAddress,
    data: StructuredCloneData,
}

impl WorkerMessageHandler {
    pub fn new(addr: TrustedWorkerAddress, data: StructuredCloneData) -> WorkerMessageHandler {
        WorkerMessageHandler {
            addr: addr,
            data: data,
        }
    }
}

impl Runnable for WorkerMessageHandler {
    fn handler(self: Box<WorkerMessageHandler>) {
        let this = *self;
        Worker::handle_message(this.addr, this.data);
    }
}
<|endoftext|>


<commit_before>//! De-/serialization functions for `std::time::SystemTime` objects represented as milliseconds
//! since the UNIX epoch. Delegates to `js_int::UInt` to ensure integer size is within bounds.

use std::{
    convert::TryInto,
    time::{Duration, SystemTime, UNIX_EPOCH},
};

use js_int::UInt;
use serde::{
    de::{self, Deserialize, Deserializer},
    ser::{self, Serialize, Serializer},
};

/// Serialize a SystemTime.
///
/// Will fail if integer is greater than the maximum integer that can be unambiguously represented
/// by an f64.
pub fn serialize<S>(time: &SystemTime, serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
    let time_since_epoch = time.duration_since(UNIX_EPOCH).map_err(ser::Error::custom)?;
    let uint: UInt = time_since_epoch.as_millis().try_into().map_err(ser::Error::custom)?;

    uint.serialize(serializer)
}

/// Deserializes a SystemTime.
///
/// Will fail if integer is greater than the maximum integer that can be unambiguously represented
/// by an f64.
pub fn deserialize<'de, D>(deserializer: D) -> Result<SystemTime, D::Error>
where
    D: Deserializer<'de>,
{
    let millis = UInt::deserialize(deserializer)?;
    UNIX_EPOCH
        .checked_add(Duration::from_millis(millis.into()))
        .ok_or_else(|| de::Error::custom("input too large for SystemTime"))
}

#[cfg(test)]
mod tests {
    use std::time::{Duration, SystemTime, UNIX_EPOCH};

    use serde::{Deserialize, Serialize};
    use serde_json::json;

    #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
    struct SystemTimeTest {
        #[serde(with = "super")]
        timestamp: SystemTime,
    }

    #[test]
    fn deserialize() {
        let json = json!({ "timestamp": 3000 });

        assert_eq!(
            serde_json::from_value::<SystemTimeTest>(json).unwrap(),
            SystemTimeTest { timestamp: UNIX_EPOCH + Duration::from_millis(3000) },
        );
    }

    #[test]
    fn serialize() {
        let request = SystemTimeTest { timestamp: UNIX_EPOCH + Duration::new(2, 0) };
        assert_eq!(serde_json::to_value(&request).unwrap(), json!({ "timestamp": 2000 }));
    }
}
<commit_msg>serde: Rewrite some tests to use assert_matches<commit_after>//! De-/serialization functions for `std::time::SystemTime` objects represented as milliseconds
//! since the UNIX epoch. Delegates to `js_int::UInt` to ensure integer size is within bounds.

use std::{
    convert::TryInto,
    time::{Duration, SystemTime, UNIX_EPOCH},
};

use js_int::UInt;
use serde::{
    de::{self, Deserialize, Deserializer},
    ser::{self, Serialize, Serializer},
};

/// Serialize a SystemTime.
///
/// Will fail if integer is greater than the maximum integer that can be unambiguously represented
/// by an f64.
pub fn serialize<S>(time: &SystemTime, serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
    let time_since_epoch = time.duration_since(UNIX_EPOCH).map_err(ser::Error::custom)?;
    let uint: UInt = time_since_epoch.as_millis().try_into().map_err(ser::Error::custom)?;

    uint.serialize(serializer)
}

/// Deserializes a SystemTime.
///
/// Will fail if integer is greater than the maximum integer that can be unambiguously represented
/// by an f64.
pub fn deserialize<'de, D>(deserializer: D) -> Result<SystemTime, D::Error>
where
    D: Deserializer<'de>,
{
    let millis = UInt::deserialize(deserializer)?;
    UNIX_EPOCH
        .checked_add(Duration::from_millis(millis.into()))
        .ok_or_else(|| de::Error::custom("input too large for SystemTime"))
}

#[cfg(test)]
mod tests {
    use std::time::{Duration, SystemTime, UNIX_EPOCH};

    use matches::assert_matches;
    use serde::{Deserialize, Serialize};
    use serde_json::json;

    #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
    struct SystemTimeTest {
        #[serde(with = "super")]
        timestamp: SystemTime,
    }

    #[test]
    fn deserialize() {
        let json = json!({ "timestamp": 3000 });

        assert_matches!(
            serde_json::from_value::<SystemTimeTest>(json),
            Ok(SystemTimeTest { timestamp })
            if timestamp == UNIX_EPOCH + Duration::from_millis(3000)
        );
    }

    #[test]
    fn serialize() {
        let request = SystemTimeTest { timestamp: UNIX_EPOCH + Duration::new(2, 0) };
        assert_matches!(
            serde_json::to_value(&request),
            Ok(value) if value == json!({ "timestamp": 2000 })
        );
    }
}
<|endoftext|>


<commit_before>extern crate log_domain;
#[macro_use]
extern crate rustomata;

use log_domain::LogDomain;
use std::fs::File;
use std::io::Read;
use std::rc::Rc;

use rustomata::approximation::ApproximationStrategy;
use rustomata::approximation::equivalence_classes::EquivalenceRelation;
use rustomata::approximation::relabel::RlbElement;
use rustomata::approximation::tts::TTSElement;
use rustomata::pmcfg::*;
use rustomata::pmcfg::negra::to_negra;
use rustomata::recognisable::*;
use rustomata::recognisable::coarse_to_fine::CoarseToFineRecogniser;
use rustomata::tree_stack_automaton::*;

fn example_tree_stack_automaton()
        -> TreeStackAutomaton<PosState<PMCFGRule<String, String, LogDomain<f64>>>, String, LogDomain<f64>>
{
    let mut grammar_file = File::open("examples/example.mcfg").unwrap();
    let mut grammar_string = String::new();
    let _ = grammar_file.read_to_string(&mut grammar_string);
    let grammar: PMCFG<String, String, _> = grammar_string.parse().unwrap();

    TreeStackAutomaton::from(grammar)
}

#[test]
fn test_example_pmcfg_to_negra() {
    let automaton = example_tree_stack_automaton();
    let tree_stack = automaton.recognise(
        String::from("aabccd").chars().map(|x| x.to_string()).collect()
    ).next().unwrap().0;

    let syntax_tree = to_abstract_syntax_tree(tree_stack.storage.to_tree());
    let separated_syntax_tree = separate_terminal_rules(&syntax_tree);

    let negra_string = to_negra(&separated_syntax_tree, 0);
    let negra_control_string = String::from(
        "#BOS 0\n\
         a\ta\t--\t--\t1\n\
         a\ta\t--\t--\t2\n\
         b\tb\t--\t--\t3\n\
         c\tc\t--\t--\t1\n\
         c\tc\t--\t--\t2\n\
         d\td\t--\t--\t3\n\
         #1\tA\t--\t--\t4\n\
         #2\tA\t--\t--\t1\n\
         #3\tB\t--\t--\t4\n\
         #4\tS\t--\t--\t0\n\
         #EOS 0"
    );

    assert_eq!(negra_control_string, negra_string);
}

#[test]
fn test_from_str_automaton() {
    let i1: TreeStackInstruction<String> = TreeStackInstruction::Up {
        n: 1,
        current_val: "zwei".to_string(),
        old_val: "drei".to_string(),
        new_val: "vier".to_string(),
    };

    let i2: TreeStackInstruction<String> = TreeStackInstruction::Push {
        n: 1,
        current_val: "zwei".to_string(),
        new_val: "vier".to_string(),
    };

    let i3: TreeStackInstruction<String> = TreeStackInstruction::Down {
        current_val: "zwei".to_string(),
        old_val: "drei".to_string(),
        new_val: "vier".to_string(),
    };

    let i1_string = "Up 1 zwei drei vier";
    let i1_string2 = "   Up 1  zwei  drei   vier  ";
    let i2_string = "Push 1 zwei vier";
    let i3_string = "Down zwei drei vier";

    assert_eq!(Ok(i1.clone()), i1_string.parse());
    assert_eq!(Ok(i1.clone()), i1_string2.parse());
    assert_eq!(Ok(i2.clone()), i2_string.parse());
    assert_eq!(Ok(i3.clone()), i3_string.parse());

    let t1 = Transition {
        word: vec!["hello".to_string(), "world".to_string()],
        weight: LogDomain::new(0.5).unwrap(),
        instruction: i1,
    };

    let t2 = Transition {
        word: vec!["\"hello\\".to_string(), "world".to_string()],
        weight: LogDomain::new(0.5).unwrap(),
        instruction: i2,
    };

    let t3 = Transition {
        word: vec!["\"hello\\".to_string(), "world".to_string()],
        weight: LogDomain::new(0.5).unwrap(),
        instruction: i3,
    };

    let mut t1_string = String::from("Transition [\"hello\",\"world\"] (");
    t1_string.push_str(i1_string);
    t1_string.push_str(") #0.5");

    let mut t2_string = String::from("Transition [\"\\\"hello\\\\\",\"world\"] (");
    t2_string.push_str(i2_string);
    t2_string.push_str(") #0.5");

    let mut t3_string = String::from("Transition [\"\\\"hello\\\\\",\"world\"] (");
    t3_string.push_str(i3_string);
    t3_string.push_str(") #0.5");

    assert_eq!(Ok(t1.clone()), t1_string.parse());
    assert_eq!(Ok(t2.clone()), t2_string.parse());
    assert_eq!(Ok(t3.clone()), t3_string.parse());

    let automaton: TreeStackAutomaton<String, String, LogDomain<f64>> = TreeStackAutomaton::new(
        vec![t1.clone(), t2.clone(), t3.clone()],
        TreeStack::new("eins".to_string())
    );

    let mut automaton_string: String = String::from("initial: eins\n\n");
    automaton_string.push_str(t1_string.as_str());
    automaton_string.push_str("\n");
    automaton_string.push_str(t2_string.as_str());
    automaton_string.push_str("\n");
    automaton_string.push_str(t3_string.as_str());
    automaton_string.push_str("\n");

    let automaton_parse: TreeStackAutomaton<String, String, LogDomain<f64>> = automaton_string.parse().unwrap();

    let ts1: Vec<_> = automaton.list_transitions().collect();
    let ts2: Vec<_> = automaton_parse.list_transitions().collect();

    assert_eq!(ts1, ts2);

    assert_eq!(
        automaton.initial(),
        automaton_parse.initial()
    );
}

#[test]
fn test_coarse_to_fine_recogniser_correctness() {
    let automaton = example_tree_stack_automaton();
    let tts = TTSElement::new();
    let rel: EquivalenceRelation<String, String> = "0 [A, B]\n1 *".parse().unwrap();
    let mapping = |ps: &PosState<_>| ps
        .map(|r: &PMCFGRule<_, _, _>| r.map_nonterminals(|nt| rel.project(nt)));
    let rlb = RlbElement::new(&mapping);
    let recogniser = coarse_to_fine_recogniser!(automaton.clone(); tts, rlb);

    let words = vec![
        "aabccd",
        "aaabcccd",
        "abccd",
        "abbcd",
    ];

    for word in words {
        let input: Vec<_> = String::from(word).chars().map(|x| x.to_string()).collect();
        assert_eq!(
            automaton.recognise(input.clone()).next(),
            recogniser.recognise(input).next()
        );
    }
}

#[test]
fn test_tts() {
    //create (and test) initial push down automata
    let r0_string = "S → [[Var 0 0, Var 1 0, Var 0 1, Var 1 1]] (A, B)   # 1";
    let r1_string = "A → [[T a, Var 0 0, T e],  [T c, Var 0 1]] (A   )   # 0.5";
    let r2_string = "A → [[],  []                             ] (    )   # 0.5";
    let r3_string = "B → [[T b, Var 0 0],  [T d, Var 0 1]     ] (B   )   # 0.5";
    let r4_string = "B → [[],  []                             ] (    )   # 0.5";

    let mut g_string = String::from("initial: [S]\n\n");
    g_string.push_str(r0_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r1_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r2_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r3_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r4_string.clone());

    let g: PMCFG<String, String, LogDomain<f64>> = g_string.parse().unwrap();

    let a = TreeStackAutomaton::from(g);

    let tts = TTSElement::new();

    let (b, _) = tts.approximate_automaton(&a);

    assert_ne!(None, a.recognise(vec!["a".to_string(), "e".to_string(), "b".to_string(), "c".to_string(), "d".to_string() ]).next());
    assert_eq!(None, a.recognise(vec!["a".to_string(), "e".to_string(), "b".to_string(), "c".to_string(), "c".to_string(), "d".to_string() ]).next());
    assert_ne!(None, b.recognise(vec!["a".to_string(), "e".to_string(), "b".to_string(), "c".to_string(), "d".to_string() ]).next());
    assert_ne!(None, b.recognise(vec!["a".to_string(), "e".to_string(), "b".to_string(), "c".to_string(), "c".to_string(), "d".to_string() ]).next());
    assert_ne!(None, b.recognise(vec!["a".to_string(), "a".to_string(), "e".to_string(), "e".to_string(), "b".to_string(), "c".to_string(), "d".to_string() ]).next());
    assert_eq!(None, b.recognise(vec!["a".to_string(), "e".to_string(), "e".to_string(), "b".to_string(), "c".to_string(), "c".to_string(), "d".to_string() ]).next());
}

#[test]
fn test_from_str_pmcfg() {
    let c0: Composition<String> = Composition {
        composition: vec![vec![VarT::Var(0, 0), VarT::Var(1, 0), VarT::Var(0, 1), VarT::Var(1, 1)]],
    };

    let c1: Composition<String> = Composition { composition: vec![vec![], vec![]] };

    let c2 = Composition {
        composition: vec![vec![VarT::T("a".to_string()),
                               VarT::Var(0, 0)],
                          vec![VarT::T("c".to_string()),
                               VarT::Var(0, 1)]],
    };

    let c3 = Composition {
        composition: vec![vec![VarT::T("b".to_string()),
                               VarT::Var(0, 0)],
                          vec![VarT::T("d".to_string()),
                               VarT::Var(0, 1)]],
    };

    let r0: PMCFGRule<String, String, LogDomain<f64>> = PMCFGRule {
        head: "S".to_string(),
        tail: vec!["A".to_string(), "B".to_string()],
        composition: c0.clone(),
        weight: LogDomain::new(1.0).unwrap(),
    };

    let r1: PMCFGRule<String, String, LogDomain<f64>> = PMCFGRule {
        head: "A".to_string(),
        tail: Vec::new(),
        composition: c1.clone(),
        weight: LogDomain::new(0.6).unwrap(),
    };

    let r2: PMCFGRule<String, String, LogDomain<f64>> = PMCFGRule {
        head: "A".to_string(),
        tail: vec!["A".to_string()],
        composition: c2.clone(),
        weight: LogDomain::new(0.4).unwrap(),
    };

    let r3: PMCFGRule<String, String, LogDomain<f64>> = PMCFGRule {
        head: "B".to_string(),
        tail: Vec::new(),
        composition: c1.clone(),
        weight: LogDomain::new(0.7).unwrap(),
    };

    let r4: PMCFGRule<String, String, LogDomain<f64>> = PMCFGRule {
        head: "B".to_string(),
        tail: vec!["B".to_string()],
        composition: c3.clone(),
        weight: LogDomain::new(0.3).unwrap(),
    };

    let r0_string = "\"S\" → [[Var 0 0, Var 1 0, Var 0 1, Var 1 1]] (\"A\", B)";
    let r1_string = "A → [[],[]] ()  # 0.6 % this is a comment";
    let r2_string = "A → [[T a, Var 0 0],[T c, Var 0 1]] (A)  # 0.4";
    let r3_string = "B → [[],[]] ()  # 0.7";
    let r4_string = "B → [[T b, Var 0 0],[T d, Var 0 1]] (B)  # 0.3";

    assert_eq!(Ok(r0.clone()),
               r0_string.parse::<PMCFGRule<String, String, LogDomain<f64>>>());
    assert_eq!(Ok(r1.clone()),
               r1_string.parse::<PMCFGRule<String, String, LogDomain<f64>>>());
    assert_eq!(Ok(r2.clone()),
               r2_string.parse::<PMCFGRule<String, String, LogDomain<f64>>>());
    assert_eq!(Ok(r3.clone()),
               r3_string.parse::<PMCFGRule<String, String, LogDomain<f64>>>());
    assert_eq!(Ok(r4.clone()),
               r4_string.parse::<PMCFGRule<String, String, LogDomain<f64>>>());

    let g: PMCFG<String, String, LogDomain<f64>> = PMCFG {
        initial: vec!["S".to_string()],
        rules: vec![r0.clone(), r1.clone(), r2.clone(), r3.clone(), r4.clone()],
    };

    let mut g_string = String::from("initial: [S]\n\n");
    g_string.push_str(r0_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r1_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r2_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r3_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r4_string.clone());

    assert_eq!(Ok(g.clone()), g_string.parse());

    let a = TreeStackAutomaton::from(g);

    assert_ne!(None, a.recognise(vec!["a".to_string(), "b".to_string(), "c".to_string(), "d".to_string()]).next());
}
<commit_msg>tests/pmcfg.rs: reworked integration test for tts<commit_after>extern crate log_domain;
#[macro_use]
extern crate rustomata;

use log_domain::LogDomain;
use std::fs::File;
use std::io::Read;
use std::rc::Rc;

use rustomata::approximation::ApproximationStrategy;
use rustomata::approximation::equivalence_classes::EquivalenceRelation;
use rustomata::approximation::relabel::RlbElement;
use rustomata::approximation::tts::TTSElement;
use rustomata::pmcfg::*;
use rustomata::pmcfg::negra::to_negra;
use rustomata::recognisable::*;
use rustomata::recognisable::coarse_to_fine::CoarseToFineRecogniser;
use rustomata::tree_stack_automaton::*;

fn example_tree_stack_automaton()
        -> TreeStackAutomaton<PosState<PMCFGRule<String, String, LogDomain<f64>>>, String, LogDomain<f64>>
{
    let mut grammar_file = File::open("examples/example.mcfg").unwrap();
    let mut grammar_string = String::new();
    let _ = grammar_file.read_to_string(&mut grammar_string);
    let grammar: PMCFG<String, String, _> = grammar_string.parse().unwrap();

    TreeStackAutomaton::from(grammar)
}

#[test]
fn test_example_pmcfg_to_negra() {
    let automaton = example_tree_stack_automaton();
    let tree_stack = automaton.recognise(
        String::from("aabccd").chars().map(|x| x.to_string()).collect()
    ).next().unwrap().0;

    let syntax_tree = to_abstract_syntax_tree(tree_stack.storage.to_tree());
    let separated_syntax_tree = separate_terminal_rules(&syntax_tree);

    let negra_string = to_negra(&separated_syntax_tree, 0);
    let negra_control_string = String::from(
        "#BOS 0\n\
         a\ta\t--\t--\t1\n\
         a\ta\t--\t--\t2\n\
         b\tb\t--\t--\t3\n\
         c\tc\t--\t--\t1\n\
         c\tc\t--\t--\t2\n\
         d\td\t--\t--\t3\n\
         #1\tA\t--\t--\t4\n\
         #2\tA\t--\t--\t1\n\
         #3\tB\t--\t--\t4\n\
         #4\tS\t--\t--\t0\n\
         #EOS 0"
    );

    assert_eq!(negra_control_string, negra_string);
}

#[test]
fn test_from_str_automaton() {
    let i1: TreeStackInstruction<String> = TreeStackInstruction::Up {
        n: 1,
        current_val: "zwei".to_string(),
        old_val: "drei".to_string(),
        new_val: "vier".to_string(),
    };

    let i2: TreeStackInstruction<String> = TreeStackInstruction::Push {
        n: 1,
        current_val: "zwei".to_string(),
        new_val: "vier".to_string(),
    };

    let i3: TreeStackInstruction<String> = TreeStackInstruction::Down {
        current_val: "zwei".to_string(),
        old_val: "drei".to_string(),
        new_val: "vier".to_string(),
    };

    let i1_string = "Up 1 zwei drei vier";
    let i1_string2 = "   Up 1  zwei  drei   vier  ";
    let i2_string = "Push 1 zwei vier";
    let i3_string = "Down zwei drei vier";

    assert_eq!(Ok(i1.clone()), i1_string.parse());
    assert_eq!(Ok(i1.clone()), i1_string2.parse());
    assert_eq!(Ok(i2.clone()), i2_string.parse());
    assert_eq!(Ok(i3.clone()), i3_string.parse());

    let t1 = Transition {
        word: vec!["hello".to_string(), "world".to_string()],
        weight: LogDomain::new(0.5).unwrap(),
        instruction: i1,
    };

    let t2 = Transition {
        word: vec!["\"hello\\".to_string(), "world".to_string()],
        weight: LogDomain::new(0.5).unwrap(),
        instruction: i2,
    };

    let t3 = Transition {
        word: vec!["\"hello\\".to_string(), "world".to_string()],
        weight: LogDomain::new(0.5).unwrap(),
        instruction: i3,
    };

    let mut t1_string = String::from("Transition [\"hello\",\"world\"] (");
    t1_string.push_str(i1_string);
    t1_string.push_str(") #0.5");

    let mut t2_string = String::from("Transition [\"\\\"hello\\\\\",\"world\"] (");
    t2_string.push_str(i2_string);
    t2_string.push_str(") #0.5");

    let mut t3_string = String::from("Transition [\"\\\"hello\\\\\",\"world\"] (");
    t3_string.push_str(i3_string);
    t3_string.push_str(") #0.5");

    assert_eq!(Ok(t1.clone()), t1_string.parse());
    assert_eq!(Ok(t2.clone()), t2_string.parse());
    assert_eq!(Ok(t3.clone()), t3_string.parse());

    let automaton: TreeStackAutomaton<String, String, LogDomain<f64>> = TreeStackAutomaton::new(
        vec![t1.clone(), t2.clone(), t3.clone()],
        TreeStack::new("eins".to_string())
    );

    let mut automaton_string: String = String::from("initial: eins\n\n");
    automaton_string.push_str(t1_string.as_str());
    automaton_string.push_str("\n");
    automaton_string.push_str(t2_string.as_str());
    automaton_string.push_str("\n");
    automaton_string.push_str(t3_string.as_str());
    automaton_string.push_str("\n");

    let automaton_parse: TreeStackAutomaton<String, String, LogDomain<f64>> = automaton_string.parse().unwrap();

    let ts1: Vec<_> = automaton.list_transitions().collect();
    let ts2: Vec<_> = automaton_parse.list_transitions().collect();

    assert_eq!(ts1, ts2);

    assert_eq!(
        automaton.initial(),
        automaton_parse.initial()
    );
}

#[test]
fn test_coarse_to_fine_recogniser_correctness() {
    let automaton = example_tree_stack_automaton();
    let tts = TTSElement::new();
    let rel: EquivalenceRelation<String, String> = "0 [A, B]\n1 *".parse().unwrap();
    let mapping = |ps: &PosState<_>| ps
        .map(|r: &PMCFGRule<_, _, _>| r.map_nonterminals(|nt| rel.project(nt)));
    let rlb = RlbElement::new(&mapping);
    let recogniser = coarse_to_fine_recogniser!(automaton.clone(); tts, rlb);

    let words = vec![
        "aabccd",
        "aaabcccd",
        "abccd",
        "abbcd",
    ];

    for word in words {
        let input: Vec<_> = String::from(word).chars().map(|x| x.to_string()).collect();
        assert_eq!(
            automaton.recognise(input.clone()).next(),
            recogniser.recognise(input).next()
        );
    }
}

#[test]
fn test_tts_correctness() {
    let automaton = example_tree_stack_automaton();
    let tts = TTSElement::new();
    let (tts_ed_automaton, _) = tts.approximate_automaton(&automaton);

    let true_positives_and_true_negatives = vec![
        "",
        "abcd",
        "aabccd",
        "aaabcccd",
    ];

    for word in true_positives_and_true_negatives {
        let input: Vec<_> = String::from(word).chars().map(|x| x.to_string()).collect();
        assert_eq!(
            automaton.recognise(input.clone()).next().is_some(),
            tts_ed_automaton.recognise(input).next().is_some()
        );
    }

    let false_positives = vec![
        "aabcd",
        "aabbcd",
        "abbcccdddd",
        "abbbccdddd",
    ];

    for word in false_positives {
        let input: Vec<_> = String::from(word).chars().map(|x| x.to_string()).collect();
        assert_eq!(false, automaton.recognise(input.clone()).next().is_some());
        assert_eq!(true, tts_ed_automaton.recognise(input).next().is_some());
    }
}

#[test]
fn test_from_str_pmcfg() {
    let c0: Composition<String> = Composition {
        composition: vec![vec![VarT::Var(0, 0), VarT::Var(1, 0), VarT::Var(0, 1), VarT::Var(1, 1)]],
    };

    let c1: Composition<String> = Composition { composition: vec![vec![], vec![]] };

    let c2 = Composition {
        composition: vec![vec![VarT::T("a".to_string()),
                               VarT::Var(0, 0)],
                          vec![VarT::T("c".to_string()),
                               VarT::Var(0, 1)]],
    };

    let c3 = Composition {
        composition: vec![vec![VarT::T("b".to_string()),
                               VarT::Var(0, 0)],
                          vec![VarT::T("d".to_string()),
                               VarT::Var(0, 1)]],
    };

    let r0: PMCFGRule<String, String, LogDomain<f64>> = PMCFGRule {
        head: "S".to_string(),
        tail: vec!["A".to_string(), "B".to_string()],
        composition: c0.clone(),
        weight: LogDomain::new(1.0).unwrap(),
    };

    let r1: PMCFGRule<String, String, LogDomain<f64>> = PMCFGRule {
        head: "A".to_string(),
        tail: Vec::new(),
        composition: c1.clone(),
        weight: LogDomain::new(0.6).unwrap(),
    };

    let r2: PMCFGRule<String, String, LogDomain<f64>> = PMCFGRule {
        head: "A".to_string(),
        tail: vec!["A".to_string()],
        composition: c2.clone(),
        weight: LogDomain::new(0.4).unwrap(),
    };

    let r3: PMCFGRule<String, String, LogDomain<f64>> = PMCFGRule {
        head: "B".to_string(),
        tail: Vec::new(),
        composition: c1.clone(),
        weight: LogDomain::new(0.7).unwrap(),
    };

    let r4: PMCFGRule<String, String, LogDomain<f64>> = PMCFGRule {
        head: "B".to_string(),
        tail: vec!["B".to_string()],
        composition: c3.clone(),
        weight: LogDomain::new(0.3).unwrap(),
    };

    let r0_string = "\"S\" → [[Var 0 0, Var 1 0, Var 0 1, Var 1 1]] (\"A\", B)";
    let r1_string = "A → [[],[]] ()  # 0.6 % this is a comment";
    let r2_string = "A → [[T a, Var 0 0],[T c, Var 0 1]] (A)  # 0.4";
    let r3_string = "B → [[],[]] ()  # 0.7";
    let r4_string = "B → [[T b, Var 0 0],[T d, Var 0 1]] (B)  # 0.3";

    assert_eq!(Ok(r0.clone()),
               r0_string.parse::<PMCFGRule<String, String, LogDomain<f64>>>());
    assert_eq!(Ok(r1.clone()),
               r1_string.parse::<PMCFGRule<String, String, LogDomain<f64>>>());
    assert_eq!(Ok(r2.clone()),
               r2_string.parse::<PMCFGRule<String, String, LogDomain<f64>>>());
    assert_eq!(Ok(r3.clone()),
               r3_string.parse::<PMCFGRule<String, String, LogDomain<f64>>>());
    assert_eq!(Ok(r4.clone()),
               r4_string.parse::<PMCFGRule<String, String, LogDomain<f64>>>());

    let g: PMCFG<String, String, LogDomain<f64>> = PMCFG {
        initial: vec!["S".to_string()],
        rules: vec![r0.clone(), r1.clone(), r2.clone(), r3.clone(), r4.clone()],
    };

    let mut g_string = String::from("initial: [S]\n\n");
    g_string.push_str(r0_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r1_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r2_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r3_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r4_string.clone());

    assert_eq!(Ok(g.clone()), g_string.parse());

    let a = TreeStackAutomaton::from(g);

    assert_ne!(None, a.recognise(vec!["a".to_string(), "b".to_string(), "c".to_string(), "d".to_string()]).next());
}
<|endoftext|>


<commit_before>use std::io::{BufferedReader, File};
use material::materials::CookTorranceMaterial;
use geometry::{Mesh, Prim};
use geometry::prims::Triangle;
use raytracer::compositor::{Surface, ColorRGBA};
use vec3::Vec3;

/// This is limited to only CookTorranceMaterials, as I couldn't get a Box<Material> to clone
/// a new material for each triangle primitive in the object model.
#[allow(dead_code)]
pub fn from_obj(position: Vec3, scale: f64, material: CookTorranceMaterial /*Box<Material>*/, flip_normals: bool, filename: &str) -> Mesh {
    let path = Path::new(filename);
    let mut file = BufferedReader::new(File::open(&path));

    let mut vertices:   Vec<Vec3> = Vec::new();
    let mut tex_coords: Vec<Vec3> = Vec::new();
    let mut normals:    Vec<Vec3> = Vec::new();
    let mut triangles:  Vec<Box<Prim+Send+Share>> = Vec::new();

    let start_time = ::time::get_time();
    let print_progress_every = 1024u;
    let mut current_line = 0;
    let mut processed_bytes = 0;
    let total_bytes = match path.stat() {
        Ok(stat) => stat.size,
        Err(e) => fail!(e)
    };

    for line_iter in file.lines() {
        let line: String = match line_iter {
            Ok(x) => x,
            Err(e) => fail!(e)
        };

        let tokens: Vec<&str> = line.as_slice().words().collect();
        if tokens.len() < 4 { continue }

        match tokens[0].as_slice() {
            "v" => {
                vertices.push(Vec3 {
                    x: parse_coord_str(tokens[1].as_slice(), scale, line.as_slice()),
                    y: parse_coord_str(tokens[2].as_slice(), scale, line.as_slice()),
                    z: parse_coord_str(tokens[3].as_slice(), scale, line.as_slice()),
                });
            },
            "vt" => {
                tex_coords.push(Vec3 {
                    x: parse_coord_str(tokens[1].as_slice(), scale, line.as_slice()),
                    y: parse_coord_str(tokens[2].as_slice(), scale, line.as_slice()),
                    z: 0.0
                });
            },
            "vn" => {
                let normals_flip_scale = if flip_normals { -1.0 } else { 1.0 } * scale;
                normals.push(Vec3 {
                    x: parse_coord_str(tokens[1].as_slice(), scale * normals_flip_scale, line.as_slice()),
                    y: parse_coord_str(tokens[2].as_slice(), scale * normals_flip_scale, line.as_slice()),
                    z: parse_coord_str(tokens[3].as_slice(), scale * normals_flip_scale, line.as_slice()),
                });
            },
            "f" => {
                // ["f", "1/2/3", "2/2/2", "12//4"] => [[1, 2, 3], [2, 2, 2], [12, -1u, 4]]
                let pairs: Vec<Vec<uint>> = tokens.tail().iter().map( |token| {
                    let str_tokens: Vec<&str> = token.as_slice().split('/').collect();

                    str_tokens.iter().map( |str_tok| {
                        match from_str::<uint>(*str_tok) {
                            Some(uint_tok) => uint_tok - 1,
                            None => -1 // No data available/not supplied
                        }
                    }).collect()
                }).collect();

                // let v0: Vec<&str> = tokens[1].split('/').collect();
                // let v1: Vec<&str> = tokens[2].split('/').collect();
                // let v2: Vec<&str> = tokens[3].split('/').collect();

                // If no texture coordinates were supplied, default to zero.
                let mut u = Vec3::zero();
                let mut v = Vec3::zero();

                // We store nothing supplied as -1 (uint=4294967295)
                if pairs[0][1] != 4294967295 {
                    u = Vec3 {
                        x: tex_coords[pairs[0][1]].x,
                        y: tex_coords[pairs[1][1]].x,
                        z: tex_coords[pairs[2][1]].x
                    };

                    v = Vec3 {
                        x: tex_coords[pairs[0][1]].y,
                        y: tex_coords[pairs[1][1]].y,
                        z: tex_coords[pairs[2][1]].y
                    };
                }

                triangles.push(box Triangle {
                    v0: vertices[pairs[0][0]],
                    v1: vertices[pairs[1][0]],
                    v2: vertices[pairs[2][0]],

                    n0: normals[pairs[0][2]],
                    n1: normals[pairs[1][2]],
                    n2: normals[pairs[2][2]],

                    u: u,
                    v: v,
                    material: box material.clone()
                });
            },
            _ => {}
        }

        current_line += 1;
        processed_bytes += line.as_bytes().len();
        if current_line % print_progress_every == 0 {
            ::util::print_progress("Bytes", start_time, processed_bytes, total_bytes as uint);
        }
    }

    // Cheat the progress meter
    ::util::print_progress("Bytes", start_time, total_bytes as uint, total_bytes as uint);

    Mesh {
        position: position,
        scale: scale,
        triangles: triangles
    }
}

fn parse_coord_str(coord: &str, scale: f64, line: &str) -> f64 {
    match from_str::<f64>(coord.as_slice()) {
        Some(f) => f * scale,
        None => fail!(format!("Bad vertex or texture coordinate in file. `{}`", line))
    }
}

#[allow(dead_code)]
pub fn from_ppm(filename: &str) -> Surface {
    let path = Path::new(filename);
    let mut file = BufferedReader::new(File::open(&path));

    let tex = match file.read_to_string() { Ok(f) => f, Err(e) => { println!("Could not open {}", filename); fail!(e) }};
    let mut tokens: Vec<&str> = tex.as_slice().words().collect();

    tokens.remove(0); // PPM type
    let width  = match tokens.remove(0) { Some(x) => uint_from_string(x), None => fail!("Bad PPM") };
    let height = match tokens.remove(0) { Some(x) => uint_from_string(x), None => fail!("Bad PPM") };
    tokens.remove(0); // Max color value

    print!("Importing image texture {}", filename);
    println!(" {}x{}", width, height);

    let mut surface = Surface::new(width, height, ColorRGBA::new_rgb(0, 0, 0));

    let mut i = 0u;

    for chunk in tokens.as_slice().chunks(3) {
        let x = i % width;
        let y = i / width;
        i += 1;

        if x >= width || y >= height { break };

        *surface.get_mut(x, y) = ColorRGBA::new_rgb(
            uint_from_string(chunk[0]) as u8,
            uint_from_string(chunk[1]) as u8,
            uint_from_string(chunk[2]) as u8
        );
    }

    surface
}

fn uint_from_string(s: &str) -> uint {
     match from_str::<uint>(s) {
        Some(x) => x,
        None => fail!("Bad uint string {}", s)
    }
}
<commit_msg>Improve OBJ import error message.<commit_after>use std::io::{BufferedReader, File};
use material::materials::CookTorranceMaterial;
use geometry::{Mesh, Prim};
use geometry::prims::Triangle;
use raytracer::compositor::{Surface, ColorRGBA};
use vec3::Vec3;

/// This is limited to only CookTorranceMaterials, as I couldn't get a Box<Material> to clone
/// a new material for each triangle primitive in the object model.
#[allow(dead_code)]
pub fn from_obj(position: Vec3, scale: f64, material: CookTorranceMaterial /*Box<Material>*/, flip_normals: bool, filename: &str) -> Mesh {
    let path = Path::new(filename);
    let mut file = BufferedReader::new(File::open(&path));

    let mut vertices:   Vec<Vec3> = Vec::new();
    let mut tex_coords: Vec<Vec3> = Vec::new();
    let mut normals:    Vec<Vec3> = Vec::new();
    let mut triangles:  Vec<Box<Prim+Send+Share>> = Vec::new();

    let start_time = ::time::get_time();
    let print_progress_every = 1024u;
    let mut current_line = 0;
    let mut processed_bytes = 0;
    let total_bytes = match path.stat() {
        Ok(stat) => stat.size,
        Err(e) => fail!(e)
    };

    for line_iter in file.lines() {
        let line: String = match line_iter {
            Ok(x) => x,
            Err(e) => fail!("Could not import OBJ file {} (file missing?): {}", filename, e)
        };

        let tokens: Vec<&str> = line.as_slice().words().collect();
        if tokens.len() < 4 { continue }

        match tokens[0].as_slice() {
            "v" => {
                vertices.push(Vec3 {
                    x: parse_coord_str(tokens[1].as_slice(), scale, line.as_slice()),
                    y: parse_coord_str(tokens[2].as_slice(), scale, line.as_slice()),
                    z: parse_coord_str(tokens[3].as_slice(), scale, line.as_slice()),
                });
            },
            "vt" => {
                tex_coords.push(Vec3 {
                    x: parse_coord_str(tokens[1].as_slice(), scale, line.as_slice()),
                    y: parse_coord_str(tokens[2].as_slice(), scale, line.as_slice()),
                    z: 0.0
                });
            },
            "vn" => {
                let normals_flip_scale = if flip_normals { -1.0 } else { 1.0 } * scale;
                normals.push(Vec3 {
                    x: parse_coord_str(tokens[1].as_slice(), scale * normals_flip_scale, line.as_slice()),
                    y: parse_coord_str(tokens[2].as_slice(), scale * normals_flip_scale, line.as_slice()),
                    z: parse_coord_str(tokens[3].as_slice(), scale * normals_flip_scale, line.as_slice()),
                });
            },
            "f" => {
                // ["f", "1/2/3", "2/2/2", "12//4"] => [[1, 2, 3], [2, 2, 2], [12, -1u, 4]]
                let pairs: Vec<Vec<uint>> = tokens.tail().iter().map( |token| {
                    let str_tokens: Vec<&str> = token.as_slice().split('/').collect();
                    str_tokens.iter().map( |str_tok| {
                        match from_str::<uint>(*str_tok) {
                            Some(uint_tok) => uint_tok - 1,
                            None => -1 // No data available/not supplied
                        }
                    }).collect()
                }).collect();

                // If no texture coordinates were supplied, default to zero.
                let mut u = Vec3::zero();
                let mut v = Vec3::zero();

                // We store nothing supplied as -1 (uint=4294967295)
                if pairs[0][1] != 4294967295 {
                    u = Vec3 {
                        x: tex_coords[pairs[0][1]].x,
                        y: tex_coords[pairs[1][1]].x,
                        z: tex_coords[pairs[2][1]].x
                    };

                    v = Vec3 {
                        x: tex_coords[pairs[0][1]].y,
                        y: tex_coords[pairs[1][1]].y,
                        z: tex_coords[pairs[2][1]].y
                    };
                }

                triangles.push(box Triangle {
                    v0: vertices[pairs[0][0]],
                    v1: vertices[pairs[1][0]],
                    v2: vertices[pairs[2][0]],

                    n0: normals[pairs[0][2]],
                    n1: normals[pairs[1][2]],
                    n2: normals[pairs[2][2]],

                    u: u,
                    v: v,
                    material: box material.clone()
                });
            },
            _ => {}
        }

        current_line += 1;
        processed_bytes += line.as_bytes().len();
        if current_line % print_progress_every == 0 {
            ::util::print_progress("Bytes", start_time, processed_bytes, total_bytes as uint);
        }
    }

    // Cheat the progress meter
    ::util::print_progress("Bytes", start_time, total_bytes as uint, total_bytes as uint);

    Mesh {
        position: position,
        scale: scale,
        triangles: triangles
    }
}

fn parse_coord_str(coord: &str, scale: f64, line: &str) -> f64 {
    match from_str::<f64>(coord.as_slice()) {
        Some(f) => f * scale,
        None => fail!(format!("Bad vertex or texture coordinate in file. `{}`", line))
    }
}

#[allow(dead_code)]
pub fn from_ppm(filename: &str) -> Surface {
    let path = Path::new(filename);
    let mut file = BufferedReader::new(File::open(&path));

    let tex = match file.read_to_string() { Ok(f) => f, Err(e) => { println!("Could not open {}", filename); fail!(e) }};
    let mut tokens: Vec<&str> = tex.as_slice().words().collect();

    tokens.remove(0); // PPM type
    let width  = match tokens.remove(0) { Some(x) => uint_from_string(x), None => fail!("Bad PPM") };
    let height = match tokens.remove(0) { Some(x) => uint_from_string(x), None => fail!("Bad PPM") };
    tokens.remove(0); // Max color value

    print!("Importing image texture {}", filename);
    println!(" {}x{}", width, height);

    let mut surface = Surface::new(width, height, ColorRGBA::new_rgb(0, 0, 0));

    let mut i = 0u;

    for chunk in tokens.as_slice().chunks(3) {
        let x = i % width;
        let y = i / width;
        i += 1;

        if x >= width || y >= height { break };

        *surface.get_mut(x, y) = ColorRGBA::new_rgb(
            uint_from_string(chunk[0]) as u8,
            uint_from_string(chunk[1]) as u8,
            uint_from_string(chunk[2]) as u8
        );
    }

    surface
}

fn uint_from_string(s: &str) -> uint {
     match from_str::<uint>(s) {
        Some(x) => x,
        None => fail!("Bad uint string {}", s)
    }
}
<|endoftext|>


<commit_before>//! # Type-based Serialization and Deserialization
//!
//! Serde provides a mechanism for low boilerplate serialization & deserialization of values to and
//! from MessagePack via the serialization API. To be able to serialize a piece of data, it must
//! implement the `serde::Serialize` trait. To be able to deserialize a piece of data, it must
//! implement the `serde::Deserialize` trait. Serde provides provides an annotation to
//! automatically generate the code for these traits: `#[derive(Serialize, Deserialize)]`.
//!
//! # Examples
//!
//! Let's try to encode and decode some built-in types.
//!
//! ```rust
//! extern crate serde;
//! extern crate rmp_serde;
//!
//! use serde::{Deserialize, Serialize};
//! use rmp_serde::{Deserializer, Serializer};
//!
//! fn main() {
//!     let mut buf = Vec::new();
//!     let val = (42u8, "the Answer");
//!     val.serialize(&mut Serializer::new(&mut buf)).unwrap();
//!
//!     assert_eq!(vec![0x92, 0x2a, 0xaa, 0x74, 0x68, 0x65, 0x20, 0x41, 0x6e, 0x73, 0x77, 0x65, 0x72], buf);
//!
//!     let mut de = Deserializer::new(&buf[..]);
//!     assert_eq!((42, "the Answer".to_owned()), Deserialize::deserialize(&mut de).unwrap());
//! }
//! ```
//!
//! No one gonna hurt if we add some reflection magic.
//!
//! ```ignore
//! #![feature(proc_macro)]
//!
//! #[macro_use] extern crate serde_derive;
//! extern crate rmp_serde;
//!
//! use std::collections::HashMap;
//! use serde::{Deserialize, Serialize};
//! use rmp_serde::{Deserializer, Serializer};
//!
//! #[derive(Debug, PartialEq, Deserialize, Serialize)]
//! struct Human {
//!     age: u32,
//!     name: String,
//! }
//!
//! fn main() {
//!     let mut buf = Vec::new();
//!     let val = Human {
//!         age: 42,
//!         name: "John".into(),
//!     };
//!
//!     val.serialize(&mut Serializer::new(&mut buf)).unwrap();
//! }
//! ```

extern crate rmp;
extern crate byteorder;
#[macro_use] extern crate serde;

pub use decode::Deserializer;
pub use encode::Serializer;

pub mod decode;
pub mod encode;
<commit_msg>serde: add convenience `to_vec` / `from_slice` functions (#93)<commit_after>//! # Type-based Serialization and Deserialization
//!
//! Serde provides a mechanism for low boilerplate serialization & deserialization of values to and
//! from MessagePack via the serialization API. To be able to serialize a piece of data, it must
//! implement the `serde::Serialize` trait. To be able to deserialize a piece of data, it must
//! implement the `serde::Deserialize` trait. Serde provides provides an annotation to
//! automatically generate the code for these traits: `#[derive(Serialize, Deserialize)]`.
//!
//! # Examples
//!
//! Let's try to encode and decode some built-in types.
//!
//! ```rust
//! extern crate serde;
//! extern crate rmp_serde;
//!
//! use serde::{Deserialize, Serialize};
//! use rmp_serde::{Deserializer, Serializer};
//!
//! fn main() {
//!     let mut buf = Vec::new();
//!     let val = (42u8, "the Answer");
//!     val.serialize(&mut Serializer::new(&mut buf)).unwrap();
//!
//!     assert_eq!(vec![0x92, 0x2a, 0xaa, 0x74, 0x68, 0x65, 0x20, 0x41, 0x6e, 0x73, 0x77, 0x65, 0x72], buf);
//!
//!     let mut de = Deserializer::new(&buf[..]);
//!     assert_eq!((42, "the Answer".to_owned()), Deserialize::deserialize(&mut de).unwrap());
//! }
//! ```
//!
//! No one gonna hurt if we add some reflection magic.
//!
//! ```ignore
//! #![feature(proc_macro)]
//!
//! #[macro_use] extern crate serde_derive;
//! extern crate rmp_serde;
//!
//! use std::collections::HashMap;
//! use serde::{Deserialize, Serialize};
//! use rmp_serde::{Deserializer, Serializer};
//!
//! #[derive(Debug, PartialEq, Deserialize, Serialize)]
//! struct Human {
//!     age: u32,
//!     name: String,
//! }
//!
//! fn main() {
//!     let mut buf = Vec::new();
//!     let val = Human {
//!         age: 42,
//!         name: "John".into(),
//!     };
//!
//!     val.serialize(&mut Serializer::new(&mut buf)).unwrap();
//! }
//! ```

extern crate rmp;
extern crate byteorder;
#[macro_use] extern crate serde;

pub use decode::Deserializer;
pub use encode::Serializer;

pub mod decode;
pub mod encode;

/// Serializes a value to a byte vector.
pub fn to_vec<T>(value: &T) -> Result<Vec<u8>, encode::Error>
        where T: serde::Serialize
{
    let mut buf = Vec::with_capacity(64);
    value.serialize(&mut Serializer::new(&mut buf))
         .and_then(|_| Ok(buf))
}

/// Deserializes a byte slice into the desired type.
pub fn from_slice<T>(input: &[u8]) -> Result<T, decode::Error>
        where T: serde::Deserialize
{
    let cur = std::io::Cursor::new(&input[..]);
    let mut de = Deserializer::new(cur);
    serde::Deserialize::deserialize(&mut de)
}
<|endoftext|>