<commit_before>extern crate lmdb;
extern crate lmdb_sys;

#[cfg(test)]
extern crate tempdir;

use std::{result, str};
use std::path::Path;
use lmdb::{Cursor, DUP_SORT, INTEGER_KEY};
use lmdb::Transaction as LmdbTransaction;

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum Error {
    DbCreateError,
    DbOpenError,
    DbWriteError,
    DbCorruptError,
    ParseError,
    TransactionError,
    PathError,
    NotFoundError,
    DuplicateEntryError,
}

pub type Result<T> = result::Result<T, Error>;

pub struct LmdbAdapter {
    env: lmdb::Environment,
    nodes: lmdb::Database,
    entries: lmdb::Database,
}

pub struct RwTransaction<'a>(lmdb::RwTransaction<'a>);
pub struct RoTransaction<'a>(lmdb::RoTransaction<'a>);

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub struct Id(u64);

#[derive(Debug, Eq, PartialEq)]
pub struct Node<'a> {
    pub id: Id,
    pub parent_id: Id,
    pub name: &'a str,
}

#[derive(Debug, Eq, PartialEq)]
pub struct Entry<'a> {
    pub node: Node<'a>,
    pub objectclass: &'a str,
}

// Ids are 64-bit integers in host-native byte order
// LMDB has special optimizations for host-native integers as keys
impl Id {
    fn root() -> Id {
        Id(0)
    }

    fn from_bytes(bytes: &[u8]) -> Result<Id> {
        if bytes.len() != 8 {
            return Err(Error::ParseError);
        }

        let mut id = [0u8; 8];
        id.copy_from_slice(&bytes[0..8]);

        Ok(Id(unsafe { std::mem::transmute(id) }))
    }

    fn as_bytes(self) -> [u8; 8] {
        let Id(id) = self;
        unsafe { std::mem::transmute(id) }
    }

    fn next(self) -> Id {
        let Id(id) = self;
        Id(id + 1)
    }
}

impl<'a> Node<'a> {
    fn root() -> Node<'a> {
        Node {
            id: Id::root(),
            parent_id: Id::root(),
            name: "/",
        }
    }

    fn from_parent_id_and_bytes(parent_id: Id, bytes: &[u8]) -> Result<Node> {
        if bytes.len() < 8 {
            return Err(Error::DbCorruptError);
        }

        let id = try!(Id::from_bytes(&bytes[0..8]));
        let name = try!(std::str::from_utf8(&bytes[8..]).map_err(|_err| Error::DbCorruptError));

        Ok(Node {
            id: id,
            parent_id: parent_id,
            name: name,
        })
    }

    fn to_bytes(&self) -> Vec<u8> {
        let mut bytes = Vec::with_capacity(8 + self.name.len());
        bytes.extend_from_slice(&self.id.as_bytes());
        bytes.extend_from_slice(self.name.as_bytes());
        bytes
    }
}

impl LmdbAdapter {
    pub fn create_database(path: &Path) -> Result<LmdbAdapter> {
        let env = try!(lmdb::Environment::new()
                           .set_max_dbs(8)
                           .open_with_permissions(&path, 0o600)
                           .map_err(|_err| Error::DbCreateError));

        let nodes = try!(env.create_db(Some("nodes"), INTEGER_KEY | DUP_SORT)
                            .map_err(|_err| Error::DbCreateError));

        let entries = try!(env.create_db(Some("entries"), INTEGER_KEY)
                              .map_err(|_err| Error::DbCreateError));

        Ok(LmdbAdapter {
            env: env,
            nodes: nodes,
            entries: entries,
        })
    }

    pub fn open_database(path: &Path) -> Result<LmdbAdapter> {
        let env = try!(lmdb::Environment::new().open(&path).map_err(|_err| Error::DbOpenError));

        let nodes = try!(env.open_db(Some("nodes")).map_err(|_err| Error::DbOpenError));

        let entries = try!(env.open_db(Some("entries")).map_err(|_err| Error::DbOpenError));

        Ok(LmdbAdapter {
            env: env,
            nodes: nodes,
            entries: entries,
        })
    }

    pub fn rw_transaction(&self) -> Result<RwTransaction> {
        match self.env.begin_rw_txn() {
            Ok(txn) => Ok(RwTransaction(txn)),
            Err(_) => Err(Error::TransactionError),
        }
    }

    pub fn ro_transaction(&self) -> Result<RoTransaction> {
        match self.env.begin_ro_txn() {
            Ok(txn) => Ok(RoTransaction(txn)),
            Err(_) => Err(Error::TransactionError),
        }
    }

    pub fn next_available_id<T: Transaction>(&self, txn: &T) -> Result<Id> {
        let cursor = try!(txn.open_ro_cursor(self.nodes)
                             .map_err(|_err| Error::TransactionError));

        let last_id = match cursor.get(None, None, lmdb_sys::MDB_LAST) {
            Ok((id, _)) => Id::from_bytes(id.unwrap()).unwrap(),
            Err(_) => Id::root(),
        };

        Ok(last_id.next())
    }

    pub fn create_entry<'a>(&'a self,
                            txn: &'a mut RwTransaction,
                            id: Id,
                            parent_id: Id,
                            name: &'a str,
                            objectclass: &'a str)
                            -> Result<Entry> {
        if txn.get(self.entries, &id.as_bytes()) != Err(Error::NotFoundError) {
            return Err(Error::DuplicateEntryError);
        }

        if txn.get(self.nodes, &parent_id.as_bytes()) != Err(Error::NotFoundError) &&
           self.find_child_node(txn, parent_id, name) != Err(Error::NotFoundError) {
            return Err(Error::DuplicateEntryError);
        }

        let node = Node {
            id: id,
            parent_id: parent_id,
            name: name,
        };

        try!(txn.put(self.nodes, &parent_id.as_bytes(), &node.to_bytes())
                .map_err(|_err| Error::DbWriteError));

        try!(txn.put(self.entries, &id.as_bytes(), &objectclass.as_bytes())
                .map_err(|_err| Error::DbWriteError));

        Ok(Entry {
            node: node,
            objectclass: objectclass,
        })
    }

    pub fn find_entry<'a, T: Transaction>(&'a self, txn: &'a T, path: &str) -> Result<Entry> {
        let node = try!(self.find_node(txn, path));

        let entry_bytes = try!(txn.get(self.entries, &node.id.as_bytes())
                                  .map_err(|_err| Error::DbCorruptError));

        let objectclass = try!(std::str::from_utf8(&entry_bytes)
                                   .map_err(|_err| Error::DbCorruptError));

        Ok(Entry {
            node: node,
            objectclass: objectclass,
        })
    }

    fn find_node<T: Transaction>(&self, txn: &T, path: &str) -> Result<Node> {
        let all_components: Vec<&str> = path.split("/").collect();

        if all_components.is_empty() {
            return Err(Error::PathError);
        }

        let (prefix, components) = all_components.split_first().unwrap();

        // Does the path start with something other than "/"?
        if !prefix.is_empty() {
            return Err(Error::PathError);
        }

        components.iter().fold(Ok(Node::root()), |parent_node, component| {
            self.find_child_node(txn, try!(parent_node).id, component)
        })
    }

    // TODO: since LMDB is ordered, we could e.g. perform a binary search
    fn find_child_node<T: Transaction>(&self, txn: &T, parent_id: Id, name: &str) -> Result<Node> {
        let mut cursor = try!(txn.open_ro_cursor(self.nodes)
                                 .map_err(|_err| Error::TransactionError));

        let mut child_node = None;

        for (id, node_bytes) in cursor.iter_from(parent_id.as_bytes()) {
            if id != parent_id.as_bytes() {
                return Err(Error::NotFoundError);
            }

            let node = try!(Node::from_parent_id_and_bytes(parent_id, node_bytes));

            if node.name == name {
                child_node = Some(node);
                break;
            }
        }

        child_node.ok_or(Error::NotFoundError)
    }
}

pub trait Transaction {
    fn get(&self, database: lmdb::Database, key: &[u8]) -> Result<&[u8]>;
    fn commit(self) -> Result<()>;
    fn open_ro_cursor(&self, db: lmdb::Database) -> lmdb::Result<lmdb::RoCursor>;
}

impl<'a> Transaction for RwTransaction<'a> {
    fn get(&self, database: lmdb::Database, key: &[u8]) -> Result<&[u8]> {
        self.0.get(database, &key).map_err(|_err| Error::NotFoundError)
    }

    fn commit(self) -> Result<()> {
        self.0.commit().map_err(|_err| Error::TransactionError)
    }

    fn open_ro_cursor(&self, db: lmdb::Database) -> lmdb::Result<lmdb::RoCursor> {
        self.0.open_ro_cursor(db)
    }
}

impl<'a> Transaction for RoTransaction<'a> {
    fn get(&self, database: lmdb::Database, key: &[u8]) -> Result<&[u8]> {
        self.0.get(database, &key).map_err(|_err| Error::NotFoundError)
    }

    fn commit(self) -> Result<()> {
        self.0.commit().map_err(|_err| Error::TransactionError)
    }

    fn open_ro_cursor(&self, db: lmdb::Database) -> lmdb::Result<lmdb::RoCursor> {
        self.0.open_ro_cursor(db)
    }
}

impl<'a> RwTransaction<'a> {
    fn put(&mut self, database: lmdb::Database, key: &[u8], data: &[u8]) -> Result<()> {
        self.0
            .put(database, &key, &data, lmdb::WriteFlags::empty())
            .map_err(|_err| Error::TransactionError)
    }
}

#[cfg(test)]
mod tests {
    use {LmdbAdapter, Id, Transaction, Error};
    use tempdir::TempDir;

    fn create_database() -> LmdbAdapter {
        let dir = TempDir::new("ithos-test").unwrap();
        LmdbAdapter::create_database(dir.path()).unwrap()
    }

    #[test]
    fn test_entry_lookup() {
        let adapter = create_database();

        {
            let mut txn = adapter.rw_transaction().unwrap();

            let domain_id = adapter.next_available_id(&txn).unwrap();
            adapter.create_entry(&mut txn, domain_id, Id::root(), "example.com", "domain").unwrap();

            let hosts_id = domain_id.next();
            adapter.create_entry(&mut txn, hosts_id, domain_id, "hosts", "ou").unwrap();

            let host_id = hosts_id.next();
            adapter.create_entry(&mut txn, host_id, hosts_id, "master.example.com", "host")
                   .unwrap();

            txn.commit().unwrap();
        }

        {
            let txn = adapter.ro_transaction().unwrap();

            {
                let entry = adapter.find_entry(&txn, "/example.com/hosts/master.example.com")
                                   .unwrap();

                assert_eq!(entry.node.name, "master.example.com");
                assert_eq!(entry.objectclass, "host");
            }

            txn.commit().unwrap();
        }
    }

    #[test]
    fn test_duplicate_entry_id() {
        let adapter = create_database();

        let mut txn = adapter.rw_transaction().unwrap();

        let domain_id = adapter.next_available_id(&txn).unwrap();
        adapter.create_entry(&mut txn, domain_id, Id::root(), "example.com", "domain").unwrap();

        assert_eq!(adapter.create_entry(&mut txn, domain_id, Id::root(), "another.com", "domain"),
                   Err(Error::DuplicateEntryError));
    }

    #[test]
    fn test_duplicate_entry_name() {
        let adapter = create_database();

        let mut txn = adapter.rw_transaction().unwrap();

        let domain_id = adapter.next_available_id(&txn).unwrap();
        adapter.create_entry(&mut txn, domain_id, Id::root(), "example.com", "domain").unwrap();

        assert_eq!(adapter.create_entry(&mut txn,
                                        domain_id.next(),
                                        Id::root(),
                                        "example.com",
                                        "domain"),
                   Err(Error::DuplicateEntryError));
    }
}
<commit_msg>Use a macro to impl Transaction newtypes<commit_after>extern crate lmdb;
extern crate lmdb_sys;

#[cfg(test)]
extern crate tempdir;

use std::{result, str};
use std::path::Path;
use lmdb::{Cursor, DUP_SORT, INTEGER_KEY};
use lmdb::Transaction as LmdbTransaction;

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum Error {
    DbCreateError,
    DbOpenError,
    DbWriteError,
    DbCorruptError,
    ParseError,
    TransactionError,
    PathError,
    NotFoundError,
    DuplicateEntryError,
}

pub type Result<T> = result::Result<T, Error>;

pub struct LmdbAdapter {
    env: lmdb::Environment,
    nodes: lmdb::Database,
    entries: lmdb::Database,
}

pub struct RwTransaction<'a>(lmdb::RwTransaction<'a>);
pub struct RoTransaction<'a>(lmdb::RoTransaction<'a>);

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub struct Id(u64);

#[derive(Debug, Eq, PartialEq)]
pub struct Node<'a> {
    pub id: Id,
    pub parent_id: Id,
    pub name: &'a str,
}

#[derive(Debug, Eq, PartialEq)]
pub struct Entry<'a> {
    pub node: Node<'a>,
    pub objectclass: &'a str,
}

// Ids are 64-bit integers in host-native byte order
// LMDB has special optimizations for host-native integers as keys
impl Id {
    fn root() -> Id {
        Id(0)
    }

    fn from_bytes(bytes: &[u8]) -> Result<Id> {
        if bytes.len() != 8 {
            return Err(Error::ParseError);
        }

        let mut id = [0u8; 8];
        id.copy_from_slice(&bytes[0..8]);

        Ok(Id(unsafe { std::mem::transmute(id) }))
    }

    fn as_bytes(self) -> [u8; 8] {
        let Id(id) = self;
        unsafe { std::mem::transmute(id) }
    }

    fn next(self) -> Id {
        let Id(id) = self;
        Id(id + 1)
    }
}

impl<'a> Node<'a> {
    fn root() -> Node<'a> {
        Node {
            id: Id::root(),
            parent_id: Id::root(),
            name: "/",
        }
    }

    fn from_parent_id_and_bytes(parent_id: Id, bytes: &[u8]) -> Result<Node> {
        if bytes.len() < 8 {
            return Err(Error::DbCorruptError);
        }

        let id = try!(Id::from_bytes(&bytes[0..8]));
        let name = try!(std::str::from_utf8(&bytes[8..]).map_err(|_err| Error::DbCorruptError));

        Ok(Node {
            id: id,
            parent_id: parent_id,
            name: name,
        })
    }

    fn to_bytes(&self) -> Vec<u8> {
        let mut bytes = Vec::with_capacity(8 + self.name.len());
        bytes.extend_from_slice(&self.id.as_bytes());
        bytes.extend_from_slice(self.name.as_bytes());
        bytes
    }
}

impl LmdbAdapter {
    pub fn create_database(path: &Path) -> Result<LmdbAdapter> {
        let env = try!(lmdb::Environment::new()
                           .set_max_dbs(8)
                           .open_with_permissions(&path, 0o600)
                           .map_err(|_err| Error::DbCreateError));

        let nodes = try!(env.create_db(Some("nodes"), INTEGER_KEY | DUP_SORT)
                            .map_err(|_err| Error::DbCreateError));

        let entries = try!(env.create_db(Some("entries"), INTEGER_KEY)
                              .map_err(|_err| Error::DbCreateError));

        Ok(LmdbAdapter {
            env: env,
            nodes: nodes,
            entries: entries,
        })
    }

    pub fn open_database(path: &Path) -> Result<LmdbAdapter> {
        let env = try!(lmdb::Environment::new().open(&path).map_err(|_err| Error::DbOpenError));

        let nodes = try!(env.open_db(Some("nodes")).map_err(|_err| Error::DbOpenError));

        let entries = try!(env.open_db(Some("entries")).map_err(|_err| Error::DbOpenError));

        Ok(LmdbAdapter {
            env: env,
            nodes: nodes,
            entries: entries,
        })
    }

    pub fn rw_transaction(&self) -> Result<RwTransaction> {
        match self.env.begin_rw_txn() {
            Ok(txn) => Ok(RwTransaction(txn)),
            Err(_) => Err(Error::TransactionError),
        }
    }

    pub fn ro_transaction(&self) -> Result<RoTransaction> {
        match self.env.begin_ro_txn() {
            Ok(txn) => Ok(RoTransaction(txn)),
            Err(_) => Err(Error::TransactionError),
        }
    }

    pub fn next_available_id<T: Transaction>(&self, txn: &T) -> Result<Id> {
        let cursor = try!(txn.open_ro_cursor(self.nodes)
                             .map_err(|_err| Error::TransactionError));

        let last_id = match cursor.get(None, None, lmdb_sys::MDB_LAST) {
            Ok((id, _)) => Id::from_bytes(id.unwrap()).unwrap(),
            Err(_) => Id::root(),
        };

        Ok(last_id.next())
    }

    pub fn create_entry<'a>(&'a self,
                            txn: &'a mut RwTransaction,
                            id: Id,
                            parent_id: Id,
                            name: &'a str,
                            objectclass: &'a str)
                            -> Result<Entry> {
        if txn.get(self.entries, &id.as_bytes()) != Err(Error::NotFoundError) {
            return Err(Error::DuplicateEntryError);
        }

        if txn.get(self.nodes, &parent_id.as_bytes()) != Err(Error::NotFoundError) &&
           self.find_child_node(txn, parent_id, name) != Err(Error::NotFoundError) {
            return Err(Error::DuplicateEntryError);
        }

        let node = Node {
            id: id,
            parent_id: parent_id,
            name: name,
        };

        try!(txn.put(self.nodes, &parent_id.as_bytes(), &node.to_bytes())
                .map_err(|_err| Error::DbWriteError));

        try!(txn.put(self.entries, &id.as_bytes(), &objectclass.as_bytes())
                .map_err(|_err| Error::DbWriteError));

        Ok(Entry {
            node: node,
            objectclass: objectclass,
        })
    }

    pub fn find_entry<'a, T: Transaction>(&'a self, txn: &'a T, path: &str) -> Result<Entry> {
        let node = try!(self.find_node(txn, path));

        let entry_bytes = try!(txn.get(self.entries, &node.id.as_bytes())
                                  .map_err(|_err| Error::DbCorruptError));

        let objectclass = try!(std::str::from_utf8(&entry_bytes)
                                   .map_err(|_err| Error::DbCorruptError));

        Ok(Entry {
            node: node,
            objectclass: objectclass,
        })
    }

    fn find_node<T: Transaction>(&self, txn: &T, path: &str) -> Result<Node> {
        let all_components: Vec<&str> = path.split("/").collect();

        if all_components.is_empty() {
            return Err(Error::PathError);
        }

        let (prefix, components) = all_components.split_first().unwrap();

        // Does the path start with something other than "/"?
        if !prefix.is_empty() {
            return Err(Error::PathError);
        }

        components.iter().fold(Ok(Node::root()), |parent_node, component| {
            self.find_child_node(txn, try!(parent_node).id, component)
        })
    }

    // TODO: since LMDB is ordered, we could e.g. perform a binary search
    fn find_child_node<T: Transaction>(&self, txn: &T, parent_id: Id, name: &str) -> Result<Node> {
        let mut cursor = try!(txn.open_ro_cursor(self.nodes)
                                 .map_err(|_err| Error::TransactionError));

        let mut child_node = None;

        for (id, node_bytes) in cursor.iter_from(parent_id.as_bytes()) {
            if id != parent_id.as_bytes() {
                return Err(Error::NotFoundError);
            }

            let node = try!(Node::from_parent_id_and_bytes(parent_id, node_bytes));

            if node.name == name {
                child_node = Some(node);
                break;
            }
        }

        child_node.ok_or(Error::NotFoundError)
    }
}

pub trait Transaction {
    fn get(&self, database: lmdb::Database, key: &[u8]) -> Result<&[u8]>;
    fn commit(self) -> Result<()>;
    fn open_ro_cursor(&self, db: lmdb::Database) -> lmdb::Result<lmdb::RoCursor>;
}

macro_rules! impl_transaction (($newtype:ident) => (
    impl<'a> Transaction for $newtype<'a> {
        fn get(&self, database: lmdb::Database, key: &[u8]) -> Result<&[u8]> {
            self.0.get(database, &key).map_err(|_err| Error::NotFoundError)
        }

        fn commit(self) -> Result<()> {
            self.0.commit().map_err(|_err| Error::TransactionError)
        }

        fn open_ro_cursor(&self, db: lmdb::Database) -> lmdb::Result<lmdb::RoCursor> {
            self.0.open_ro_cursor(db)
        }
    }
));

impl_transaction!(RwTransaction);
impl_transaction!(RoTransaction);

impl<'a> RwTransaction<'a> {
    fn put(&mut self, database: lmdb::Database, key: &[u8], data: &[u8]) -> Result<()> {
        self.0
            .put(database, &key, &data, lmdb::WriteFlags::empty())
            .map_err(|_err| Error::TransactionError)
    }
}

#[cfg(test)]
mod tests {
    use {LmdbAdapter, Id, Transaction, Error};
    use tempdir::TempDir;

    fn create_database() -> LmdbAdapter {
        let dir = TempDir::new("ithos-test").unwrap();
        LmdbAdapter::create_database(dir.path()).unwrap()
    }

    #[test]
    fn test_entry_lookup() {
        let adapter = create_database();

        {
            let mut txn = adapter.rw_transaction().unwrap();

            let domain_id = adapter.next_available_id(&txn).unwrap();
            adapter.create_entry(&mut txn, domain_id, Id::root(), "example.com", "domain").unwrap();

            let hosts_id = domain_id.next();
            adapter.create_entry(&mut txn, hosts_id, domain_id, "hosts", "ou").unwrap();

            let host_id = hosts_id.next();
            adapter.create_entry(&mut txn, host_id, hosts_id, "master.example.com", "host")
                   .unwrap();

            txn.commit().unwrap();
        }

        {
            let txn = adapter.ro_transaction().unwrap();

            {
                let entry = adapter.find_entry(&txn, "/example.com/hosts/master.example.com")
                                   .unwrap();

                assert_eq!(entry.node.name, "master.example.com");
                assert_eq!(entry.objectclass, "host");
            }

            txn.commit().unwrap();
        }
    }

    #[test]
    fn test_duplicate_entry_id() {
        let adapter = create_database();

        let mut txn = adapter.rw_transaction().unwrap();

        let domain_id = adapter.next_available_id(&txn).unwrap();
        adapter.create_entry(&mut txn, domain_id, Id::root(), "example.com", "domain").unwrap();

        assert_eq!(adapter.create_entry(&mut txn, domain_id, Id::root(), "another.com", "domain"),
                   Err(Error::DuplicateEntryError));
    }

    #[test]
    fn test_duplicate_entry_name() {
        let adapter = create_database();

        let mut txn = adapter.rw_transaction().unwrap();

        let domain_id = adapter.next_available_id(&txn).unwrap();
        adapter.create_entry(&mut txn, domain_id, Id::root(), "example.com", "domain").unwrap();

        assert_eq!(adapter.create_entry(&mut txn,
                                        domain_id.next(),
                                        Id::root(),
                                        "example.com",
                                        "domain"),
                   Err(Error::DuplicateEntryError));
    }
}
<|endoftext|>


<commit_before>//! Yet Another Entity Component System
// #![deny(missing_docs)]
extern crate anymap;

use anymap::AnyMap;

use std::any::Any;
use std::fmt::{Debug, Formatter, Result};

/// An `Entity` is simply an identifier for a bag of components. In general, `System`s operate on
/// a subset of all entities that posess components the `System` is interested in.
#[derive(Debug)]
pub struct Entity {
  /// A user-defined label for this entity. This could be thrown out if in future we run into
  /// memory issues, but for now its convenient as it allows us to more easily identify an entity.
  pub label: String,
  /// Bag of components
  pub components: AnyMap
}

impl Entity {
  /// Creates a new `Entity` with an empty bag of components
  pub fn new(label: &'static str) -> Entity {
    Entity {
      label: String::from(label),
      components: AnyMap::new(),
    }
  }
}

pub struct EntityBuilder(Entity);

impl EntityBuilder {
  pub fn create(label: &'static str) -> EntityBuilder {
    EntityBuilder(Entity::new(label))
  }

  pub fn add<T: Any>(mut self, component: T) -> EntityBuilder {
    self.0.components.insert(component);
    self
  }

  pub fn build(self) -> Entity {
    self.0
  }
}

pub type Globals = AnyMap;

pub trait System {
  fn process(&self, entities: &mut Vec<Entity>, globals: &mut Globals);
}

impl Debug for System {
  fn fmt(&self, f: &mut Formatter) -> Result {
    write!(f, "System")
  }
}

pub struct World {
  entities: Vec<Entity>,
  globals: Globals,
  systems: Vec<Box<System>>,
}

impl World {
  pub fn new() -> World {
    World {
      entities: vec!(),
      globals: Globals::new(),
      systems: vec!(),
    }
  }

  pub fn add_entity(&mut self, entity: Entity) {
    self.entities.push(entity);
  }

  pub fn add_global<T: Any>(&mut self, global: T) {
    self.globals.insert(global);
  }

  pub fn add_system<T: System + 'static>(&mut self, system: T) {
    self.systems.push(Box::new(system));
  }

  pub fn get_global<T: Any>(&self) -> Option<&T> {
    self.globals.get::<T>()
  }

  pub fn update(&mut self) {
    for system in &self.systems {
      (*system).process(&mut self.entities, &mut self.globals);
    }
  }
}

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

  #[derive(Debug, PartialEq)]
  struct TestComponent(u8);

  struct AnotherComponent;

  #[derive(Debug, PartialEq)]
  struct TestSystem;

  impl System for TestSystem {
    fn process(&self, _: &mut Vec<Entity>, _: &mut AnyMap) { }
  }

  #[test]
  fn entity_can_be_built() {
    let entity = EntityBuilder::create("test").build();
    assert_eq!(entity.label, "test");
  }

  #[test]
  fn entity_can_contain_components() {
    let entity = EntityBuilder::create("test")
                                .add(TestComponent(1))
                                .build();
    assert_eq!(entity.label, "test");
    assert_eq!(entity.components.get::<TestComponent>(), Some(&TestComponent(1)));
  }

  #[test]
  fn entity_has_components_works() {
    let entity = EntityBuilder::create("test")
                                .add(TestComponent(1))
                                .build();
    assert!(entity.components.contains::<TestComponent>());
    assert!(!entity.components.contains::<AnotherComponent>());

    let entity = EntityBuilder::create("test")
                                .add(AnotherComponent)
                                .build();
    assert!(!entity.components.contains::<TestComponent>());
    assert!(entity.components.contains::<AnotherComponent>());
  }

  #[test]
  fn world_can_be_created() {
    let world = World::new();
    assert!(world.entities.is_empty());
  }

  #[test]
  fn world_can_contain_entities() {
    let mut world = World::new();
    world.add_entity(EntityBuilder::create("test")
                                  .add(TestComponent(1))
                                  .build());

    assert!(!world.entities.is_empty());
    let ref entity = world.entities[0];
    assert_eq!(entity.label, "test");
    assert_eq!(entity.components.get(), Some(&TestComponent(1)));
  }

  #[test]
  fn world_can_contain_systems() {
    let mut world = World::new();

    assert!(world.systems.is_empty());
    world.add_system(TestSystem);
    assert!(!world.systems.is_empty());
  }
}
<commit_msg>Run rustfmt over the codebase.<commit_after>//! Yet Another Entity Component System
//! #![deny(missing_docs)]
extern crate anymap;

use anymap::AnyMap;

use std::any::Any;
use std::fmt::{Debug, Formatter, Result};

/// An `Entity` is simply an identifier for a bag of components. In general, `System`s operate on
/// a subset of all entities that posess components the `System` is interested in.
#[derive(Debug)]
pub struct Entity {
    /// A user-defined label for this entity. This could be thrown out if in future we run into
    /// memory issues, but for now its convenient as it allows us to more easily identify an entity.
    pub label: String,
    /// Bag of components
    pub components: AnyMap,
}

impl Entity {
    /// Creates a new `Entity` with an empty bag of components
    pub fn new(label: &'static str) -> Entity {
        Entity {
            label: String::from(label),
            components: AnyMap::new(),
        }
    }
}

pub struct EntityBuilder(Entity);

impl EntityBuilder {
    pub fn create(label: &'static str) -> EntityBuilder {
        EntityBuilder(Entity::new(label))
    }

    pub fn add<T: Any>(mut self, component: T) -> EntityBuilder {
        self.0.components.insert(component);
        self
    }

    pub fn build(self) -> Entity {
        self.0
    }
}

pub type Globals = AnyMap;

pub trait System {
    fn process(&self, entities: &mut Vec<Entity>, globals: &mut Globals);
}

impl Debug for System {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "System")
    }
}

pub struct World {
    entities: Vec<Entity>,
    globals: Globals,
    systems: Vec<Box<System>>,
}

impl World {
    pub fn new() -> World {
        World {
            entities: vec![],
            globals: Globals::new(),
            systems: vec![],
        }
    }

    pub fn add_entity(&mut self, entity: Entity) {
        self.entities.push(entity);
    }

    pub fn add_global<T: Any>(&mut self, global: T) {
        self.globals.insert(global);
    }

    pub fn add_system<T: System + 'static>(&mut self, system: T) {
        self.systems.push(Box::new(system));
    }

    pub fn get_global<T: Any>(&self) -> Option<&T> {
        self.globals.get::<T>()
    }

    pub fn update(&mut self) {
        for system in &self.systems {
            (*system).process(&mut self.entities, &mut self.globals);
        }
    }
}

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

    #[derive(Debug, PartialEq)]
    struct TestComponent(u8);

    struct AnotherComponent;

    #[derive(Debug, PartialEq)]
    struct TestSystem;

    impl System for TestSystem {
        fn process(&self, _: &mut Vec<Entity>, _: &mut AnyMap) {}
    }

    #[test]
    fn entity_can_be_built() {
        let entity = EntityBuilder::create("test").build();
        assert_eq!(entity.label, "test");
    }

    #[test]
    fn entity_can_contain_components() {
        let entity = EntityBuilder::create("test")
            .add(TestComponent(1))
            .build();
        assert_eq!(entity.label, "test");
        assert_eq!(entity.components.get::<TestComponent>(),
                   Some(&TestComponent(1)));
    }

    #[test]
    fn entity_has_components_works() {
        let entity = EntityBuilder::create("test")
            .add(TestComponent(1))
            .build();
        assert!(entity.components.contains::<TestComponent>());
        assert!(!entity.components.contains::<AnotherComponent>());

        let entity = EntityBuilder::create("test")
            .add(AnotherComponent)
            .build();
        assert!(!entity.components.contains::<TestComponent>());
        assert!(entity.components.contains::<AnotherComponent>());
    }

    #[test]
    fn world_can_be_created() {
        let world = World::new();
        assert!(world.entities.is_empty());
    }

    #[test]
    fn world_can_contain_entities() {
        let mut world = World::new();
        world.add_entity(EntityBuilder::create("test")
            .add(TestComponent(1))
            .build());

        assert!(!world.entities.is_empty());
        let ref entity = world.entities[0];
        assert_eq!(entity.label, "test");
        assert_eq!(entity.components.get(), Some(&TestComponent(1)));
    }

    #[test]
    fn world_can_contain_systems() {
        let mut world = World::new();

        assert!(world.systems.is_empty());
        world.add_system(TestSystem);
        assert!(!world.systems.is_empty());
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use std::collections::HashMap;
use rand::Rng;

/// A bigram is simply two consecutive words.
type Bigram<'a> = (&'a str, &'a str);

/// Simple order two Markov chain implementation.
///
/// The [Markov chain] is a chain of order two, which means that it
/// will use the previous two words (a bigram) when predicting the
/// next word. This is normally enough to generate random text that
/// looks somewhat plausible. The implementation is based on
/// [Generating arbitrary text with Markov chains in Rust][blog post].
///
/// [Markov chain]: https://en.wikipedia.org/wiki/Markov_chain
/// [blog post]: https://blakewilliams.me/posts/generating-arbitrary-text-with-markov-chains-in-rust
#[derive(Default)]
pub struct MarkovChain<'a> {
    map: HashMap<Bigram<'a>, Vec<&'a str>>,
}

impl<'a> MarkovChain<'a> {
    /// Create a new Markov chain. It will use a default thread-local
    /// random number generator.
    pub fn new() -> MarkovChain<'a> {
        MarkovChain { map: HashMap::new() }
    }

    /// Add new text to the Markov chain. This can be called several
    /// times to build up the chain.
    pub fn learn(&mut self, sentence: &'a str) {
        let words = sentence.split_whitespace().collect::<Vec<&str>>();
        for window in words.windows(3) {
            let (a, b, c) = (window[0], window[1], window[2]);
            self.map.entry((a, b)).or_insert(vec![]).push(c);
        }
    }

    /// Generate `n` words worth of lorem ipsum text. The text will
    /// start from a random point in the Markov chain.
    pub fn generate(&self, n: usize) -> String {
        if self.map.is_empty() {
            // The learn method has not been called.
            return String::new();
        }

        let mut rng = rand::thread_rng();
        let keys = self.map.keys().collect::<Vec<&(&str, &str)>>();
        self.generate_from(n, **rng.choose(&keys).unwrap())
    }

    /// Generate `n` words worth of lorem ipsum text. The text will
    /// start from the given bigram.
    pub fn generate_from(&self, n: usize, from: Bigram<'a>) -> String {
        let mut rng = rand::thread_rng(); // make part of struct
        let keys = self.map.keys().collect::<Vec<&Bigram>>();
        let (mut a, mut b) = from;
        let mut sentence = String::from(a) + " " + b;

        for _ in 0..n {
            while !self.map.contains_key(&(a, b)) {
                let new_key = **rng.choose(&keys).unwrap();
                a = new_key.0;
                b = new_key.1;
            }

            let next_words = &self.map[&(a, b)];
            let c = rng.choose(next_words).unwrap();
            sentence.push(' ');
            sentence.push_str(c);
            a = b;
            b = c;
        }

        return sentence;
    }
}

/// The traditional lorem ipsum text as given in [Wikipedia]. Using
/// this text alone for a Markov chain of order two doesn't work very
/// well since each bigram (two consequtive words) is followed by just
/// one other word. In other words, the Markov chain will always
/// produce the same output and recreate the lorem ipsum text
/// precisely. However, combining it with the full text in
/// [`LIBER_PRIMUS`] works well.
///
/// [Wikipedia]: https://en.wikipedia.org/wiki/Lorem_ipsum
/// [`LIBER_PRIMUS`]: constant.LIBER_PRIMUS.html
const LOREM_IPSUM: &str = include_str!("lorem-ipsum.txt");

/// The first book in Cicero's work De finibus bonorum et malorum ("On
/// the ends of good and evil"). The lorem ipsum text in
/// [`LOREM_IPSUM`] is derived from part of this text.
///
/// [`LOREM_IPSUM`]: constant.LOREM_IPSUM.html
const LIBER_PRIMUS: &str = include_str!("liber-primus.txt");

/// Generate a standard lorem ipsum text.
pub fn lipsum() -> String {
    String::from(LOREM_IPSUM)
}

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

    #[test]
    fn starts_with_lorem_ipsum() {
        assert_eq!(&lipsum()[..11], "Lorem ipsum");
    }

    #[test]
    fn empty_chain() {
        let chain = MarkovChain::new();
        assert_eq!(chain.generate(10), "");
    }

    #[test]
    fn generate_from() {
        let mut chain = MarkovChain::new();
        chain.learn("foo bar baz quuz");
        assert_eq!(chain.generate_from(1, ("foo", "bar")), "foo bar baz");
        assert_eq!(chain.generate_from(1, ("bar", "baz")), "bar baz quuz");
    }

    #[test]
    fn generate_from_no_panic() {
        // No panic when asked to generate a chain from a starting
        // point that doesn't exist in the chain.
        let mut chain = MarkovChain::new();
        chain.learn("foo bar baz");
        assert_eq!(chain.generate_from(1, ("xxx", "yyy")), "xxx yyy baz");
    }

    #[test]
    fn chain_map() {
        let mut chain = MarkovChain::new();
        chain.learn("foo bar baz quuz");
        let map = &chain.map;

        assert_eq!(map.len(), 2);
        assert_eq!(map[&("foo", "bar")], vec!["baz"]);
        assert_eq!(map[&("bar", "baz")], vec!["quuz"]);
    }
}
<commit_msg>lipsum: generate random lorem ipsum text<commit_after>extern crate rand;

use std::collections::HashMap;
use rand::Rng;

/// A bigram is simply two consecutive words.
type Bigram<'a> = (&'a str, &'a str);

/// Simple order two Markov chain implementation.
///
/// The [Markov chain] is a chain of order two, which means that it
/// will use the previous two words (a bigram) when predicting the
/// next word. This is normally enough to generate random text that
/// looks somewhat plausible. The implementation is based on
/// [Generating arbitrary text with Markov chains in Rust][blog post].
///
/// [Markov chain]: https://en.wikipedia.org/wiki/Markov_chain
/// [blog post]: https://blakewilliams.me/posts/generating-arbitrary-text-with-markov-chains-in-rust
#[derive(Default)]
pub struct MarkovChain<'a> {
    map: HashMap<Bigram<'a>, Vec<&'a str>>,
}

impl<'a> MarkovChain<'a> {
    /// Create a new Markov chain. It will use a default thread-local
    /// random number generator.
    pub fn new() -> MarkovChain<'a> {
        MarkovChain { map: HashMap::new() }
    }

    /// Add new text to the Markov chain. This can be called several
    /// times to build up the chain.
    pub fn learn(&mut self, sentence: &'a str) {
        let words = sentence.split_whitespace().collect::<Vec<&str>>();
        for window in words.windows(3) {
            let (a, b, c) = (window[0], window[1], window[2]);
            self.map.entry((a, b)).or_insert(vec![]).push(c);
        }
    }

    /// Generate `n` words worth of lorem ipsum text. The text will
    /// start from a random point in the Markov chain.
    pub fn generate(&self, n: usize) -> String {
        if self.map.is_empty() {
            // The learn method has not been called.
            return String::new();
        }

        let mut rng = rand::thread_rng();
        let keys = self.map.keys().collect::<Vec<&(&str, &str)>>();
        self.generate_from(n, **rng.choose(&keys).unwrap())
    }

    /// Generate `n` words worth of lorem ipsum text. The text will
    /// start from the given bigram.
    pub fn generate_from(&self, n: usize, from: Bigram<'a>) -> String {
        let mut rng = rand::thread_rng(); // make part of struct
        let keys = self.map.keys().collect::<Vec<&Bigram>>();
        let (mut a, mut b) = from;
        let mut sentence = String::from(a) + " " + b;

        for _ in 0..n {
            while !self.map.contains_key(&(a, b)) {
                let new_key = **rng.choose(&keys).unwrap();
                a = new_key.0;
                b = new_key.1;
            }

            let next_words = &self.map[&(a, b)];
            let c = rng.choose(next_words).unwrap();
            sentence.push(' ');
            sentence.push_str(c);
            a = b;
            b = c;
        }

        return sentence;
    }
}

/// The traditional lorem ipsum text as given in [Wikipedia]. Using
/// this text alone for a Markov chain of order two doesn't work very
/// well since each bigram (two consequtive words) is followed by just
/// one other word. In other words, the Markov chain will always
/// produce the same output and recreate the lorem ipsum text
/// precisely. However, combining it with the full text in
/// [`LIBER_PRIMUS`] works well.
///
/// [Wikipedia]: https://en.wikipedia.org/wiki/Lorem_ipsum
/// [`LIBER_PRIMUS`]: constant.LIBER_PRIMUS.html
const LOREM_IPSUM: &str = include_str!("lorem-ipsum.txt");

/// The first book in Cicero's work De finibus bonorum et malorum ("On
/// the ends of good and evil"). The lorem ipsum text in
/// [`LOREM_IPSUM`] is derived from part of this text.
///
/// [`LOREM_IPSUM`]: constant.LOREM_IPSUM.html
const LIBER_PRIMUS: &str = include_str!("liber-primus.txt");

/// Generate `n` words of lorem ipsum text. The output starts with
/// "Lorem ipsum" and continues with the standard lorem ipsum text
/// from [`LOREM_IPSUM`]. The text will become random if sufficiently
/// long output is requested.
///
/// [`LOREM_IPSUM`]: constant.LOREM_IPSUM.html
pub fn lipsum(n: usize) -> String {
    let mut chain = MarkovChain::new();
    chain.learn(LOREM_IPSUM);
    chain.learn(LIBER_PRIMUS);
    chain.generate_from(n, ("Lorem", "ipsum"))
}

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

    #[test]
    fn starts_with_lorem_ipsum() {
        assert_eq!(&lipsum(10)[..11], "Lorem ipsum");
    }

    #[test]
    fn empty_chain() {
        let chain = MarkovChain::new();
        assert_eq!(chain.generate(10), "");
    }

    #[test]
    fn generate_from() {
        let mut chain = MarkovChain::new();
        chain.learn("foo bar baz quuz");
        assert_eq!(chain.generate_from(1, ("foo", "bar")), "foo bar baz");
        assert_eq!(chain.generate_from(1, ("bar", "baz")), "bar baz quuz");
    }

    #[test]
    fn generate_from_no_panic() {
        // No panic when asked to generate a chain from a starting
        // point that doesn't exist in the chain.
        let mut chain = MarkovChain::new();
        chain.learn("foo bar baz");
        assert_eq!(chain.generate_from(1, ("xxx", "yyy")), "xxx yyy baz");
    }

    #[test]
    fn chain_map() {
        let mut chain = MarkovChain::new();
        chain.learn("foo bar baz quuz");
        let map = &chain.map;

        assert_eq!(map.len(), 2);
        assert_eq!(map[&("foo", "bar")], vec!["baz"]);
        assert_eq!(map[&("bar", "baz")], vec!["quuz"]);
    }
}
<|endoftext|>


<commit_before>extern crate ascii;

mod pascal_str;
mod pascal_string;

const PASCAL_STRING_BUF_SIZE: usize = 255;

pub use pascal_str::{Chars, CharsMut, PascalStr};
pub use pascal_string::{PascalString, PascalStringAppendError, PascalStringCreateError, AsciiError};

#[cfg(test)]
mod tests {
    use super::*;
    use ascii::*;
    use std::borrow::Cow;
    use std::ffi::{CStr, CString};

    #[test]
    fn test_string_creation() {
        let test = "Hello, my world!".to_owned();
        let test_pascal = PascalString::from(&test).unwrap();
        assert_eq!(&test, test_pascal.as_str());

        let too_many_bytes = vec![12u8; 256];
        assert!(match PascalString::from(&too_many_bytes) {
            Err(PascalStringCreateError::InputTooLong) => true,
            _ => false
        });
    }

    #[test]
    fn test_character_append() {
        let mut string = PascalString::new();
        assert!(string.try_push('h').is_ok());
        string.push('e');
        string.push(76u8);
        string.push('l');
        string.push(AsciiChar::L);
        string.push('o');
        string.push(AsciiChar::Null);

        println!("{}", string);
        assert_eq!(string.as_str(), "heLlLo\0");
    }

    #[test]
    fn test_string_append() {
        let mut string = PascalString::new();
        string.push_str("Hola, ");
        string.push_str("Senor!");
        assert_eq!(string.as_str(), "Hola, Senor!");
    }

    #[test]
    fn test_string_indexing_and_char_iteration() {
        let mut string = PascalString::from("q").unwrap();
        assert_eq!(string[0u8], AsciiChar::q);

        let mut string2 = PascalString::from("WASD").unwrap();
        let mut iter = string2.chars();
        assert_eq!(iter.next(), Some(&AsciiChar::W));
        assert_eq!(iter.next(), Some(&AsciiChar::A));
        assert_eq!(iter.next(), Some(&AsciiChar::S));
        assert_eq!(iter.next(), Some(&AsciiChar::D));
    }

    #[test]
    fn test_as_cstr() {
        let msg = "I am your favourite cookie monster >:-)\0";
        let pstr = PascalString::from(&msg).unwrap();
        let cstr = CStr::from_bytes_with_nul(msg.as_bytes()).unwrap();
        let pstr_as_cstr = pstr.as_cstr().unwrap();
        assert!(match pstr_as_cstr {
            Cow::Borrowed(_) => true,
            _ => false
        });
        assert_eq!(&*pstr_as_cstr, cstr);

        let oversized = ['l'; 255];
        let mut string_oversized = {
            let mut s = String::new();
            for i in 0..oversized.len() {
                s.push(oversized[i]);
            }
            s
        };
        let pstr_oversized = PascalString::from_fixed_ascii_array(255, oversized).unwrap();
        println!("oversized: {}", pstr_oversized.is_full());
        let cstr_from_pstr_oversized = pstr_oversized.as_cstr().unwrap();
        let cstr_from_string_oversized = CString::new(string_oversized).unwrap();
        assert!(match cstr_from_pstr_oversized {
            Cow::Owned(_) => true,
            _ => false
        });
        assert_eq!(cstr_from_pstr_oversized.into_owned(), cstr_from_string_oversized);
    }
}
<commit_msg>Move different test areas into their own blocks to prevent variable name pollution.<commit_after>extern crate ascii;

mod pascal_str;
mod pascal_string;

const PASCAL_STRING_BUF_SIZE: usize = 255;

pub use pascal_str::{Chars, CharsMut, PascalStr};
pub use pascal_string::{PascalString, PascalStringAppendError, PascalStringCreateError, AsciiError};

#[cfg(test)]
mod tests {
    use super::*;
    use ascii::*;
    use std::borrow::Cow;
    use std::ffi::{CStr, CString};

    #[test]
    fn test_string_creation() {
        let test = "Hello, my world!".to_owned();
        let test_pascal = PascalString::from(&test).unwrap();
        assert_eq!(&test, test_pascal.as_str());

        let too_many_bytes = vec![12u8; 256];
        assert!(match PascalString::from(&too_many_bytes) {
            Err(PascalStringCreateError::InputTooLong) => true,
            _ => false
        });
    }

    #[test]
    fn test_character_append() {
        let mut string = PascalString::new();
        assert!(string.try_push('h').is_ok());
        string.push('e');
        string.push(76u8);
        string.push('l');
        string.push(AsciiChar::L);
        string.push('o');
        string.push(AsciiChar::Null);

        println!("{}", string);
        assert_eq!(string.as_str(), "heLlLo\0");
    }

    #[test]
    fn test_string_append() {
        let mut string = PascalString::new();
        string.push_str("Hola, ");
        string.push_str("Senor!");
        assert_eq!(string.as_str(), "Hola, Senor!");
    }

    #[test]
    fn test_string_indexing_and_char_iteration() {
        let mut string = PascalString::from("q").unwrap();
        assert_eq!(string[0u8], AsciiChar::q);

        let mut string2 = PascalString::from("WASD").unwrap();
        let mut iter = string2.chars();
        assert_eq!(iter.next(), Some(&AsciiChar::W));
        assert_eq!(iter.next(), Some(&AsciiChar::A));
        assert_eq!(iter.next(), Some(&AsciiChar::S));
        assert_eq!(iter.next(), Some(&AsciiChar::D));
    }

    #[test]
    fn test_as_cstr() {
        {
            let msg = "I am your favourite cookie monster >:-)\0";
            let pstr = PascalString::from(&msg).unwrap();
            let cstr = CStr::from_bytes_with_nul(msg.as_bytes()).unwrap();
            let pstr_as_cstr = pstr.as_cstr().unwrap();
            assert!(match pstr_as_cstr {
                Cow::Borrowed(_) => true,
                _ => false
            });
            assert_eq!(&*pstr_as_cstr, cstr);
        }

        {
            let oversized = ['l'; 255];
            let mut string_oversized = {
                let mut s = String::new();
                for i in 0..oversized.len() {
                    s.push(oversized[i]);
                }
                s
            };
            let pstr_oversized = PascalString::from_fixed_ascii_array(255, oversized).unwrap();
            println!("oversized: {}", pstr_oversized.is_full());
            let cstr_from_pstr_oversized = pstr_oversized.as_cstr().unwrap();
            let cstr_from_string_oversized = CString::new(string_oversized).unwrap();
            assert!(match cstr_from_pstr_oversized {
                Cow::Owned(_) => true,
                _ => false
            });
            assert_eq!(cstr_from_pstr_oversized.into_owned(), cstr_from_string_oversized);
        }
    }
}
<|endoftext|>


<commit_before>//! # `attaca` - distributed, resilient version control with a git-like interface

#![feature(proc_macro, conservative_impl_trait, generators, offset_to)]
#![recursion_limit="256"]

#[cfg(not(target_pointer_width = "64"))]
compile_error!(
    "Must be compiled on a 64-bit architecture due to the use of memory-mapping for potentially extremely large files!"
);

#[cfg(test)]
extern crate histogram;

#[cfg(test)]
extern crate rand;

#[cfg(test)]
#[macro_use]
extern crate quickcheck;

extern crate bincode;
extern crate chrono;
extern crate digest_writer;
#[macro_use]
extern crate error_chain;
extern crate futures_await as futures;
extern crate futures_bufio;
extern crate futures_cpupool;
extern crate generic_array;
extern crate globset;
extern crate itertools;
#[macro_use]
extern crate lazy_static;
extern crate libc;
extern crate memmap;
extern crate owning_ref;
extern crate qp_trie;
extern crate rad;
extern crate seahash;
#[macro_use]
extern crate serde_derive;
extern crate sequence_trie;
extern crate sha3;
extern crate stable_deref_trait;
extern crate toml;
extern crate typenum;

pub mod arc_slice;
pub mod catalog;
pub mod context;
pub mod errors;
pub mod index;
pub mod marshal;
pub mod repository;
pub mod split;
pub mod store;
pub mod trace;

pub use errors::*;
pub use repository::Repository;
pub use store::Store;

use std::collections::HashSet;
use std::path::{Path, PathBuf};

/// Controls the size of the MPSC queue between marshal tasks and write tasks.
const BATCH_FUTURE_BUFFER_SIZE: usize = 64;

/// Controls the size of buffers over buffered streams created when writing to remotes.
const WRITE_FUTURE_BUFFER_SIZE: usize = 64;

lazy_static! {
    /// Controls the name of the "hidden" `.attaca` repository metadata directory.
    static ref METADATA_PATH: &'static Path = Path::new(".attaca");

    /// The relative path of the repository config file.
    static ref CONFIG_PATH: PathBuf = METADATA_PATH.join("config.toml");

    /// The relative path of the blob directory within a repository.
    static ref BLOBS_PATH: PathBuf = METADATA_PATH.join("blobs");

    /// The relative path of the remote catalog directory.
    static ref REMOTE_CATALOGS_PATH: PathBuf = METADATA_PATH.join("remote-catalogs");

    /// The location of the local catalog file.
    static ref LOCAL_CATALOG_PATH: PathBuf = METADATA_PATH.join("local.catalog");

    /// The location of the index file.
    static ref INDEX_PATH: PathBuf = METADATA_PATH.join("index.bin");

    /// The location of the HEAD file.
    static ref REFS_PATH: PathBuf = METADATA_PATH.join("refs.toml");

    /// Default paths to ignore.
    static ref DEFAULT_IGNORES: HashSet<PathBuf> = {
        let mut set = HashSet::new();

        set.insert(METADATA_PATH.to_owned());
        set.insert(PathBuf::from(".git"));
        set.insert(PathBuf::from("insta-rados")); // HACK HACK HACK!

        set
    };
}
<commit_msg>lib.rs: update REFS_PATH to indicate it's bincode instead of toml now<commit_after>//! # `attaca` - distributed, resilient version control with a git-like interface

#![feature(proc_macro, conservative_impl_trait, generators, offset_to)]
#![recursion_limit="256"]

#[cfg(not(target_pointer_width = "64"))]
compile_error!(
    "Must be compiled on a 64-bit architecture due to the use of memory-mapping for potentially extremely large files!"
);

#[cfg(test)]
extern crate histogram;

#[cfg(test)]
extern crate rand;

#[cfg(test)]
#[macro_use]
extern crate quickcheck;

extern crate bincode;
extern crate chrono;
extern crate digest_writer;
#[macro_use]
extern crate error_chain;
extern crate futures_await as futures;
extern crate futures_bufio;
extern crate futures_cpupool;
extern crate generic_array;
extern crate globset;
extern crate itertools;
#[macro_use]
extern crate lazy_static;
extern crate libc;
extern crate memmap;
extern crate owning_ref;
extern crate qp_trie;
extern crate rad;
extern crate seahash;
#[macro_use]
extern crate serde_derive;
extern crate sequence_trie;
extern crate sha3;
extern crate stable_deref_trait;
extern crate toml;
extern crate typenum;

pub mod arc_slice;
pub mod catalog;
pub mod context;
pub mod errors;
pub mod index;
pub mod marshal;
pub mod repository;
pub mod split;
pub mod store;
pub mod trace;

pub use errors::*;
pub use repository::Repository;
pub use store::Store;

use std::collections::HashSet;
use std::path::{Path, PathBuf};

/// Controls the size of the MPSC queue between marshal tasks and write tasks.
const BATCH_FUTURE_BUFFER_SIZE: usize = 64;

/// Controls the size of buffers over buffered streams created when writing to remotes.
const WRITE_FUTURE_BUFFER_SIZE: usize = 64;

lazy_static! {
    /// Controls the name of the "hidden" `.attaca` repository metadata directory.
    static ref METADATA_PATH: &'static Path = Path::new(".attaca");

    /// The relative path of the repository config file.
    static ref CONFIG_PATH: PathBuf = METADATA_PATH.join("config.toml");

    /// The relative path of the blob directory within a repository.
    static ref BLOBS_PATH: PathBuf = METADATA_PATH.join("blobs");

    /// The relative path of the remote catalog directory.
    static ref REMOTE_CATALOGS_PATH: PathBuf = METADATA_PATH.join("remote-catalogs");

    /// The location of the local catalog file.
    static ref LOCAL_CATALOG_PATH: PathBuf = METADATA_PATH.join("local.catalog");

    /// The location of the index file.
    static ref INDEX_PATH: PathBuf = METADATA_PATH.join("index.bin");

    /// The location of the HEAD file.
    static ref REFS_PATH: PathBuf = METADATA_PATH.join("refs.bin");

    /// Default paths to ignore.
    static ref DEFAULT_IGNORES: HashSet<PathBuf> = {
        let mut set = HashSet::new();

        set.insert(METADATA_PATH.to_owned());
        set.insert(PathBuf::from(".git"));
        set.insert(PathBuf::from("insta-rados")); // HACK HACK HACK!

        set
    };
}
<|endoftext|>


<commit_before>//! Prefabricated shapes for the glium OpenGL wrapper.
//!
//! # Building a shape
//!
//! Each shape is constructed using a builder object. The builder objects allow us
//! to customise the resultant shape.
//!
//! In the following example, we use a `CuboidBuilder` to construct a 2x3x4 `Cuboid`
//! with its base at the origin:
//!
//! ```rust
//! let cuboid = glium_shapes::cuboid::CuboidBuilder::new()
//!              .translate(0.0, 0.5, 0.0)
//!              .scale(2.0, 3.0, 4.0)
//!              .build(display)
//!              .expect("Failed to build cuboid shape");
//! ```
//!
//! # Drawing a shape
//!
//! All of the shapes provided in this library are a source of both vertices and
//! indices, such that you can pass them directly to the `glium::Surface::draw` method
//! like so:
//!
//! ```rust
//! frame.draw( /*vertices=*/ &cuboid, /*indices=*/ &cuboid, program, uniforms, params );
//! ```
//!
//! The shader program, uniform buffers, and draw parameters are not provided by this library.
extern crate cgmath;

#[macro_use]
extern crate glium;

pub mod cuboid;
pub mod errors;
pub mod vertex;
<commit_msg>Ignoring documentation examples when testing until we can mock the glium display<commit_after>//! Prefabricated shapes for the glium OpenGL wrapper.
//!
//! # Building a shape
//!
//! Each shape is constructed using a builder object. The builder objects allow us
//! to customise the resultant shape.
//!
//! In the following example, we use a `CuboidBuilder` to construct a 2x3x4 `Cuboid`
//! with its base at the origin:
//!
//! ```ignore
//! let cuboid = glium_shapes::cuboid::CuboidBuilder::new()
//!              .translate(0.0, 0.5, 0.0)
//!              .scale(2.0, 3.0, 4.0)
//!              .build(display)
//!              .expect("Failed to build cuboid shape");
//! ```
//!
//! # Drawing a shape
//!
//! All of the shapes provided in this library are a source of both vertices and
//! indices, such that you can pass them directly to the `glium::Surface::draw` method
//! like so:
//!
//! ```ignore
//! frame.draw( /*vertices=*/ &cuboid, /*indices=*/ &cuboid, program, uniforms, params );
//! ```
//!
//! The shader program, uniform buffers, and draw parameters are not provided by this library.
extern crate cgmath;

#[macro_use]
extern crate glium;

pub mod cuboid;
pub mod errors;
pub mod vertex;
<|endoftext|>


<commit_before>//! TODO
#![deny(missing_docs)]

extern crate loirc;

#[macro_use]
mod macros;
mod core;
pub mod ext;
mod listener;

pub use core::{dispatch};
pub use core::{Channel, ConnectionStatus, Error, Irc, Settings};
pub use listener::Listener;
pub use loirc::{Duration, Event, MonitorSettings, ReconnectionSettings};
<commit_msg>Add crate documentation<commit_after>#![deny(missing_docs)]
//! `hiirc` is a library built on top of [loirc](https://github.com/SBSTP/loirc). The goal
//! is to offer a friendly, event-based API.
//!
//! To use the library, implement the listener trait and give an instance of your implementation
//! to the dispatch function, accompanied with an instance of the Settings struct configured to
//! your needs.

extern crate loirc;

#[macro_use]
mod macros;
mod core;
pub mod ext;
mod listener;

pub use core::{dispatch};
pub use core::{Channel, ConnectionStatus, Error, Irc, Settings};
pub use listener::Listener;
pub use loirc::{Duration, Event, MonitorSettings, ReconnectionSettings};
<|endoftext|>


<commit_before>//! A minimal implementation of SHA1 for rust.
//!
//! Example:
//!
//! ```rust
//! extern crate sha1;
//! # fn main() {
//!
//! let mut m = sha1::Sha1::new();
//! m.update("Hello World!".as_bytes());
//! assert_eq!(m.hexdigest().as_slice(),
//!            "2ef7bde608ce5404e97d5f042f95f89f1c232871");
//! # }
//! ```

#![feature(core, collections)]
#![unstable]

extern crate byteorder;
use std::io::{Cursor,Write};
use std::io::BufWriter;
use std::num::Int;
use byteorder::{BigEndian, WriteBytesExt};

/// Represents a Sha1 hash object in memory.
#[derive(Clone)]
pub struct Sha1 {
    state: [u32; 5],
    data: Vec<u8>,
    len: u64,
}

const DEFAULT_STATE : [u32; 5] =
    [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];

fn to_hex(input: &[u8]) -> String {
    let mut s = String::new();
    for b in input.iter() {
        s.push_str(&format!("{:02x}", *b));
    }
    return s;
}

impl Sha1 {

    /// Creates an fresh sha1 hash object.
    pub fn new() -> Sha1 {
        Sha1 {
            state: DEFAULT_STATE,
            data: Vec::new(),
            len: 0,
        }
    }

    fn process_block(&mut self, block: &[u8]) {
        assert_eq!(block.len(), 64);

        let mut words = [0u32; 80];
        for (i, chunk) in block.chunks(4).enumerate() {
            words[i] = (chunk[3] as u32) |
                       ((chunk[2] as u32) << 8) |
                       ((chunk[1] as u32) << 16) |
                       ((chunk[0] as u32) << 24);
        }

        fn ff(b: u32, c: u32, d: u32) -> u32 { d ^ (b & (c ^ d)) }
        fn gg(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }
        fn hh(b: u32, c: u32, d: u32) -> u32 { (b & c) | (d & (b | c)) }
        fn ii(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }

        for i in 16..80 {
            let n = words[i - 3] ^ words[i - 8] ^ words[i - 14] ^ words[i - 16];
            words[i] = n.rotate_left(1);
        }

        let mut a = self.state[0];
        let mut b = self.state[1];
        let mut c = self.state[2];
        let mut d = self.state[3];
        let mut e = self.state[4];

        for i in 0..80 {
            let (f, k) = match i {
                0 ... 19 => (ff(b, c, d), 0x5a827999),
                20 ... 39 => (gg(b, c, d), 0x6ed9eba1),
                40 ... 59 => (hh(b, c, d), 0x8f1bbcdc),
                60 ... 79 => (ii(b, c, d), 0xca62c1d6),
                _ => (0, 0),
            };

            let tmp = a.rotate_left(5)
                .wrapping_add(f)
                .wrapping_add(e)
                .wrapping_add(k)
                .wrapping_add(words[i]);
            e = d;
            d = c;
            c = b.rotate_left(30);
            b = a;
            a = tmp;
        }

        self.state[0] = self.state[0].wrapping_add(a);
        self.state[1] = self.state[1].wrapping_add(b);
        self.state[2] = self.state[2].wrapping_add(c);
        self.state[3] = self.state[3].wrapping_add(d);
        self.state[4] = self.state[4].wrapping_add(e);
    }

    /// Resets the hash object to it's initial state.
    pub fn reset(&mut self) {
        self.state = DEFAULT_STATE;
        self.data.clear();
        self.len = 0;
    }

    /// Update hash with input data.
    pub fn update(&mut self, data: &[u8]) {
        let mut d = self.data.clone();
        self.data.clear();

        d.push_all(data);

        for chunk in d.chunks(64) {
            if chunk.len() == 64 {
                self.len += chunk.len() as u64;
                self.process_block(chunk);
            } else {
                self.data.push_all(chunk);
            }
        }
    }

    /// Retrieve digest result.  The output must be large enough to
    /// contain result (20 bytes).
    pub fn output(&self, out: &mut [u8]) {
        // these are unlikely to fail, since we're writing to memory
        #![allow(unused_must_use)]

        let mut m = Sha1 {
            state: self.state,
            data: Vec::new(),
            len: 0,
        };

        let mut w : Cursor<Vec<u8>> = Cursor::new(Vec::new());
        w.write(&*self.data);
        w.write_all(&[0x80]);
        let padding = 64 - ((self.data.len() + 9) % 64);
        for _ in 0..padding {
            w.write(&[0u8]);
        }

        w.write_u64::<BigEndian>((self.data.len() as u64 + self.len) * 8);
        for chunk in w.into_inner().chunks(64) {
            m.process_block(chunk);
        }

        let mut w = BufWriter::new(out);
        for &n in m.state.iter() {
            w.write_u32::<BigEndian>(n);
        }
    }

    /// Shortcut for getting `output` into a new vector.
    pub fn digest(&self) -> Vec<u8> {
        let mut buf = [0u8; 20].to_vec();
        self.output(&mut buf);
        buf
    }

    /// Shortcut for getting a hex output of the vector.
    pub fn hexdigest(&self) -> String {
        to_hex(&self.digest())
    }
}

#[test]
fn test_simple() {
    let mut m = Sha1::new();

    let tests = [
        ("The quick brown fox jumps over the lazy dog",
         "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"),
        ("The quick brown fox jumps over the lazy cog",
         "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3"),
        ("", "da39a3ee5e6b4b0d3255bfef95601890afd80709"),
        ("testing\n", "9801739daae44ec5293d4e1f53d3f4d2d426d91c"),
        ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
         "025ecbd5d70f8fb3c5457cd96bab13fda305dc59"),
    ];

    for &(s, ref h) in tests.iter() {
        let data = s.as_bytes();

        m.reset();
        m.update(data);
        let hh = m.hexdigest();

        assert_eq!(hh.len(), h.len());
		assert_eq!(hh, *h);
    }
}

#[test]
fn test_multiple_updates() {
    let mut m = Sha1::new();

    m.reset();
    m.update("The quick brown ".as_bytes());
    m.update("fox jumps over ".as_bytes());
    m.update("the lazy dog".as_bytes());
    let hh = m.hexdigest();

    let h = "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12";
    assert_eq!(hh.len(), h.len());
    assert_eq!(hh, &*h);
}
<commit_msg>Correctly compare strings<commit_after>//! A minimal implementation of SHA1 for rust.
//!
//! Example:
//!
//! ```rust
//! extern crate sha1;
//! # fn main() {
//!
//! let mut m = sha1::Sha1::new();
//! m.update("Hello World!".as_bytes());
//! assert_eq!(m.hexdigest(),
//!            "2ef7bde608ce5404e97d5f042f95f89f1c232871");
//! # }
//! ```

#![feature(core, collections)]
#![unstable]

extern crate byteorder;
use std::io::{Cursor,Write};
use std::io::BufWriter;
use std::num::Int;
use byteorder::{BigEndian, WriteBytesExt};

/// Represents a Sha1 hash object in memory.
#[derive(Clone)]
pub struct Sha1 {
    state: [u32; 5],
    data: Vec<u8>,
    len: u64,
}

const DEFAULT_STATE : [u32; 5] =
    [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];

fn to_hex(input: &[u8]) -> String {
    let mut s = String::new();
    for b in input.iter() {
        s.push_str(&format!("{:02x}", *b));
    }
    return s;
}

impl Sha1 {

    /// Creates an fresh sha1 hash object.
    pub fn new() -> Sha1 {
        Sha1 {
            state: DEFAULT_STATE,
            data: Vec::new(),
            len: 0,
        }
    }

    fn process_block(&mut self, block: &[u8]) {
        assert_eq!(block.len(), 64);

        let mut words = [0u32; 80];
        for (i, chunk) in block.chunks(4).enumerate() {
            words[i] = (chunk[3] as u32) |
                       ((chunk[2] as u32) << 8) |
                       ((chunk[1] as u32) << 16) |
                       ((chunk[0] as u32) << 24);
        }

        fn ff(b: u32, c: u32, d: u32) -> u32 { d ^ (b & (c ^ d)) }
        fn gg(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }
        fn hh(b: u32, c: u32, d: u32) -> u32 { (b & c) | (d & (b | c)) }
        fn ii(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }

        for i in 16..80 {
            let n = words[i - 3] ^ words[i - 8] ^ words[i - 14] ^ words[i - 16];
            words[i] = n.rotate_left(1);
        }

        let mut a = self.state[0];
        let mut b = self.state[1];
        let mut c = self.state[2];
        let mut d = self.state[3];
        let mut e = self.state[4];

        for i in 0..80 {
            let (f, k) = match i {
                0 ... 19 => (ff(b, c, d), 0x5a827999),
                20 ... 39 => (gg(b, c, d), 0x6ed9eba1),
                40 ... 59 => (hh(b, c, d), 0x8f1bbcdc),
                60 ... 79 => (ii(b, c, d), 0xca62c1d6),
                _ => (0, 0),
            };

            let tmp = a.rotate_left(5)
                .wrapping_add(f)
                .wrapping_add(e)
                .wrapping_add(k)
                .wrapping_add(words[i]);
            e = d;
            d = c;
            c = b.rotate_left(30);
            b = a;
            a = tmp;
        }

        self.state[0] = self.state[0].wrapping_add(a);
        self.state[1] = self.state[1].wrapping_add(b);
        self.state[2] = self.state[2].wrapping_add(c);
        self.state[3] = self.state[3].wrapping_add(d);
        self.state[4] = self.state[4].wrapping_add(e);
    }

    /// Resets the hash object to it's initial state.
    pub fn reset(&mut self) {
        self.state = DEFAULT_STATE;
        self.data.clear();
        self.len = 0;
    }

    /// Update hash with input data.
    pub fn update(&mut self, data: &[u8]) {
        let mut d = self.data.clone();
        self.data.clear();

        d.push_all(data);

        for chunk in d.chunks(64) {
            if chunk.len() == 64 {
                self.len += chunk.len() as u64;
                self.process_block(chunk);
            } else {
                self.data.push_all(chunk);
            }
        }
    }

    /// Retrieve digest result.  The output must be large enough to
    /// contain result (20 bytes).
    pub fn output(&self, out: &mut [u8]) {
        // these are unlikely to fail, since we're writing to memory
        #![allow(unused_must_use)]

        let mut m = Sha1 {
            state: self.state,
            data: Vec::new(),
            len: 0,
        };

        let mut w : Cursor<Vec<u8>> = Cursor::new(Vec::new());
        w.write(&*self.data);
        w.write_all(&[0x80]);
        let padding = 64 - ((self.data.len() + 9) % 64);
        for _ in 0..padding {
            w.write(&[0u8]);
        }

        w.write_u64::<BigEndian>((self.data.len() as u64 + self.len) * 8);
        for chunk in w.into_inner().chunks(64) {
            m.process_block(chunk);
        }

        let mut w = BufWriter::new(out);
        for &n in m.state.iter() {
            w.write_u32::<BigEndian>(n);
        }
    }

    /// Shortcut for getting `output` into a new vector.
    pub fn digest(&self) -> Vec<u8> {
        let mut buf = [0u8; 20].to_vec();
        self.output(&mut buf);
        buf
    }

    /// Shortcut for getting a hex output of the vector.
    pub fn hexdigest(&self) -> String {
        to_hex(&self.digest())
    }
}

#[test]
fn test_simple() {
    let mut m = Sha1::new();

    let tests = [
        ("The quick brown fox jumps over the lazy dog",
         "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"),
        ("The quick brown fox jumps over the lazy cog",
         "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3"),
        ("", "da39a3ee5e6b4b0d3255bfef95601890afd80709"),
        ("testing\n", "9801739daae44ec5293d4e1f53d3f4d2d426d91c"),
        ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
         "025ecbd5d70f8fb3c5457cd96bab13fda305dc59"),
    ];

    for &(s, ref h) in tests.iter() {
        let data = s.as_bytes();

        m.reset();
        m.update(data);
        let hh = m.hexdigest();

        assert_eq!(hh.len(), h.len());
		assert_eq!(hh, *h);
    }
}

#[test]
fn test_multiple_updates() {
    let mut m = Sha1::new();

    m.reset();
    m.update("The quick brown ".as_bytes());
    m.update("fox jumps over ".as_bytes());
    m.update("the lazy dog".as_bytes());
    let hh = m.hexdigest();

    let h = "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12";
    assert_eq!(hh.len(), h.len());
    assert_eq!(hh, &*h);
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate mongo_c_driver_wrapper;
extern crate bson;

use std::result;

use mongo_c_driver_wrapper::bindings;

pub mod bsonc;
pub mod client;
pub mod collection;
pub mod cursor;
pub mod database;
pub mod error;
pub mod flags;
pub mod read_prefs;
pub mod uri;
pub mod write_concern;

pub use error::{MongoError,BsoncError,InvalidParamsError};

pub type Result<T> = result::Result<T, MongoError>;

static mut INITIALIZED: bool = false;

/// Init mongo driver, needs to be called once before doing
/// anything else.
pub fn init() {
  unsafe {
      bindings::mongoc_init();
      INITIALIZED = true;
  }
}

/// Clean up mongo driver's resources
pub fn cleanup() {
    unsafe {
        bindings::mongoc_cleanup();
        INITIALIZED = false;
    }
}

pub fn is_initialized() -> bool {
    unsafe { INITIALIZED }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_init_and_cleanup() {
        super::init();
        assert!(super::is_initialized());

        super::cleanup();
        assert!(!super::is_initialized());
    }
}
<commit_msg>Use std::sync::Once for init<commit_after>extern crate libc;
extern crate mongo_c_driver_wrapper;
extern crate bson;

use std::result;
use std::sync::{Once,ONCE_INIT};

use mongo_c_driver_wrapper::bindings;

pub mod bsonc;
pub mod client;
pub mod collection;
pub mod cursor;
pub mod database;
pub mod error;
pub mod flags;
pub mod read_prefs;
pub mod uri;
pub mod write_concern;

pub use error::{MongoError,BsoncError,InvalidParamsError};

pub type Result<T> = result::Result<T, MongoError>;

static MONGOC_INIT: Once = ONCE_INIT;

/// Init mongo driver, needs to be called once before doing
/// anything else.
pub fn init() {
    MONGOC_INIT.call_once(|| {
        unsafe { bindings::mongoc_init(); }
    });
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_init() {
        super::init();
        super::init();
    }
}
<|endoftext|>


<commit_before>#![feature(convert, from_raw_os, collections)]
#![cfg_attr(windows, feature(fs_ext))]
//! Securely create and manage temporary files. Temporary files created by this create are
//! automatically deleted on exit (actually, they're usually deleted immediately after they are
//! created).
//!
extern crate libc;
extern crate rand;

use std::io::{self, Read, Write, Seek, SeekFrom};
use std::fs::File;
use std::path::Path;
use std::env;

mod imp;
mod util;

pub struct TempFile(File);

impl TempFile {
    /// Create a new temporary file.
    #[inline(always)]
    pub fn new() -> io::Result<TempFile> {
        Self::new_in(&env::temp_dir())
    }

    /// Create a new temporary file in the specified directory.
    #[inline(always)]
    pub fn new_in<P: AsRef<Path>>(dir: P) -> io::Result<TempFile> {
        imp::create(dir.as_ref()).map(|f| TempFile(f))
    }

    /// Create a new temporary file and open it `count` times returning `count` independent
    /// references to the same file.
    ///
    /// This can be useful if you want multiple seek positions in the same temporary file.
    /// Additionally, this function guarantees that all of the returned temporary file objects
    /// refer to the same underlying temporary file even in the presence of a pathological
    /// temporary file cleaner.
    #[inline(always)]
    pub fn shared(count: usize) -> io::Result<Vec<TempFile>> {
        Self::shared_in(&env::temp_dir(), count)
    }

    /// Same as `shared` but creates the file in the specified directory.
    #[inline(always)]
    pub fn shared_in<P: AsRef<Path>>(dir: P, count: usize) -> io::Result<Vec<TempFile>> {
        imp::create_shared(dir.as_ref(), count).map(|files| files.map_in_place(|f|TempFile(f)))
    }

    /// Number of bytes in the file.
    #[inline(always)]
    pub fn len(&self) -> io::Result<u64> {
        self.0.metadata().map(|m| m.len())
    }

    /// Truncate the file to `size` bytes.
    #[inline(always)]
    pub fn set_len(&self, size: u64) -> io::Result<()> {
        self.0.set_len(size)
    }

    /// Re-open the temporary file. The returned TempFile will refer to the same underlying
    /// temporary file but will have an independent offset.
    ///
    /// This method is only available on windows and Linux, not FreeBSD/MacOS. Unfortunately, it is
    /// impossible to reliably implement this method on those operating systems.
    ///
    /// If you need your code to be cross-platform, please use `shared`/`shared_in` defined above.
    #[cfg(any(windows, target_os = "linux"))]
    #[inline(always)]
    pub fn reopen(&self) -> io::Result<TempFile> {
        imp::reopen(&self.0).map(|f|TempFile(f))
    }
}

impl Read for TempFile {
    #[inline(always)]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

impl Write for TempFile {
    #[inline(always)]
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }
    #[inline(always)]
    fn flush(&mut self) -> io::Result<()> {
        self.0.flush()
    }
}

impl Seek for TempFile {
    #[inline(always)]
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        self.0.seek(pos)
    }
}

#[cfg(unix)]
impl std::os::unix::io::AsRawFd for TempFile {
    #[inline(always)]
    fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
        self.0.as_raw_fd()
    }
}

#[cfg(windows)]
impl std::os::windows::io::AsRawHandle for TempFile {
    #[inline(always)]
    fn as_raw_handle(&self) -> std::os::windows::io::RawHandle {
        self.0.as_raw_handle()
    }
}
<commit_msg>Explain removal.<commit_after>#![feature(convert, from_raw_os, collections)]
#![cfg_attr(windows, feature(fs_ext))]
//! Securely create and manage temporary files. Temporary files created by this create are
//! automatically deleted. When they are deleted depends on the platform:
//!
//! *nix: The temporary file is immediately unlinked. The OS will delete it when the last open
//! copy of it is closed (the last TempFile reference to it is dropped).
//!
//! Windows: The temporary file is marked DeleteOnClose and, again, will be deleted when the last
//! open copy of it is closed. Unlike *nix operating systems, the file is not immediately unlinked
//! from the filesystem.
extern crate libc;
extern crate rand;

use std::io::{self, Read, Write, Seek, SeekFrom};
use std::fs::File;
use std::path::Path;
use std::env;

mod imp;
mod util;

pub struct TempFile(File);

impl TempFile {
    /// Create a new temporary file.
    #[inline(always)]
    pub fn new() -> io::Result<TempFile> {
        Self::new_in(&env::temp_dir())
    }

    /// Create a new temporary file in the specified directory.
    #[inline(always)]
    pub fn new_in<P: AsRef<Path>>(dir: P) -> io::Result<TempFile> {
        imp::create(dir.as_ref()).map(|f| TempFile(f))
    }

    /// Create a new temporary file and open it `count` times returning `count` independent
    /// references to the same file.
    ///
    /// This can be useful if you want multiple seek positions in the same temporary file.
    /// Additionally, this function guarantees that all of the returned temporary file objects
    /// refer to the same underlying temporary file even in the presence of a pathological
    /// temporary file cleaner.
    #[inline(always)]
    pub fn shared(count: usize) -> io::Result<Vec<TempFile>> {
        Self::shared_in(&env::temp_dir(), count)
    }

    /// Same as `shared` but creates the file in the specified directory.
    #[inline(always)]
    pub fn shared_in<P: AsRef<Path>>(dir: P, count: usize) -> io::Result<Vec<TempFile>> {
        imp::create_shared(dir.as_ref(), count).map(|files| files.map_in_place(|f|TempFile(f)))
    }

    /// Number of bytes in the file.
    #[inline(always)]
    pub fn len(&self) -> io::Result<u64> {
        self.0.metadata().map(|m| m.len())
    }

    /// Truncate the file to `size` bytes.
    #[inline(always)]
    pub fn set_len(&self, size: u64) -> io::Result<()> {
        self.0.set_len(size)
    }

    /// Re-open the temporary file. The returned TempFile will refer to the same underlying
    /// temporary file but will have an independent offset.
    ///
    /// This method is only available on windows and Linux, not FreeBSD/MacOS. Unfortunately, it is
    /// impossible to reliably implement this method on those operating systems.
    ///
    /// If you need your code to be cross-platform, please use `shared`/`shared_in` defined above.
    #[cfg(any(windows, target_os = "linux"))]
    #[inline(always)]
    pub fn reopen(&self) -> io::Result<TempFile> {
        imp::reopen(&self.0).map(|f|TempFile(f))
    }
}

impl Read for TempFile {
    #[inline(always)]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

impl Write for TempFile {
    #[inline(always)]
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }
    #[inline(always)]
    fn flush(&mut self) -> io::Result<()> {
        self.0.flush()
    }
}

impl Seek for TempFile {
    #[inline(always)]
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        self.0.seek(pos)
    }
}

#[cfg(unix)]
impl std::os::unix::io::AsRawFd for TempFile {
    #[inline(always)]
    fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
        self.0.as_raw_fd()
    }
}

#[cfg(windows)]
impl std::os::windows::io::AsRawHandle for TempFile {
    #[inline(always)]
    fn as_raw_handle(&self) -> std::os::windows::io::RawHandle {
        self.0.as_raw_handle()
    }
}
<|endoftext|>


<commit_before>//! A crate that provides support for half-precision 16-bit floating point types.
//!
//! This crate provides the [`f16`] type, which is an implementation of the IEEE 754-2008 standard
//! [`binary16`] a.k.a `half` floating point type. This 16-bit floating point type is intended for
//! efficient storage where the full range and precision of a larger floating point value is not
//! required. This is especially useful for image storage formats.
//!
//! This crate also provides a [`bf16`] type, an alternative 16-bit floating point format. The
//! [`bfloat16`] format is a truncated IEEE 754 standard `binary32` float that preserves the
//! exponent to allow the same range as `f32` but with only 8 bits of precision (instead of 11
//! bits for [`f16`]). See the [`bf16`] type for details.
//!
//! Because [`f16`] and [`bf16`] are primarily for efficient storage, floating point operations such as
//! addition, multiplication, etc. are not implemented. Operations should be performed with `f32`
//! or higher-precision types and converted to/from [`f16`] or [`bf16`] as necessary.
//!
//! This crate also provides a [`slice`] module for zero-copy in-place conversions of `u16` slices
//! to both [`f16`] and [`bf16`], as well as efficient vectorized conversions of larger buffers of
//! floating point values to and from these half formats.
//!
//! A [`prelude`] module is provided for easy importing of available utility traits.
//!
//! Some hardware architectures provide support for 16-bit floating point conversions. Enable the
//! `use-intrinsics` feature to use LLVM intrinsics for hardware conversions. This crate does no
//! checks on whether the hardware supports the feature. This feature currently only works on
//! nightly Rust due to a compiler feature gate. When this feature is enabled and the hardware
//! supports it, the [`slice`] trait conversions will use vectorized SIMD intructions for
//! increased efficiency.
//!
//! Support for [`serde`] crate `Serialize` and `Deserialize` traits is provided when the `serde`
//! feature is enabled. This adds a dependency on [`serde`] crate so is an optional cargo feature.
//!
//! The crate uses `#[no_std]` by default, so can be used in embedded environments without using the
//! Rust `std` library. A `std` feature is available, which enables additional utilities using the
//! `std` library, such as the `vec` module that provides zero-copy `Vec` conversions.
//!
//! [`f16`]: struct.f16.html
//! [`binary16`]: https://en.wikipedia.org/wiki/Half-precision_floating-point_format
//! [`bf16`]: struct.bf16.html
//! [`bfloat16`]: https://en.wikipedia.org/wiki/Bfloat16_floating-point_format
//! [`slice`]: slice/index.html
//! [`prelude`]: prelude/index.html
//! [`serde`]: https://crates.io/crates/serde

#![warn(
    missing_docs,
    missing_copy_implementations,
    missing_debug_implementations,
    trivial_numeric_casts,
    unused_extern_crates,
    unused_import_braces,
    future_incompatible,
    rust_2018_compatibility,
    rust_2018_idioms,
    clippy::all
)]
#![allow(clippy::verbose_bit_mask, clippy::cast_lossless)]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(
    all(
        feature = "use-intrinsics",
        any(target_arch = "x86", target_arch = "x86_64")
    ),
    feature(stdsimd, f16c_target_feature)
)]
#![doc(html_root_url = "https://docs.rs/half/1.4.0")]

mod bfloat;
mod binary16;
pub mod slice;
#[cfg(feature = "std")]
pub mod vec;

pub use binary16::f16;

#[allow(deprecated)]
pub use binary16::consts;

pub use bfloat::bf16;

/// A collection of the most used items and traits in this crate for easy importing.
///
/// # Examples
///
/// ```rust
/// use half::prelude::*;
/// ```
pub mod prelude {
    #[doc(no_inline)]
    pub use crate::{
        bf16, f16,
        slice::{HalfBitsSliceExt, HalfFloatSliceExt},
    };

    #[cfg(feature = "std")]
    pub use crate::vec::{HalfBitsVecExt, HalfFloatVecExt};
}

// Keep this module private to crate
pub(crate) mod private {
    use crate::{bf16, f16};

    pub trait SealedHalf {}

    impl SealedHalf for f16 {}
    impl SealedHalf for bf16 {}
}
<commit_msg>minor doc link update<commit_after>//! A crate that provides support for half-precision 16-bit floating point types.
//!
//! This crate provides the [`f16`] type, which is an implementation of the IEEE 754-2008 standard
//! [`binary16`] a.k.a `half` floating point type. This 16-bit floating point type is intended for
//! efficient storage where the full range and precision of a larger floating point value is not
//! required. This is especially useful for image storage formats.
//!
//! This crate also provides a [`bf16`] type, an alternative 16-bit floating point format. The
//! [`bfloat16`] format is a truncated IEEE 754 standard `binary32` float that preserves the
//! exponent to allow the same range as `f32` but with only 8 bits of precision (instead of 11
//! bits for [`f16`]). See the [`bf16`] type for details.
//!
//! Because [`f16`] and [`bf16`] are primarily for efficient storage, floating point operations such as
//! addition, multiplication, etc. are not implemented. Operations should be performed with `f32`
//! or higher-precision types and converted to/from [`f16`] or [`bf16`] as necessary.
//!
//! This crate also provides a [`slice`] module for zero-copy in-place conversions of `u16` slices
//! to both [`f16`] and [`bf16`], as well as efficient vectorized conversions of larger buffers of
//! floating point values to and from these half formats.
//!
//! A [`prelude`] module is provided for easy importing of available utility traits.
//!
//! Some hardware architectures provide support for 16-bit floating point conversions. Enable the
//! `use-intrinsics` feature to use LLVM intrinsics for hardware conversions. This crate does no
//! checks on whether the hardware supports the feature. This feature currently only works on
//! nightly Rust due to a compiler feature gate. When this feature is enabled and the hardware
//! supports it, the [`slice`] trait conversions will use vectorized SIMD intructions for
//! increased efficiency.
//!
//! Support for [`serde`] crate `Serialize` and `Deserialize` traits is provided when the `serde`
//! feature is enabled. This adds a dependency on [`serde`] crate so is an optional cargo feature.
//!
//! The crate uses `#[no_std]` by default, so can be used in embedded environments without using the
//! Rust `std` library. A `std` feature is available, which enables additional utilities using the
//! `std` library, such as the [`vec`] module that provides zero-copy `Vec` conversions.
//!
//! [`f16`]: struct.f16.html
//! [`binary16`]: https://en.wikipedia.org/wiki/Half-precision_floating-point_format
//! [`bf16`]: struct.bf16.html
//! [`bfloat16`]: https://en.wikipedia.org/wiki/Bfloat16_floating-point_format
//! [`slice`]: slice/index.html
//! [`prelude`]: prelude/index.html
//! [`serde`]: https://crates.io/crates/serde
//! [`vec`]: vec/index.html

#![warn(
    missing_docs,
    missing_copy_implementations,
    missing_debug_implementations,
    trivial_numeric_casts,
    unused_extern_crates,
    unused_import_braces,
    future_incompatible,
    rust_2018_compatibility,
    rust_2018_idioms,
    clippy::all
)]
#![allow(clippy::verbose_bit_mask, clippy::cast_lossless)]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(
    all(
        feature = "use-intrinsics",
        any(target_arch = "x86", target_arch = "x86_64")
    ),
    feature(stdsimd, f16c_target_feature)
)]
#![doc(html_root_url = "https://docs.rs/half/1.4.0")]

mod bfloat;
mod binary16;
pub mod slice;
#[cfg(feature = "std")]
pub mod vec;

pub use binary16::f16;

#[allow(deprecated)]
pub use binary16::consts;

pub use bfloat::bf16;

/// A collection of the most used items and traits in this crate for easy importing.
///
/// # Examples
///
/// ```rust
/// use half::prelude::*;
/// ```
pub mod prelude {
    #[doc(no_inline)]
    pub use crate::{
        bf16, f16,
        slice::{HalfBitsSliceExt, HalfFloatSliceExt},
    };

    #[cfg(feature = "std")]
    pub use crate::vec::{HalfBitsVecExt, HalfFloatVecExt};
}

// Keep this module private to crate
pub(crate) mod private {
    use crate::{bf16, f16};

    pub trait SealedHalf {}

    impl SealedHalf for f16 {}
    impl SealedHalf for bf16 {}
}
<|endoftext|>


<commit_before>
pub fn puzzle(input: &str) -> u32 {
    0
}

#[cfg(test)]
mod test {
    use super::*;
}
<commit_msg>Try to make a method that can say a string has an ABBA or not<commit_after>
pub fn puzzle(input: &str) -> u32 {
    0
}

pub fn contains_abba(candidate: &str) -> bool {
    let by_chars: Vec<char> = candidate.chars().collect();

    for (i, &c) in by_chars.iter().enumerate() {
        if c != by_chars[i + 1] &&
            by_chars[i + 1] == by_chars[i + 2] &&
            by_chars[i + 3] == c {
            return true
        }
    }
    false
}

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

    #[test]
    fn does_contain_abba() {
        assert!(contains_abba("abba"));
        assert!(contains_abba("ioxxoj"));
    }

    #[test]
    fn does_not_contain_abba() {
        assert!( ! contains_abba("mnop") );
        assert!( ! contains_abba("aaaa") );
    }
}
<|endoftext|>


<commit_before>//! Replaces the deprecated functionality of std::os::num_cpus.
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![allow(non_snake_case)]

#[cfg(not(windows))]
extern crate libc;

/// Returns the number of CPUs of the current machine.
#[inline]
pub fn get() -> usize {
    get_num_cpus()
}

/// Returns the number of physical cores of the current machine.
/// If not possible on the particular architecture returns same as get() which
/// is the logical CPUs.
#[inline]
pub fn get_physical() -> usize {
    get_num_physical_cpus()
}

#[cfg(not(target_os = "linux"))]
#[inline]
fn get_num_physical_cpus() -> usize {
    // Not implemented, fallback
    get_num_cpus()
}

#[cfg(target_os = "linux")]
fn get_num_physical_cpus() -> usize {
    use std::io::BufReader;
    use std::io::BufRead;
    use std::fs::File;
    use std::collections::HashMap;

    let file = match File::open("/proc/cpuinfo") {
        Ok(val) => val,
        Err(_) => {return get_num_cpus()},
    };
    let reader = BufReader::new(file);
    let mut map = HashMap::new();
    for line in reader.lines().filter_map(|result| result.ok()) {
        let parts: Vec<&str> = line.split(':').map(|s| s.trim()).collect();
        if parts.len() != 2 {
            continue
        }
        if parts[0] == "core id" {
            map.insert(parts[1].to_string(), true);
        }
    }
    let count = map.len();
    if count == 0 { get_num_cpus() } else { count }
}

#[cfg(windows)]
fn get_num_cpus() -> usize {
    #[repr(C)]
    struct SYSTEM_INFO {
        wProcessorArchitecture: u16,
        wReserved: u16,
        dwPageSize: u32,
        lpMinimumApplicationAddress: *mut u8,
        lpMaximumApplicationAddress: *mut u8,
        dwActiveProcessorMask: *mut u8,
        dwNumberOfProcessors: u32,
        dwProcessorType: u32,
        dwAllocationGranularity: u32,
        wProcessorLevel: u16,
        wProcessorRevision: u16,
    }

    extern "system" {
        fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
    }

    unsafe {
        let mut sysinfo: SYSTEM_INFO = std::mem::uninitialized();
        GetSystemInfo(&mut sysinfo);
        sysinfo.dwNumberOfProcessors as usize
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "netbsd"))]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    unsafe {
        cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
    }
    if cpus < 1 {
        let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
        unsafe {
            libc::sysctl(mib.as_mut_ptr(),
                         2,
                         &mut cpus as *mut _ as *mut _,
                         &mut cpus_size as *mut _ as *mut _,
                         0 as *mut _,
                         0);
        }
        if cpus < 1 {
            cpus = 1;
        }
    }
    cpus as usize
}

#[cfg(target_os = "openbsd")]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);
    let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];

    unsafe {
        libc::sysctl(mib.as_mut_ptr(),
                     2,
                     &mut cpus as *mut _ as *mut _,
                     &mut cpus_size as *mut _ as *mut _,
                     0 as *mut _,
                     0);
    }
    if cpus < 1 {
        cpus = 1;
    }
    cpus as usize
}

#[cfg(
    any(
        target_os = "linux",
        target_os = "nacl",
        target_os = "macos",
        target_os = "ios",
        target_os = "android",
        target_os = "solaris",
        target_os = "fuchsia",
    )
)]
fn get_num_cpus() -> usize {
    unsafe {
        libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize
    }
}
#[cfg(target_os = "emscripten")]
fn get_num_cpus() -> usize {
    1
}

#[test]
fn lower_bound() {
    assert!(get() > 0);
    assert!(get_physical() > 0);
}

#[test]
fn upper_bound() {
    assert!(get() < 236_451);
    assert!(get_physical() < 236_451);
}
<commit_msg>Count physical cores properly on linux<commit_after>//! Replaces the deprecated functionality of std::os::num_cpus.
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![allow(non_snake_case)]

#[cfg(not(windows))]
extern crate libc;

/// Returns the number of CPUs of the current machine.
#[inline]
pub fn get() -> usize {
    get_num_cpus()
}

/// Returns the number of physical cores of the current machine.
/// If not possible on the particular architecture returns same as get() which
/// is the logical CPUs.
#[inline]
pub fn get_physical() -> usize {
    get_num_physical_cpus()
}

#[cfg(not(target_os = "linux"))]
#[inline]
fn get_num_physical_cpus() -> usize {
    // Not implemented, fallback
    get_num_cpus()
}

#[cfg(target_os = "linux")]
fn get_num_physical_cpus() -> usize {
    use std::io::BufReader;
    use std::io::BufRead;
    use std::fs::File;
    use std::collections::HashMap;

    let file = match File::open("/proc/cpuinfo") {
        Ok(val) => val,
        Err(_) => {return get_num_cpus()},
    };
    let reader = BufReader::new(file);
    let mut map = HashMap::new();
    let mut coreid: u64 = 0;
    let mut physid: u64 = 0;
    let mut chgcount = 0;
    for line in reader.lines().filter_map(|result| result.ok()) {
        let parts: Vec<&str> = line.split(':').map(|s| s.trim()).collect();
        if parts.len() != 2 {
            continue
        }
        if parts[0] == "core id" || parts[0] == "physical id" {
            let value: u64 = match parts[1].trim().parse() {
              Ok(val) => val,
              Err(_) => {break;}
            };
            match parts[0] {
                "core id"     => { coreid = value;},
                "physical id" => { physid = value;},
                _ => {},
            }
            chgcount += 1;
        }
        if chgcount == 2 {
            map.insert((physid<<32)|coreid, true);
            chgcount = 0;
        }
    }
    let count = map.len();
    if count == 0 { get_num_cpus() } else { count }
}

#[cfg(windows)]
fn get_num_cpus() -> usize {
    #[repr(C)]
    struct SYSTEM_INFO {
        wProcessorArchitecture: u16,
        wReserved: u16,
        dwPageSize: u32,
        lpMinimumApplicationAddress: *mut u8,
        lpMaximumApplicationAddress: *mut u8,
        dwActiveProcessorMask: *mut u8,
        dwNumberOfProcessors: u32,
        dwProcessorType: u32,
        dwAllocationGranularity: u32,
        wProcessorLevel: u16,
        wProcessorRevision: u16,
    }

    extern "system" {
        fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
    }

    unsafe {
        let mut sysinfo: SYSTEM_INFO = std::mem::uninitialized();
        GetSystemInfo(&mut sysinfo);
        sysinfo.dwNumberOfProcessors as usize
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "netbsd"))]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    unsafe {
        cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
    }
    if cpus < 1 {
        let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
        unsafe {
            libc::sysctl(mib.as_mut_ptr(),
                         2,
                         &mut cpus as *mut _ as *mut _,
                         &mut cpus_size as *mut _ as *mut _,
                         0 as *mut _,
                         0);
        }
        if cpus < 1 {
            cpus = 1;
        }
    }
    cpus as usize
}

#[cfg(target_os = "openbsd")]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);
    let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];

    unsafe {
        libc::sysctl(mib.as_mut_ptr(),
                     2,
                     &mut cpus as *mut _ as *mut _,
                     &mut cpus_size as *mut _ as *mut _,
                     0 as *mut _,
                     0);
    }
    if cpus < 1 {
        cpus = 1;
    }
    cpus as usize
}

#[cfg(
    any(
        target_os = "linux",
        target_os = "nacl",
        target_os = "macos",
        target_os = "ios",
        target_os = "android",
        target_os = "solaris",
        target_os = "fuchsia",
    )
)]
fn get_num_cpus() -> usize {
    unsafe {
        libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize
    }
}
#[cfg(target_os = "emscripten")]
fn get_num_cpus() -> usize {
    1
}

#[test]
fn lower_bound() {
    assert!(get() > 0);
    assert!(get_physical() > 0);
}

#[test]
fn upper_bound() {
    assert!(get() < 236_451);
    assert!(get_physical() < 236_451);
}
<|endoftext|>