<commit_before>//! Entity component system

#![deny(missing_docs)]

#[macro_use]
extern crate serde_derive;
extern crate serde;

use std::default::Default;
use std::ops;
use std::slice;

use serde::{Serialize, Deserialize};

/// Handle for an entity in the entity component system.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
pub struct Entity {
    uid: u32,
    idx: u32,
}

/// Indexing entity index to data array.
#[derive(Copy, Clone, PartialEq, Eq, Default, Debug, Serialize, Deserialize)]
struct Index {
    /// Must match the uid for the entity that is querying for component.
    uid: u32,
    /// Index for this entity in the data array.
    data_idx: u32,
}

/// Operations all components must support.
pub trait AnyComponent {
    /// Remove an entity's component.
    fn remove(&mut self, e: Entity);
}

/// Nonredundant component data, in separate struct for efficient serialization.
#[derive(Serialize, Deserialize)]
struct DenseComponentData<C> {
    /// Dense component data.
    data: Vec<C>,
    /// Entity idx corresponding to elements in data.
    entities: Vec<Entity>,
}

/// Storage for a single component type.
pub struct ComponentData<C> {
    inner: DenseComponentData<C>,
    /// Map entity indices to component data.
    ///
    /// This array spans all live component indices.
    entity_idx_to_data: Vec<Index>,
}

impl<C> ComponentData<C> {
    /// Construct new empty `ComponentData` instance.
    pub fn new() -> ComponentData<C> {
        ComponentData {
            inner: DenseComponentData {
                data: Vec::new(),
                entities: Vec::new(),
            },
            entity_idx_to_data: Vec::new(),
        }
    }

    /// Insert a component to an entity.
    pub fn insert(&mut self, e: Entity, comp: C) {
        debug_assert!(self.inner.data.len() == self.inner.entities.len());

        if self.contains(e) {
            // Component is set for entity, replace existing component.
            self.inner.data[self.entity_idx_to_data[e.idx as usize].data_idx as usize] = comp;
        } else {
            // Grow lookup vector if needed.
            if e.idx as usize >= self.entity_idx_to_data.len() {
                self.entity_idx_to_data.resize(e.idx as usize + 1, Default::default());
            }

            // Add a new component.
            let data_idx = self.inner.data.len() as u32;
            self.inner.data.push(comp);
            self.inner.entities.push(e);
            self.entity_idx_to_data[e.idx as usize] = Index {
                uid: e.uid,
                data_idx: data_idx,
            };
        }
    }

    /// Return whether an entity contains this component.
    #[inline(always)]
    pub fn contains(&self, e: Entity) -> bool {
        debug_assert!(e.uid != 0);

        (e.idx as usize) < self.entity_idx_to_data.len() &&
            self.entity_idx_to_data[e.idx as usize].uid == e.uid
    }

    /// Get a reference to a component only if it exists for this entity.
    #[inline(always)]
    pub fn get(&self, e: Entity) -> Option<&C> {
        if self.contains(e) {
            Some(&self.inner.data[self.entity_idx_to_data[e.idx as usize].data_idx as usize])
        } else {
            None
        }
    }

    /// Get a mutable reference to a component only if it exists for this entity.
    #[inline(always)]
    pub fn get_mut(&mut self, e: Entity) -> Option<&mut C> {
        if self.contains(e) {
            Some(&mut self.inner.data[self.entity_idx_to_data[e.idx as usize].data_idx as usize])
        } else {
            None
        }
    }

    /// Iterate entity ids in this component.
    pub fn ent_iter(&self) -> slice::Iter<Entity> {
        self.inner.entities.iter()
    }

    /// Iterate elements in this component.
    pub fn iter(&self) -> slice::Iter<C> {
        self.inner.data.iter()
    }

    /// Iterate mutable elements in this component.
    pub fn iter_mut(&mut self) -> slice::IterMut<C> {
        self.inner.data.iter_mut()
    }
}

impl<C> ops::Index<Entity> for ComponentData<C> {
    type Output = C;

    fn index<'a>(&'a self, e: Entity) -> &'a C {
        self.get(e).unwrap()
    }
}

impl<C> ops::IndexMut<Entity> for ComponentData<C> {
    fn index_mut<'a>(&'a mut self, e: Entity) -> &'a mut C {
        self.get_mut(e).unwrap()
    }
}

impl<C> AnyComponent for ComponentData<C> {
    fn remove(&mut self, e: Entity) {
        debug_assert!(self.inner.data.len() == self.inner.entities.len());
        if self.contains(e) {
            let removed_index = self.entity_idx_to_data[e.idx as usize];
            self.entity_idx_to_data[e.idx as usize] = Default::default();

            // To keep the data compact, we do swap-remove with the last data item and update the
            // lookup on the moved item. If the component being removed isn't the last item in the
            // list, we need to reset the lookup value for the component that was moved.
            if removed_index.data_idx as usize != self.inner.entities.len() - 1 {
                let last_entity = self.inner.entities[self.inner.entities.len() - 1];
                self.inner.entities.swap_remove(removed_index.data_idx as usize);
                self.entity_idx_to_data[last_entity.idx as usize] = Index {
                    uid: last_entity.uid,
                    data_idx: removed_index.data_idx,
                };
            } else {
                self.inner.entities.swap_remove(removed_index.data_idx as usize);
            }

            self.inner.data.swap_remove(removed_index.data_idx as usize);
        }
    }
}

#[derive(Serialize, Deserialize)]
struct Packed<C> {
    entity_count: u32,
    data: Vec<C>,
    entities: Vec<Entity>,
}

impl<C: Serialize+Clone> serde::Serialize for ComponentData<C> {
    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        self.inner.serialize(s)
    }
}

impl<C: Deserialize> serde::Deserialize for ComponentData<C> {
    fn deserialize<D: serde::Deserializer>(d: D) -> Result<Self, D::Error> {
        let inner: DenseComponentData<C> = serde::Deserialize::deserialize(d)?;

        // Regenerate cache.
        let mut entity_idx_to_data = Vec::new();
        for (i, e) in inner.entities.iter().enumerate() {
            if e.idx as usize >= entity_idx_to_data.len() {
                entity_idx_to_data.resize(e.idx as usize + 1, Default::default());
            }
            entity_idx_to_data[e.idx as usize] = Index { uid: e.uid, data_idx: i as u32 };
        }

        Ok(ComponentData {
            inner: inner,
            entity_idx_to_data: entity_idx_to_data,
        })
    }
}

/// Operations for the internal component store object.
pub trait Store {
    /// Perform an operation for each component container.
    fn for_each_component<F>(&mut self, f: F) where F: FnMut(&mut AnyComponent);
}

/// Generic entity component system container
///
/// Needs to be specified with the parametrized `Store` type that has struct fields for the actual
/// components. This can be done with the `Ecs!` macro.
#[derive(Serialize, Deserialize)]
pub struct Ecs<ST> {
    next_uid: u32,
    next_idx: u32,
    free_indices: Vec<u32>,
    active: ComponentData<bool>,
    store: ST,
}

impl<ST: Default + Store> Ecs<ST> {
    /// Construct a new entity component system.
    pub fn new() -> Ecs<ST> {
        Ecs {
            next_uid: 1,
            next_idx: 0,
            free_indices: Vec::new(),
            active: ComponentData::new(),
            store: Default::default(),
        }
    }

    /// Create a new empty entity.
    pub fn make(&mut self) -> Entity {
        let uid = self.next_uid;
        self.next_uid += 1;

        let idx = if let Some(idx) = self.free_indices.pop() {
            idx
        } else {
            self.next_idx += 1;
            self.next_idx - 1
        };

        let ret = Entity {
            uid: uid,
            idx: idx,
        };
        self.active.insert(ret, true);
        ret
    }

    /// Remove an entity from the system and clear its components.
    pub fn remove(&mut self, e: Entity) {
        self.free_indices.push(e.idx);
        self.active.remove(e);
        self.store.for_each_component(|c| c.remove(e));
    }

    /// Return whether the system contains an entity.
    pub fn contains(&self, e: Entity) -> bool {
        self.active.contains(e)
    }

    /// Iterate through all the active entities.
    pub fn iter(&self) -> slice::Iter<Entity> {
        self.active.ent_iter()
    }
}

impl<ST> ops::Deref for Ecs<ST> {
    type Target = ST;

    fn deref(&self) -> &ST {
        &self.store
    }
}

impl<ST> ops::DerefMut for Ecs<ST> {
    fn deref_mut(&mut self) -> &mut ST {
        &mut self.store
    }
}

/// Entity component system builder macro.
///
/// Defines a local `Ecs` type that's parametrized with a custom component
/// store type with the component types you specify. Will also define a trait
/// `Component` which will be implemented for the component types.
#[macro_export]
macro_rules! Ecs {
    {
        // Declare the type of the (plain old data) component and the
        // identifier to use for it in the ECS.
        $($compname:ident: $comptype:ty,)+
    } => {
        mod _ecs_inner {
            // Use the enum to convert components to numbers for component bit masks etc.
            #[allow(non_camel_case_types, dead_code)]
            pub enum ComponentNum {
                $($compname,)+
            }

        }

        pub use self::_ecs_inner::ComponentNum;

        #[derive(Serialize, Deserialize)]
        pub struct _ComponentStore {
            $(pub $compname: $crate::ComponentData<$comptype>),+
        }

        impl ::std::default::Default for _ComponentStore {
            fn default() -> _ComponentStore {
                _ComponentStore {
                    $($compname: $crate::ComponentData::new()),+
                }
            }
        }

        impl $crate::Store for _ComponentStore {
            fn for_each_component<F>(&mut self, mut f: F)
                where F: FnMut(&mut $crate::AnyComponent)
            {
                $(f(&mut self.$compname as &mut $crate::AnyComponent);)+
            }
        }

        #[allow(dead_code)]
        pub fn matches_mask(ecs: &$crate::Ecs<_ComponentStore>, e: $crate::Entity, mask: u64) -> bool {
            $(if mask & (1 << ComponentNum::$compname as u8) != 0 && !ecs.$compname.contains(e) {
                return false;
            })+
            return true;
        }

        /// Common operations for ECS component value types.
        pub trait Component {
            /// Add a clone of the component value to an entity in an ECS.
            ///
            /// Can't move the component itself since we might be using this
            /// through a trait object.
            fn add_to_ecs(&self, ecs: &mut $crate::Ecs<_ComponentStore>, e: $crate::Entity);

            /// Add a clone of the component to a loadout struct.
            fn add_to_loadout(self, loadout: &mut Loadout);
        }

        $(impl Component for $comptype {
            fn add_to_ecs(&self, ecs: &mut $crate::Ecs<_ComponentStore>, e: $crate::Entity) {
                ecs.$compname.insert(e, self.clone());
            }

            fn add_to_loadout(self, loadout: &mut Loadout) {
                loadout.$compname = Some(self);
            }
        })+

        pub type Ecs = $crate::Ecs<_ComponentStore>;

        /// A straightforward representation for the complete data of an
        /// entity.
        #[derive(Clone, Debug, Serialize, Deserialize)]
        pub struct Loadout {
            $(pub $compname: Option<$comptype>),+
        }

        impl ::std::default::Default for Loadout {
            fn default() -> Loadout {
                Loadout {
                    $($compname: None),+
                }
            }
        }

        #[allow(dead_code)]
        impl Loadout {
            /// Create a new blank loadout.
            pub fn new() -> Loadout { Default::default() }

            /// Get the loadout that corresponds to an existing entity.
            pub fn get(ecs: &Ecs, e: $crate::Entity) -> Loadout {
                Loadout {
                    $($compname: ecs.$compname.get(e).cloned()),+
                }
            }

            /// Create a new entity in the ECS with this loadout.
            pub fn make(&self, ecs: &mut Ecs) -> $crate::Entity {
                let e = ecs.make();
                $(self.$compname.as_ref().map(|c| ecs.$compname.insert(e, c.clone()));)+
                e
            }

            /// Builder method for adding a component to this loadout.
            pub fn c<C: Component>(mut self, comp: C) -> Loadout {
                comp.add_to_loadout(&mut self);
                self
            }
        }
    }
}

/// Build a component type mask to match component iteration with.
///
/// You must have ComponentNum enum from the Ecs! macro expansion in scope
/// when using this.
#[macro_export]
macro_rules! build_mask {
    ( $($compname:ident),+ ) => {
        0u64 $(| (1u64 << ComponentNum::$compname as u8))+
    }
}
<commit_msg>Clippy fixes<commit_after>//! Entity component system

#![deny(missing_docs)]

#[macro_use]
extern crate serde_derive;
extern crate serde;

use std::default::Default;
use std::ops;
use std::slice;

use serde::{Serialize, Deserialize};

/// Handle for an entity in the entity component system.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Serialize, Deserialize)]
pub struct Entity {
    uid: u32,
    idx: u32,
}

/// Indexing entity index to data array.
#[derive(Copy, Clone, PartialEq, Eq, Default, Debug, Serialize, Deserialize)]
struct Index {
    /// Must match the uid for the entity that is querying for component.
    uid: u32,
    /// Index for this entity in the data array.
    data_idx: u32,
}

/// Operations all components must support.
pub trait AnyComponent {
    /// Remove an entity's component.
    fn remove(&mut self, e: Entity);
}

/// Nonredundant component data, in separate struct for efficient serialization.
#[derive(Serialize, Deserialize)]
struct DenseComponentData<C> {
    /// Dense component data.
    data: Vec<C>,
    /// Entity idx corresponding to elements in data.
    entities: Vec<Entity>,
}

/// Storage for a single component type.
pub struct ComponentData<C> {
    inner: DenseComponentData<C>,
    /// Map entity indices to component data.
    ///
    /// This array spans all live component indices.
    entity_idx_to_data: Vec<Index>,
}

impl<C> ComponentData<C> {
    /// Construct new empty `ComponentData` instance.
    pub fn new() -> ComponentData<C> {
        ComponentData {
            inner: DenseComponentData {
                data: Vec::new(),
                entities: Vec::new(),
            },
            entity_idx_to_data: Vec::new(),
        }
    }

    /// Insert a component to an entity.
    pub fn insert(&mut self, e: Entity, comp: C) {
        debug_assert_eq!(self.inner.data.len(), self.inner.entities.len());

        if self.contains(e) {
            // Component is set for entity, replace existing component.
            self.inner.data[self.entity_idx_to_data[e.idx as usize].data_idx as usize] = comp;
        } else {
            // Grow lookup vector if needed.
            if e.idx as usize >= self.entity_idx_to_data.len() {
                self.entity_idx_to_data.resize(e.idx as usize + 1, Default::default());
            }

            // Add a new component.
            let data_idx = self.inner.data.len() as u32;
            self.inner.data.push(comp);
            self.inner.entities.push(e);
            self.entity_idx_to_data[e.idx as usize] = Index {
                uid: e.uid,
                data_idx: data_idx,
            };
        }
    }

    /// Return whether an entity contains this component.
    pub fn contains(&self, e: Entity) -> bool {
        debug_assert_ne!(e.uid, 0);

        (e.idx as usize) < self.entity_idx_to_data.len() &&
        self.entity_idx_to_data[e.idx as usize].uid == e.uid
    }

    /// Get a reference to a component only if it exists for this entity.
    pub fn get(&self, e: Entity) -> Option<&C> {
        if self.contains(e) {
            Some(&self.inner.data[self.entity_idx_to_data[e.idx as usize].data_idx as usize])
        } else {
            None
        }
    }

    /// Get a mutable reference to a component only if it exists for this entity.
    pub fn get_mut(&mut self, e: Entity) -> Option<&mut C> {
        if self.contains(e) {
            Some(&mut self.inner.data[self.entity_idx_to_data[e.idx as usize].data_idx as usize])
        } else {
            None
        }
    }

    /// Iterate entity ids in this component.
    pub fn ent_iter(&self) -> slice::Iter<Entity> {
        self.inner.entities.iter()
    }

    /// Iterate elements in this component.
    pub fn iter(&self) -> slice::Iter<C> {
        self.inner.data.iter()
    }

    /// Iterate mutable elements in this component.
    pub fn iter_mut(&mut self) -> slice::IterMut<C> {
        self.inner.data.iter_mut()
    }
}

impl<C> ops::Index<Entity> for ComponentData<C> {
    type Output = C;

    fn index(&self, e: Entity) -> &C {
        self.get(e).unwrap()
    }
}

impl<C> ops::IndexMut<Entity> for ComponentData<C> {
    fn index_mut(&mut self, e: Entity) -> &mut C {
        self.get_mut(e).unwrap()
    }
}

impl<C> AnyComponent for ComponentData<C> {
    fn remove(&mut self, e: Entity) {
        debug_assert_eq!(self.inner.data.len(), self.inner.entities.len());
        if self.contains(e) {
            let removed_index = self.entity_idx_to_data[e.idx as usize];
            self.entity_idx_to_data[e.idx as usize] = Default::default();

            // To keep the data compact, we do swap-remove with the last data item and update the
            // lookup on the moved item. If the component being removed isn't the last item in the
            // list, we need to reset the lookup value for the component that was moved.
            if removed_index.data_idx as usize != self.inner.entities.len() - 1 {
                let last_entity = self.inner.entities[self.inner.entities.len() - 1];
                self.inner.entities.swap_remove(removed_index.data_idx as usize);
                self.entity_idx_to_data[last_entity.idx as usize] = Index {
                    uid: last_entity.uid,
                    data_idx: removed_index.data_idx,
                };
            } else {
                self.inner.entities.swap_remove(removed_index.data_idx as usize);
            }

            self.inner.data.swap_remove(removed_index.data_idx as usize);
        }
    }
}

#[derive(Serialize, Deserialize)]
struct Packed<C> {
    entity_count: u32,
    data: Vec<C>,
    entities: Vec<Entity>,
}

impl<C: Serialize + Clone> serde::Serialize for ComponentData<C> {
    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        self.inner.serialize(s)
    }
}

impl<C: Deserialize> serde::Deserialize for ComponentData<C> {
    fn deserialize<D: serde::Deserializer>(d: D) -> Result<Self, D::Error> {
        let inner: DenseComponentData<C> = serde::Deserialize::deserialize(d)?;;

        // Regenerate cache.
        let mut entity_idx_to_data = Vec::new();
        for (i, e) in inner.entities.iter().enumerate() {
            if e.idx as usize >= entity_idx_to_data.len() {
                entity_idx_to_data.resize(e.idx as usize + 1, Default::default());
            }
            entity_idx_to_data[e.idx as usize] = Index {
                uid: e.uid,
                data_idx: i as u32,
            };
        }

        Ok(ComponentData {
            inner: inner,
            entity_idx_to_data: entity_idx_to_data,
        })
    }
}

/// Operations for the internal component store object.
pub trait Store {
    /// Perform an operation for each component container.
    fn for_each_component<F>(&mut self, f: F) where F: FnMut(&mut AnyComponent);
}

/// Generic entity component system container
///
/// Needs to be specified with the parametrized `Store` type that has struct fields for the actual
/// components. This can be done with the `Ecs!` macro.
#[derive(Serialize, Deserialize)]
pub struct Ecs<ST> {
    next_uid: u32,
    next_idx: u32,
    free_indices: Vec<u32>,
    active: ComponentData<bool>,
    store: ST,
}

impl<ST: Default + Store> Ecs<ST> {
    /// Construct a new entity component system.
    pub fn new() -> Ecs<ST> {
        Ecs {
            next_uid: 1,
            next_idx: 0,
            free_indices: Vec::new(),
            active: ComponentData::new(),
            store: Default::default(),
        }
    }

    /// Create a new empty entity.
    pub fn make(&mut self) -> Entity {
        let uid = self.next_uid;
        self.next_uid += 1;

        let idx = if let Some(idx) = self.free_indices.pop() {
            idx
        } else {
            self.next_idx += 1;
            self.next_idx - 1
        };

        let ret = Entity {
            uid: uid,
            idx: idx,
        };
        self.active.insert(ret, true);
        ret
    }

    /// Remove an entity from the system and clear its components.
    pub fn remove(&mut self, e: Entity) {
        self.free_indices.push(e.idx);
        self.active.remove(e);
        self.store.for_each_component(|c| c.remove(e));
    }

    /// Return whether the system contains an entity.
    pub fn contains(&self, e: Entity) -> bool {
        self.active.contains(e)
    }

    /// Iterate through all the active entities.
    pub fn iter(&self) -> slice::Iter<Entity> {
        self.active.ent_iter()
    }
}

impl<ST> ops::Deref for Ecs<ST> {
    type Target = ST;

    fn deref(&self) -> &ST {
        &self.store
    }
}

impl<ST> ops::DerefMut for Ecs<ST> {
    fn deref_mut(&mut self) -> &mut ST {
        &mut self.store
    }
}

/// Entity component system builder macro.
///
/// Defines a local `Ecs` type that's parametrized with a custom component
/// store type with the component types you specify. Will also define a trait
/// `Component` which will be implemented for the component types.
#[macro_export]
macro_rules! Ecs {
    {
        // Declare the type of the (plain old data) component and the
        // identifier to use for it in the ECS.
        $($compname:ident: $comptype:ty,)+
    } => {
        mod _ecs_inner {
            // Use the enum to convert components to numbers for component bit masks etc.
            #[allow(non_camel_case_types, dead_code)]
            pub enum ComponentNum {
                $($compname,)+
            }

        }

        pub use self::_ecs_inner::ComponentNum;

        #[derive(Serialize, Deserialize)]
        pub struct _ComponentStore {
            $(pub $compname: $crate::ComponentData<$comptype>),+
        }

        impl ::std::default::Default for _ComponentStore {
            fn default() -> _ComponentStore {
                _ComponentStore {
                    $($compname: $crate::ComponentData::new()),+
                }
            }
        }

        impl $crate::Store for _ComponentStore {
            fn for_each_component<F>(&mut self, mut f: F)
                where F: FnMut(&mut $crate::AnyComponent)
            {
                $(f(&mut self.$compname as &mut $crate::AnyComponent);)+
            }
        }

        #[allow(dead_code)]
        pub fn matches_mask(ecs: &$crate::Ecs<_ComponentStore>, e: $crate::Entity, mask: u64) -> bool {
            $(if mask & (1 << ComponentNum::$compname as u8) != 0 && !ecs.$compname.contains(e) {
                return false;
            })+
            return true;
        }

        /// Common operations for ECS component value types.
        pub trait Component {
            /// Add a clone of the component value to an entity in an ECS.
            ///
            /// Can't move the component itself since we might be using this
            /// through a trait object.
            fn add_to_ecs(&self, ecs: &mut $crate::Ecs<_ComponentStore>, e: $crate::Entity);

            /// Add a clone of the component to a loadout struct.
            fn add_to_loadout(self, loadout: &mut Loadout);
        }

        $(impl Component for $comptype {
            fn add_to_ecs(&self, ecs: &mut $crate::Ecs<_ComponentStore>, e: $crate::Entity) {
                ecs.$compname.insert(e, self.clone());
            }

            fn add_to_loadout(self, loadout: &mut Loadout) {
                loadout.$compname = Some(self);
            }
        })+

        pub type Ecs = $crate::Ecs<_ComponentStore>;

        /// A straightforward representation for the complete data of an
        /// entity.
        #[derive(Clone, Debug, Serialize, Deserialize)]
        pub struct Loadout {
            $(pub $compname: Option<$comptype>),+
        }

        impl ::std::default::Default for Loadout {
            fn default() -> Loadout {
                Loadout {
                    $($compname: None),+
                }
            }
        }

        #[allow(dead_code)]
        impl Loadout {
            /// Create a new blank loadout.
            pub fn new() -> Loadout { Default::default() }

            /// Get the loadout that corresponds to an existing entity.
            pub fn get(ecs: &Ecs, e: $crate::Entity) -> Loadout {
                Loadout {
                    $($compname: ecs.$compname.get(e).cloned()),+
                }
            }

            /// Create a new entity in the ECS with this loadout.
            pub fn make(&self, ecs: &mut Ecs) -> $crate::Entity {
                let e = ecs.make();
                $(self.$compname.as_ref().map(|c| ecs.$compname.insert(e, c.clone()));)+
                e
            }

            /// Builder method for adding a component to this loadout.
            pub fn c<C: Component>(mut self, comp: C) -> Loadout {
                comp.add_to_loadout(&mut self);
                self
            }
        }
    }
}

/// Build a component type mask to match component iteration with.
///
/// You must have `ComponentNum` enum from the Ecs! macro expansion in scope
/// when using this.
#[macro_export]
macro_rules! build_mask {
    ( $($compname:ident),+ ) => {
        0u64 $(| (1u64 << ComponentNum::$compname as u8))+
    }
}
<|endoftext|>


<commit_before>// DOCS

extern crate tempdir;

use std::error::Error as ErrorTrait;
use std::fmt;
use std::io;
use std::fs;
use std::borrow::Borrow;
use std::path;
use std::convert::AsRef;

use tempdir::TempDir;

pub use OverwriteBehavior::{AllowOverwrite, DisallowOverwrite};

#[derive(Clone,Copy)]
pub enum OverwriteBehavior {
    /// Overwrite files silently.
    AllowOverwrite,

    /// Don't overwrite files. `AtomicFile.write` will raise errors for such conditions only after
    /// you've already written your data.
    DisallowOverwrite
}

/// Represents an error raised by `AtomicFile.write`.
#[derive(Debug)]
pub enum Error<E> {
    /// The error originated in the library itself, while it was either creating a temporary file
    /// or moving the file into place.
    Internal(io::Error),
    /// The error originated in the user-supplied callback.
    User(E)
}

impl From<Error<io::Error>> for io::Error {
    fn from(e: Error<io::Error>) -> Self {
        match e {
            Error::Internal(x) => x,
            Error::User(x) => x
        }
    }
}

impl<E: fmt::Display> fmt::Display for Error<E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Internal(ref e) => e.fmt(f),
            Error::User(ref e) => e.fmt(f)
        }
    }
}

impl<E: ErrorTrait> ErrorTrait for Error<E> {
    fn description(&self) -> &str {
        match *self {
            Error::Internal(ref e) => e.description(),
            Error::User(ref e) => e.description()
        }
    }

    fn cause(&self) -> Option<&ErrorTrait> {
        match *self {
            Error::Internal(ref e) => Some(e),
            Error::User(ref e) => Some(e)
        }
    }
}

fn safe_parent(p: &path::Path) -> Option<&path::Path> {
    match p.parent() {
        None => None,
        Some(x) if x.as_os_str().len() == 0 => Some(&path::Path::new(".")),
        x => x
    }
}

pub struct AtomicFile {
    path: path::PathBuf,
    overwrite: OverwriteBehavior,
    tmpdir: path::PathBuf
}

impl AtomicFile {
    /// Helper for writing to `path` in write-only mode.
    ///
    /// If `DisallowOverwrite` is given, errors will be returned from `self.write(...)` if the file
    /// exists.
    pub fn new<P: AsRef<path::Path>>(path: P, overwrite: OverwriteBehavior) -> Self {
        let p = path.as_ref();
        AtomicFile::new_with_tmpdir(p, overwrite, safe_parent(p).unwrap_or(path::Path::new(".")))
    }

    pub fn new_with_tmpdir<P: AsRef<path::Path>>(path: P, overwrite: OverwriteBehavior, tmpdir: P) -> Self {
        AtomicFile {
            path: path.as_ref().to_path_buf(),
            overwrite: overwrite,
            tmpdir: tmpdir.as_ref().to_path_buf()
        }
    }

    fn commit(&self, tmppath: &path::Path) -> io::Result<()> {
        match self.overwrite {
            AllowOverwrite => replace_atomic(tmppath, self.path()),
            DisallowOverwrite => move_atomic(tmppath, self.path())
        }
    }

    /// Get the target filepath.
    pub fn path(&self) -> &path::Path { &self.path.borrow() }

    /// Open a temporary file, call `f` on it (which is supposed to write to it), then move the
    /// file atomically to `self.path`.
    pub fn write<T, E, F>(&self, f: F) -> Result<T, Error<E>> where
        F: FnOnce(&mut fs::File) -> Result<T, E>
    {
        let tmpdir = try!(TempDir::new_in(
            &self.tmpdir,
            ".atomicwrite"
        ).map_err(Error::Internal));

        let tmppath = tmpdir.path().join("tmpfile.tmp");
        let rv = {
            let mut tmpfile = try!(fs::File::create(&tmppath).map_err(Error::Internal));
            try!(f(&mut tmpfile).map_err(Error::User))
        };
        try!(self.commit(&tmppath).map_err(Error::Internal));
        Ok(rv)
    }
}

#[cfg(unix)]
mod imp {
    extern crate nix;

    use super::safe_parent;

    use std::{io,fs,path};
    use std::os::unix::io::AsRawFd;

    fn fsync<T: AsRawFd>(f: T) -> io::Result<()> {
        match nix::unistd::fsync(f.as_raw_fd()) {
            Ok(()) => Ok(()),
            Err(nix::Error::Sys(errno)) => Err(errno.into()),
            Err(nix::Error::InvalidPath) => Err(io::Error::new(io::ErrorKind::Other, "invalid path")),
            Err(nix::Error::InvalidUtf8) => Err(io::Error::new(io::ErrorKind::Other, "invalid utf-8")),
            Err(nix::Error::UnsupportedOperation) => Err(io::Error::new(io::ErrorKind::Other, "unsupported operation"))
        }
    }

    fn fsync_dir(x: &path::Path) -> io::Result<()> {
        let f = try!(fs::File::open(x));
        try!(fsync(f));
        Ok(())
    }

    pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        try!(fs::rename(src, dst));

        let dst_directory = safe_parent(dst).unwrap();
        try!(fsync_dir(dst_directory));
        Ok(())
    }

    pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        try!(fs::hard_link(src, dst));
        try!(fs::remove_file(src));

        let src_directory = safe_parent(src).unwrap();
        let dst_directory = safe_parent(dst).unwrap();
        try!(fsync_dir(dst_directory));
        if src_directory != dst_directory { try!(fsync_dir(src_directory)); }
        Ok(())
    }
}

#[cfg(windows)]
mod imp {
    extern crate winapi;

    use std::{io,path};
    use std::ffi::OsStr;
    use std::os::windows::ffi::OsStrExt;

    macro_rules! call {
        ($e: expr) => (
            if $e != 0 {
                Ok(())
            } else {
                Err(io::Error::last_os_error())
            }
        )
    }

    fn path_to_windows_str<T: AsRef<OsStr>>(x: T) -> Vec<winapi::shared::ntdef::WCHAR> {
        x.as_ref().encode_wide().chain(Some(0)).collect()
    }

    pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        call!(unsafe {winapi::um::winbase::MoveFileExW(
            path_to_windows_str(src).as_ptr(), path_to_windows_str(dst).as_ptr(),
            winapi::um::winbase::MOVEFILE_WRITE_THROUGH | winapi::um::winbase::MOVEFILE_REPLACE_EXISTING
        )})
    }

    pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        call!(unsafe {winapi::um::winbase::MoveFileExW(
            path_to_windows_str(src).as_ptr(), path_to_windows_str(dst).as_ptr(),
            winapi::um::winbase::MOVEFILE_WRITE_THROUGH
        )})
    }
}

/// Move `src` to `dst`. If `dst` exists, it will be silently overwritten.
///
/// Both paths must reside on the same filesystem for the operation to be atomic.
pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    imp::replace_atomic(src, dst)
}

/// Move `src` to `dst`. An error will be returned if `dst` exists.
///
/// Both paths must reside on the same filesystem for the operation to be atomic.
pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    imp::move_atomic(src, dst)
}
<commit_msg>Replace some trait bounds to be less restrictive (#25)<commit_after>// DOCS

extern crate tempdir;

use std::error::Error as ErrorTrait;
use std::fmt;
use std::io;
use std::fs;
use std::borrow::Borrow;
use std::path;
use std::convert::AsRef;

use tempdir::TempDir;

pub use OverwriteBehavior::{AllowOverwrite, DisallowOverwrite};

#[derive(Clone,Copy)]
pub enum OverwriteBehavior {
    /// Overwrite files silently.
    AllowOverwrite,

    /// Don't overwrite files. `AtomicFile.write` will raise errors for such conditions only after
    /// you've already written your data.
    DisallowOverwrite
}

/// Represents an error raised by `AtomicFile.write`.
#[derive(Debug)]
pub enum Error<E> {
    /// The error originated in the library itself, while it was either creating a temporary file
    /// or moving the file into place.
    Internal(io::Error),
    /// The error originated in the user-supplied callback.
    User(E)
}

impl From<Error<io::Error>> for io::Error {
    fn from(e: Error<io::Error>) -> Self {
        match e {
            Error::Internal(x) => x,
            Error::User(x) => x
        }
    }
}

impl<E: fmt::Display> fmt::Display for Error<E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Internal(ref e) => e.fmt(f),
            Error::User(ref e) => e.fmt(f)
        }
    }
}

impl<E: ErrorTrait> ErrorTrait for Error<E> {
    fn description(&self) -> &str {
        match *self {
            Error::Internal(ref e) => e.description(),
            Error::User(ref e) => e.description()
        }
    }

    fn cause(&self) -> Option<&ErrorTrait> {
        match *self {
            Error::Internal(ref e) => Some(e),
            Error::User(ref e) => Some(e)
        }
    }
}

fn safe_parent(p: &path::Path) -> Option<&path::Path> {
    match p.parent() {
        None => None,
        Some(x) if x.as_os_str().len() == 0 => Some(&path::Path::new(".")),
        x => x
    }
}

pub struct AtomicFile {
    path: path::PathBuf,
    overwrite: OverwriteBehavior,
    tmpdir: path::PathBuf
}

impl AtomicFile {
    /// Helper for writing to `path` in write-only mode.
    ///
    /// If `DisallowOverwrite` is given, errors will be returned from `self.write(...)` if the file
    /// exists.
    pub fn new<P>(path: P, overwrite: OverwriteBehavior) -> Self
    where P: AsRef<path::Path>
    {
        let p = path.as_ref();
        AtomicFile::new_with_tmpdir(p, overwrite, safe_parent(p).unwrap_or(path::Path::new(".")))
    }

    pub fn new_with_tmpdir<P, Q>(path: P, overwrite: OverwriteBehavior, tmpdir: Q) -> Self
    where P: AsRef<path::Path>,
          Q: AsRef<path::Path>
    {
        AtomicFile {
            path: path.as_ref().to_path_buf(),
            overwrite: overwrite,
            tmpdir: tmpdir.as_ref().to_path_buf()
        }
    }

    fn commit(&self, tmppath: &path::Path) -> io::Result<()> {
        match self.overwrite {
            AllowOverwrite => replace_atomic(tmppath, self.path()),
            DisallowOverwrite => move_atomic(tmppath, self.path())
        }
    }

    /// Get the target filepath.
    pub fn path(&self) -> &path::Path { &self.path.borrow() }

    /// Open a temporary file, call `f` on it (which is supposed to write to it), then move the
    /// file atomically to `self.path`.
    pub fn write<T, E, F>(&self, f: F) -> Result<T, Error<E>>
    where F: FnOnce(&mut fs::File) -> Result<T, E>
    {
        let tmpdir = try!(TempDir::new_in(
            &self.tmpdir,
            ".atomicwrite"
        ).map_err(Error::Internal));

        let tmppath = tmpdir.path().join("tmpfile.tmp");
        let rv = {
            let mut tmpfile = try!(fs::File::create(&tmppath).map_err(Error::Internal));
            try!(f(&mut tmpfile).map_err(Error::User))
        };
        try!(self.commit(&tmppath).map_err(Error::Internal));
        Ok(rv)
    }
}

#[cfg(unix)]
mod imp {
    extern crate nix;

    use super::safe_parent;

    use std::{io,fs,path};
    use std::os::unix::io::AsRawFd;

    fn fsync<T: AsRawFd>(f: T) -> io::Result<()> {
        match nix::unistd::fsync(f.as_raw_fd()) {
            Ok(()) => Ok(()),
            Err(nix::Error::Sys(errno)) => Err(errno.into()),
            Err(nix::Error::InvalidPath) => Err(io::Error::new(io::ErrorKind::Other, "invalid path")),
            Err(nix::Error::InvalidUtf8) => Err(io::Error::new(io::ErrorKind::Other, "invalid utf-8")),
            Err(nix::Error::UnsupportedOperation) => Err(io::Error::new(io::ErrorKind::Other, "unsupported operation"))
        }
    }

    fn fsync_dir(x: &path::Path) -> io::Result<()> {
        let f = try!(fs::File::open(x));
        try!(fsync(f));
        Ok(())
    }

    pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        try!(fs::rename(src, dst));

        let dst_directory = safe_parent(dst).unwrap();
        try!(fsync_dir(dst_directory));
        Ok(())
    }

    pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        try!(fs::hard_link(src, dst));
        try!(fs::remove_file(src));

        let src_directory = safe_parent(src).unwrap();
        let dst_directory = safe_parent(dst).unwrap();
        try!(fsync_dir(dst_directory));
        if src_directory != dst_directory { try!(fsync_dir(src_directory)); }
        Ok(())
    }
}

#[cfg(windows)]
mod imp {
    extern crate winapi;

    use std::{io,path};
    use std::ffi::OsStr;
    use std::os::windows::ffi::OsStrExt;

    macro_rules! call {
        ($e: expr) => (
            if $e != 0 {
                Ok(())
            } else {
                Err(io::Error::last_os_error())
            }
        )
    }

    fn path_to_windows_str<T: AsRef<OsStr>>(x: T) -> Vec<winapi::shared::ntdef::WCHAR> {
        x.as_ref().encode_wide().chain(Some(0)).collect()
    }

    pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        call!(unsafe {winapi::um::winbase::MoveFileExW(
            path_to_windows_str(src).as_ptr(), path_to_windows_str(dst).as_ptr(),
            winapi::um::winbase::MOVEFILE_WRITE_THROUGH | winapi::um::winbase::MOVEFILE_REPLACE_EXISTING
        )})
    }

    pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
        call!(unsafe {winapi::um::winbase::MoveFileExW(
            path_to_windows_str(src).as_ptr(), path_to_windows_str(dst).as_ptr(),
            winapi::um::winbase::MOVEFILE_WRITE_THROUGH
        )})
    }
}

/// Move `src` to `dst`. If `dst` exists, it will be silently overwritten.
///
/// Both paths must reside on the same filesystem for the operation to be atomic.
pub fn replace_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    imp::replace_atomic(src, dst)
}

/// Move `src` to `dst`. An error will be returned if `dst` exists.
///
/// Both paths must reside on the same filesystem for the operation to be atomic.
pub fn move_atomic(src: &path::Path, dst: &path::Path) -> io::Result<()> {
    imp::move_atomic(src, dst)
}
<|endoftext|>


<commit_before>//! Leaf is a open, fast and a well-designed, modular Framework for distributed
//! Deep Learning on {C, G}PUs.
//!
//! ## Overview
//!
//! To build a Deep Neural Network you create a [Network][network] which is a
//! container for all different types of [Layers][layers].
//! These layers are grouped in different types such as
//! [Activation Layers][activation] and [Loss Layers][loss] which states the
//! characteristics of the layer.
//!
//! Now to train your network you will use one of the [Solvers][solvers].
//! The Solver defines the [Optimization Method][optimization]
//! and keeps track on the learning progress.
//!
//! The operations can run on different Backends {CPU, GPU} and must not be
//! defined at compile time, which allows for easy backend swapping.
//!
//! ## Philosophy
//!
//! We are strong believers in the technology of Machine Learning.
//! We put our experience in
//! software engineering into Leaf, to solve our own need for a modern,
//! performant and easy-to-use Deep Learning Framework.
//! These principles direct our decisions on Leaf and related projects.
//!
//! * __Cutting Edge Performance__:

//! For research and industry speed and efficency are curcial for
//! state-of-the-art machine learning over massive data and networks.
//! * __Open and Expressive Architecture__:

//! Designing an open architecture that follows best practices and concepts in
//! Engineering such as modularity, flexibility and expressiveness is critical
//! to stimulate future innovation.
//! * __Clear and Transparent Documentation__:

//! A well-written documentation that addresses both concepts and
//! implementations, empowers developers and researchers to contribute their
//! unique experience to the project for the benefit of everyone.
//!
//! ## Examples
//!
//! ```
//! # extern crate leaf;
//! # use leaf::network::{NetworkConfig};
//! # fn main() {
//! # }
//! ```
//!
//! ## Development
//!
//! The implementation of various Layers is pretty scarce at the moment.

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

//! Progress is tracked at

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

#[macro_use]
extern crate log;
extern crate rblas;
extern crate phloem;
pub mod shared_memory;
mod math;
pub mod layer;
pub mod layers;
pub mod solver;
pub mod solvers;
pub mod network;
<commit_msg>docs/core: Fix Grammar in Main Crate Documentation<commit_after>//! Leaf is a open, fast and a well-designed, modular Framework for distributed
//! Deep Learning on {C, G}PUs.
//!
//! ## Overview
//!
//! To build a Deep Neural Network you first need to create a
//! [Network][network] which is a container for all different types of
//! [Layers][layers]. These layers are grouped in different types such as
//! [Activation Layers][activation] and [Loss Layers][loss] (these state the
//! characteristics of the layer).
//!
//! Now to train your network you can use one of the [Solvers][solvers]. The
//! Solver defines the [Optimization Method][optimization] and keeps track on
//! the learning progress.
//!
//! The operations can run on different Backends {CPU, GPU} and doesn't have
//! to be defined at compile time, which allows for easy backend swapping.
//!
//! ## Philosophy
//!
//! We are strong believers in the technology of Machine Learning.
//!
//! We put our experience in software engineering into Leaf, to solve our own
//! need for a modern, performant and easy-to-use Deep Learning Framework.
//! These principles direct our decisions on Leaf and related projects.
//!
//! * __Cutting Edge Performance__:

//! For research and industry speed and efficency are curcial for
//! state-of-the-art machine learning over massive data and networks.
//! * __Open and Expressive Architecture__:

//! Designing an open architecture that follows best practices and concepts in
//! Engineering such as modularity, flexibility and expressiveness is critical
//! to stimulate future innovation.
//! * __Clear and Transparent Documentation__:

//! A well-written documentation that addresses both concepts and
//! implementations, empowers developers and researchers to contribute their
//! unique experience to the project for the benefit of everyone.
//!
//! ## Examples
//!
//! ```
//! # extern crate leaf;
//! # use leaf::network::{NetworkConfig};
//! # fn main() {
//! # }
//! ```
//!
//! ## Development
//!
//! The implementation of various Layers is pretty scarce at the moment.

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

//! Progress is tracked at

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

#[macro_use]
extern crate log;
extern crate rblas;
extern crate phloem;
pub mod shared_memory;
mod math;
pub mod layer;
pub mod layers;
pub mod solver;
pub mod solvers;
pub mod network;
<|endoftext|>


<commit_before>//! Struct and methods for union-find operation.

#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

use std::{iter, mem};

#[derive(Clone, Show)]
enum UFNode {
    Key(uint),
    Size(uint)
}

/// Struct for union-find operation.
#[derive(Clone, Show)]
pub struct UnionFind {
    data: Vec<UFNode>
}

impl UnionFind {
    /// Creates empty `UnionFind` struct.
    #[inline]
    pub fn new(len: uint) -> UnionFind {
        UnionFind { data: iter::repeat(UFNode::Size(1)).take(len).collect() }
    }

    /// Join two sets that contains given keys (Union operation).
    ///
    /// Returns `true` if these keys are belonged to different sets.
    pub fn union(&mut self, key1: uint, key2: uint) -> bool {
        let (key1, size1) = self.get_key_size(key1);
        let (key2, size2) = self.get_key_size(key2);
        if key1 == key2 { return false; }

        let mut key1 = key1; let mut size1 = size1;
        let mut key2 = key2; let mut size2 = size2;

        if size1 < size2 {
            mem::swap(&mut key1, &mut key2);
            mem::swap(&mut size1, &mut size2);
        }

        self.data[key1] = UFNode::Size(size1 + size2);
        self.data[key2] = UFNode::Key(key1);

        return true;
    }

    /// Returns `true` if two keys contained by the same set (find operation).
    #[inline]
    pub fn find(&mut self, key1: uint, key2: uint) -> bool {
        return self.get_key(key1) == self.get_key(key2);
    }

    /// Returns the number of the elements that belongs to the same set with key.
    #[inline]
    pub fn get_size(&mut self, key: uint) -> uint {
        self.get_key_size(key).1
    }

    fn get_key(&mut self, key: uint) -> uint {
        self.get_key_size(key).0
    }

    fn get_key_size(&mut self, key: uint) -> (uint, uint) {
        let (root_key, size) = match self.data[key] {
            UFNode::Size(size) => { return (key, size); }
            UFNode::Key(key) => self.get_key_size(key)
        };
        self.data[key] = UFNode::Key(root_key);
        return (root_key, size);
    }
}

#[test]
fn test_union_find() {
    let mut uf = UnionFind::new(100);
    assert_eq!(uf.get_size(0), 1);
    assert_eq!(uf.get_size(1), 1);
    assert!(!uf.find(0, 1));
    assert!(!uf.find(1, 2));
    assert!(uf.union(0, 1));
    assert!(uf.find(0, 1));
    assert_eq!(uf.get_size(0), 2);
    assert_eq!(uf.get_size(1), 2);
    assert_eq!(uf.get_size(2), 1);
    assert!(!uf.union(0, 1));
    assert_eq!(uf.get_size(0), 2);
    assert_eq!(uf.get_size(1), 2);
    assert_eq!(uf.get_size(2), 1);
    assert!(uf.union(1, 2));
    assert_eq!(uf.get_size(0), 3);
    assert_eq!(uf.get_size(1), 3);
    assert_eq!(uf.get_size(2), 3);
    assert!(uf.find(0, 1));
    assert!(uf.find(2, 1));
}
<commit_msg>fix compiler warnings<commit_after>//! Struct and methods for union-find operation.

#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

use std::{iter, mem};

#[derive(Clone, Show)]
enum UFNode {
    Key(usize),
    Size(usize)
}

/// Struct for union-find operation.
#[derive(Clone, Show)]
pub struct UnionFind {
    data: Vec<UFNode>
}

impl UnionFind {
    /// Creates empty `UnionFind` struct.
    #[inline]
    pub fn new(len: usize) -> UnionFind {
        UnionFind { data: iter::repeat(UFNode::Size(1)).take(len).collect() }
    }

    /// Join two sets that contains given keys (Union operation).
    ///
    /// Returns `true` if these keys are belonged to different sets.
    pub fn union(&mut self, key1: usize, key2: usize) -> bool {
        let (key1, size1) = self.get_key_size(key1);
        let (key2, size2) = self.get_key_size(key2);
        if key1 == key2 { return false; }

        let mut key1 = key1; let mut size1 = size1;
        let mut key2 = key2; let mut size2 = size2;

        if size1 < size2 {
            mem::swap(&mut key1, &mut key2);
            mem::swap(&mut size1, &mut size2);
        }

        self.data[key1] = UFNode::Size(size1 + size2);
        self.data[key2] = UFNode::Key(key1);

        return true;
    }

    /// Returns `true` if two keys contained by the same set (find operation).
    #[inline]
    pub fn find(&mut self, key1: usize, key2: usize) -> bool {
        return self.get_key(key1) == self.get_key(key2);
    }

    /// Returns the number of the elements that belongs to the same set with key.
    #[inline]
    pub fn get_size(&mut self, key: usize) -> usize {
        self.get_key_size(key).1
    }

    fn get_key(&mut self, key: usize) -> usize {
        self.get_key_size(key).0
    }

    fn get_key_size(&mut self, key: usize) -> (usize, usize) {
        let (root_key, size) = match self.data[key] {
            UFNode::Size(size) => { return (key, size); }
            UFNode::Key(key) => self.get_key_size(key)
        };
        self.data[key] = UFNode::Key(root_key);
        return (root_key, size);
    }
}

#[test]
fn test_union_find() {
    let mut uf = UnionFind::new(100);
    assert_eq!(uf.get_size(0), 1);
    assert_eq!(uf.get_size(1), 1);
    assert!(!uf.find(0, 1));
    assert!(!uf.find(1, 2));
    assert!(uf.union(0, 1));
    assert!(uf.find(0, 1));
    assert_eq!(uf.get_size(0), 2);
    assert_eq!(uf.get_size(1), 2);
    assert_eq!(uf.get_size(2), 1);
    assert!(!uf.union(0, 1));
    assert_eq!(uf.get_size(0), 2);
    assert_eq!(uf.get_size(1), 2);
    assert_eq!(uf.get_size(2), 1);
    assert!(uf.union(1, 2));
    assert_eq!(uf.get_size(0), 3);
    assert_eq!(uf.get_size(1), 3);
    assert_eq!(uf.get_size(2), 3);
    assert!(uf.find(0, 1));
    assert!(uf.find(2, 1));
}
<|endoftext|>


<commit_before>// Copyright (C) 2016  ParadoxSpiral
//
// This file is part of mpv-rs.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#![deny(missing_docs)]
#![allow(unknown_lints)]
#![feature(pub_restricted, const_fn, stmt_expr_attributes, untagged_unions)]

//! This crate provides abstractions for (libmpv)[https://github.com/mpv-player/mpv/tree/master/libmpv] of the (mpv media player)[https://github.com/mpv-player/mpv].
//!
//! Libmpv requires `LC_NUMERIC` to be `C`. This is set once when the first parent is created.
//! Do not change this during the usage of this crate.
//!
//! # Examples
//!
//! See the 'examples' directory in the crate root.

extern crate libc;
extern crate parking_lot;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate enum_primitive;

/// Contains bindings to libmpv functions and data structures.
pub mod raw;
pub use raw::MpvLogLevel as LogLevel;
pub use raw::MpvError;
mod wrapper;
pub use wrapper::*;
#[cfg(test)]
mod tests;

#[allow(missing_docs)]
pub const MPV_CLIENT_API_MAJOR: u32 = 1;
#[allow(missing_docs)]
pub const MPV_CLIENT_API_MINOR: u32 = 23;
#[allow(missing_docs)]
pub const MPV_CLIENT_API_VERSION: u32 = mpv_make_version(MPV_CLIENT_API_MAJOR,
                                                         MPV_CLIENT_API_MINOR);
const fn mpv_make_version(major: u32, minor: u32) -> u32 {
    major << 16 | minor
}

#[all(feature="embed_libmpv", windows)]
// env var set in build script
pub const LIBMPV_DLL: &'static str = include_str!(env!("LIBMPV_LOCATION"));

#[all(feature="embed_libmpv", unix)]
// env var set in build script
pub const LIBMPV_A: &'static str = include_str!(env!("LIBMPV_LOCATION"));
<commit_msg>[build] add fn to write libmpv to file, partially fix attributes of libmpv consts<commit_after>// Copyright (C) 2016  ParadoxSpiral
//
// This file is part of mpv-rs.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#![deny(missing_docs)]
#![allow(unknown_lints)]
#![feature(pub_restricted, const_fn, stmt_expr_attributes, untagged_unions)]

//! This crate provides abstractions for (libmpv)[https://github.com/mpv-player/mpv/tree/master/libmpv] of the (mpv media player)[https://github.com/mpv-player/mpv].
//!
//! Libmpv requires `LC_NUMERIC` to be `C`. This is set once when the first parent is created.
//! Do not change this during the usage of this crate.
//!
//! # Examples
//!
//! See the 'examples' directory in the crate root.

extern crate libc;
extern crate parking_lot;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate enum_primitive;

/// Contains bindings to libmpv functions and data structures.
pub mod raw;
pub use raw::MpvLogLevel as LogLevel;
pub use raw::MpvError;
mod wrapper;
pub use wrapper::*;
#[cfg(test)]
mod tests;

#[allow(missing_docs)]
pub const MPV_CLIENT_API_MAJOR: u32 = 1;
#[allow(missing_docs)]
pub const MPV_CLIENT_API_MINOR: u32 = 23;
#[allow(missing_docs)]
pub const MPV_CLIENT_API_VERSION: u32 = mpv_make_version(MPV_CLIENT_API_MAJOR,
                                                         MPV_CLIENT_API_MINOR);
const fn mpv_make_version(major: u32, minor: u32) -> u32 {
    major << 16 | minor
}

#[all(feature="embed_libmpv", windows)]
#[cfg_attr(all(feature="embed_libmpv", windows), allow(missing_docs))]
// env var set in build script
pub const LIBMPV_DLL: &'static str = include_str!(env!("LIBMPV_LOCATION"));

#[all(feature="embed_libmpv", unix)]
#[cfg_attr(all(feature="embed_libmpv", unix), allow(missing_docs))]
pub const LIBMPV_A: &'static str = include_str!(env!("LIBMPV_LOCATION"));

#[cfg(feature="embed_libmpv")]
/// Note that the file has to be in a format the platform will recognize,
/// e.g. `mpv-1.dll` on windows and `libmpv.a` on unix.
pub fn write_libmpv_to_file(path: ::std::path::Path) -> Result<(), ::std::io::Error> {
	use std::io::prelude::*;

	let file = try!(File::create(path));
	#[windows] {
		try!(file.write_all(LIBMPV_DLL));
	}
	#[unix] {
		try!(file.write_all(LIBMPV_A));
	}
	Ok(())
}
<|endoftext|>


<commit_before>#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Param {
    Short(char),
    Long(String),
}

use std::borrow::Borrow;

impl Borrow<str> for Param {
    fn borrow(&self) -> &str {
        if let Param::Long(ref string) = *self {
            string
        } else {
            ""
        }
    }
}

impl Borrow<char> for Param {
    fn borrow(&self) -> &char {
        if let Param::Short(ref ch) = *self {
            ch
        } else {
            const CH: &'static char = &'\0';
            CH
        }
    }
}

use std::hash::{Hash,Hasher};

impl Hash for Param {
    fn hash<H: Hasher>(&self, state: &mut H) {
        match *self {
            Param::Short(ref c) => c.hash(state),
            Param::Long(ref s) => s.hash(state)
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
enum Value {
    Flag(bool),
    Opt(Option<String>),
}

use std::collections::HashMap;

/// Our homebrewed Arg Parser
#[derive(Clone, Debug, Default)]
pub struct ArgParser {
    params: HashMap<Param, Value>,
    invalid: Vec<Param>,
    pub args: Vec<String>,
}

impl ArgParser {
    /// Create a new ArgParser object
    ///
    /// The capacity specifies the initial capacity of the number parameters.
    /// Always good to set it at the number of flags and opts total.
    pub fn new(capacity: usize) -> Self {
        ArgParser {
            params: HashMap::with_capacity(capacity),
            invalid: Vec::new(),
            args: Vec::new(),
        }
    }

    /// Builder method for adding both short and long flags
    ///
    /// Flags are just parameters that have no assigned values. They are used
    /// for when certain features or options have been enabled for the application
    ///
    /// For example
    /// > ls -l --human-readable
    ///   ^  ^  ^
    ///   |  |  |
    ///   |  |  `-- A long flag to enable human readable numbers.
    ///   |  `-- A short flag to enable the long format.
    ///   `-- The command to list files.
    pub fn add_flag(mut self, short: &str, long: &str) -> Self {
        if let Some(short) = short.chars().next() {
            self.params.insert(Param::Short(short), Value::Flag(false));
        }
        if !long.is_empty() {
            self.params.insert(Param::Long(long.to_owned()), Value::Flag(false));
        }
        self
    }

    /// Builder method for adding both short and long opts
    ///
    /// Opts are parameters that hold assigned values. They are used
    /// for when certain features or options have been enabled for the application
    ///
    /// For example
    /// > ls -T 4 --color=always
    ///   ^  ^    ^
    ///   |  |    |
    ///   |  |    `-- A long opt to enable the use of color with value `always`.
    ///   |  `-- A short opt to set tab size to the value `4`.
    ///   `-- The command to list files.
    pub fn add_opt(mut self, short: &str, long: &str) -> Self {
        if let Some(short) = short.chars().next() {
            self.params.insert(Param::Short(short), Value::Opt(None));
        }
        if !long.is_empty() {
            self.params.insert(Param::Long(long.to_owned()), Value::Opt(None));
        }
        self
    }

    /// Start parsing user inputted args for which flags and opts are used at
    /// runtime. The rest of the args that are not associated to opts get added
    /// to `ArgParser.args`.
    pub fn initialize<A: Iterator<Item=String>>(&mut self, args: A) {
        let mut args = args.skip(1);
        while let Some(arg) = args.next() {
            if arg.starts_with("--") {
                // Remove both dashes
                let arg = &arg[2..];
                if let Some(i) = arg.find('=') {
                    let (lhs, rhs) = arg.split_at(i);
                    match self.params.get_mut(lhs) {
                        // slice off the `=` char
                        Some(&mut Value::Opt(ref mut value)) => *value = Some(rhs[1..].to_owned()),
                        _ => self.invalid.push(Param::Long(lhs.to_owned())),
                    }
                }
                else {
                    match self.params.get_mut(arg) {
                        Some(&mut Value::Flag(ref mut switch)) => *switch = true,
                        _ => self.invalid.push(Param::Long(arg.to_owned())),
                    }
                }
            }
            else if arg.starts_with("-") {
                let mut chars = arg[1..].chars();
                while let Some(ch) = chars.next() {
                    match self.params.get_mut(&ch) {
                        Some(&mut Value::Flag(ref mut switch)) => *switch = true,
                        Some(&mut Value::Opt(ref mut value)) => {
                            let rest: String = chars.collect();
                            if rest.len() > 0 {
                                *value = Some(rest);
                            } else {
                                *value = args.next()
                            }
                            break;
                        },
                        None => self.invalid.push(Param::Short(ch)),
                    }
                }
            }
            else {
                self.args.push(arg);
            }
        }
    }

    /// Check if a Flag or Opt has been found after initialization.
    pub fn flagged
(&self, name: &P) -> bool
        where Param: Borrow

    {
        match self.params.get(name) {
            Some(&Value::Flag(switch)) => switch,
            Some(&Value::Opt(Some(_))) => true,
            _ => false,
        }
    }

    /// Modify the state of a flag. Use `true` if the flag is to be enabled. Use `false` to
    /// disable its use.
    pub fn set_flag<F: Hash + Eq + ?Sized>(&mut self, flag: &F, state: bool)
        where Param: Borrow<F>
    {
        if let Some(&mut Value::Flag(ref mut switch)) = self.params.get_mut(flag) {
            *switch = state;
        }
    }

    /// Modify the state value of an opt. Use `Some(String)` to set if the opt is to be enabled and
    /// has been assigned a value from `String`. Use `None` to disable the opt's use.
    pub fn set_opt<O: Hash + Eq + ?Sized>(&mut self, opt: &O, state: Option<String>)
        where Param: Borrow<O>
    {
        if let Some(&mut Value::Opt(ref mut value)) = self.params.get_mut(opt) {
            *value = state;
        }
    }

    /// Get the state of an Opt. If it has been enabled, it will return a `Some(String)` value
    /// otherwise it will return None.
    pub fn get_opt<O: Hash + Eq + ?Sized>(&self, opt: &O) -> Option<String>
        where Param: Borrow<O>
    {
        if let Some(&Value::Opt(ref value)) = self.params.get(opt) {
            return value.clone();
        }
        None
    }

    pub fn flagged_invalid(&self) -> Result<(), String> {
        if self.invalid.is_empty() {
            return Ok(());
        }

        let mut and: bool = false;
        let mut output =
            if self.invalid.len() == 1 {
                "Invalid parameter"
            } else {
                and = true;
                "Invalid parameters"
            }.to_owned();

        let mut iter = self.invalid.iter().peekable();
        while let Some(param) = iter.next() {
            match param {
                &Param::Short(ch) => {
                    output += " '-";
                    output.push(ch);
                    output.push('\'');
                }
                &Param::Long(ref s) => {
                    output += " '--";
                    output += s;
                    output.push('\'');
                }
            }
            if and && iter.peek().is_some() {
                output += " and"
            }
        }
        output.push('\n');
        Err(output)
    }
}

pub fn to_human_readable_string(size: u64) -> String {
    if size < 1024 {
        return format!("{}", size);
    }

    static UNITS: [&'static str; 7] = ["", "K", "M", "G", "T", "P", "E"];

    let sizef = size as f64;
    let digit_groups = (sizef.log10() / 1024f64.log10()) as i32;
    format!("{:.1}{}",
            sizef / 1024f64.powf(digit_groups as f64),
            UNITS[digit_groups as usize])
}
<commit_msg>Implement `--` which stops parsing<commit_after>#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Param {
    Short(char),
    Long(String),
}

use std::borrow::Borrow;

impl Borrow<str> for Param {
    fn borrow(&self) -> &str {
        if let Param::Long(ref string) = *self {
            string
        } else {
            ""
        }
    }
}

impl Borrow<char> for Param {
    fn borrow(&self) -> &char {
        if let Param::Short(ref ch) = *self {
            ch
        } else {
            const CH: &'static char = &'\0';
            CH
        }
    }
}

use std::hash::{Hash,Hasher};

impl Hash for Param {
    fn hash<H: Hasher>(&self, state: &mut H) {
        match *self {
            Param::Short(ref c) => c.hash(state),
            Param::Long(ref s) => s.hash(state)
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
enum Value {
    Flag(bool),
    Opt(Option<String>),
}

use std::collections::HashMap;

/// Our homebrewed Arg Parser
#[derive(Clone, Debug, Default)]
pub struct ArgParser {
    params: HashMap<Param, Value>,
    invalid: Vec<Param>,
    pub args: Vec<String>,
}

impl ArgParser {
    /// Create a new ArgParser object
    ///
    /// The capacity specifies the initial capacity of the number parameters.
    /// Always good to set it at the number of flags and opts total.
    pub fn new(capacity: usize) -> Self {
        ArgParser {
            params: HashMap::with_capacity(capacity),
            invalid: Vec::new(),
            args: Vec::new(),
        }
    }

    /// Builder method for adding both short and long flags
    ///
    /// Flags are just parameters that have no assigned values. They are used
    /// for when certain features or options have been enabled for the application
    ///
    /// For example
    /// > ls -l --human-readable
    ///   ^  ^  ^
    ///   |  |  |
    ///   |  |  `-- A long flag to enable human readable numbers.
    ///   |  `-- A short flag to enable the long format.
    ///   `-- The command to list files.
    pub fn add_flag(mut self, short: &str, long: &str) -> Self {
        if let Some(short) = short.chars().next() {
            self.params.insert(Param::Short(short), Value::Flag(false));
        }
        if !long.is_empty() {
            self.params.insert(Param::Long(long.to_owned()), Value::Flag(false));
        }
        self
    }

    /// Builder method for adding both short and long opts
    ///
    /// Opts are parameters that hold assigned values. They are used
    /// for when certain features or options have been enabled for the application
    ///
    /// For example
    /// > ls -T 4 --color=always
    ///   ^  ^    ^
    ///   |  |    |
    ///   |  |    `-- A long opt to enable the use of color with value `always`.
    ///   |  `-- A short opt to set tab size to the value `4`.
    ///   `-- The command to list files.
    pub fn add_opt(mut self, short: &str, long: &str) -> Self {
        if let Some(short) = short.chars().next() {
            self.params.insert(Param::Short(short), Value::Opt(None));
        }
        if !long.is_empty() {
            self.params.insert(Param::Long(long.to_owned()), Value::Opt(None));
        }
        self
    }

    /// Start parsing user inputted args for which flags and opts are used at
    /// runtime. The rest of the args that are not associated to opts get added
    /// to `ArgParser.args`.
    pub fn initialize<A: Iterator<Item=String>>(&mut self, args: A) {
        let mut args = args.skip(1);
        while let Some(arg) = args.next() {
            if arg.starts_with("--") {
                // Remove both dashes
                let arg = &arg[2..];
                if arg.len() == 0 {
                    //Arg `--` means we are done parsing args, collect the rest
                    self.args.extend(args);
                    break;
                }
                if let Some(i) = arg.find('=') {
                    let (lhs, rhs) = arg.split_at(i);
                    match self.params.get_mut(lhs) {
                        // slice off the `=` char
                        Some(&mut Value::Opt(ref mut value)) => *value = Some(rhs[1..].to_owned()),
                        _ => self.invalid.push(Param::Long(lhs.to_owned())),
                    }
                }
                else {
                    match self.params.get_mut(arg) {
                        Some(&mut Value::Flag(ref mut switch)) => *switch = true,
                        _ => self.invalid.push(Param::Long(arg.to_owned())),
                    }
                }
            }
            else if arg.starts_with("-") {
                let mut chars = arg[1..].chars();
                while let Some(ch) = chars.next() {
                    match self.params.get_mut(&ch) {
                        Some(&mut Value::Flag(ref mut switch)) => *switch = true,
                        Some(&mut Value::Opt(ref mut value)) => {
                            let rest: String = chars.collect();
                            if rest.len() > 0 {
                                *value = Some(rest);
                            } else {
                                *value = args.next()
                            }
                            break;
                        },
                        None => self.invalid.push(Param::Short(ch)),
                    }
                }
            }
            else {
                self.args.push(arg);
            }
        }
    }

    /// Check if a Flag or Opt has been found after initialization.
    pub fn flagged
(&self, name: &P) -> bool
        where Param: Borrow

    {
        match self.params.get(name) {
            Some(&Value::Flag(switch)) => switch,
            Some(&Value::Opt(Some(_))) => true,
            _ => false,
        }
    }

    /// Modify the state of a flag. Use `true` if the flag is to be enabled. Use `false` to
    /// disable its use.
    pub fn set_flag<F: Hash + Eq + ?Sized>(&mut self, flag: &F, state: bool)
        where Param: Borrow<F>
    {
        if let Some(&mut Value::Flag(ref mut switch)) = self.params.get_mut(flag) {
            *switch = state;
        }
    }

    /// Modify the state value of an opt. Use `Some(String)` to set if the opt is to be enabled and
    /// has been assigned a value from `String`. Use `None` to disable the opt's use.
    pub fn set_opt<O: Hash + Eq + ?Sized>(&mut self, opt: &O, state: Option<String>)
        where Param: Borrow<O>
    {
        if let Some(&mut Value::Opt(ref mut value)) = self.params.get_mut(opt) {
            *value = state;
        }
    }

    /// Get the state of an Opt. If it has been enabled, it will return a `Some(String)` value
    /// otherwise it will return None.
    pub fn get_opt<O: Hash + Eq + ?Sized>(&self, opt: &O) -> Option<String>
        where Param: Borrow<O>
    {
        if let Some(&Value::Opt(ref value)) = self.params.get(opt) {
            return value.clone();
        }
        None
    }

    pub fn flagged_invalid(&self) -> Result<(), String> {
        if self.invalid.is_empty() {
            return Ok(());
        }

        let mut and: bool = false;
        let mut output =
            if self.invalid.len() == 1 {
                "Invalid parameter"
            } else {
                and = true;
                "Invalid parameters"
            }.to_owned();

        let mut iter = self.invalid.iter().peekable();
        while let Some(param) = iter.next() {
            match param {
                &Param::Short(ch) => {
                    output += " '-";
                    output.push(ch);
                    output.push('\'');
                }
                &Param::Long(ref s) => {
                    output += " '--";
                    output += s;
                    output.push('\'');
                }
            }
            if and && iter.peek().is_some() {
                output += " and"
            }
        }
        output.push('\n');
        Err(output)
    }
}

pub fn to_human_readable_string(size: u64) -> String {
    if size < 1024 {
        return format!("{}", size);
    }

    static UNITS: [&'static str; 7] = ["", "K", "M", "G", "T", "P", "E"];

    let sizef = size as f64;
    let digit_groups = (sizef.log10() / 1024f64.log10()) as i32;
    format!("{:.1}{}",
            sizef / 1024f64.powf(digit_groups as f64),
            UNITS[digit_groups as usize])
}
<|endoftext|>


<commit_before>// Future TimeSteward API goals:
//
// – groups
// I made up API functions for this before, but I'm not sure they were perfect.
// We can use RowId's for group ids, but what kinds of things can be stored IN a group? Previously I said only RowId's could, which doesn't seem ideal. I think it would work to allow anything hashable. That would basically make a group behave like a HashSet. But then, why not make it behave like a HashMap instead? But accessor itself already behaves like a HashMap over RowId's – the essential thing groups do is to allow iterating particular subsets of that HashMap.
//
// – conveniences for serializing snapshots (not sure what)
//
// – be able to construct a new TimeSteward from any snapshot
// Issues: should snapshots expose the predictors? Also, the predictors can't be serialized. So you'd probably actually have to construct a TimeSteward from snapshot + predictors. This requires a way to iterate all fields (and group data if we add groups) in a snapshot, which is similar to the previous 2 items (iterating the whole set, which is a special case of iterating a subset; and serializing requires you to iterate everything as well)
//
// – parallelism support for predictors and events
// When an event or predictor gets invalidated while it is still running, it would be nice for it to save time by exiting early.
// Moreover, it would probably be more efficient to discard invalidated fields than to preserve them for predictors/events that are in process. The natural way for the accessors to handle this is to have get() return None, which would mean that you can never safely unwrap() the result. We could provide a "unwrap or return" macro.
//
// – Optimization features
// one possibility: user can provide a function FieldId->[(PredictorId, RowId)] that lists predictors you KNOW will be invalidated by a change to that field, then have that predictor run its get() calls with an input called "promise_inferred" or something so that we don't spend time and memory recording the dependency
// another: a predictor might have a costly computation to find the exact time of a future event, which it won't need to do if it gets invalidated long before that time comes. For that, we can provide a defer_until(time) method
//
//
//

#![feature(unboxed_closures, fn_traits, specialization, never_type, shared)]
// #![feature (plugin, custom_derive)]
// #![plugin (serde_macros)]
// #![plugin (quickcheck_macros)]

extern crate rand;
extern crate nalgebra;
extern crate siphasher;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate bincode;
extern crate crossbeam;
#[macro_use]
extern crate quickcheck;

macro_rules! printlnerr(
    ($($arg:tt)*) => { {use std::io::Write;
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

/// Used by TimeSteward implementations.
///
/// These are public in case someone wants to try implementing a TimeSteward
/// outside of this crate, sharing some of the details with my own implementations.
/// However, anything inside this module should be
/// considered very unstable at present.
#[macro_use]
pub mod implementation_support {
  #[macro_use]
  pub mod list_of_types;
  pub mod insert_only;
  pub mod data_structures;
  #[macro_use]
  pub mod common;
}

/*#[macro_use]
/// Allows dynamic dispatch to object-unsafe traits, with some caveats.
pub mod dynamic {
  #[macro_use]
  pub mod list_of_types;
  pub mod thin_arc;
}*/

mod deterministic_random_id;
pub use deterministic_random_id::*;
#[macro_use]
mod api;
#[macro_use]
mod api_macros;
pub use api::*;
pub use implementation_support::list_of_types::{ColumnType, EventType, PredictorType};

#[macro_use]
pub mod stewards {
  pub mod inefficient_flat;
  pub mod memoized_flat;
  pub mod amortized;
  //pub mod optimized;

  pub mod flat_to_inefficient_full;
  pub mod crossverified;
  pub mod simply_synchronized;
}

#[macro_use]
pub mod support {
  pub mod rounding_error_tolerant_math;
  pub mod time_functions;
  pub mod collision_detection;
}
<commit_msg>Add the new modules in a commented-out form<commit_after>// Future TimeSteward API goals:
//
// – groups
// I made up API functions for this before, but I'm not sure they were perfect.
// We can use RowId's for group ids, but what kinds of things can be stored IN a group? Previously I said only RowId's could, which doesn't seem ideal. I think it would work to allow anything hashable. That would basically make a group behave like a HashSet. But then, why not make it behave like a HashMap instead? But accessor itself already behaves like a HashMap over RowId's – the essential thing groups do is to allow iterating particular subsets of that HashMap.
//
// – conveniences for serializing snapshots (not sure what)
//
// – be able to construct a new TimeSteward from any snapshot
// Issues: should snapshots expose the predictors? Also, the predictors can't be serialized. So you'd probably actually have to construct a TimeSteward from snapshot + predictors. This requires a way to iterate all fields (and group data if we add groups) in a snapshot, which is similar to the previous 2 items (iterating the whole set, which is a special case of iterating a subset; and serializing requires you to iterate everything as well)
//
// – parallelism support for predictors and events
// When an event or predictor gets invalidated while it is still running, it would be nice for it to save time by exiting early.
// Moreover, it would probably be more efficient to discard invalidated fields than to preserve them for predictors/events that are in process. The natural way for the accessors to handle this is to have get() return None, which would mean that you can never safely unwrap() the result. We could provide a "unwrap or return" macro.
//
// – Optimization features
// one possibility: user can provide a function FieldId->[(PredictorId, RowId)] that lists predictors you KNOW will be invalidated by a change to that field, then have that predictor run its get() calls with an input called "promise_inferred" or something so that we don't spend time and memory recording the dependency
// another: a predictor might have a costly computation to find the exact time of a future event, which it won't need to do if it gets invalidated long before that time comes. For that, we can provide a defer_until(time) method
//
//
//

#![feature(unboxed_closures, fn_traits, specialization, never_type, shared)]
// #![feature (plugin, custom_derive)]
// #![plugin (serde_macros)]
// #![plugin (quickcheck_macros)]

extern crate rand;
extern crate nalgebra;
extern crate siphasher;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate bincode;
extern crate crossbeam;
#[macro_use]
extern crate quickcheck;

macro_rules! printlnerr(
    ($($arg:tt)*) => { {use std::io::Write;
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

/// Used by TimeSteward implementations.
///
/// These are public in case someone wants to try implementing a TimeSteward
/// outside of this crate, sharing some of the details with my own implementations.
/// However, anything inside this module should be
/// considered very unstable at present.
#[macro_use]
pub mod implementation_support {
  #[macro_use]
  pub mod list_of_types;
  pub mod insert_only;
  pub mod data_structures;
  #[macro_use]
  pub mod common;
}

/*#[macro_use]
/// Allows dynamic dispatch to object-unsafe traits, with some caveats.
pub mod dynamic {
  #[macro_use]
  pub mod list_of_types;
  pub mod thin_arc;
}*/

mod deterministic_random_id;
pub use deterministic_random_id::*;
#[macro_use]
mod api;
#[macro_use]
mod api_macros;
pub use api::*;
pub use implementation_support::list_of_types::{ColumnType, EventType, PredictorType};

#[macro_use]
pub mod stewards {
  pub mod inefficient_flat;
  pub mod memoized_flat;
  pub mod amortized;
  //pub mod optimized;

  pub mod flat_to_inefficient_full;
  pub mod crossverified;
  pub mod simply_synchronized;
}

#[macro_use]
pub mod support {
  pub mod rounding_error_tolerant_math;
  pub mod time_functions;
  pub mod collision_detection;
}

/*
mod rowless {
  pub mod api;
  pub mod api_impls;
  pub mod support { mod automatic_tracking; }
}
*/
<|endoftext|>


<commit_before>#![crate_name = "vector"]
#![deny(missing_docs)]

//! Simple vector library

use std::ops::{ Add, Mul, Neg, Sub };

/// 2D Vector; A Vector with 2 components
#[derive(Debug, Copy, Clone)]
pub struct Vector2<T: Copy> {
    e0: T,
    e1: T,
}

impl<T> Vector2<T>  where T: Copy {

    /// Create new Vector2 with two entries of type T
    #[inline(always)]
    pub fn new(e0: T, e1: T) -> Vector2<T> {
        Vector2::<T> { e0: e0, e1: e1 }
    }

    /// First entry in the Vector2
    #[inline(always)]
    pub fn x(self) -> T {
        self.e0
    }

    /// Second entry in the Vector2
    #[inline(always)]
    pub fn y(self) -> T {
        self.e1
    }

    /// Get entry by index
    #[inline(always)]
    pub fn get(self, index: usize) -> T {
        match index {
            0 => self.e0,
            1 => self.e1,
            _ => panic!("index out of bounds: the len is 2 but the index is {}", index)
        }
    }
}

/// Adds other to self
impl<T> Add<Vector2<T>> for Vector2<T> where T: Copy + Add<T, Output = T> {
    type Output = Vector2<T>;

    #[inline(always)]
    fn add (self, other: Vector2<T>) -> Vector2<T> {
        Vector2::<T> { e0: self.e0 + other.e0, e1: self.e1 + other.e1 }
    }
}

/// Compute the DOT PRODUCT of self & other
impl<T> Mul<Vector2<T>> for Vector2<T> where T: Copy + Mul<T, Output = T> + Add<T, Output = T> {
    type Output = T;

    #[inline(always)]
    fn mul (self, other: Vector2<T>) -> T {
        self.e0 * other.e0 + self.e1 * other.e1
    }
}

/// Compute the DOT PRODUCT of self & other
impl<T> Mul<T> for Vector2<T> where T: Copy + Mul<T, Output = T> {
    type Output = Vector2<T>;

    #[inline(always)]
    fn mul (self, scalar: T) -> Vector2<T> {
        Vector2::<T> { e0: self.e0 * scalar, e1: self.e1 * scalar }
    }
}

/// Subtracts other from self
impl<T> Sub<Vector2<T>> for Vector2<T> where T: Copy + Sub<T, Output = T> {
    type Output = Vector2<T>;

    #[inline(always)]
    fn sub (self, other: Vector2<T>) -> Vector2<T> {
        Vector2::<T> { e0: self.e0 - other.e0, e1: self.e1 - other.e1 }
    }
}

/// Negate each entry in the Vector2
impl<T> Neg for Vector2<T> where T: Copy + Neg<Output = T> {
    type Output = Vector2<T>;

    #[inline(always)]
    fn neg(self) -> Vector2<T> {
        Vector2::<T>{ e0: -self.e0, e1: -self.e1 }
    }
}

#[test]
fn test_vector2_add() {
    let v1 = Vector2::<i32> { e0: 2, e1: 6 };
    let v2 = Vector2::<i32> { e0: 4, e1: 8 };
    let v3 = v1 + v2;

    assert_eq!(v3.e0, 6);
    assert_eq!(v3.e1, 14);
}

#[test]
fn test_vector2_sub() {
    let v1 = Vector2::<i32> { e0: 7, e1: 8 };
    let v2 = Vector2::<i32> { e0: 2, e1: 9 };
    let v3 = v1 - v2;

    assert_eq!(v3.e0, 5);
    assert_eq!(v3.e1, -1);
}

#[test]
fn test_vector2_neg() {
    let v1 = Vector2::<i32> { e0: 1, e1: -1 };
    let v2 = -v1;

    assert_eq!(v2.e0, -1);
    assert_eq!(v2.e1, 1);
}

#[test]
fn test_vector2_dot() {
    let v1 = Vector2::<i32> { e0: 2, e1: 3 };
    let v2 = Vector2::<i32> { e0: 4, e1: 5 };
    let s = v1 * v2;

    assert_eq!(s, 23);
}

#[test]
fn test_vector2_mut_scalar() {
    let v1 = Vector2::<i32>::new(1, 2);
    let v2 = v1 * 2;

    assert_eq!(v2.e0, 2);
    assert_eq!(v2.e1, 4);
}

#[test]
#[should_panic(expected = "index out of bounds: the len is 2 but the index is 2")]
fn test_get_xy() {
    let v = Vector2::<i32> { e0: 1, e1: 2 };

    assert_eq!(v.get(0), 1);
    assert_eq!(v.get(1), 2);
    v.get(2);
}
<commit_msg>Make Vector2 struct fields public<commit_after>#![crate_name = "vector"]
#![deny(missing_docs)]

//! Simple vector library

use std::ops::{ Add, Mul, Neg, Sub };

/// 2D Vector; A Vector with 2 components
#[derive(Debug, Copy, Clone)]
pub struct Vector2<T: Copy> {
    /// Element at index 0
    pub e0: T,
    /// Element at index 1
    pub e1: T,
}

impl<T> Vector2<T>  where T: Copy {

    /// Create new Vector2 with two entries of type T
    #[inline(always)]
    pub fn new(e0: T, e1: T) -> Vector2<T> {
        Vector2::<T> { e0: e0, e1: e1 }
    }

    /// Get entry by index
    #[inline(always)]
    pub fn get(self, index: usize) -> T {
        match index {
            0 => self.e0,
            1 => self.e1,
            _ => panic!("index out of bounds: the len is 2 but the index is {}", index)
        }
    }
}

/// Adds other to self
impl<T> Add<Vector2<T>> for Vector2<T> where T: Copy + Add<T, Output = T> {
    type Output = Vector2<T>;

    #[inline(always)]
    fn add (self, other: Vector2<T>) -> Vector2<T> {
        Vector2::<T> { e0: self.e0 + other.e0, e1: self.e1 + other.e1 }
    }
}

/// Compute the DOT PRODUCT
impl<T> Mul<Vector2<T>> for Vector2<T> where T: Copy + Mul<T, Output = T> + Add<T, Output = T> {
    type Output = T;

    #[inline(always)]
    fn mul (self, other: Vector2<T>) -> T {
        self.e0 * other.e0 + self.e1 * other.e1
    }
}

/// Preform an element-wise multiplication
impl<T> Mul<T> for Vector2<T> where T: Copy + Mul<T, Output = T> {
    type Output = Vector2<T>;

    #[inline(always)]
    fn mul (self, scalar: T) -> Vector2<T> {
        Vector2::<T> { e0: self.e0 * scalar, e1: self.e1 * scalar }
    }
}

/// Subtracts other from self
impl<T> Sub<Vector2<T>> for Vector2<T> where T: Copy + Sub<T, Output = T> {
    type Output = Vector2<T>;

    #[inline(always)]
    fn sub (self, other: Vector2<T>) -> Vector2<T> {
        Vector2::<T> { e0: self.e0 - other.e0, e1: self.e1 - other.e1 }
    }
}

/// Negate each entry in the Vector2
impl<T> Neg for Vector2<T> where T: Copy + Neg<Output = T> {
    type Output = Vector2<T>;

    #[inline(always)]
    fn neg(self) -> Vector2<T> {
        Vector2::<T>{ e0: -self.e0, e1: -self.e1 }
    }
}

#[test]
fn test_vector2_add() {
    let v1 = Vector2::<i32> { e0: 2, e1: 6 };
    let v2 = Vector2::<i32> { e0: 4, e1: 8 };
    let v3 = v1 + v2;

    assert_eq!(v3.e0, 6);
    assert_eq!(v3.e1, 14);
}

#[test]
fn test_vector2_sub() {
    let v1 = Vector2::<i32> { e0: 7, e1: 8 };
    let v2 = Vector2::<i32> { e0: 2, e1: 9 };
    let v3 = v1 - v2;

    assert_eq!(v3.e0, 5);
    assert_eq!(v3.e1, -1);
}

#[test]
fn test_vector2_neg() {
    let v1 = Vector2::<i32> { e0: 1, e1: -1 };
    let v2 = -v1;

    assert_eq!(v2.e0, -1);
    assert_eq!(v2.e1, 1);
}

#[test]
fn test_vector2_dot() {
    let v1 = Vector2::<i32> { e0: 2, e1: 3 };
    let v2 = Vector2::<i32> { e0: 4, e1: 5 };
    let s = v1 * v2;

    assert_eq!(s, 23);
}

#[test]
fn test_vector2_mut_scalar() {
    let v1 = Vector2::<i32>::new(1, 2);
    let v2 = v1 * 2;

    assert_eq!(v2.e0, 2);
    assert_eq!(v2.e1, 4);
}

#[test]
#[should_panic(expected = "index out of bounds: the len is 2 but the index is 2")]
fn test_get_xy() {
    let v = Vector2::<i32> { e0: 1, e1: 2 };

    assert_eq!(v.get(0), 1);
    assert_eq!(v.get(1), 2);
    v.get(2);
}
<|endoftext|>