<commit_before>pub mod metrics;

use std::collections::HashMap;
use std::fmt::{self, Debug, Formatter};
use std::iter::Extend;
use std::default::Default;

/// A node within the [BK-tree](https://en.wikipedia.org/wiki/BK-tree).
pub struct BKNode<K: Clone> {
    /// The key determining the node.
    pub key: K,
    /// A hash-map of children, indexed by their distance from this node based
    /// on the metric being used by the tree.
    pub children: HashMap<u64, BKNode<K>>,
}

impl<K> BKNode<K> where K: Clone
{
    /// Constructs a new `BKNode<K>`.
    pub fn new(key: K) -> BKNode<K>
        where K: Clone
    {
        BKNode {
            key: key,
            children: HashMap::new(),
        }
    }

    /// Add a child to the node.
    ///
    /// Given the distance from this node's key, add the given key as a child
    /// node. *Warning:* this does not test the invariant that the distance as
    /// measured by the tree between this node's key and the provided key
    /// actually matches the distance passed in.
    ///
    /// # Examples
    ///
    /// ```
    /// use bk_tree::BKNode;
    ///
    /// let mut foo = BKNode::new("foo");
    /// foo.add_child(1, "fop");
    /// ```
    pub fn add_child(&mut self, distance: u64, key: K) {
        self.children.insert(distance, BKNode::new(key));
    }
}

impl<K> Debug for BKNode<K> where K: Debug + Clone
{
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "BKNode({:?}: {:?})", self.key, self.children)
    }
}

/// A representation of a [BK-tree](https://en.wikipedia.org/wiki/BK-tree).
pub struct BKTree<K>
    where K: Clone
{
    /// The root node. May be empty if nothing has been put in the tree yet.
    pub root: Option<BKNode<K>>,
    /// The metric being used to determine the distance between nodes on the
    /// tree.
    metric: Box<Fn(K, K) -> u64>,
}

impl<K> BKTree<K> where K: Clone
{
    /// Constructs a new `BKTree<K>` using the provided metric.
    ///
    /// Note that we make no assumptions about the metric function provided.
    /// *Ideally* it is actually a
    /// [valid metric](https://en.wikipedia.org/wiki/Metric_(mathematics)),
    /// but you may choose to use one that is not technically a valid metric.
    /// If you do not use a valid metric, however, you may find that the tree
    /// behaves confusingly for some values.
    ///
    /// # Examples
    ///
    /// ```
    /// use bk_tree::{BKTree, metrics};
    ///
    /// let tree: BKTree<&str> = BKTree::new(metrics::levenshtein);
    /// ```
    pub fn new<M: 'static>(metric: M) -> BKTree<K>
        where M: Fn(K, K) -> u64
    {
        BKTree {
            root: None,
            metric: Box::new(metric),
        }
    }

    /// Adds a key to the tree.
    ///
    /// If the tree is empty, this simply sets the root to
    /// `Some(BKNode::new(key))`. Otherwise, we iterate downwards through the
    /// tree until we see a node that does not have a child with the same
    /// distance. If we encounter a node that is exactly the same distance from
    /// the root node, then the new key is the same as that node's key and so we
    /// do nothing. **Note**: This means that if your metric allows for unequal
    /// keys to return 0, you will see improper behavior!
    ///
    /// # Examples
    ///
    /// ```
    /// use bk_tree::{BKTree, metrics};
    ///
    /// let mut tree: BKTree<&str> = BKTree::new(metrics::levenshtein);
    ///
    /// tree.add("foo");
    /// tree.add("bar");
    /// ```
    pub fn add(&mut self, key: K) {
        match self.root {
            Some(ref mut root) => {
                let mut cur_node = root;
                let mut cur_dist = (&self.metric)(cur_node.key.clone(), key.clone());
                while cur_node.children.contains_key(&cur_dist) && cur_dist > 0 {
                    // We have to do some moving around here to safely get the
                    // child corresponding to the current distance away without
                    // accidentally trying to mutate the wrong thing.
                    //
                    let current = cur_node;
                    let next_node = current.children.get_mut(&cur_dist).unwrap();

                    cur_node = next_node;
                    cur_dist = (&self.metric)(cur_node.key.clone(), key.clone());
                }
                cur_node.add_child(cur_dist, key);
            }
            None => {
                self.root = Some(BKNode::new(key));
            }
        }
    }

    /// Searches for a key in the BK-tree given a certain tolerance.
    ///
    /// This traverses the tree searching for all keys with distance within
    /// `tolerance` of of the key provided. The tolerance may be zero, in which
    /// case this searches for exact matches. The results are returned in a
    /// `Vec<K>`.
    ///
    /// *Note:* There is no guarantee on the order of the vector provided. The
    /// elements returned may or may not be sorted in terms of distance from the
    /// provided key.
    ///
    /// # Examples
    /// ```
    /// use bk_tree::{BKTree, metrics};
    ///
    /// let mut tree: BKTree<&str> = BKTree::new(metrics::levenshtein);
    ///
    /// tree.add("foo");
    /// tree.add("fop");
    /// tree.add("bar");
    ///
    /// assert_eq!(tree.find("foo", 0), vec!["foo"]);
    /// assert_eq!(tree.find("foo", 1), vec!["foo", "fop"]);
    /// assert!(tree.find("foz", 0).is_empty());
    /// ```
    pub fn find(&self, key: K, tolerance: u64) -> Vec<K> {
        match self.root {
            Some(ref root) => {
                let mut result: Vec<K> = Vec::new();
                self.recursive_find(root, &mut result, key.clone(), tolerance);
                result
            }
            None => Vec::new(),
        }
    }

    fn recursive_find(&self, node: &BKNode<K>, result: &mut Vec<K>, key: K, tolerance: u64) {
        let cur_dist = (&self.metric)(node.key.clone(), key.clone());
        let min_dist = if cur_dist < tolerance {
            0
        } else {
            cur_dist - tolerance
        };
        let max_dist = cur_dist + tolerance;

        if cur_dist <= tolerance {
            result.push(node.key.clone());
        }

        let mut child_result = Vec::new();
        for (dist, ref child) in node.children.iter() {
            if *dist >= min_dist && *dist <= max_dist {
                self.recursive_find(child, &mut child_result, key.clone(), tolerance);
            }
        }
        result.extend(child_result);
    }

    /// Searches for an exact match in the tree.
    ///
    /// This is pretty much the same as calling `find` with a tolerance of 0,
    /// with the addition of pulling the value out of the vector if there was
    /// a match.
    ///
    /// # Examples
    /// ```
    /// use bk_tree::{BKTree, metrics};
    ///
    /// let mut tree: BKTree<&str> = BKTree::new(metrics::levenshtein);
    ///
    /// tree.add("foo");
    /// tree.add("fop");
    /// tree.add("bar");
    ///
    /// assert_eq!(tree.find_exact("foz"), None);
    /// assert_eq!(tree.find_exact("foo"), Some("foo"));
    /// ```
    pub fn find_exact(&self, key: K) -> Option<K> {
        let result = self.find(key, 0);
        if result.is_empty() {
            None
        } else {
            Some(result[0].clone())
        }
    }
}

impl<K: Clone> Extend<K> for BKTree<K> {
    /// Adds multiple keys to the tree.
    ///
    /// Given an iterator with items of type `K`, this method simply adds every
    /// item to the tree.
    ///
    /// # Examples
    ///
    /// ```
    /// use bk_tree::{BKTree, metrics};
    ///
    /// let mut tree: BKTree<&str> = BKTree::new(metrics::levenshtein);
    ///
    /// tree.extend(vec!["foo", "bar"]);
    /// ```
    fn extend<I: IntoIterator<Item = K>>(&mut self, keys: I) {
        for key in keys {
            self.add(key);
        }
    }
}

impl<K: 'static + Clone + ToString> Default for BKTree<K> {
    fn default() -> BKTree<K> {
        BKTree::new(metrics::levenshtein)
    }
}
<commit_msg>Idiomatic for loop iteration<commit_after>pub mod metrics;

use std::collections::HashMap;
use std::fmt::{self, Debug, Formatter};
use std::iter::Extend;
use std::default::Default;

/// A node within the [BK-tree](https://en.wikipedia.org/wiki/BK-tree).
pub struct BKNode<K: Clone> {
    /// The key determining the node.
    pub key: K,
    /// A hash-map of children, indexed by their distance from this node based
    /// on the metric being used by the tree.
    pub children: HashMap<u64, BKNode<K>>,
}

impl<K> BKNode<K> where K: Clone
{
    /// Constructs a new `BKNode<K>`.
    pub fn new(key: K) -> BKNode<K>
        where K: Clone
    {
        BKNode {
            key: key,
            children: HashMap::new(),
        }
    }

    /// Add a child to the node.
    ///
    /// Given the distance from this node's key, add the given key as a child
    /// node. *Warning:* this does not test the invariant that the distance as
    /// measured by the tree between this node's key and the provided key
    /// actually matches the distance passed in.
    ///
    /// # Examples
    ///
    /// ```
    /// use bk_tree::BKNode;
    ///
    /// let mut foo = BKNode::new("foo");
    /// foo.add_child(1, "fop");
    /// ```
    pub fn add_child(&mut self, distance: u64, key: K) {
        self.children.insert(distance, BKNode::new(key));
    }
}

impl<K> Debug for BKNode<K> where K: Debug + Clone
{
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "BKNode({:?}: {:?})", self.key, self.children)
    }
}

/// A representation of a [BK-tree](https://en.wikipedia.org/wiki/BK-tree).
pub struct BKTree<K>
    where K: Clone
{
    /// The root node. May be empty if nothing has been put in the tree yet.
    pub root: Option<BKNode<K>>,
    /// The metric being used to determine the distance between nodes on the
    /// tree.
    metric: Box<Fn(K, K) -> u64>,
}

impl<K> BKTree<K> where K: Clone
{
    /// Constructs a new `BKTree<K>` using the provided metric.
    ///
    /// Note that we make no assumptions about the metric function provided.
    /// *Ideally* it is actually a
    /// [valid metric](https://en.wikipedia.org/wiki/Metric_(mathematics)),
    /// but you may choose to use one that is not technically a valid metric.
    /// If you do not use a valid metric, however, you may find that the tree
    /// behaves confusingly for some values.
    ///
    /// # Examples
    ///
    /// ```
    /// use bk_tree::{BKTree, metrics};
    ///
    /// let tree: BKTree<&str> = BKTree::new(metrics::levenshtein);
    /// ```
    pub fn new<M: 'static>(metric: M) -> BKTree<K>
        where M: Fn(K, K) -> u64
    {
        BKTree {
            root: None,
            metric: Box::new(metric),
        }
    }

    /// Adds a key to the tree.
    ///
    /// If the tree is empty, this simply sets the root to
    /// `Some(BKNode::new(key))`. Otherwise, we iterate downwards through the
    /// tree until we see a node that does not have a child with the same
    /// distance. If we encounter a node that is exactly the same distance from
    /// the root node, then the new key is the same as that node's key and so we
    /// do nothing. **Note**: This means that if your metric allows for unequal
    /// keys to return 0, you will see improper behavior!
    ///
    /// # Examples
    ///
    /// ```
    /// use bk_tree::{BKTree, metrics};
    ///
    /// let mut tree: BKTree<&str> = BKTree::new(metrics::levenshtein);
    ///
    /// tree.add("foo");
    /// tree.add("bar");
    /// ```
    pub fn add(&mut self, key: K) {
        match self.root {
            Some(ref mut root) => {
                let mut cur_node = root;
                let mut cur_dist = (&self.metric)(cur_node.key.clone(), key.clone());
                while cur_node.children.contains_key(&cur_dist) && cur_dist > 0 {
                    // We have to do some moving around here to safely get the
                    // child corresponding to the current distance away without
                    // accidentally trying to mutate the wrong thing.
                    //
                    let current = cur_node;
                    let next_node = current.children.get_mut(&cur_dist).unwrap();

                    cur_node = next_node;
                    cur_dist = (&self.metric)(cur_node.key.clone(), key.clone());
                }
                cur_node.add_child(cur_dist, key);
            }
            None => {
                self.root = Some(BKNode::new(key));
            }
        }
    }

    /// Searches for a key in the BK-tree given a certain tolerance.
    ///
    /// This traverses the tree searching for all keys with distance within
    /// `tolerance` of of the key provided. The tolerance may be zero, in which
    /// case this searches for exact matches. The results are returned in a
    /// `Vec<K>`.
    ///
    /// *Note:* There is no guarantee on the order of the vector provided. The
    /// elements returned may or may not be sorted in terms of distance from the
    /// provided key.
    ///
    /// # Examples
    /// ```
    /// use bk_tree::{BKTree, metrics};
    ///
    /// let mut tree: BKTree<&str> = BKTree::new(metrics::levenshtein);
    ///
    /// tree.add("foo");
    /// tree.add("fop");
    /// tree.add("bar");
    ///
    /// assert_eq!(tree.find("foo", 0), vec!["foo"]);
    /// assert_eq!(tree.find("foo", 1), vec!["foo", "fop"]);
    /// assert!(tree.find("foz", 0).is_empty());
    /// ```
    pub fn find(&self, key: K, tolerance: u64) -> Vec<K> {
        match self.root {
            Some(ref root) => {
                let mut result: Vec<K> = Vec::new();
                self.recursive_find(root, &mut result, key.clone(), tolerance);
                result
            }
            None => Vec::new(),
        }
    }

    fn recursive_find(&self, node: &BKNode<K>, result: &mut Vec<K>, key: K, tolerance: u64) {
        let cur_dist = (&self.metric)(node.key.clone(), key.clone());
        let min_dist = if cur_dist < tolerance {
            0
        } else {
            cur_dist - tolerance
        };
        let max_dist = cur_dist + tolerance;

        if cur_dist <= tolerance {
            result.push(node.key.clone());
        }

        let mut child_result = Vec::new();
        for (dist, ref child) in &node.children {
            if *dist >= min_dist && *dist <= max_dist {
                self.recursive_find(child, &mut child_result, key.clone(), tolerance);
            }
        }
        result.extend(child_result);
    }

    /// Searches for an exact match in the tree.
    ///
    /// This is pretty much the same as calling `find` with a tolerance of 0,
    /// with the addition of pulling the value out of the vector if there was
    /// a match.
    ///
    /// # Examples
    /// ```
    /// use bk_tree::{BKTree, metrics};
    ///
    /// let mut tree: BKTree<&str> = BKTree::new(metrics::levenshtein);
    ///
    /// tree.add("foo");
    /// tree.add("fop");
    /// tree.add("bar");
    ///
    /// assert_eq!(tree.find_exact("foz"), None);
    /// assert_eq!(tree.find_exact("foo"), Some("foo"));
    /// ```
    pub fn find_exact(&self, key: K) -> Option<K> {
        let result = self.find(key, 0);
        if result.is_empty() {
            None
        } else {
            Some(result[0].clone())
        }
    }
}

impl<K: Clone> Extend<K> for BKTree<K> {
    /// Adds multiple keys to the tree.
    ///
    /// Given an iterator with items of type `K`, this method simply adds every
    /// item to the tree.
    ///
    /// # Examples
    ///
    /// ```
    /// use bk_tree::{BKTree, metrics};
    ///
    /// let mut tree: BKTree<&str> = BKTree::new(metrics::levenshtein);
    ///
    /// tree.extend(vec!["foo", "bar"]);
    /// ```
    fn extend<I: IntoIterator<Item = K>>(&mut self, keys: I) {
        for key in keys {
            self.add(key);
        }
    }
}

impl<K: 'static + Clone + ToString> Default for BKTree<K> {
    fn default() -> BKTree<K> {
        BKTree::new(metrics::levenshtein)
    }
}
<|endoftext|>


<commit_before>#![feature(associated_consts)]
extern crate lmdb_rs as lmdb;

use lmdb::{FromMdbValue, ToMdbValue, MdbValue, DbFlags, DbHandle, Database, Environment, Transaction, ReadonlyTransaction, Cursor, MDB_val};
use lmdb::core::MdbResult;
use std::marker::PhantomData;

#[macro_export]
macro_rules! table_def {
    (
        $structname:ident, $tableclass:ty, $str:expr
    ) => {
        #[derive(Clone)]
        struct $structname;
        impl TableDef for $structname {
            type C = $tableclass;
            fn table_name() -> &'static str { $str }
        }
    };
}

#[macro_export]
macro_rules! lmdb_not_found {
    (
        $x:expr
    ) => {
        match $x {
            Err(lmdb::MdbError::NotFound) => true,
            _ => false
        }
    };
}

/// A TableClass describes the types of key/value and the behaviour (sort function) of a Table.
pub trait TableClass: Sized {
    type Key: ToMdbValue + FromMdbValue;
    type Value: ToMdbValue + FromMdbValue;

    /// Flags used for creation/open
    fn dbflags() -> DbFlags;

    /// Is called before accessing a database. Used to setup custom sort functions etc.
    fn prepare_database(db: &Database) -> MdbResult<()>;
}

/// A TableDef is a concrete instance of a TableClass with a given table name.
pub trait TableDef: Sized {
    type C: TableClass;
    fn table_name() -> &'static str;

    fn create_table(env: &Environment) -> MdbResult<TableHandle<Self>> {
        env.create_db(Self::table_name(), Self::C::dbflags()).map(|dbh| {
            TableHandle {
                dbh: dbh,
                tabledef: PhantomData,
            }
        })
    }

    fn open_table(env: &Environment) -> MdbResult<TableHandle<Self>> {
        env.get_db(Self::table_name(), Self::C::dbflags()).map(|dbh| {
            TableHandle {
                dbh: dbh,
                tabledef: PhantomData,
            }
        })
    }

}

/// Wraps a lmdb::DbHandle, keeping the TableDef in the type signature.
pub struct TableHandle<D: TableDef> {
    dbh: DbHandle,
    tabledef: PhantomData<D>,
}

impl<D: TableDef> TableHandle<D> {
    /// Bind a TableHandle towards a transaction. Returns a Table which you can use to
    /// modify the database.
    #[inline(always)]
    pub fn bind_transaction<'txn>(&self, txn: &'txn Transaction) -> MdbResult<Table<'txn, D>> {
        let db = txn.bind(&self.dbh);
        try!(D::C::prepare_database(&db));
        Ok(Table {
            db: db,
            tabledef: PhantomData,
        })
    }

    /// Bind a TableHandle towards a readonly transaction.
    /// XXX: This should return a ReadonlyTable?
    #[inline(always)]
    pub fn bind_reader<'txn>(&self, txn: &'txn ReadonlyTransaction) -> MdbResult<Table<'txn, D>> {
        let db = txn.bind(&self.dbh);
        try!(D::C::prepare_database(&db));
        Ok(Table {
                db: db,
                tabledef: PhantomData,
            }
        )
    }

}

/// Wraps a lmdb::Database, keeping the TableDef in the type signature.
pub struct Table<'db, D: TableDef> {
    db: Database<'db>,
    tabledef: PhantomData<D>,
}

impl<'db, D: TableDef> Table<'db, D> {
    #[inline(always)]
    pub fn set(&self, key: &<<D as TableDef>::C as TableClass>::Key, value: &<<D as TableDef>::C as TableClass>::Value) -> MdbResult<()> {
        self.db.set(key, value)
    }

    #[inline(always)]
    pub fn insert(&self, key: &<<D as TableDef>::C as TableClass>::Key, value: &<<D as TableDef>::C as TableClass>::Value) -> MdbResult<()> {
        self.db.insert(key, value)
    }

    #[inline(always)]
    pub fn get(&self, key: &<<D as TableDef>::C as TableClass>::Key) -> MdbResult<<<D as TableDef>::C as TableClass>::Value> {
        self.db.get(key)
    }

    #[inline(always)]
    pub fn del(&self, key: &<<D as TableDef>::C as TableClass>::Key) -> MdbResult<()> {
        self.db.del(key)
    }

    #[inline(always)]
    pub fn del_item(&self, key: &<<D as TableDef>::C as TableClass>::Key, value: &<<D as TableDef>::C as TableClass>::Value) -> MdbResult<()> {
        self.db.del_item(key, value)
    }

    #[inline(always)]
    pub fn new_cursor<'table>(&'table self) -> MdbResult<TypedCursor<'table, D>> {
        self.db.new_cursor().map(|c| TypedCursor {cursor: c, tabledef: PhantomData})
    }
}

/// Is a typed version of lmdb::Cursor.
pub struct TypedCursor<'table, D: TableDef> {
    cursor: Cursor<'table>,
    tabledef: PhantomData<D>,
}

impl<'table, D: TableDef> TypedCursor<'table, D> {
    #[inline(always)]
    pub fn to_first(&mut self) -> MdbResult<()> {
        self.cursor.to_first()
    }

    #[inline(always)]
    pub fn to_last(&mut self) -> MdbResult<()> {
        self.cursor.to_last()
    }

    #[inline(always)]
    pub fn to_key(&mut self, key: &<<D as TableDef>::C as TableClass>::Key) -> MdbResult<()> {
        self.cursor.to_key(key)
    }

    #[inline(always)]
    pub fn to_gte_key(&mut self, key: &<<D as TableDef>::C as TableClass>::Key) -> MdbResult<()> {
        self.cursor.to_gte_key(key)
    }

    #[inline(always)]
    pub fn to_next_key(&mut self) -> MdbResult<()> {
        self.cursor.to_next_key()
    }

    #[inline(always)]
    pub fn to_prev_key(&mut self) -> MdbResult<()> {
        self.cursor.to_prev_key()
    }

    #[inline(always)]
    pub fn to_item(&mut self, key: &<<D as TableDef>::C as TableClass>::Key, value: &<<D as TableDef>::C as TableClass>::Value) -> MdbResult<()> {
        self.cursor.to_item(key, value)
    }

    #[inline(always)]
    pub fn to_first_item(&mut self) -> MdbResult<()> {
        self.cursor.to_first_item()
    }

    #[inline(always)]
    pub fn to_last_item(&mut self) -> MdbResult<()> {
        self.cursor.to_last_item()
    }

    #[inline(always)]
    pub fn to_next_item(&mut self) -> MdbResult<()> {
        self.cursor.to_next_item()
    }

    #[inline(always)]
    pub fn to_prev_item(&mut self) -> MdbResult<()> {
        self.cursor.to_prev_item()
    }

    #[inline(always)]
    pub fn item_count(&mut self) -> MdbResult<u64> {
        self.cursor.item_count()
    }

    #[inline(always)]
    pub fn get<'a>(&'a mut self) -> MdbResult<(<<D as TableDef>::C as TableClass>::Key, <<D as TableDef>::C as TableClass>::Value)> /*where D::C::Key: 'a, D::C::Value: 'a*/ {
        self.cursor.get()
    }

    #[inline(always)]
    pub fn get_value<'a>(&'a mut self) -> MdbResult<<<D as TableDef>::C as TableClass>::Value> {
        self.cursor.get_value()
    }

    #[inline(always)]
    pub fn get_key<'a>(&'a mut self) -> MdbResult<<<D as TableDef>::C as TableClass>::Key> {
        self.cursor.get_key()
    }

    #[inline(always)]
    pub fn replace(&mut self, value: &<<D as TableDef>::C as TableClass>::Value) -> MdbResult<()> {
        self.cursor.replace(value)
    }

}

extern "C" fn sort<T:FromMdbValue+Ord>(lhs_val: *const MDB_val, rhs_val: *const MDB_val) -> lmdb::c_int {
    let lhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(lhs_val)});
    let rhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(rhs_val)});

    let order: i8 = unsafe { std::mem::transmute(lhs.cmp(&rhs)) };
    order as lmdb::c_int
}

extern "C" fn sort_reverse<T:FromMdbValue+Ord>(lhs_val: *const MDB_val, rhs_val: *const MDB_val) -> lmdb::c_int {
    let lhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(lhs_val)});
    let rhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(rhs_val)});
    let order: i8 = unsafe { std::mem::transmute(lhs.cmp(&rhs).reverse()) };
    order as lmdb::c_int
}

pub mod table_classes {
    use super::{TableClass};
    use super::lmdb::{self, Database, DbFlags};
    use super::lmdb::core::{MdbResult, DbIntKey, DbAllowDups, DbAllowIntDups, DbDupFixed};
    use super::{sort, sort_reverse};

    pub type Id64 = u64;

    /// CREATE TABLE (a: Id64, b: Id64, UNIQUE (a ASC, b ASC))
    pub struct Unique__Id64_Id64;

    impl TableClass for Unique__Id64_Id64 {
        type Key = Id64;
        type Value = Id64;

        fn dbflags() -> DbFlags {
            use ::std::mem;
            assert!(mem::size_of::<Self::Key>() == mem::size_of::<usize>());
            assert!(mem::size_of::<Self::Value>() == mem::size_of::<usize>());
            DbIntKey | DbAllowDups | DbAllowIntDups | DbDupFixed
        }

        // Uses default sort order for both key and value
        fn prepare_database(_db: &Database) -> MdbResult<()> { Ok(()) }
    }

    /// CREATE TABLE (a: Id64, b: Id64, UNIQUE (a ASC, b DESC))
    pub struct Unique__Id64_Id64Rev;

    impl super::TableClass for Unique__Id64_Id64Rev {
        type Key = Id64;
        type Value = Id64;

        fn dbflags() -> DbFlags {
            use ::std::mem;
            assert!(mem::size_of::<Self::Key>() == mem::size_of::<usize>());
            assert!(mem::size_of::<Self::Value>() == mem::size_of::<usize>());
            DbIntKey | DbAllowDups | DbAllowIntDups | DbDupFixed
        }

        // Uses reverse sort order for value, default for key.
        fn prepare_database(db: &Database) -> MdbResult<()> {
            db.set_dupsort(sort_reverse::<Self::Value>)
        }
    }
}

#[test]
fn test_simple_table() {
    use std::path::Path;

    let env = lmdb::EnvBuilder::new().max_dbs(2).autocreate_dir(true).open(&Path::new("./test/db1"), 0o777).unwrap();

    table_def!(MyFirstTable, table_classes::Unique__Id64_Id64Rev, "my_first_table");

    // A Unique(Id64, Id64 DESC) table
    let table_handle = MyFirstTable::create_table(&env).unwrap();

    // prepare database
    {
        let txn = env.new_transaction().unwrap();
        {
            let table = table_handle.bind_transaction(&txn).unwrap();
            let key = 1u64;
            table.set(&key, &200u64).unwrap();
            table.set(&key, &100u64).unwrap();
            table.set(&key, &2u64).unwrap();
            table.set(&key, &2u64).unwrap();
            table.set(&key, &2u64).unwrap();
            table.set(&key, &2u64).unwrap();
            table.set(&key, &1u64).unwrap();
            table.set(&key, &2u64).unwrap();
            table.set(&key, &3u64).unwrap();
            table.set(&key, &100u64).unwrap();
        }
        txn.commit().unwrap();
    }
    // read
    {
        let rdr = env.get_reader().unwrap();
        let table = table_handle.bind_reader(&rdr).unwrap();

        let key = 1u64;

        let mut cursor = table.new_cursor().unwrap();
        cursor.to_key(&1u64).unwrap(); //  positions on first item of key
        assert_eq!((1u64, 200u64), cursor.get().unwrap());

        cursor.to_next_item().unwrap();
        assert_eq!((1u64, 100u64), cursor.get().unwrap());

        cursor.to_next_item().unwrap();
        assert_eq!((1u64, 3u64), cursor.get().unwrap());

        cursor.to_next_item().unwrap();
        assert_eq!((1u64, 2u64), cursor.get().unwrap());

        cursor.to_next_item().unwrap();
        assert_eq!((1u64, 1u64), cursor.get().unwrap());

        assert!(lmdb_not_found!(cursor.to_next_item()));

        let mut cursor = table.new_cursor().unwrap();
        {
            assert!(lmdb_not_found!(cursor.to_item(&2u64, &3u64)));

            cursor.to_item(&1u64, &3u64).unwrap();
            assert_eq!((1u64, 3u64), cursor.get().unwrap());

            cursor.to_next_item().unwrap();
            assert_eq!((1u64, 2u64), cursor.get().unwrap());

            cursor.to_next_item().unwrap();
            assert_eq!((1u64, 1u64), cursor.get().unwrap());

            assert!(lmdb_not_found!(cursor.to_next_item()));
        }
    }
}

<commit_msg>Add more types<commit_after>#![feature(associated_consts)]
extern crate lmdb_rs as lmdb;

use lmdb::{FromMdbValue, ToMdbValue, MdbValue, DbFlags, DbHandle, Database, Environment, Transaction, ReadonlyTransaction, Cursor, MDB_val};
use lmdb::core::MdbResult;
use std::marker::PhantomData;

#[macro_export]
macro_rules! table_def {
    (
        $structname:ident, $tableclass:ty, $str:expr
    ) => {
        #[derive(Clone)]
        struct $structname;
        impl TableDef for $structname {
            type C = $tableclass;
            fn table_name() -> &'static str { $str }
        }
    };
}

#[macro_export]
macro_rules! lmdb_not_found {
    (
        $x:expr
    ) => {
        match $x {
            Err(lmdb::MdbError::NotFound) => true,
            _ => false
        }
    };
}

/// A TableClass describes the types of key/value and the behaviour (sort function) of a Table.
pub trait TableClass: Sized {
    type Key: ToMdbValue + FromMdbValue;
    type Value: ToMdbValue + FromMdbValue;

    /// Flags used for creation/open
    fn dbflags() -> DbFlags;

    /// Is called before accessing a database. Used to setup custom sort functions etc.
    fn prepare_database(db: &Database) -> MdbResult<()>;
}

/// A TableDef is a concrete instance of a TableClass with a given table name.
pub trait TableDef: Sized {
    type C: TableClass;
    fn table_name() -> &'static str;

    fn create_table(env: &Environment) -> MdbResult<TableHandle<Self>> {
        env.create_db(Self::table_name(), Self::C::dbflags()).map(|dbh| {
            TableHandle {
                dbh: dbh,
                tabledef: PhantomData,
            }
        })
    }

    fn open_table(env: &Environment) -> MdbResult<TableHandle<Self>> {
        env.get_db(Self::table_name(), Self::C::dbflags()).map(|dbh| {
            TableHandle {
                dbh: dbh,
                tabledef: PhantomData,
            }
        })
    }

}

/// Wraps a lmdb::DbHandle, keeping the TableDef in the type signature.
pub struct TableHandle<D: TableDef> {
    dbh: DbHandle,
    tabledef: PhantomData<D>,
}

impl<D: TableDef> TableHandle<D> {
    /// Bind a TableHandle towards a transaction. Returns a Table which you can use to
    /// modify the database.
    #[inline(always)]
    pub fn bind_transaction<'txn>(&self, txn: &'txn Transaction) -> MdbResult<Table<'txn, D>> {
        let db = txn.bind(&self.dbh);
        try!(D::C::prepare_database(&db));
        Ok(Table {
            db: db,
            tabledef: PhantomData,
        })
    }

    /// Bind a TableHandle towards a readonly transaction.
    /// XXX: This should return a ReadonlyTable?
    #[inline(always)]
    pub fn bind_reader<'txn>(&self, txn: &'txn ReadonlyTransaction) -> MdbResult<Table<'txn, D>> {
        let db = txn.bind(&self.dbh);
        try!(D::C::prepare_database(&db));
        Ok(Table {
                db: db,
                tabledef: PhantomData,
            }
        )
    }

}

/// Wraps a lmdb::Database, keeping the TableDef in the type signature.
pub struct Table<'db, D: TableDef> {
    db: Database<'db>,
    tabledef: PhantomData<D>,
}

impl<'db, D: TableDef> Table<'db, D> {
    #[inline(always)]
    pub fn set(&self, key: &<<D as TableDef>::C as TableClass>::Key, value: &<<D as TableDef>::C as TableClass>::Value) -> MdbResult<()> {
        self.db.set(key, value)
    }

    #[inline(always)]
    pub fn insert(&self, key: &<<D as TableDef>::C as TableClass>::Key, value: &<<D as TableDef>::C as TableClass>::Value) -> MdbResult<()> {
        self.db.insert(key, value)
    }

    #[inline(always)]
    pub fn get(&self, key: &<<D as TableDef>::C as TableClass>::Key) -> MdbResult<<<D as TableDef>::C as TableClass>::Value> {
        self.db.get(key)
    }

    #[inline(always)]
    pub fn del(&self, key: &<<D as TableDef>::C as TableClass>::Key) -> MdbResult<()> {
        self.db.del(key)
    }

    #[inline(always)]
    pub fn del_item(&self, key: &<<D as TableDef>::C as TableClass>::Key, value: &<<D as TableDef>::C as TableClass>::Value) -> MdbResult<()> {
        self.db.del_item(key, value)
    }

    #[inline(always)]
    pub fn new_cursor<'table>(&'table self) -> MdbResult<TypedCursor<'table, D>> {
        self.db.new_cursor().map(|c| TypedCursor {cursor: c, tabledef: PhantomData})
    }
}

/// Is a typed version of lmdb::Cursor.
pub struct TypedCursor<'table, D: TableDef> {
    cursor: Cursor<'table>,
    tabledef: PhantomData<D>,
}

impl<'table, D: TableDef> TypedCursor<'table, D> {
    #[inline(always)]
    pub fn to_first(&mut self) -> MdbResult<()> {
        self.cursor.to_first()
    }

    #[inline(always)]
    pub fn to_last(&mut self) -> MdbResult<()> {
        self.cursor.to_last()
    }

    #[inline(always)]
    pub fn to_key(&mut self, key: &<<D as TableDef>::C as TableClass>::Key) -> MdbResult<()> {
        self.cursor.to_key(key)
    }

    #[inline(always)]
    pub fn to_gte_key(&mut self, key: &<<D as TableDef>::C as TableClass>::Key) -> MdbResult<()> {
        self.cursor.to_gte_key(key)
    }

    #[inline(always)]
    pub fn to_next_key(&mut self) -> MdbResult<()> {
        self.cursor.to_next_key()
    }

    #[inline(always)]
    pub fn to_prev_key(&mut self) -> MdbResult<()> {
        self.cursor.to_prev_key()
    }

    #[inline(always)]
    pub fn to_item(&mut self, key: &<<D as TableDef>::C as TableClass>::Key, value: &<<D as TableDef>::C as TableClass>::Value) -> MdbResult<()> {
        self.cursor.to_item(key, value)
    }

    #[inline(always)]
    pub fn to_first_item(&mut self) -> MdbResult<()> {
        self.cursor.to_first_item()
    }

    #[inline(always)]
    pub fn to_last_item(&mut self) -> MdbResult<()> {
        self.cursor.to_last_item()
    }

    #[inline(always)]
    pub fn to_next_item(&mut self) -> MdbResult<()> {
        self.cursor.to_next_item()
    }

    #[inline(always)]
    pub fn to_prev_item(&mut self) -> MdbResult<()> {
        self.cursor.to_prev_item()
    }

    #[inline(always)]
    pub fn item_count(&mut self) -> MdbResult<u64> {
        self.cursor.item_count()
    }

    #[inline(always)]
    pub fn get<'a>(&'a mut self) -> MdbResult<(<<D as TableDef>::C as TableClass>::Key, <<D as TableDef>::C as TableClass>::Value)> /*where D::C::Key: 'a, D::C::Value: 'a*/ {
        self.cursor.get()
    }

    #[inline(always)]
    pub fn get_value<'a>(&'a mut self) -> MdbResult<<<D as TableDef>::C as TableClass>::Value> {
        self.cursor.get_value()
    }

    #[inline(always)]
    pub fn get_key<'a>(&'a mut self) -> MdbResult<<<D as TableDef>::C as TableClass>::Key> {
        self.cursor.get_key()
    }

    #[inline(always)]
    pub fn replace(&mut self, value: &<<D as TableDef>::C as TableClass>::Value) -> MdbResult<()> {
        self.cursor.replace(value)
    }

}

extern "C" fn sort<T:FromMdbValue+Ord>(lhs_val: *const MDB_val, rhs_val: *const MDB_val) -> lmdb::c_int {
    let lhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(lhs_val)});
    let rhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(rhs_val)});

    let order: i8 = unsafe { std::mem::transmute(lhs.cmp(&rhs)) };
    order as lmdb::c_int
}

extern "C" fn sort_reverse<T:FromMdbValue+Ord>(lhs_val: *const MDB_val, rhs_val: *const MDB_val) -> lmdb::c_int {
    let lhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(lhs_val)});
    let rhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(rhs_val)});
    let order: i8 = unsafe { std::mem::transmute(lhs.cmp(&rhs).reverse()) };
    order as lmdb::c_int
}

pub mod table_classes {
    use super::{TableClass};
    use super::lmdb::{self, Database, DbFlags, FromMdbValue, ToMdbValue, MdbValue};
    use super::lmdb::core::{MdbResult, DbIntKey, DbAllowDups, DbAllowIntDups, DbDupFixed};
    use super::{sort, sort_reverse};
    use ::std::mem;

    pub type Id64 = u64;
    pub type Idx16 = u16;

    #[repr(C, packed)]
    #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
    pub struct Id64x2(pub Id64, pub Id64);

    impl FromMdbValue for Id64x2 {
        #[inline(always)]
        fn from_mdb_value(value: &MdbValue) -> Id64x2 {
            assert!(value.get_size() == mem::size_of::<Id64x2>());
            unsafe {
                let ptr: *const Id64x2 = value.get_ref() as *const Id64x2;
                return *ptr;
            }
        }
    }

    impl ToMdbValue for Id64x2 {
        fn to_mdb_value<'a>(&'a self) -> MdbValue<'a> {
            unsafe {
                MdbValue::new(mem::transmute(self as *const Id64x2), mem::size_of::<Id64x2>())
            }
        }
    }

    #[repr(C, packed)]
    #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
    pub struct Idx16Id64(pub Idx16, pub Id64);

    impl FromMdbValue for Idx16Id64 {
        #[inline(always)]
        fn from_mdb_value(value: &MdbValue) -> Idx16Id64 {
            assert!(value.get_size() == mem::size_of::<Idx16Id64>());
            unsafe {
                let ptr: *const Idx16Id64 = value.get_ref() as *const Idx16Id64;
                return *ptr;
            }
        }
    }

    impl ToMdbValue for Idx16Id64 {
        fn to_mdb_value<'a>(&'a self) -> MdbValue<'a> {
            unsafe {
                MdbValue::new(mem::transmute(self as *const Idx16Id64), mem::size_of::<Idx16Id64>())
            }
        }
    }

    /// CREATE TABLE (key: Id64, val: Id64, UNIQUE (key ASC, val ASC))
    pub struct Unique__Id64_Id64;

    impl TableClass for Unique__Id64_Id64 {
        type Key = Id64;
        type Value = Id64;

        fn dbflags() -> DbFlags {
            assert!(mem::size_of::<Self::Key>() == mem::size_of::<usize>());
            assert!(mem::size_of::<Self::Value>() == mem::size_of::<usize>());
            DbIntKey | DbAllowDups | DbAllowIntDups | DbDupFixed
        }

        // Uses default sort order for both key and value
        fn prepare_database(_db: &Database) -> MdbResult<()> { Ok(()) }
    }

    /// CREATE TABLE (key: Id64, val: Id64, UNIQUE (key ASC, val DESC))
    pub struct Unique__Id64_Id64Rev;

    impl super::TableClass for Unique__Id64_Id64Rev {
        type Key = Id64;
        type Value = Id64;

        fn dbflags() -> DbFlags {
            use ::std::mem;
            assert!(mem::size_of::<Self::Key>() == mem::size_of::<usize>());
            assert!(mem::size_of::<Self::Value>() == mem::size_of::<usize>());
            DbIntKey | DbAllowDups | DbAllowIntDups | DbDupFixed
        }

        // Uses reverse sort order for value, default for key.
        fn prepare_database(db: &Database) -> MdbResult<()> {
            db.set_dupsort(sort_reverse::<Self::Value>)
        }
    }

    /// CREATE TABLE (key: (Id64, Id64), val: Id64, UNIQUE (key ASC, val ASC))
    pub struct Unique__Id64x2_Id64;

    impl TableClass for Unique__Id64x2_Id64 {
        type Key = Id64x2;
        type Value = Id64;

        fn dbflags() -> DbFlags {
            assert!(mem::size_of::<Self::Value>() == mem::size_of::<usize>());
            DbAllowDups | DbAllowIntDups | DbDupFixed
        }

        // Uses default sort order for both key and value
        fn prepare_database(_db: &Database) -> MdbResult<()> { Ok(()) }
    }

}

#[test]
fn test_simple_table() {
    use std::path::Path;

    let env = lmdb::EnvBuilder::new().max_dbs(2).autocreate_dir(true).open(&Path::new("./test/db1"), 0o777).unwrap();

    table_def!(MyFirstTable, table_classes::Unique__Id64_Id64Rev, "my_first_table");

    // A Unique(Id64, Id64 DESC) table
    let table_handle = MyFirstTable::create_table(&env).unwrap();

    // prepare database
    {
        let txn = env.new_transaction().unwrap();
        {
            let table = table_handle.bind_transaction(&txn).unwrap();
            let key = 1u64;
            table.set(&key, &200u64).unwrap();
            table.set(&key, &100u64).unwrap();
            table.set(&key, &2u64).unwrap();
            table.set(&key, &2u64).unwrap();
            table.set(&key, &2u64).unwrap();
            table.set(&key, &2u64).unwrap();
            table.set(&key, &1u64).unwrap();
            table.set(&key, &2u64).unwrap();
            table.set(&key, &3u64).unwrap();
            table.set(&key, &100u64).unwrap();
        }
        txn.commit().unwrap();
    }
    // read
    {
        let rdr = env.get_reader().unwrap();
        let table = table_handle.bind_reader(&rdr).unwrap();

        let key = 1u64;

        let mut cursor = table.new_cursor().unwrap();
        cursor.to_key(&1u64).unwrap(); //  positions on first item of key
        assert_eq!((1u64, 200u64), cursor.get().unwrap());

        cursor.to_next_item().unwrap();
        assert_eq!((1u64, 100u64), cursor.get().unwrap());

        cursor.to_next_item().unwrap();
        assert_eq!((1u64, 3u64), cursor.get().unwrap());

        cursor.to_next_item().unwrap();
        assert_eq!((1u64, 2u64), cursor.get().unwrap());

        cursor.to_next_item().unwrap();
        assert_eq!((1u64, 1u64), cursor.get().unwrap());

        assert!(lmdb_not_found!(cursor.to_next_item()));

        let mut cursor = table.new_cursor().unwrap();
        {
            assert!(lmdb_not_found!(cursor.to_item(&2u64, &3u64)));

            cursor.to_item(&1u64, &3u64).unwrap();
            assert_eq!((1u64, 3u64), cursor.get().unwrap());

            cursor.to_next_item().unwrap();
            assert_eq!((1u64, 2u64), cursor.get().unwrap());

            cursor.to_next_item().unwrap();
            assert_eq!((1u64, 1u64), cursor.get().unwrap());

            assert!(lmdb_not_found!(cursor.to_next_item()));
        }
    }
}

<|endoftext|>


<commit_before>//! Transit - A transport layer library for Rust
//!
//! Currently supporting only UDP, the idea is to create easy abstraction layers around transport
//! protocols. Do not think about sending byte arrays around or handing sockets/file descriptors.
#![cfg_attr(test, feature(custom_derive, plugin))]
#![cfg_attr(test, plugin(serde_macros))]

extern crate serde;

#[cfg(feature = "msgpack_serialization")]
extern crate rmp_serde as msgpack;
#[cfg(feature = "json_serialization")]
extern crate serde_json;

pub mod udp;
<commit_msg>Add more documentation on lib.rs<commit_after>//! Transit - A transport layer library for Rust
//!
//! Currently supporting only UDP, the idea is to create easy abstraction layers around transport
//! protocols. Do not think about sending byte arrays around or handing sockets/file descriptors.
//!
//! For serialization, Transit depends on the `serde` framework. Both JSON encoding and Msgpack
//! encoding are supported through the use of features. Make sure to compile transit with either
//! the `json_serialization` or the `msgpack_serialization` feature.
#![cfg_attr(test, feature(custom_derive, plugin))]
#![cfg_attr(test, plugin(serde_macros))]

extern crate serde;

#[cfg(feature = "msgpack_serialization")]
extern crate rmp_serde as msgpack;
#[cfg(feature = "json_serialization")]
extern crate serde_json;

pub mod udp;
<|endoftext|>


<commit_before>//! A Undo/Redo library.
//!
//! # Example
//! ```
//! use std::rc::Rc;
//! use std::cell::RefCell;
//! use undo::{UndoCmd, UndoStack};
//!
//! /// Pops an element from a vector.
//! #[derive(Clone)]
//! struct PopCmd {
//!     vec: Rc<RefCell<Vec<i32>>>,
//!     e: Option<i32>,
//! }
//!
//! impl UndoCmd for PopCmd {
//!     fn redo(&mut self) {
//!         self.e = self.vec.borrow_mut().pop();
//!     }
//!
//!     fn undo(&mut self) {
//!         self.vec.borrow_mut().push(self.e.unwrap());
//!         self.e = None;
//!     }
//! }
//!
//! // We need to use Rc<RefCell> since all commands are going to mutate the vec.
//! let vec = Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
//! let mut undo_stack = UndoStack::new()
//!     .on_clean(|| println!("This is called when the stack changes from dirty to clean!"))
//!     .on_dirty(|| println!("This is called when the stack changes from clean to dirty!"));
//!
//! let cmd = PopCmd { vec: vec.clone(), e: None };
//! undo_stack.push(cmd.clone());
//! undo_stack.push(cmd.clone());
//! undo_stack.push(cmd.clone());
//!
//! assert_eq!(vec.borrow().len(), 7);
//!
//! undo_stack.undo();
//! undo_stack.undo();
//! undo_stack.undo();
//!
//! assert_eq!(vec.borrow().len(), 10);
//! ```

/// Every command needs to implement the `UndoCmd` trait to be able to be used with the `UndoStack`.
pub trait UndoCmd {
    /// Executes the desired command.
    fn redo(&mut self);
    /// Restores the state as it was before `redo` was called.
    fn undo(&mut self);
}

/// `UndoStack` maintains a stack of `UndoCmd`s that can be undone and redone by using methods
/// on the `UndoStack`.
///
/// `UndoStack` will notice when it's state changes to either dirty or clean, and the user can
/// set methods that should be called for either state change. This is useful for example if
/// you want to automatically enable or disable undo or redo buttons based on there are any
/// more actions that can be undone or redone.
pub struct UndoStack<T: UndoCmd> {
    stack: Vec<T>,
    len: usize,
    on_clean: Option<Box<FnMut()>>,
    on_dirty: Option<Box<FnMut()>>,
}

impl<T: UndoCmd> UndoStack<T> {
    pub fn new() -> Self {
        UndoStack {
            stack: Vec::new(),
            len: 0,
            on_clean: None,
            on_dirty: None,
        }
    }

    pub fn with_capacity(capacity: usize) -> Self {
        UndoStack {
            stack: Vec::with_capacity(capacity),
            len: 0,
            on_clean: None,
            on_dirty: None,
        }
    }

    pub fn on_clean<F: FnMut() + 'static>(mut self, f: F) -> Self {
        self.on_clean = Some(Box::new(f));
        self
    }

    pub fn on_dirty<F: FnMut() + 'static>(mut self, f: F) -> Self {
        self.on_dirty = Some(Box::new(f));
        self
    }

    pub fn is_clean(&self) -> bool {
        self.len == self.stack.len()
    }

    pub fn is_dirty(&self) -> bool {
        !self.is_clean()
    }

    pub fn push(&mut self, mut cmd: T) {
        let is_dirty = self.is_dirty();
        self.stack.truncate(self.len);
        cmd.redo();
        self.stack.push(cmd);
        self.len += 1;
        // Check if stack went from dirty to clean.
        if is_dirty == self.is_clean() {
            if let Some(ref mut f) = self.on_clean {
                f();
            }
        }
    }

    pub fn redo(&mut self) {
        let len = self.stack.len();
        if len != 0 && self.len < len {
            let is_dirty = self.is_dirty();
            {
                let ref mut cmd = self.stack[self.len - 1];
                cmd.redo();
            }
            self.len += 1;
            // Check if stack went from dirty to clean.
            if is_dirty == self.is_clean() {
                if let Some(ref mut f) = self.on_clean {
                    f();
                }
            }
        }
    }

    pub fn undo(&mut self) {
        if !self.stack.is_empty() {
            let is_clean = self.is_clean();
            {
                let ref mut cmd = self.stack[self.len - 1];
                cmd.undo();
            }
            self.len -= 1;
            // Check if stack went from clean to dirty.
            if is_clean == self.is_dirty() {
                if let Some(ref mut f) = self.on_dirty {
                    f();
                }
            }
        }
    }
}

#[cfg(test)]
mod test {
    use {UndoStack, UndoCmd};

    #[test]
    fn pop() {
        use std::rc::Rc;
        use std::cell::RefCell;

        /// Pops an element from a vector.
        #[derive(Clone)]
        struct PopCmd {
            vec: Rc<RefCell<Vec<i32>>>,
            e: Option<i32>,
        }

        impl UndoCmd for PopCmd {
            fn redo(&mut self) {
                self.e = self.vec.borrow_mut().pop();
            }

            fn undo(&mut self) {
                self.vec.borrow_mut().push(self.e.unwrap());
                self.e = None;
            }
        }

        // We need to use Rc<RefCell> since all commands are going to mutate the vec.
        let vec = Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
        let mut undo_stack = UndoStack::with_capacity(3);

        let cmd = PopCmd { vec: vec.clone(), e: None };
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());

        assert!(vec.borrow().is_empty());

        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();

        assert_eq!(vec, Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9])));
    }
}
<commit_msg>Add documentation and fix bug in redo method<commit_after>//! A Undo/Redo library.
//!
//! It uses the [Command Pattern](https://en.wikipedia.org/wiki/Command_pattern) where the user
//! implements the `UndoCmd` trait for each command and then the commands can be used with the
//! `UndoStack`.
//!
//! The `UndoStack` has two different states, the clean state and the dirty state. The `UndoStack`
//! is in a clean state when there are no more commands that can be redone, otherwise it's in a dirty
//! state.
//!
//! # Example
//! ```
//! use std::rc::Rc;
//! use std::cell::RefCell;
//! use undo::{UndoCmd, UndoStack};
//!
//! /// Pops an element from a vector.
//! #[derive(Clone)]
//! struct PopCmd {
//!     vec: Rc<RefCell<Vec<i32>>>,
//!     e: Option<i32>,
//! }
//!
//! impl UndoCmd for PopCmd {
//!     fn redo(&mut self) {
//!         self.e = self.vec.borrow_mut().pop();
//!     }
//!
//!     fn undo(&mut self) {
//!         self.vec.borrow_mut().push(self.e.unwrap());
//!         self.e = None;
//!     }
//! }
//!
//! // We need to use Rc<RefCell> since all commands are going to mutate the vec.
//! let vec = Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
//! let mut undo_stack = UndoStack::new()
//!     .on_clean(|| println!("This is called when the stack changes from dirty to clean!"))
//!     .on_dirty(|| println!("This is called when the stack changes from clean to dirty!"));
//!
//! let cmd = PopCmd { vec: vec.clone(), e: None };
//! undo_stack.push(cmd.clone());
//! undo_stack.push(cmd.clone());
//! undo_stack.push(cmd.clone());
//!
//! assert_eq!(vec.borrow().len(), 7);
//!
//! undo_stack.undo(); // on_dirty is going to be called here.
//! undo_stack.undo();
//! undo_stack.undo();
//!
//! assert_eq!(vec.borrow().len(), 10);
//! ```

/// Every command needs to implement the `UndoCmd` trait to be able to be used with the `UndoStack`.
pub trait UndoCmd {
    /// Executes the desired command.
    fn redo(&mut self);
    /// Restores the state as it was before `redo` was called.
    fn undo(&mut self);
}

/// `UndoStack` maintains a stack of `UndoCmd`s that can be undone and redone by using methods
/// on the `UndoStack`.
///
/// `UndoStack` will notice when it's state changes to either dirty or clean, and the user can
/// set methods that should be called for either state change. This is useful for example if
/// you want to automatically enable or disable undo or redo buttons based on there are any
/// more actions that can be undone or redone.
///
/// Note: An empty `UndoStack` is clean, so the first push will not trigger the clean method.
pub struct UndoStack<'a, T: UndoCmd> {
    stack: Vec<T>,
    len: usize,
    on_clean: Option<Box<FnMut() + 'a>>,
    on_dirty: Option<Box<FnMut() + 'a>>,
}

impl<'a, T: UndoCmd> UndoStack<'a, T> {
    /// Creates a new `UndoStack`.
    pub fn new() -> Self {
        UndoStack {
            stack: Vec::new(),
            len: 0,
            on_clean: None,
            on_dirty: None,
        }
    }

    /// Creates a new `UndoStack` with the specified capacity.
    pub fn with_capacity(capacity: usize) -> Self {
        UndoStack {
            stack: Vec::with_capacity(capacity),
            len: 0,
            on_clean: None,
            on_dirty: None,
        }
    }

    /// Sets what should happen if the state changes from dirty to clean.
    /// By default the `UndoStack` does nothing when the state changes.
    /// Consumes the `UndoStack` so this method should be called when creating the `UndoStack`.
    pub fn on_clean<F: FnMut() + 'a>(mut self, f: F) -> Self {
        self.on_clean = Some(Box::new(f));
        self
    }

    /// Sets what should happen if the state changes from clean to dirty.
    /// By default the `UndoStack` does nothing when the state changes.
    /// Consumes the `UndoStack` so this method should be called when creating the `UndoStack`.
    pub fn on_dirty<F: FnMut() + 'a>(mut self, f: F) -> Self {
        self.on_dirty = Some(Box::new(f));
        self
    }

    /// Returns true if the state of `UndoStack` is clean.
    pub fn is_clean(&self) -> bool {
        self.len == self.stack.len()
    }

    /// Returns true if the state of `UndoStack` is dirty.
    pub fn is_dirty(&self) -> bool {
        !self.is_clean()
    }

    /// Pushes a `UndoCmd` to the top of the `UndoStack` and executes its `redo()` method.
    /// This pops off all `UndoCmd`s that is above the active `UndoCmd` from the `UndoStack`.
    pub fn push(&mut self, mut cmd: T) {
        let is_dirty = self.is_dirty();
        self.stack.truncate(self.len);
        cmd.redo();
        self.stack.push(cmd);
        self.len = self.stack.len();
        // Check if stack went from dirty to clean.
        if is_dirty {
            if let Some(ref mut f) = self.on_clean {
                f();
            }
        }
    }

    /// Calls the `redo()` method for the active `UndoCmd` and sets the next `UndoCmd` as the new
    /// active `UndoCmd`.
    pub fn redo(&mut self) {
        if self.len < self.stack.len() {
            let is_dirty = self.is_dirty();
            self.len += 1;
            {
                let ref mut cmd = self.stack[self.len - 1];
                cmd.redo();
            }
            // Check if stack went from dirty to clean.
            if is_dirty == self.is_clean() {
                if let Some(ref mut f) = self.on_clean {
                    f();
                }
            }
        }
    }

    /// Calls the `undo()` method for the active `UndoCmd` and sets the previous `UndoCmd` as the
    /// new active `UndoCmd`.
    pub fn undo(&mut self) {
        if !self.stack.is_empty() {
            let is_clean = self.is_clean();
            {
                let ref mut cmd = self.stack[self.len - 1];
                cmd.undo();
            }
            self.len -= 1;
            // Check if stack went from clean to dirty.
            if is_clean == self.is_dirty() {
                if let Some(ref mut f) = self.on_dirty {
                    f();
                }
            }
        }
    }
}

#[cfg(test)]
mod test {
    use {UndoStack, UndoCmd};

    #[test]
    fn pop() {
        use std::rc::Rc;
        use std::cell::{Cell, RefCell};

        /// Pops an element from a vector.
        #[derive(Clone)]
        struct PopCmd {
            vec: Rc<RefCell<Vec<i32>>>,
            e: Option<i32>,
        }

        impl UndoCmd for PopCmd {
            fn redo(&mut self) {
                self.e = self.vec.borrow_mut().pop();
            }

            fn undo(&mut self) {
                self.vec.borrow_mut().push(self.e.unwrap());
                self.e = None;
            }
        }

        let a = Cell::new(0);
        let b = Cell::new(0);
        // We need to use Rc<RefCell> since all commands are going to mutate the vec.
        let vec = Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
        let mut undo_stack = UndoStack::with_capacity(3)
            .on_clean(|| a.set(1))
            .on_dirty(|| b.set(1));

        let cmd = PopCmd { vec: vec.clone(), e: None };
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());
        undo_stack.push(cmd.clone());

        assert!(vec.borrow().is_empty());

        assert_eq!(b.get(), 0);
        undo_stack.undo();
        assert_eq!(b.get(), 1);
        b.set(0);

        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();
        undo_stack.undo();

        assert_eq!(vec, Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9])));

        assert_eq!(a.get(), 0);
        undo_stack.push(cmd.clone());
        assert_eq!(a.get(), 1);
        a.set(0);

        assert_eq!(vec, Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8])));

        assert_eq!(b.get(), 0);
        undo_stack.undo();
        assert_eq!(b.get(), 1);
        b.set(0);

        assert_eq!(vec, Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9])));

        assert_eq!(a.get(), 0);
        undo_stack.redo();
        assert_eq!(a.get(), 1);
        a.set(0);

        assert_eq!(vec, Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8])));
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::io::prelude::*;

enum DomainOrIPAddressLiteral<'a> {
    ADomain(Domain<'a>),
    IPAddressLiteral(&'a str), // TODO: Better type
}

// TODO: Better type:
type Domain<'a> = &'a str;

// TODO: Better type:
type Postmaster<'a> = &'a str;

fn postmaster<'a>() -> &'a str {
    "Postmaster"
}

enum AddressOrPostmaster<'a> {
    AnAddress(Address<'a>),
    Postmaster,
}

struct Address<'a> {
    local_part: &'a str, // TODO: Better type
    domain: Domain<'a>,
}

enum OneOrMore<T> {
    One(T),
    More(T, Box<OneOrMore<T>>),
}

enum ProtocolExtension {
    EightBitMIME, // TODO: List more
}

struct Envelope<'a> {
    originator: Address<'a>,
    recipients: OneOrMore<Address<'a>>,
    protocol_extensions: Vec<ProtocolExtension>,
}

struct Header<'a> {
    fields: BTreeMap<&'a str, &'a str>, // TODO: Case-insensitivity
}

struct Content<'a> {
    header: Header<'a>,
    body: &'a str, // TODO: Better type
}

struct MailObject<'a> {
    envelope: Envelope<'a>,
    content: Content<'a>,
}

// TODO: Better types:
type ReversePath<'a> = &'a str;
type MailParameter<'a> = &'a str;
type RecipientParameter<'a> = &'a str;

enum SMTPCommand<'a> {
    Hello(Domain<'a>),
    ExtendedHello(DomainOrIPAddressLiteral<'a>),
    Mail(ReversePath<'a>, Vec<MailParameter<'a>>),
    Recipient(Vec<AddressOrPostmaster<'a>>, Vec<RecipientParameter<'a>>),
    Data,
    Reset,
    Verify(&'a str), // TODO: Better type
    Expand(&'a str), // TODO: Better type
    Help(Option<&'a str>), // TODO: Better type
    NoOp(Option<&'a str>), // TODO: Better type
    Quit,
}

fn serialize_helo(domain: Domain) -> String {
    format!("HELO {}", domain)
}

fn serialize_ehlo(domain_or_ip_address_literal: DomainOrIPAddressLiteral) -> String {
    let host = match domain_or_ip_address_literal {
        DomainOrIPAddressLiteral::ADomain(domain) => domain,
        DomainOrIPAddressLiteral::IPAddressLiteral(ip) => ip,
    };
    format!("EHLO {}", host)

}

type ExtendedHelloGreet<'a> = &'a str; // TODO: Better type
type ExtendedHelloLine<'a> = &'a str; // TODO: Better type

enum SMTPResponse<'a> {
    ExtendedHelloOkResponse(Domain<'a>, Option<ExtendedHelloGreet<'a>>, Vec<ExtendedHelloLine<'a>>),
}

fn serialize(command: SMTPCommand) -> String {
    match command {
        SMTPCommand::Hello(domain) => serialize_helo(domain),
        SMTPCommand::ExtendedHello(domain_or_ip_address_literal) => serialize_ehlo(domain_or_ip_address_literal),
        _ => "OOPS!".to_string(),
    }
}

fn send_command(stream: &mut Write, command: SMTPCommand) -> std::io::Result<usize> {
    stream.write(serialize(command).as_bytes())
}

#[test]
fn it_works() {
    let mail_object = MailObject {
        envelope: Envelope {
            originator: Address {
                local_part: "kyle.marek.spartz",
                domain: "gmail.com",
            },
            recipients: OneOrMore::More(Address {
                                            local_part: "zeckalpha",
                                            domain: "gmail.com",
                                        },
                                        Box::new(OneOrMore::One(Address {
                                            local_part: "kyle",
                                            domain: "marek-spartz.org",
                                        }))),
            protocol_extensions: vec![
                ProtocolExtension::EightBitMIME,
            ],
        },
        content: Content {
            header: Header {
                fields: {
                    let mut fields = BTreeMap::new();
                    fields.insert("orig-date", "...");
                    fields.insert("from", "kyle.marek.spartz@gmail.com");
                    fields
                },
            },
            body: "LOL",
        },
    };
    assert_eq!("LOL", mail_object.content.body);
}

#[test]
fn send_command_sends_hello() {
    extern crate tempfile;
    use std::io::{Write, Read, Seek, SeekFrom};

    let mut temp_file = tempfile::TempFile::new().unwrap();
    let mut content = String::new();
    let hello = SMTPCommand::Hello("mail.google.com");

    assert_eq!(20, send_command(&mut temp_file, hello).ok().unwrap());

    temp_file.flush();
    temp_file.seek(SeekFrom::Start(0)).unwrap();

    assert_eq!(20, temp_file.read_to_string(&mut content).ok().unwrap());
    assert_eq!("HELO mail.google.com", content);
}

#[test]
fn hello_serializes() {
    let hello_google = SMTPCommand::Hello("mail.google.com");
    let hello_yahoo = SMTPCommand::Hello("mail.yahoo.com");

    assert_eq!("HELO mail.google.com", serialize(hello_google));
    assert_eq!("HELO mail.yahoo.com", serialize(hello_yahoo));
}

#[test]
fn extended_hello_serializes() {
    let extended_hello_google = SMTPCommand::ExtendedHello(DomainOrIPAddressLiteral::ADomain("mail.google.com"));
    let extended_hello_yahoo = SMTPCommand::ExtendedHello(DomainOrIPAddressLiteral::ADomain("mail.yahoo.com"));

    assert_eq!("EHLO mail.google.com", serialize(extended_hello_google));
    assert_eq!("EHLO mail.yahoo.com", serialize(extended_hello_yahoo));
}
<commit_msg>Clean warnings<commit_after>#![allow(dead_code)]

use std::collections::BTreeMap;
use std::io::prelude::*;

enum DomainOrIPAddressLiteral<'a> {
    ADomain(Domain<'a>),
    IPAddressLiteral(&'a str), // TODO: Better type
}

// TODO: Better type:
type Domain<'a> = &'a str;

// TODO: Better type:
type Postmaster<'a> = &'a str;

fn postmaster<'a>() -> &'a str {
    "Postmaster"
}

enum AddressOrPostmaster<'a> {
    AnAddress(Address<'a>),
    Postmaster,
}

struct Address<'a> {
    local_part: &'a str, // TODO: Better type
    domain: Domain<'a>,
}

enum OneOrMore<T> {
    One(T),
    More(T, Box<OneOrMore<T>>),
}

enum ProtocolExtension {
    EightBitMIME, // TODO: List more
}

struct Envelope<'a> {
    originator: Address<'a>,
    recipients: OneOrMore<Address<'a>>,
    protocol_extensions: Vec<ProtocolExtension>,
}

struct Header<'a> {
    fields: BTreeMap<&'a str, &'a str>, // TODO: Case-insensitivity
}

struct Content<'a> {
    header: Header<'a>,
    body: &'a str, // TODO: Better type
}

struct MailObject<'a> {
    envelope: Envelope<'a>,
    content: Content<'a>,
}

// TODO: Better types:
type ReversePath<'a> = &'a str;
type MailParameter<'a> = &'a str;
type RecipientParameter<'a> = &'a str;

enum SMTPCommand<'a> {
    Hello(Domain<'a>),
    ExtendedHello(DomainOrIPAddressLiteral<'a>),
    Mail(ReversePath<'a>, Vec<MailParameter<'a>>),
    Recipient(Vec<AddressOrPostmaster<'a>>, Vec<RecipientParameter<'a>>),
    Data,
    Reset,
    Verify(&'a str), // TODO: Better type
    Expand(&'a str), // TODO: Better type
    Help(Option<&'a str>), // TODO: Better type
    NoOp(Option<&'a str>), // TODO: Better type
    Quit,
}

fn serialize_helo(domain: Domain) -> String {
    format!("HELO {}", domain)
}

fn serialize_ehlo(domain_or_ip_address_literal: DomainOrIPAddressLiteral) -> String {
    let host = match domain_or_ip_address_literal {
        DomainOrIPAddressLiteral::ADomain(domain) => domain,
        DomainOrIPAddressLiteral::IPAddressLiteral(ip) => ip,
    };
    format!("EHLO {}", host)

}

type ExtendedHelloGreet<'a> = &'a str; // TODO: Better type
type ExtendedHelloLine<'a> = &'a str; // TODO: Better type

enum SMTPResponse<'a> {
    ExtendedHelloOkResponse(Domain<'a>, Option<ExtendedHelloGreet<'a>>, Vec<ExtendedHelloLine<'a>>),
}

fn serialize(command: SMTPCommand) -> String {
    match command {
        SMTPCommand::Hello(domain) => serialize_helo(domain),
        SMTPCommand::ExtendedHello(domain_or_ip_address_literal) => serialize_ehlo(domain_or_ip_address_literal),
        _ => "OOPS!".to_string(),
    }
}

fn send_command(stream: &mut Write, command: SMTPCommand) -> std::io::Result<usize> {
    stream.write(serialize(command).as_bytes())
}

#[test]
fn it_works() {
    let mail_object = MailObject {
        envelope: Envelope {
            originator: Address {
                local_part: "kyle.marek.spartz",
                domain: "gmail.com",
            },
            recipients: OneOrMore::More(Address {
                                            local_part: "zeckalpha",
                                            domain: "gmail.com",
                                        },
                                        Box::new(OneOrMore::One(Address {
                                            local_part: "kyle",
                                            domain: "marek-spartz.org",
                                        }))),
            protocol_extensions: vec![
                ProtocolExtension::EightBitMIME,
            ],
        },
        content: Content {
            header: Header {
                fields: {
                    let mut fields = BTreeMap::new();
                    fields.insert("orig-date", "...");
                    fields.insert("from", "kyle.marek.spartz@gmail.com");
                    fields
                },
            },
            body: "LOL",
        },
    };
    assert_eq!("LOL", mail_object.content.body);
}

#[test]
fn send_command_sends_hello() {
    extern crate tempfile;
    use std::io::{Write, Read, Seek, SeekFrom};

    let mut temp_file = tempfile::TempFile::new().unwrap();
    let mut content = String::new();
    let hello = SMTPCommand::Hello("mail.google.com");

    assert_eq!(20, send_command(&mut temp_file, hello).ok().unwrap());

    let _ = temp_file.flush();
    temp_file.seek(SeekFrom::Start(0)).unwrap();

    assert_eq!(20, temp_file.read_to_string(&mut content).ok().unwrap());
    assert_eq!("HELO mail.google.com", content);
}

#[test]
fn hello_serializes() {
    let hello_google = SMTPCommand::Hello("mail.google.com");
    let hello_yahoo = SMTPCommand::Hello("mail.yahoo.com");

    assert_eq!("HELO mail.google.com", serialize(hello_google));
    assert_eq!("HELO mail.yahoo.com", serialize(hello_yahoo));
}

#[test]
fn extended_hello_serializes() {
    let extended_hello_google = SMTPCommand::ExtendedHello(DomainOrIPAddressLiteral::ADomain("mail.google.com"));
    let extended_hello_yahoo = SMTPCommand::ExtendedHello(DomainOrIPAddressLiteral::ADomain("mail.yahoo.com"));

    assert_eq!("EHLO mail.google.com", serialize(extended_hello_google));
    assert_eq!("EHLO mail.yahoo.com", serialize(extended_hello_yahoo));
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(asm)]
#![feature(int_uint)]
#![feature(simd)]
#![feature(slicing_syntax)]

#![allow(unstable)]

extern crate "rustc-serialize" as serialize;
extern crate time;
#[cfg(test)] extern crate test;

pub mod aes;
pub mod aessafe;
pub mod bcrypt;
pub mod bcrypt_pbkdf;
pub mod blake2b;
pub mod blockmodes;
pub mod blowfish;
pub mod buffer;
pub mod chacha20;
mod cryptoutil;
pub mod curve25519;
pub mod digest;
pub mod ed25519;
pub mod fortuna;
pub mod ghash;
pub mod hmac;
pub mod mac;
pub mod md5;
pub mod pbkdf2;
pub mod poly1305;
pub mod rc4;
pub mod ripemd160;
pub mod salsa20;
pub mod scrypt;
pub mod sha1;
pub mod sha2;
pub mod symmetriccipher;
pub mod util;

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub mod aesni;
<commit_msg>Add #![feature(box_syntax)] to lib.rs to silence errors using boxing syntax until box syntax stabilizes<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(asm)]
#![feature(box_syntax)]
#![feature(int_uint)]
#![feature(simd)]
#![feature(slicing_syntax)]

#![allow(unstable)]

extern crate "rustc-serialize" as serialize;
extern crate time;
#[cfg(test)] extern crate test;

pub mod aes;
pub mod aessafe;
pub mod bcrypt;
pub mod bcrypt_pbkdf;
pub mod blake2b;
pub mod blockmodes;
pub mod blowfish;
pub mod buffer;
pub mod chacha20;
mod cryptoutil;
pub mod curve25519;
pub mod digest;
pub mod ed25519;
pub mod fortuna;
pub mod ghash;
pub mod hmac;
pub mod mac;
pub mod md5;
pub mod pbkdf2;
pub mod poly1305;
pub mod rc4;
pub mod ripemd160;
pub mod salsa20;
pub mod scrypt;
pub mod sha1;
pub mod sha2;
pub mod symmetriccipher;
pub mod util;

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub mod aesni;
<|endoftext|>


<commit_before>//! A Hamelin process-hosting backend.
#![feature(collections, io, old_io, old_path)]

extern crate mio;
extern crate nix;

use std::borrow::ToOwned;
use std::io::{Error, ErrorKind, Result};
use std::io::ErrorKind::{Other, TimedOut};
use std::old_io::{IoError, IoErrorKind, Writer};
use std::old_io::process::{Command, Process};
use std::old_path::BytesContainer;
use std::os::unix::prelude::*;
use std::str::from_utf8;
use mio::{FromFd, TryRead, TryWrite, PipeReader};
use nix::fcntl::{O_NONBLOCK, O_CLOEXEC, fcntl};
use nix::fcntl::FcntlArg::F_SETFL;
use nix::unistd::close;

/// A Hamelin daemon.
pub struct Hamelin {
    process: String,
    args: Option<Vec<String>>,
}

impl Hamelin {
    /// Constructs a Hamelin daemon from the process and optionally arguments.
    pub fn new(process: &str, args: Option<&[String]>) -> Hamelin {
        Hamelin {
            process: process.to_owned(),
            args: args.map(|s| s.to_owned()),
        }
    }

    /// Spawns a Hamelin server from the daemon.
    pub fn spawn(&self) -> Result<HamelinGuard> {
        let client_str = format!("{} ({:?})", self.process, self.args);
        let mut cmd = Command::new(&self.process);
        cmd.env_set_all(&[("H-VERSION", "hamelin.rs"),
                          ("H-TYPE", "HAMELIN.RS-GENERIC-0.1"),
                          ("H-CLIENT", &client_str)]);
        if let Some(ref args) = self.args {
            cmd.args(args);
        }
        Ok(HamelinGuard::new(try!(cmd.spawn().map_err(convert_io_error))))
    }

    /// Spawns a Hamelin server from the daemon using the specified environment variables.
    pub fn spawn_with_env<T, U>(&self, env: &[(T, U)]) -> Result<HamelinGuard>
        where T: BytesContainer, U: BytesContainer {
        let mut cmd = Command::new(&self.process);
        cmd.env_set_all(env);
        cmd.env("H-VERSION", "hamelin.rs");
        if let Some(ref args) = self.args {
            cmd.args(args);
        }
        Ok(HamelinGuard::new(try!(cmd.spawn().map_err(convert_io_error))))
    }
}

/// A Hamelin server.
pub struct HamelinGuard {
    process: Process,
    alr: AsyncLineReader,
}

impl HamelinGuard {
    /// Creates a new Hamelin server from the specified process.
    pub fn new(process: Process) -> HamelinGuard {
        let pipe = process.stdout.as_ref().map(|s| s.clone()).unwrap();
        let fd = pipe.as_raw_fd();
        fcntl(fd, F_SETFL(O_NONBLOCK | O_CLOEXEC)).unwrap();
        HamelinGuard {
            process: process,
            alr: AsyncLineReader::new(FromFd::from_fd(fd)),
        }
    }

    /// Writes a line to the server's stdin.
    pub fn write_line(&mut self, line: &str) -> Result<()> {
        self.process.stdin.as_mut().map(|mut s| s.write_line(line)).unwrap()
            .map_err(convert_io_error)
    }

    /// Reads a line asynchronously from the server's stdout.
    pub fn read_line(&mut self) -> Result<String> {
        self.alr.read_line()
    }

    /// Closes the server's stdin.
    pub fn eof(&mut self) -> Result<()> {
        self.process.stdin.as_ref().map(|s| close(s.as_raw_fd())).unwrap().map_err(|_|
            Error::new(Other, "Failed to close stdin.")
        )
    }

    /// Awaits the completion of the server.
    pub fn wait(&mut self) -> Result<()> {
        self.process.wait().map(|_| ()).map_err(convert_io_error)
    }

    /// Sends a kill signal to the server.
    pub fn kill(&mut self) -> Result<()> {
        try!(self.process.signal_exit().map_err(convert_io_error));
        self.process.set_timeout(Some(1000));
        if let Ok(_) = self.process.wait() {
            return Ok(())
        }
        self.process.signal_kill().map_err(convert_io_error)
    }
}

struct AsyncLineReader { read: PipeReader, buf: Vec<u8> }

impl AsyncLineReader {
    pub fn new(pr: PipeReader) -> AsyncLineReader {
        AsyncLineReader { read: pr, buf: Vec::new() }
    }

    pub fn read_line(&mut self) -> Result<String> {
        if let Some(pos) = self.buf.iter().position(|x| x == &b'\n') {
            let mut rest = self.buf.split_off(pos);
            rest.remove(0);
            let result = from_utf8(&self.buf).unwrap().to_owned();
            self.buf = rest;
            return Ok(result);
        }
        let mut buf = [0; 100];
        match self.read.read_slice(&mut buf) {
            Ok(None) => {
                return Err(Error::new(TimedOut, "Reading would've blocked."))
            },
            Ok(Some(size)) => {
                self.buf.extend(buf[..size].iter().map(|x| *x));
                match self.buf.iter().position(|x| x == &b'\n') {
                    Some(pos) => {
                        let mut rest = self.buf.split_off(pos);
                        rest.remove(0);
                        let result = from_utf8(&self.buf).unwrap().to_owned();
                        self.buf = rest;
                        return Ok(result);
                    }
                    None => {
                        return Err(Error::new(TimedOut, "Reading would've blocked."))
                    }
                }
            }
            Err(_) => Err(Error::new(TimedOut, "Reading would've blocked."))
        }
    }
}

pub struct AsyncBufStream<T: TryRead + TryWrite> {
    pub stream: T,
    read_buf: Vec<u8>
}

impl<T: TryRead + TryWrite> AsyncBufStream<T> {
    pub fn new(stream: T) -> AsyncBufStream<T> {
        AsyncBufStream { stream: stream, read_buf: Vec::new() }
    }

    pub fn read_line(&mut self) -> Result<String> {
        if let Some(pos) = self.read_buf.iter().position(|x| x == &b'\n') {
            let mut rest = self.read_buf.split_off(pos);
            rest.remove(0);
            let result = from_utf8(&self.read_buf).unwrap().to_owned();
            self.read_buf = rest;
            return Ok(result);
        } else if let Some(_) = self.read_buf.iter().position(|x| x == &4) {
            return Err(Error::new(Other, "End of File reached."));
        }
        let mut buf = [0; 100];
        match self.stream.read_slice(&mut buf) {
            Ok(None) => Err(Error::new(TimedOut, "Reading would've blocked.")),
            Ok(Some(0)) => Err(Error::new(TimedOut, "Reading would've blocked.")),
            Ok(Some(size)) => {
                self.read_buf.extend(buf[..size].iter().map(|x| *x));
                match self.read_buf.iter().position(|x| x == &b'\n') {
                    Some(pos) => {
                        let mut rest = self.read_buf.split_off(pos);
                        rest.remove(0);
                        let result = from_utf8(&self.read_buf).unwrap().to_owned();
                        self.read_buf = rest;
                        return Ok(result);
                    }
                    None => {
                        return Err(Error::new(TimedOut, "Reading would've blocked."))
                    }
                }
            }
            Err(_) => Err(Error::new(TimedOut, "Reading would've blocked."))
        }
    }

    pub fn write_line(&mut self, s: &str) -> Result<()> {
        match self.stream.write_slice(&s.as_bytes()) {
            Ok(None) => Err(Error::new(TimedOut, "Writing would've blocked.")),
            Ok(Some(0)) => Err(Error::new(Other, "End of File reached.")),
            Ok(Some(_)) => {
                match self.stream.write_slice(b"\n") {
                    Ok(None) => Err(Error::new(TimedOut, "Writing would've blocked.")),
                    Ok(_) => Ok(()),
                    Err(_) => Err(Error::new(TimedOut, "Writing would've blocked."))
                }
            }
            Err(_) => Err(Error::new(TimedOut, "Writing would've blocked."))
        }
    }
}

fn convert_io_error(e: IoError) -> Error {
    Error::new(match e.kind {
        IoErrorKind::FileNotFound => ErrorKind::NotFound,
        IoErrorKind::PermissionDenied => ErrorKind::PermissionDenied,
        IoErrorKind::ConnectionRefused => ErrorKind::ConnectionRefused,
        IoErrorKind::ConnectionReset => ErrorKind::ConnectionReset,
        IoErrorKind::ConnectionAborted => ErrorKind::ConnectionAborted,
        IoErrorKind::NotConnected => ErrorKind::NotConnected,
        IoErrorKind::BrokenPipe => ErrorKind::BrokenPipe,
        IoErrorKind::PathAlreadyExists => ErrorKind::AlreadyExists,
        IoErrorKind::PathDoesntExist => ErrorKind::NotFound,
        IoErrorKind::InvalidInput => ErrorKind::InvalidInput,
        IoErrorKind::TimedOut => ErrorKind::TimedOut,
        IoErrorKind::ShortWrite(0) => ErrorKind::WriteZero,
        _ => ErrorKind::Other
    }, e.desc)
}
<commit_msg>Made some progress on updating for latest Rust.<commit_after>//! A Hamelin process-hosting backend.
#![feature(collections, io)]

extern crate mio;
extern crate nix;

use std::borrow::ToOwned;
use std::ffi::OsStr;
use std::io::{Error, ErrorKind, Result};
use std::io::ErrorKind::{Other, TimedOut};
use std::os::unix::io::AsRawFd;
use std::process::{Child, Command};
use std::str::from_utf8;
use mio::{Buf, MutBuf, TryRead, TryWrite};
use mio::unix::{FromRawFd, PipeReader};
use nix::fcntl::{O_NONBLOCK, O_CLOEXEC, fcntl};
use nix::fcntl::FcntlArg::F_SETFL;
use nix::unistd::close;

/// A Hamelin daemon.
pub struct Hamelin {
    child: String,
    args: Option<Vec<String>>,
}

impl Hamelin {
    /// Constructs a Hamelin daemon from the child and optionally arguments.
    pub fn new(child: &str, args: Option<&[String]>) -> Hamelin {
        Hamelin {
            child: child.to_owned(),
            args: args.map(|s| s.to_owned()),
        }
    }

    /// Spawns a Hamelin server from the daemon.
    pub fn spawn(&self) -> Result<HamelinGuard> {
        let client_str = format!("{} ({:?})", self.child, self.args);
        let mut cmd = Command::new(&self.child);
        /*[("H-VERSION", "hamelin.rs"),
         ("H-TYPE", "HAMELIN.RS-GENERIC-0.1"),
         ("H-CLIENT", &client_str)])*/
        if let Some(ref args) = self.args {
            cmd.args(args);
        }
        Ok(HamelinGuard::new(try!(cmd.spawn())))
    }

    /// Spawns a Hamelin server from the daemon using the specified environment variables.
    pub fn spawn_with_env<K, V>(&self, env: &[(K, V)]) -> Result<HamelinGuard>
        where K: AsRef<OsStr>, V: AsRef<OsStr> {
        let mut cmd = Command::new(&self.child);
        //cmd.env_set_all(env);
        cmd.env("H-VERSION", "hamelin.rs");
        if let Some(ref args) = self.args {
            cmd.args(args);
        }
        Ok(HamelinGuard::new(try!(cmd.spawn())))
    }
}

/// A Hamelin server.
pub struct HamelinGuard {
    child: Child,
    alr: AsyncLineReader,
}

impl HamelinGuard {
    /// Creates a new Hamelin server from the specified child process.
    pub fn new(child: Child) -> HamelinGuard {
        let pipe = child.stdout.as_ref().map(|s| s.clone()).unwrap();
        let fd = pipe.as_raw_fd();
        fcntl(fd, F_SETFL(O_NONBLOCK | O_CLOEXEC)).unwrap();
        HamelinGuard {
            child: child,
            alr: AsyncLineReader::new(FromRawFd::from_raw_fd(fd)),
        }
    }

    /// Writes a line to the server's stdin.
    pub fn write_line(&mut self, line: &str) -> Result<()> {
        self.child.stdin.as_mut().map(|mut s| s.write_line(line)).unwrap()

    }

    /// Reads a line asynchronously from the server's stdout.
    pub fn read_line(&mut self) -> Result<String> {
        self.alr.read_line()
    }

    /// Closes the server's stdin.
    pub fn eof(&mut self) -> Result<()> {
        self.child.stdin.as_ref().map(|s| close(s.as_raw_fd())).unwrap().map_err(|_|
            Error::new(Other, "Failed to close stdin.")
        )
    }

    /// Awaits the completion of the server.
    pub fn wait(&mut self) -> Result<()> {
        self.child.wait().map(|_| ())
    }

    /// Sends a kill signal to the server.
    pub fn kill(&mut self) -> Result<()> {
        self.child.kill()
    }
}

struct AsyncLineReader { read: PipeReader, buf: Vec<u8> }

impl AsyncLineReader {
    pub fn new(pr: PipeReader) -> AsyncLineReader {
        AsyncLineReader { read: pr, buf: Vec::new() }
    }

    pub fn read_line(&mut self) -> Result<String> {
        if let Some(pos) = self.buf.iter().position(|x| x == &b'\n') {
            let mut rest = self.buf.split_off(pos);
            rest.remove(0);
            let result = from_utf8(&self.buf).unwrap().to_owned();
            self.buf = rest;
            return Ok(result);
        }
        let mut buf = [0; 100];
        match self.read.read_slice(&mut buf) {
            Ok(None) => {
                return Err(Error::new(TimedOut, "Reading would've blocked."))
            },
            Ok(Some(size)) => {
                self.buf.extend(buf[..size].iter().map(|x| *x));
                match self.buf.iter().position(|x| x == &b'\n') {
                    Some(pos) => {
                        let mut rest = self.buf.split_off(pos);
                        rest.remove(0);
                        let result = from_utf8(&self.buf).unwrap().to_owned();
                        self.buf = rest;
                        return Ok(result);
                    }
                    None => {
                        return Err(Error::new(TimedOut, "Reading would've blocked."))
                    }
                }
            }
            Err(_) => Err(Error::new(TimedOut, "Reading would've blocked."))
        }
    }
}

pub struct AsyncBufStream<T: Buf + MutBuf + TryRead + TryWrite> {
    pub stream: T,
    read_buf: Vec<u8>
}

impl<T: Buf + MutBuf + TryRead + TryWrite> AsyncBufStream<T> {
    pub fn new(stream: T) -> AsyncBufStream<T> {
        AsyncBufStream { stream: stream, read_buf: Vec::new() }
    }

    pub fn read_line(&mut self) -> Result<String> {
        if let Some(pos) = self.read_buf.iter().position(|x| x == &b'\n') {
            let mut rest = self.read_buf.split_off(pos);
            rest.remove(0);
            let result = from_utf8(&self.read_buf).unwrap().to_owned();
            self.read_buf = rest;
            return Ok(result);
        } else if let Some(_) = self.read_buf.iter().position(|x| x == &4) {
            return Err(Error::new(Other, "End of File reached."));
        }
        let mut buf = [0; 100];
        match self.stream.read_slice(&mut buf) {
            Ok(None) => Err(Error::new(TimedOut, "Reading would've blocked.")),
            Ok(Some(0)) => Err(Error::new(TimedOut, "Reading would've blocked.")),
            Ok(Some(size)) => {
                self.read_buf.extend(buf[..size].iter().map(|x| *x));
                match self.read_buf.iter().position(|x| x == &b'\n') {
                    Some(pos) => {
                        let mut rest = self.read_buf.split_off(pos);
                        rest.remove(0);
                        let result = from_utf8(&self.read_buf).unwrap().to_owned();
                        self.read_buf = rest;
                        return Ok(result);
                    }
                    None => {
                        return Err(Error::new(TimedOut, "Reading would've blocked."))
                    }
                }
            }
            Err(_) => Err(Error::new(TimedOut, "Reading would've blocked."))
        }
    }

    pub fn write_line(&mut self, s: &str) -> Result<()> {
        self.stream.write_slice(&s.as_bytes());
        self.stream.write_slice(b"\n");
        Ok(())
    }
}
<|endoftext|>


<commit_before>#![feature(specialization)]
#![feature(test)]
extern crate test;
extern crate memchr;

#[macro_use]
extern crate log;

#[cfg(test)]
mod benchmarks;

mod boyer_moore_memchr;
mod horspool_memchr;
mod boyer_moore;
mod skip_search;
mod horspool;
// internal for benchmarks
mod naive_search;
mod memchr_search;

pub use boyer_moore::BoyerMoore;
pub use horspool::Horspool;

pub trait SearchIn<'a, H: ?Sized> {
    type Iter: Iterator<Item = usize>;
    fn find_in(&'a self, haystack: &'a H) -> Self::Iter;
    fn find_overlapping_in(&'a self, haystack: &'a H) -> Self::Iter;

    /// Finds the first occurence of the search term in haystack and returns the index if it is found.
    fn find_first_in(&'a self, haystack: &'a H) -> Option<usize> {
        self.find_in(&haystack).next()
    }
}

pub trait CountIn<'a, H: ?Sized> {
    fn count_in(&'a self, haystack: &'a H) -> usize;
    fn occurs_in(&'a self, haystack: &'a H) -> bool {
        self.count_in(&haystack) > 0
    }
}

impl <'a, H: ?Sized, S> CountIn<'a, H> for S
    where S: SearchIn<'a, H>
{
    fn count_in(&'a self, haystack: &'a H) -> usize {
        self.find_in(&haystack).count()
    }

    fn occurs_in(&'a self, haystack: &'a H) -> bool {
        self.find_first_in(&haystack).is_some()
    }
}<commit_msg>make #[feature(test)] test/bench-only<commit_after>#![feature(specialization)]
#![cfg_attr(test, feature(test))]
#![cfg(test)]
extern crate test;
extern crate memchr;

#[macro_use]
extern crate log;

#[cfg(test)]
mod benchmarks;

mod boyer_moore_memchr;
mod horspool_memchr;
mod boyer_moore;
mod skip_search;
mod horspool;
// internal for benchmarks
mod naive_search;
mod memchr_search;

pub use boyer_moore::BoyerMoore;
pub use horspool::Horspool;

pub trait SearchIn<'a, H: ?Sized> {
    type Iter: Iterator<Item = usize>;
    fn find_in(&'a self, haystack: &'a H) -> Self::Iter;
    fn find_overlapping_in(&'a self, haystack: &'a H) -> Self::Iter;

    /// Finds the first occurence of the search term in haystack and returns the index if it is found.
    fn find_first_in(&'a self, haystack: &'a H) -> Option<usize> {
        self.find_in(&haystack).next()
    }
}

pub trait CountIn<'a, H: ?Sized> {
    fn count_in(&'a self, haystack: &'a H) -> usize;
    fn occurs_in(&'a self, haystack: &'a H) -> bool {
        self.count_in(&haystack) > 0
    }
}

impl <'a, H: ?Sized, S> CountIn<'a, H> for S
    where S: SearchIn<'a, H>
{
    fn count_in(&'a self, haystack: &'a H) -> usize {
        self.find_in(&haystack).count()
    }

    fn occurs_in(&'a self, haystack: &'a H) -> bool {
        self.find_first_in(&haystack).is_some()
    }
}
<|endoftext|>


<commit_before>pub mod response;
pub use self::response::Response;
<commit_msg>rename response to json_response<commit_after>pub mod json_response;
pub use self::json_response::Response;
<|endoftext|>