<commit_before>
//! Management of entities, components, systems, and managers

use std::cell::RefCell;
use std::collections::HashMap;
use std::mem;

use {Component, ComponentId};
use Entity;
use {Manager, MutableManager};
use Phantom;
use {Passive, System};
use component::ComponentList;
use entity::EntityManager;

pub struct World
{
    entities: RefCell<EntityManager>,
    components: ComponentManager,
    systems: RefCell<SystemManager>,
    mut_managers: Vec<RefCell<Box<MutableManager>>>,
    managers: Vec<Box<Manager>>,
    locked: bool,
}

pub struct Components<'a>
{
    inner: &'a mut ComponentManager,
}

struct ComponentManager
{
    components: HashMap<ComponentId, ComponentList>,
}

struct SystemManager
{
    systems: Vec<Box<System>>,
    passive: HashMap<&'static str, Box<Passive>>,
}

impl World
{
    pub fn new() -> World
    {
        World
        {
            entities: RefCell::new(EntityManager::new()),
            components: ComponentManager::new(),
            systems: RefCell::new(SystemManager::new()),
            mut_managers: Vec::new(),
            managers: Vec::new(),
            locked: false,
        }
    }

    /// Lock down the managers and systems, and components of a world.
    ///
    /// This must be called before entities can be created and modified.
    /// After it is called, no systems/managers/components may be registered.
    pub fn finalise(&mut self)
    {
        if self.locked
        {
            fail!("World is already finalised")
        }
        self.locked = true;
    }

    /// Returns if an entity has been activated.
    #[inline]
    pub fn is_active(&self, entity: &Entity) -> bool
    {
        self.entities.borrow().is_activated(entity)
    }

    /// Registers a mutable manager.
    ///
    /// # Failure
    ///
    /// If the world has been finalised
    #[experimental]
    pub fn register_manager_mut(&mut self, manager: Box<MutableManager>)
    {
        if self.locked
        {
            fail!("World is locked. Managers may not be registered")
        }
        self.mut_managers.push(RefCell::new(manager));
    }

    /// Registers an immutable manager.
    ///
    /// # Failure
    ///
    /// If the world has been finalised
    #[experimental]
    pub fn register_manager(&mut self, manager: Box<Manager>)
    {
        if self.locked
        {
            fail!("World is locked. Managers may not be registered")
        }
        self.managers.push(manager);
    }

    /// Registers a component.
    ///
    /// # Failure
    ///
    /// If the world has been finalised
    pub fn register_component<T: Component>(&mut self)
    {
        if self.locked
        {
            fail!("World is locked. Components may not be registered")
        }
        self.components.register(ComponentList::new(Phantom::<T>));
    }

    /// Registers a system.
    ///
    /// # Failure
    ///
    /// If the world has been finalised
    pub fn register_system(&mut self, sys: Box<System>)
    {
        if self.locked
        {
            fail!("World is locked. Systems may not be registered")
        }
        self.systems.borrow_mut().register(sys);
    }

    /// Registers a passive system.
    ///
    /// # Failure
    ///
    /// If the world has been finalised
    pub fn register_passive(&mut self, key: &'static str, sys: Box<Passive>)
    {
        if self.locked
        {
            fail!("World is locked. Systems may not be registered")
        }
        self.systems.borrow_mut().register_passive(key, sys);
    }

    /// Updates the world by processing all systems.
    ///
    /// # Failure
    ///
    /// If the world has not been finalised
    pub fn update(&mut self)
    {
        if !self.locked
        {
            fail!("World must be locked before updating")
        }
        self.systems.borrow_mut().update(self, self.components());
    }

    /// Updates the passive system corresponding to `key`
    ///
    /// # Failure
    ///
    /// If the world has not been finalised
    pub fn update_passive(&mut self, key: &'static str)
    {
        if !self.locked
        {
            fail!("World must be locked before updating")
        }
        self.systems.borrow_mut().update_passive(key, self);
    }

    fn components(&self) -> Components
    {
        Components
        {
            inner: unsafe {
                mem::transmute(&self.components())
            },
        }
    }

    /// Creates an entity
    ///
    /// # Failure
    ///
    /// If the world has not been finalised
    pub fn create_entity(&mut self) -> Entity
    {
        if !self.locked
        {
            fail!("World must be locked before creating entities")
        }
        let ret = self.entities.borrow_mut().create_entity();
        for ref manager in self.mut_managers.iter()
        {
            manager.borrow_mut().added(&ret, self);
        }
        for ref manager in self.managers.iter()
        {
            manager.added(&ret, self);
        }
        ret
    }

    /// Activates an entity
    ///
    /// Once activated, components cannot be added to the entity,
    /// and systems will be able to process it.
    ///
    /// # Failure
    ///
    /// If the entity is invalid or already activated
    pub fn activate_entity(&mut self, entity: &Entity)
    {
        if self.is_active(entity)
        {
            fail!("Entity is already activated")
        }
        if !self.entities.borrow().is_valid(entity)
        {
            fail!("Cannot activate invalid entity")
        }
        self.entities.borrow_mut().activate_entity(entity);
        self.systems.borrow_mut().activated(entity, self);
        for ref manager in self.mut_managers.iter()
        {
            manager.borrow_mut().activated(entity, self);
        }
        for ref manager in self.managers.iter()
        {
            manager.activated(entity, self);
        }
    }

    /// Deactivates an entity
    ///
    /// It will then be ignored by all systems.
    /// Components can only be added/removed from an entity while deactivated.
    ///
    /// # Failure
    ///
    /// If the entity is not already activated
    pub fn deactivate_entity(&mut self, entity: &Entity)
    {
        if !self.is_active(entity)
        {
            fail!("Cannot deactivate unactivated entity")
        }
        self.entities.borrow_mut().deactivate_entity(entity);
        self.systems.borrow_mut().deactivated(entity, self);
        for ref manager in self.mut_managers.iter()
        {
            manager.borrow_mut().deactivated(entity, self);
        }
        for ref manager in self.managers.iter()
        {
            manager.deactivated(entity, self);
        }
    }

    /// Deletes an entity, deactivating it if it is activated
    ///
    /// # Failure
    ///
    /// If an entity is invalid
    pub fn delete_entity(&mut self, entity: &Entity)
    {
        if !self.entities.borrow().is_valid(entity)
        {
            fail!("Cannot delete invalid entity")
        }
        if self.is_active(entity)
        {
            self.deactivate_entity(entity);
        }
        self.entities.borrow_mut().delete_entity(entity);
        self.components.delete_entity(entity);
        for ref manager in self.mut_managers.iter()
        {
            manager.borrow_mut().removed(entity, self);
        }
        for ref manager in self.managers.iter()
        {
            manager.removed(entity, self);
        }
    }

    /// Add a component to an entity
    ///
    /// Returns false if the component could not be added (entity invalid or activated).
    pub fn add_component<T: Component>(&mut self, entity: &Entity, component: T) -> bool
    {
        self.entities.borrow().is_valid(entity)
        && !self.is_active(entity)
        && self.components.add::<T>(entity, component)
    }

    /// Removes a component from an entity.
    ///
    /// Returns false if the component could not be removed (entity invalid or activated).
    pub fn remove_component<T: Component>(&mut self, entity: &Entity) -> bool
    {
        self.entities.borrow().is_valid(entity)
        && !self.is_active(entity)
        && self.components.remove::<T>(entity)
    }

    /// Set the value of a component for an entity
    ///
    /// Returns false if the entity does not contain that component.
    pub fn set_component<T: Component>(&mut self, entity: &Entity, component: T) -> bool
    {
        self.entities.borrow().is_valid(entity)
        && self.components.set::<T>(entity, component)
    }

    /// Returns the value of a component for an entity (or None)
    pub fn get_component<T: Component>(&self, entity: &Entity) -> Option<T>
    {
        if self.entities.borrow().is_valid(entity)
        {
            self.components.get::<T>(entity)
        }
        else
        {
            None
        }
    }

    /// Returns if an entity contains a component.
    pub fn has_component(&self, entity: &Entity, id: ComponentId) -> bool
    {
        self.components.has(entity, id)
    }

    /// Returns a reference to an entity's component. (or None)
    pub fn borrow_component<T: Component>(&self, entity: &Entity) -> Option<&T>
    {
        if self.is_active(entity)
        {
            self.components.borrow::<T>(entity)
        }
        else
        {
            None
        }
    }

    /// Returns a mutable reference to an entity's component. (or None)
    pub fn borrow_mut_component<T: Component>(&mut self, entity: &Entity) -> Option<&mut T>
    {
        if self.is_active(entity)
        {
            self.components.borrow_mut::<T>(entity)
        }
        else
        {
            None
        }
    }
}

impl SystemManager
{
    pub fn new() -> SystemManager
    {
        SystemManager
        {
            systems: Vec::new(),
            passive: HashMap::new(),
        }
    }

    pub fn register(&mut self, sys: Box<System>)
    {
        self.systems.push(sys);
    }

    pub fn register_passive(&mut self, key: &'static str, sys: Box<Passive>)
    {
        self.passive.insert(key, sys);
    }

    pub fn update(&mut self, world: &World, mut components: Components)
    {
        for sys in self.systems.mut_iter()
        {
            sys.preprocess(world);
        }
        for sys in self.systems.iter()
        {
            sys.process(world, &mut components);
        }
        for sys in self.systems.mut_iter()
        {
            sys.postprocess(world);
        }
    }

    pub fn update_passive(&mut self, key: &'static str, world: &World)
    {
        self.passive.get_mut(&key).process(world);
    }
}

impl MutableManager for SystemManager
{
    fn added(&mut self, _: &Entity, _: &World)
    {

    }

    fn removed(&mut self, _: &Entity, _: &World)
    {

    }

    fn activated(&mut self, e: &Entity, w: &World)
    {
        for sys in self.systems.mut_iter()
        {
            sys.activated(e, w);
        }
    }

    fn deactivated(&mut self, e: &Entity, _: &World)
    {
        for sys in self.systems.mut_iter()
        {
            sys.deactivated(e);
        }
    }
}

impl ComponentManager
{
    pub fn new() -> ComponentManager
    {
        ComponentManager
        {
            components: HashMap::new(),
        }
    }

    pub fn register(&mut self, list: ComponentList)
    {
        self.components.insert(list.get_cid(), list);
    }

    fn delete_entity(&mut self, entity: &Entity)
    {
        for (_, list) in self.components.mut_iter()
        {
            list.rm(entity);
        }
    }

    fn add<T:Component>(&mut self, entity: &Entity, component: T) -> bool
    {
        self.components.get_mut(&Component::cid(Phantom::<T>)).add::<T>(entity, &component)
    }

    fn set<T:Component>(&mut self, entity: &Entity, component: T) -> bool
    {
        self.components.get_mut(&Component::cid(Phantom::<T>)).set::<T>(entity, &component)
    }

    fn get<T:Component>(&self, entity: &Entity) -> Option<T>
    {
        self.components[Component::cid(Phantom::<T>)].get::<T>(entity)
    }

    pub fn has(&self, entity: &Entity, id: ComponentId) -> bool
    {
        self.components[id].has(entity)
    }

    fn borrow<T:Component>(&self, entity: &Entity) -> Option<&T>
    {
        self.components[Component::cid(Phantom::<T>)].borrow::<T>(entity)
    }

    fn borrow_mut<T:Component>(&mut self, entity: &Entity) -> Option<&mut T>
    {
        self.components.get_mut(&Component::cid(Phantom::<T>)).borrow_mut::<T>(entity)
    }

    fn remove<T:Component>(&mut self, entity: &Entity) -> bool
    {
        self.components.get_mut(&Component::cid(Phantom::<T>)).rm(entity)
    }
}

impl<'a> Components<'a>
{
    pub fn borrow<T:Component>(&self, entity: &Entity) -> Option<&T>
    {
        self.inner.borrow::<T>(entity)
    }

    pub fn borrow_mut<T:Component>(&mut self, entity: &Entity) -> Option<&mut T>
    {
        self.inner.borrow_mut::<T>(entity)
    }
}
<commit_msg>fixed typo causing stack overflow<commit_after>
//! Management of entities, components, systems, and managers

use std::cell::RefCell;
use std::collections::HashMap;
use std::mem;

use {Component, ComponentId};
use Entity;
use {Manager, MutableManager};
use Phantom;
use {Passive, System};
use component::ComponentList;
use entity::EntityManager;

pub struct World
{
    entities: RefCell<EntityManager>,
    components: ComponentManager,
    systems: RefCell<SystemManager>,
    mut_managers: Vec<RefCell<Box<MutableManager>>>,
    managers: Vec<Box<Manager>>,
    locked: bool,
}

pub struct Components<'a>
{
    inner: &'a mut ComponentManager,
}

struct ComponentManager
{
    components: HashMap<ComponentId, ComponentList>,
}

struct SystemManager
{
    systems: Vec<Box<System>>,
    passive: HashMap<&'static str, Box<Passive>>,
}

impl World
{
    pub fn new() -> World
    {
        World
        {
            entities: RefCell::new(EntityManager::new()),
            components: ComponentManager::new(),
            systems: RefCell::new(SystemManager::new()),
            mut_managers: Vec::new(),
            managers: Vec::new(),
            locked: false,
        }
    }

    /// Lock down the managers and systems, and components of a world.
    ///
    /// This must be called before entities can be created and modified.
    /// After it is called, no systems/managers/components may be registered.
    pub fn finalise(&mut self)
    {
        if self.locked
        {
            fail!("World is already finalised")
        }
        self.locked = true;
    }

    /// Returns if an entity has been activated.
    #[inline]
    pub fn is_active(&self, entity: &Entity) -> bool
    {
        self.entities.borrow().is_activated(entity)
    }

    /// Registers a mutable manager.
    ///
    /// # Failure
    ///
    /// If the world has been finalised
    #[experimental]
    pub fn register_manager_mut(&mut self, manager: Box<MutableManager>)
    {
        if self.locked
        {
            fail!("World is locked. Managers may not be registered")
        }
        self.mut_managers.push(RefCell::new(manager));
    }

    /// Registers an immutable manager.
    ///
    /// # Failure
    ///
    /// If the world has been finalised
    #[experimental]
    pub fn register_manager(&mut self, manager: Box<Manager>)
    {
        if self.locked
        {
            fail!("World is locked. Managers may not be registered")
        }
        self.managers.push(manager);
    }

    /// Registers a component.
    ///
    /// # Failure
    ///
    /// If the world has been finalised
    pub fn register_component<T: Component>(&mut self)
    {
        if self.locked
        {
            fail!("World is locked. Components may not be registered")
        }
        self.components.register(ComponentList::new(Phantom::<T>));
    }

    /// Registers a system.
    ///
    /// # Failure
    ///
    /// If the world has been finalised
    pub fn register_system(&mut self, sys: Box<System>)
    {
        if self.locked
        {
            fail!("World is locked. Systems may not be registered")
        }
        self.systems.borrow_mut().register(sys);
    }

    /// Registers a passive system.
    ///
    /// # Failure
    ///
    /// If the world has been finalised
    pub fn register_passive(&mut self, key: &'static str, sys: Box<Passive>)
    {
        if self.locked
        {
            fail!("World is locked. Systems may not be registered")
        }
        self.systems.borrow_mut().register_passive(key, sys);
    }

    /// Updates the world by processing all systems.
    ///
    /// # Failure
    ///
    /// If the world has not been finalised
    pub fn update(&mut self)
    {
        if !self.locked
        {
            fail!("World must be locked before updating")
        }
        self.systems.borrow_mut().update(self, self.components());
    }

    /// Updates the passive system corresponding to `key`
    ///
    /// # Failure
    ///
    /// If the world has not been finalised
    pub fn update_passive(&mut self, key: &'static str)
    {
        if !self.locked
        {
            fail!("World must be locked before updating")
        }
        self.systems.borrow_mut().update_passive(key, self);
    }

    fn components(&self) -> Components
    {
        Components
        {
            inner: unsafe {
                mem::transmute(&self.components)
            },
        }
    }

    /// Creates an entity
    ///
    /// # Failure
    ///
    /// If the world has not been finalised
    pub fn create_entity(&mut self) -> Entity
    {
        if !self.locked
        {
            fail!("World must be locked before creating entities")
        }
        let ret = self.entities.borrow_mut().create_entity();
        for ref manager in self.mut_managers.iter()
        {
            manager.borrow_mut().added(&ret, self);
        }
        for ref manager in self.managers.iter()
        {
            manager.added(&ret, self);
        }
        ret
    }

    /// Activates an entity
    ///
    /// Once activated, components cannot be added to the entity,
    /// and systems will be able to process it.
    ///
    /// # Failure
    ///
    /// If the entity is invalid or already activated
    pub fn activate_entity(&mut self, entity: &Entity)
    {
        if self.is_active(entity)
        {
            fail!("Entity is already activated")
        }
        if !self.entities.borrow().is_valid(entity)
        {
            fail!("Cannot activate invalid entity")
        }
        self.entities.borrow_mut().activate_entity(entity);
        self.systems.borrow_mut().activated(entity, self);
        for ref manager in self.mut_managers.iter()
        {
            manager.borrow_mut().activated(entity, self);
        }
        for ref manager in self.managers.iter()
        {
            manager.activated(entity, self);
        }
    }

    /// Deactivates an entity
    ///
    /// It will then be ignored by all systems.
    /// Components can only be added/removed from an entity while deactivated.
    ///
    /// # Failure
    ///
    /// If the entity is not already activated
    pub fn deactivate_entity(&mut self, entity: &Entity)
    {
        if !self.is_active(entity)
        {
            fail!("Cannot deactivate unactivated entity")
        }
        self.entities.borrow_mut().deactivate_entity(entity);
        self.systems.borrow_mut().deactivated(entity, self);
        for ref manager in self.mut_managers.iter()
        {
            manager.borrow_mut().deactivated(entity, self);
        }
        for ref manager in self.managers.iter()
        {
            manager.deactivated(entity, self);
        }
    }

    /// Deletes an entity, deactivating it if it is activated
    ///
    /// # Failure
    ///
    /// If an entity is invalid
    pub fn delete_entity(&mut self, entity: &Entity)
    {
        if !self.entities.borrow().is_valid(entity)
        {
            fail!("Cannot delete invalid entity")
        }
        if self.is_active(entity)
        {
            self.deactivate_entity(entity);
        }
        self.entities.borrow_mut().delete_entity(entity);
        self.components.delete_entity(entity);
        for ref manager in self.mut_managers.iter()
        {
            manager.borrow_mut().removed(entity, self);
        }
        for ref manager in self.managers.iter()
        {
            manager.removed(entity, self);
        }
    }

    /// Add a component to an entity
    ///
    /// Returns false if the component could not be added (entity invalid or activated).
    pub fn add_component<T: Component>(&mut self, entity: &Entity, component: T) -> bool
    {
        self.entities.borrow().is_valid(entity)
        && !self.is_active(entity)
        && self.components.add::<T>(entity, component)
    }

    /// Removes a component from an entity.
    ///
    /// Returns false if the component could not be removed (entity invalid or activated).
    pub fn remove_component<T: Component>(&mut self, entity: &Entity) -> bool
    {
        self.entities.borrow().is_valid(entity)
        && !self.is_active(entity)
        && self.components.remove::<T>(entity)
    }

    /// Set the value of a component for an entity
    ///
    /// Returns false if the entity does not contain that component.
    pub fn set_component<T: Component>(&mut self, entity: &Entity, component: T) -> bool
    {
        self.entities.borrow().is_valid(entity)
        && self.components.set::<T>(entity, component)
    }

    /// Returns the value of a component for an entity (or None)
    pub fn get_component<T: Component>(&self, entity: &Entity) -> Option<T>
    {
        if self.entities.borrow().is_valid(entity)
        {
            self.components.get::<T>(entity)
        }
        else
        {
            None
        }
    }

    /// Returns if an entity contains a component.
    pub fn has_component(&self, entity: &Entity, id: ComponentId) -> bool
    {
        self.components.has(entity, id)
    }

    /// Returns a reference to an entity's component. (or None)
    pub fn borrow_component<T: Component>(&self, entity: &Entity) -> Option<&T>
    {
        if self.is_active(entity)
        {
            self.components.borrow::<T>(entity)
        }
        else
        {
            None
        }
    }

    /// Returns a mutable reference to an entity's component. (or None)
    pub fn borrow_mut_component<T: Component>(&mut self, entity: &Entity) -> Option<&mut T>
    {
        if self.is_active(entity)
        {
            self.components.borrow_mut::<T>(entity)
        }
        else
        {
            None
        }
    }
}

impl SystemManager
{
    pub fn new() -> SystemManager
    {
        SystemManager
        {
            systems: Vec::new(),
            passive: HashMap::new(),
        }
    }

    pub fn register(&mut self, sys: Box<System>)
    {
        self.systems.push(sys);
    }

    pub fn register_passive(&mut self, key: &'static str, sys: Box<Passive>)
    {
        self.passive.insert(key, sys);
    }

    pub fn update(&mut self, world: &World, mut components: Components)
    {
        for sys in self.systems.mut_iter()
        {
            sys.preprocess(world);
        }
        for sys in self.systems.iter()
        {
            sys.process(world, &mut components);
        }
        for sys in self.systems.mut_iter()
        {
            sys.postprocess(world);
        }
    }

    pub fn update_passive(&mut self, key: &'static str, world: &World)
    {
        self.passive.get_mut(&key).process(world);
    }
}

impl MutableManager for SystemManager
{
    fn added(&mut self, _: &Entity, _: &World)
    {

    }

    fn removed(&mut self, _: &Entity, _: &World)
    {

    }

    fn activated(&mut self, e: &Entity, w: &World)
    {
        for sys in self.systems.mut_iter()
        {
            sys.activated(e, w);
        }
    }

    fn deactivated(&mut self, e: &Entity, _: &World)
    {
        for sys in self.systems.mut_iter()
        {
            sys.deactivated(e);
        }
    }
}

impl ComponentManager
{
    pub fn new() -> ComponentManager
    {
        ComponentManager
        {
            components: HashMap::new(),
        }
    }

    pub fn register(&mut self, list: ComponentList)
    {
        self.components.insert(list.get_cid(), list);
    }

    fn delete_entity(&mut self, entity: &Entity)
    {
        for (_, list) in self.components.mut_iter()
        {
            list.rm(entity);
        }
    }

    fn add<T:Component>(&mut self, entity: &Entity, component: T) -> bool
    {
        self.components.get_mut(&Component::cid(Phantom::<T>)).add::<T>(entity, &component)
    }

    fn set<T:Component>(&mut self, entity: &Entity, component: T) -> bool
    {
        self.components.get_mut(&Component::cid(Phantom::<T>)).set::<T>(entity, &component)
    }

    fn get<T:Component>(&self, entity: &Entity) -> Option<T>
    {
        self.components[Component::cid(Phantom::<T>)].get::<T>(entity)
    }

    pub fn has(&self, entity: &Entity, id: ComponentId) -> bool
    {
        self.components[id].has(entity)
    }

    fn borrow<T:Component>(&self, entity: &Entity) -> Option<&T>
    {
        self.components[Component::cid(Phantom::<T>)].borrow::<T>(entity)
    }

    fn borrow_mut<T:Component>(&mut self, entity: &Entity) -> Option<&mut T>
    {
        self.components.get_mut(&Component::cid(Phantom::<T>)).borrow_mut::<T>(entity)
    }

    fn remove<T:Component>(&mut self, entity: &Entity) -> bool
    {
        self.components.get_mut(&Component::cid(Phantom::<T>)).rm(entity)
    }
}

impl<'a> Components<'a>
{
    pub fn borrow<T:Component>(&self, entity: &Entity) -> Option<&T>
    {
        self.inner.borrow::<T>(entity)
    }

    pub fn borrow_mut<T:Component>(&mut self, entity: &Entity) -> Option<&mut T>
    {
        self.inner.borrow_mut::<T>(entity)
    }
}
<|endoftext|>


<commit_before>extern crate cretonne_wasm;
extern crate cretonne;

use cretonne_wasm::{translate_module, FunctionTranslation, DummyRuntime, WasmRuntime};
use std::path::PathBuf;
use std::fs::File;
use std::error::Error;
use std::io;
use std::io::BufReader;
use std::io::prelude::*;
use std::fs;
use cretonne::ir;
use cretonne::ir::entities::AnyEntity;
use cretonne::isa::TargetIsa;
use cretonne::verifier;

#[test]
fn testsuite() {
    let mut paths: Vec<_> = fs::read_dir("../../wasmtests")
        .unwrap()
        .map(|r| r.unwrap())
        .collect();
    paths.sort_by_key(|dir| dir.path());
    for path in paths {
        let path = path.path();
        match handle_module(path) {
            Ok(()) => (),
            Err(message) => println!("{}", message),
        };
    }
}

fn read_wasm_file(path: PathBuf) -> Result<Vec<u8>, io::Error> {
    let mut buf: Vec<u8> = Vec::new();
    let file = File::open(path)?;
    let mut buf_reader = BufReader::new(file);
    buf_reader.read_to_end(&mut buf)?;
    Ok(buf)
}

fn handle_module(path: PathBuf) -> Result<(), String> {
    let data = match path.extension() {
        None => {
            return Err(String::from("the file extension is not wasm or wast"));
        }
        Some(ext) => {
            match ext.to_str() {
                Some("wasm") => {
                    match read_wasm_file(path.clone()) {
                        Ok(data) => data,
                        Err(err) => {
                            return Err(String::from(err.description()));
                        }
                    }
                }
                None | Some(&_) => {
                    return Err(String::from("the file extension is not wasm or wast"));
                }
            }
        }
    };
    let mut dummy_runtime = DummyRuntime::new();
    let translation = {
        let mut runtime: &mut WasmRuntime = &mut dummy_runtime;
        match translate_module(&data, runtime) {
            Ok(x) => x,
            Err(string) => {
                return Err(string);
            }
        }
    };
    for func in translation.functions.iter() {
        let il = match func {
            &FunctionTranslation::Import() => continue,
            &FunctionTranslation::Code { ref il, .. } => il.clone(),
        };
        match verifier::verify_function(&il, None) {
            Ok(()) => (),
            Err(err) => return Err(pretty_verifier_error(&il, None, err)),
        }
    }
    Ok(())
}

/// Pretty-print a verifier error.
pub fn pretty_verifier_error(func: &ir::Function,
                             isa: Option<&TargetIsa>,
                             err: verifier::Error)
                             -> String {
    let msg = err.to_string();
    let str1 = match err.location {
        AnyEntity::Inst(inst) => {
            format!("{}\n{}: {}\n\n",
                    msg,
                    inst,
                    func.dfg.display_inst(inst, isa))
        }
        _ => String::from(format!("{}\n", msg)),
    };
    format!("{}{}", str1, func.display(isa))
}
<commit_msg>Remove an unnecessary `mut`, fixing a compiler warning.<commit_after>extern crate cretonne_wasm;
extern crate cretonne;

use cretonne_wasm::{translate_module, FunctionTranslation, DummyRuntime, WasmRuntime};
use std::path::PathBuf;
use std::fs::File;
use std::error::Error;
use std::io;
use std::io::BufReader;
use std::io::prelude::*;
use std::fs;
use cretonne::ir;
use cretonne::ir::entities::AnyEntity;
use cretonne::isa::TargetIsa;
use cretonne::verifier;

#[test]
fn testsuite() {
    let mut paths: Vec<_> = fs::read_dir("../../wasmtests")
        .unwrap()
        .map(|r| r.unwrap())
        .collect();
    paths.sort_by_key(|dir| dir.path());
    for path in paths {
        let path = path.path();
        match handle_module(path) {
            Ok(()) => (),
            Err(message) => println!("{}", message),
        };
    }
}

fn read_wasm_file(path: PathBuf) -> Result<Vec<u8>, io::Error> {
    let mut buf: Vec<u8> = Vec::new();
    let file = File::open(path)?;
    let mut buf_reader = BufReader::new(file);
    buf_reader.read_to_end(&mut buf)?;
    Ok(buf)
}

fn handle_module(path: PathBuf) -> Result<(), String> {
    let data = match path.extension() {
        None => {
            return Err(String::from("the file extension is not wasm or wast"));
        }
        Some(ext) => {
            match ext.to_str() {
                Some("wasm") => {
                    match read_wasm_file(path.clone()) {
                        Ok(data) => data,
                        Err(err) => {
                            return Err(String::from(err.description()));
                        }
                    }
                }
                None | Some(&_) => {
                    return Err(String::from("the file extension is not wasm or wast"));
                }
            }
        }
    };
    let mut dummy_runtime = DummyRuntime::new();
    let translation = {
        let runtime: &mut WasmRuntime = &mut dummy_runtime;
        match translate_module(&data, runtime) {
            Ok(x) => x,
            Err(string) => {
                return Err(string);
            }
        }
    };
    for func in translation.functions.iter() {
        let il = match func {
            &FunctionTranslation::Import() => continue,
            &FunctionTranslation::Code { ref il, .. } => il.clone(),
        };
        match verifier::verify_function(&il, None) {
            Ok(()) => (),
            Err(err) => return Err(pretty_verifier_error(&il, None, err)),
        }
    }
    Ok(())
}

/// Pretty-print a verifier error.
pub fn pretty_verifier_error(func: &ir::Function,
                             isa: Option<&TargetIsa>,
                             err: verifier::Error)
                             -> String {
    let msg = err.to_string();
    let str1 = match err.location {
        AnyEntity::Inst(inst) => {
            format!("{}\n{}: {}\n\n",
                    msg,
                    inst,
                    func.dfg.display_inst(inst, isa))
        }
        _ => String::from(format!("{}\n", msg)),
    };
    format!("{}{}", str1, func.display(isa))
}
<|endoftext|>


<commit_before>pub(crate) mod http_request_to_grpc_frames_typed;
pub(crate) mod http_response_to_grpc_frames;
pub(crate) mod http_response_to_grpc_frames_typed;
pub(crate) mod req_sink;
pub(crate) mod types;

use std::net::SocketAddr;

use bytes::Bytes;

use httpbis;
use httpbis::Header;
use httpbis::Headers;
use httpbis::HttpScheme;

use tls_api;

use method::MethodDescriptor;

use error::*;
use result;

use client::http_request_to_grpc_frames_typed::http_req_to_grpc_frames_typed;
use client::http_response_to_grpc_frames_typed::http_response_to_grpc_frames_typed;
use client::req_sink::ClientRequestSink;
use error;
use futures::future;
use futures::Future;
use proto::grpc_frame::write_grpc_frame_to_vec;
use req::*;
use resp::*;
use or_static::arc::ArcOrStatic;

#[derive(Default, Debug, Clone)]
pub struct ClientConf {
    pub http: httpbis::ClientConf,
}

impl ClientConf {
    pub fn new() -> ClientConf {
        Default::default()
    }
}

/// gRPC client implementation.
/// Used by generated code.
#[derive(Debug)]
pub struct Client {
    client: ::std::sync::Arc<httpbis::Client>,
    host: String,
    http_scheme: HttpScheme,
    port: Option<u16>,
}

impl Client {
    /// Create a client connected to specified host and port.
    pub fn new_plain(host: &str, port: u16, conf: ClientConf) -> result::Result<Client> {
        let mut conf = conf;
        conf.http.thread_name = Some(
            conf.http
                .thread_name
                .unwrap_or_else(|| "grpc-client-loop".to_owned()),
        );

        httpbis::Client::new_plain(host, port, conf.http)
            .map(|client| Client {
                client: ::std::sync::Arc::new(client),
                host: host.to_owned(),
                http_scheme: HttpScheme::Http,
                port: Some(port.to_owned()),
            }).map_err(Error::from)
    }

    /// Create a client connected to specified Unix domain socket.
    #[cfg(unix)]
    pub fn new_plain_unix(addr: &str, conf: ClientConf) -> result::Result<Client> {
        let mut conf = conf;
        conf.http.thread_name = Some(
            conf.http
                .thread_name
                .unwrap_or_else(|| "grpc-client-loop".to_owned()),
        );

        httpbis::Client::new_plain_unix(addr, conf.http)
            .map(|client| Client {
                client: ::std::sync::Arc::new(client),
                host: addr.to_owned(),
                http_scheme: HttpScheme::Http,
                port: None,
            }).map_err(Error::from)
    }

    /// Create a client connected to specified host and port.
    pub fn new_tls<C: tls_api::TlsConnector>(
        host: &str,
        port: u16,
        conf: ClientConf,
    ) -> result::Result<Client> {
        let mut conf = conf;
        conf.http.thread_name = Some(
            conf.http
                .thread_name
                .unwrap_or_else(|| "grpc-client-loop".to_owned()),
        );

        httpbis::Client::new_tls::<C>(host, port, conf.http)
            .map(|client| Client {
                client: ::std::sync::Arc::new(client),
                host: host.to_owned(),
                http_scheme: HttpScheme::Https,
                port: Some(port.to_owned()),
            }).map_err(Error::from)
    }

    pub fn new_expl<C: tls_api::TlsConnector>(
        addr: &SocketAddr,
        host: &str,
        tls: httpbis::ClientTlsOption<C>,
        conf: ClientConf,
    ) -> result::Result<Client> {
        let mut conf = conf;
        conf.http.thread_name = Some(
            conf.http
                .thread_name
                .unwrap_or_else(|| "grpc-client-loop".to_owned()),
        );

        let http_scheme = tls.http_scheme();

        httpbis::Client::new_expl(addr, tls, conf.http)
            .map(|client| Client {
                client: ::std::sync::Arc::new(client),
                host: host.to_owned(),
                http_scheme: http_scheme,
                port: Some(addr.port()),
            }).map_err(Error::from)
    }

    fn call_impl<Req, Resp>(
        &self,
        options: RequestOptions,
        req: Option<Req>,
        method: ArcOrStatic<MethodDescriptor<Req, Resp>>,
    ) -> Box<
        Future<Item = (ClientRequestSink<Req>, StreamingResponse<Resp>), Error = error::Error>
            + Send,
    >
    where
        Req: Send + 'static,
        Resp: Send + 'static,
    {
        let mut authority = self.host.clone();
        if let Some(port_value) = self.port {
            authority = format!("{}:{}", authority, port_value);
        }

        info!("start call {}/{}", authority, method.name);

        if options.cachable {
            // TODO: GET
            // https://github.com/grpc/grpc/issues/18230
        }

        let mut headers = Headers::from_vec(vec![
            Header::new(Bytes::from_static(b":method"), Bytes::from_static(b"POST")),
            // TODO: do not allocate static
            Header::new(Bytes::from_static(b":path"), method.name.to_string()),
            Header::new(Bytes::from_static(b":authority"), authority),
            Header::new(
                Bytes::from_static(b":scheme"),
                Bytes::from_static(self.http_scheme.as_bytes()),
            ),
            Header::new(
                Bytes::from_static(b"content-type"),
                Bytes::from_static(b"application/grpc"),
            ),
            Header::new(Bytes::from_static(b"te"), Bytes::from_static(b"trailers")),
        ]);

        headers.extend(options.metadata.into_headers());

        let req_bytes = match req {
            Some(req) => match method.req_marshaller.write(&req) {
                Ok(bytes) => {
                    // TODO: extra allocation
                    Some(Bytes::from(write_grpc_frame_to_vec(&bytes)))
                }
                Err(e) => return Box::new(future::err(e)),
            },
            None => None,
        };

        let end_stream = req_bytes.is_some();

        //        let request_frames = {
        //            let method = method.clone();
        //            req.0
        //                .and_then(move |req| {
        //                    let grpc_frame = method.req_marshaller.write(&req)?;
        //                    Ok(Bytes::from(write_grpc_frame_to_vec(&grpc_frame)))
        //                }).map_err(|_e| httpbis::Error::Other("grpc error")) // TODO: preserve error
        //        };

        let http_future = self
            .client
            .start_request(headers, req_bytes, None, end_stream);

        let http_future = http_future.map_err(error::Error::from);

        let req_marshaller = method.req_marshaller.clone();
        let resp_marshaller = method.resp_marshaller.clone();

        Box::new(http_future.map(move |(req, resp)| {
            let grpc_req = http_req_to_grpc_frames_typed(req, req_marshaller);
            let grpc_resp = http_response_to_grpc_frames_typed(resp, resp_marshaller);
            (grpc_req, grpc_resp)
        }))

        //        Box::new(http_future
        //            .map(|(req, resp)| {
        //                let grpc_req = ClientRequestSink {
        //                    common: SinkCommon {
        //                        marshaller: method.req_marshaller,
        //                        sink: req,
        //                    }
    }

    pub fn call_unary<Req, Resp>(
        &self,
        o: RequestOptions,
        req: Req,
        method: ArcOrStatic<MethodDescriptor<Req, Resp>>,
    ) -> SingleResponse<Resp>
    where
        Req: Send + 'static,
        Resp: Send + 'static,
    {
        SingleResponse::new(
            self.call_impl(o, Some(req), method)
                .and_then(|(_req, resp)| resp.single()),
        )
    }

    pub fn call_server_streaming<Req, Resp>(
        &self,
        o: RequestOptions,
        req: Req,
        method: ArcOrStatic<MethodDescriptor<Req, Resp>>,
    ) -> StreamingResponse<Resp>
    where
        Req: Send + 'static,
        Resp: Send + 'static,
    {
        StreamingResponse::new(
            self.call_impl(o, Some(req), method)
                .map(|(_req, resp)| resp.0)
                .flatten(),
        )
    }

    pub fn call_client_streaming<Req, Resp>(
        &self,
        o: RequestOptions,
        method: ArcOrStatic<MethodDescriptor<Req, Resp>>,
    ) -> impl Future<Item = (ClientRequestSink<Req>, SingleResponse<Resp>), Error = error::Error>
    where
        Req: Send + 'static,
        Resp: Send + 'static,
    {
        self.call_impl(o, None, method)
            .map(|(req, resp)| (req, resp.single()))
    }

    pub fn call_bidi<Req, Resp>(
        &self,
        o: RequestOptions,
        method: ArcOrStatic<MethodDescriptor<Req, Resp>>,
    ) -> impl Future<Item = (ClientRequestSink<Req>, StreamingResponse<Resp>), Error = error::Error>
    where
        Req: Send + 'static,
        Resp: Send + 'static,
    {
        self.call_impl(o, None, method)
    }
}

fn _assert_types() {
    ::assert_types::assert_send::<Client>();
    ::assert_types::assert_sync::<Client>();
}
<commit_msg>Update mod.rs<commit_after>pub(crate) mod http_request_to_grpc_frames_typed;
pub(crate) mod http_response_to_grpc_frames;
pub(crate) mod http_response_to_grpc_frames_typed;
pub(crate) mod req_sink;
pub(crate) mod types;

use std::net::SocketAddr;

use bytes::Bytes;

use httpbis;
use httpbis::Header;
use httpbis::Headers;
use httpbis::HttpScheme;

use tls_api;

use method::MethodDescriptor;

use error::*;
use result;

use client::http_request_to_grpc_frames_typed::http_req_to_grpc_frames_typed;
use client::http_response_to_grpc_frames_typed::http_response_to_grpc_frames_typed;
use client::req_sink::ClientRequestSink;
use error;
use futures::future;
use futures::Future;
use proto::grpc_frame::write_grpc_frame_to_vec;
use req::*;
use resp::*;
use or_static::arc::ArcOrStatic;

#[derive(Default, Debug, Clone)]
pub struct ClientConf {
    pub http: httpbis::ClientConf,
}

impl ClientConf {
    pub fn new() -> ClientConf {
        Default::default()
    }
}

/// gRPC client implementation.
/// Used by generated code.
#[derive(Debug)]
pub struct Client {
    client: ::std::sync::Arc<httpbis::Client>,
    host: String,
    http_scheme: HttpScheme,
    port: Option<u16>,
}

impl Client {
    /// Create a client connected to specified host and port.
    pub fn new_plain(host: &str, port: u16, conf: ClientConf) -> result::Result<Client> {
        let mut conf = conf;
        conf.http.thread_name = Some(
            conf.http
                .thread_name
                .unwrap_or_else(|| "grpc-client-loop".to_owned()),
        );

        httpbis::Client::new_plain(host, port, conf.http)
            .map(|client| Client {
                client: ::std::sync::Arc::new(client),
                host: host.to_owned(),
                http_scheme: HttpScheme::Http,
                port: Some(port.to_owned()),
            }).map_err(Error::from)
    }

    /// Create a client connected to specified Unix domain socket.
    #[cfg(unix)]
    pub fn new_plain_unix(addr: &str, conf: ClientConf) -> result::Result<Client> {
        let mut conf = conf;
        conf.http.thread_name = Some(
            conf.http
                .thread_name
                .unwrap_or_else(|| "grpc-client-loop".to_owned()),
        );

        httpbis::Client::new_plain_unix(addr, conf.http)
            .map(|client| Client {
                client: ::std::sync::Arc::new(client),
                host: addr.to_owned(),
                http_scheme: HttpScheme::Http,
                port: None,
            }).map_err(Error::from)
    }

    /// Create a client connected to specified host and port.
    pub fn new_tls<C: tls_api::TlsConnector>(
        host: &str,
        port: u16,
        conf: ClientConf,
    ) -> result::Result<Client> {
        let mut conf = conf;
        conf.http.thread_name = Some(
            conf.http
                .thread_name
                .unwrap_or_else(|| "grpc-client-loop".to_owned()),
        );

        httpbis::Client::new_tls::<C>(host, port, conf.http)
            .map(|client| Client {
                client: ::std::sync::Arc::new(client),
                host: host.to_owned(),
                http_scheme: HttpScheme::Https,
                port: Some(port.to_owned()),
            }).map_err(Error::from)
    }

    pub fn new_expl<C: tls_api::TlsConnector>(
        addr: &SocketAddr,
        host: &str,
        tls: httpbis::ClientTlsOption<C>,
        conf: ClientConf,
    ) -> result::Result<Client> {
        let mut conf = conf;
        conf.http.thread_name = Some(
            conf.http
                .thread_name
                .unwrap_or_else(|| "grpc-client-loop".to_owned()),
        );

        let http_scheme = tls.http_scheme();

        httpbis::Client::new_expl(addr, tls, conf.http)
            .map(|client| Client {
                client: ::std::sync::Arc::new(client),
                host: host.to_owned(),
                http_scheme: http_scheme,
                port: Some(addr.port()),
            }).map_err(Error::from)
    }

    fn call_impl<Req, Resp>(
        &self,
        options: RequestOptions,
        req: Option<Req>,
        method: ArcOrStatic<MethodDescriptor<Req, Resp>>,
    ) -> Box<
        Future<Item = (ClientRequestSink<Req>, StreamingResponse<Resp>), Error = error::Error>
            + Send,
    >
    where
        Req: Send + 'static,
        Resp: Send + 'static,
    {
        let mut authority = self.host.clone();
        if let Some(port_value) = self.port {
            authority = format!("{}:{}", authority, port_value);
        }

        debug!("start call {}/{}", authority, method.name);

        if options.cachable {
            // TODO: GET
            // https://github.com/grpc/grpc/issues/18230
        }

        let mut headers = Headers::from_vec(vec![
            Header::new(Bytes::from_static(b":method"), Bytes::from_static(b"POST")),
            // TODO: do not allocate static
            Header::new(Bytes::from_static(b":path"), method.name.to_string()),
            Header::new(Bytes::from_static(b":authority"), authority),
            Header::new(
                Bytes::from_static(b":scheme"),
                Bytes::from_static(self.http_scheme.as_bytes()),
            ),
            Header::new(
                Bytes::from_static(b"content-type"),
                Bytes::from_static(b"application/grpc"),
            ),
            Header::new(Bytes::from_static(b"te"), Bytes::from_static(b"trailers")),
        ]);

        headers.extend(options.metadata.into_headers());

        let req_bytes = match req {
            Some(req) => match method.req_marshaller.write(&req) {
                Ok(bytes) => {
                    // TODO: extra allocation
                    Some(Bytes::from(write_grpc_frame_to_vec(&bytes)))
                }
                Err(e) => return Box::new(future::err(e)),
            },
            None => None,
        };

        let end_stream = req_bytes.is_some();

        //        let request_frames = {
        //            let method = method.clone();
        //            req.0
        //                .and_then(move |req| {
        //                    let grpc_frame = method.req_marshaller.write(&req)?;
        //                    Ok(Bytes::from(write_grpc_frame_to_vec(&grpc_frame)))
        //                }).map_err(|_e| httpbis::Error::Other("grpc error")) // TODO: preserve error
        //        };

        let http_future = self
            .client
            .start_request(headers, req_bytes, None, end_stream);

        let http_future = http_future.map_err(error::Error::from);

        let req_marshaller = method.req_marshaller.clone();
        let resp_marshaller = method.resp_marshaller.clone();

        Box::new(http_future.map(move |(req, resp)| {
            let grpc_req = http_req_to_grpc_frames_typed(req, req_marshaller);
            let grpc_resp = http_response_to_grpc_frames_typed(resp, resp_marshaller);
            (grpc_req, grpc_resp)
        }))

        //        Box::new(http_future
        //            .map(|(req, resp)| {
        //                let grpc_req = ClientRequestSink {
        //                    common: SinkCommon {
        //                        marshaller: method.req_marshaller,
        //                        sink: req,
        //                    }
    }

    pub fn call_unary<Req, Resp>(
        &self,
        o: RequestOptions,
        req: Req,
        method: ArcOrStatic<MethodDescriptor<Req, Resp>>,
    ) -> SingleResponse<Resp>
    where
        Req: Send + 'static,
        Resp: Send + 'static,
    {
        SingleResponse::new(
            self.call_impl(o, Some(req), method)
                .and_then(|(_req, resp)| resp.single()),
        )
    }

    pub fn call_server_streaming<Req, Resp>(
        &self,
        o: RequestOptions,
        req: Req,
        method: ArcOrStatic<MethodDescriptor<Req, Resp>>,
    ) -> StreamingResponse<Resp>
    where
        Req: Send + 'static,
        Resp: Send + 'static,
    {
        StreamingResponse::new(
            self.call_impl(o, Some(req), method)
                .map(|(_req, resp)| resp.0)
                .flatten(),
        )
    }

    pub fn call_client_streaming<Req, Resp>(
        &self,
        o: RequestOptions,
        method: ArcOrStatic<MethodDescriptor<Req, Resp>>,
    ) -> impl Future<Item = (ClientRequestSink<Req>, SingleResponse<Resp>), Error = error::Error>
    where
        Req: Send + 'static,
        Resp: Send + 'static,
    {
        self.call_impl(o, None, method)
            .map(|(req, resp)| (req, resp.single()))
    }

    pub fn call_bidi<Req, Resp>(
        &self,
        o: RequestOptions,
        method: ArcOrStatic<MethodDescriptor<Req, Resp>>,
    ) -> impl Future<Item = (ClientRequestSink<Req>, StreamingResponse<Resp>), Error = error::Error>
    where
        Req: Send + 'static,
        Resp: Send + 'static,
    {
        self.call_impl(o, None, method)
    }
}

fn _assert_types() {
    ::assert_types::assert_send::<Client>();
    ::assert_types::assert_sync::<Client>();
}
<|endoftext|>


<commit_before>extern crate flate2;
#[cfg(feature = "ndarray_volumes")]
extern crate ndarray;
extern crate nifti;
#[macro_use]
extern crate pretty_assertions;

use nifti::{
    Endianness, InMemNiftiObject, NiftiHeader, NiftiObject, NiftiType, NiftiVolume,
    RandomAccessNiftiVolume, XForm,
};

#[test]
fn minimal_nii_gz() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 352.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"n+1\0",
        endianness: Endianness::Big,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.nii.gz";
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn minimal_nii() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 352.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"n+1\0",
        endianness: Endianness::Big,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.nii";
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn minimal_by_hdr() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 0.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"ni1\0",
        endianness: Endianness::Big,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.hdr";
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn minimal_by_hdr_and_img_gz() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 0.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"ni1\0",
        endianness: Endianness::Big,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal2.hdr";
    // should attempt to read "resources/minimal2.img.gz"
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn minimal_by_hdr_gz() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 0.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"ni1\0",
        endianness: Endianness::Big,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.hdr.gz";
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn minimal_by_pair() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 0.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"ni1\0",
        endianness: Endianness::Big,
        ..Default::default()
    };

    const HDR_FILE_NAME: &str = "resources/minimal.hdr.gz";
    const IMG_FILE_NAME: &str = "resources/minimal.img.gz";
    let obj = InMemNiftiObject::from_file_pair(HDR_FILE_NAME, IMG_FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn f32_nii_gz() {
    let f32_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 11, 11, 11, 1, 1, 1, 1],
        datatype: 16,
        bitpix: 32,
        pixdim: [1., 1., 1., 1., 1., 1., 1., 1.],
        vox_offset: 352.,
        scl_slope: 1.,
        scl_inter: 0.,
        srow_x: [1., 0., 0., 0.],
        srow_y: [0., 1., 0., 0.],
        srow_z: [0., 0., 1., 0.],
        sform_code: 2,
        magic: *b"n+1\0",
        endianness: Endianness::Little,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/f32.nii.gz";
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &f32_hdr);

    assert_eq!(obj.header().sform().unwrap(), XForm::AlignedAnat);

    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Float32);
    assert_eq!(volume.dim(), [11, 11, 11].as_ref());

    assert_eq!(volume.get_f32(&[5, 5, 5]).unwrap(), 1.);
    assert_eq!(volume.get_f32(&[5, 0, 0]).unwrap(), 0.);
    assert_eq!(volume.get_f32(&[0, 5, 0]).unwrap(), 0.);
    assert_eq!(volume.get_f32(&[0, 0, 5]).unwrap(), 0.);
    assert_eq!(volume.get_f32(&[5, 0, 4]).unwrap(), 0.4);
    assert_eq!(volume.get_f32(&[0, 8, 5]).unwrap(), 0.8);
}

#[test]
fn bad_file_1() {
    let _ = InMemNiftiObject::from_file("resources/fuzz_artifacts/crash-1.nii");
    // must not panic
}
<commit_msg>Add more tests for streamed objects<commit_after>extern crate flate2;
#[cfg(feature = "ndarray_volumes")]
extern crate ndarray;
extern crate nifti;
#[macro_use]
extern crate pretty_assertions;

use nifti::{
    Endianness, InMemNiftiObject, StreamedNiftiObject, NiftiHeader, NiftiObject, NiftiType,
    NiftiVolume, RandomAccessNiftiVolume, XForm,
};

#[test]
fn minimal_nii_gz() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 352.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"n+1\0",
        endianness: Endianness::Big,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.nii.gz";
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn streamed_minimal_nii_gz() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 352.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"n+1\0",
        endianness: Endianness::Big,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.nii.gz";
    let obj = StreamedNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn minimal_nii() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 352.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"n+1\0",
        endianness: Endianness::Big,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.nii";
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn streamed_minimal_nii() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 352.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"n+1\0",
        endianness: Endianness::Big,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.nii";
    let obj = StreamedNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn minimal_by_hdr() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 0.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"ni1\0",
        endianness: Endianness::Big,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.hdr";
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn streamed_minimal_by_hdr() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 0.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"ni1\0",
        endianness: Endianness::Big,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.hdr";
    let obj = StreamedNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn minimal_by_hdr_and_img_gz() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 0.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"ni1\0",
        endianness: Endianness::Big,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal2.hdr";
    // should attempt to read "resources/minimal2.img.gz"
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn minimal_by_hdr_gz() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 0.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"ni1\0",
        endianness: Endianness::Big,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.hdr.gz";
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn minimal_by_pair() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 0.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"ni1\0",
        endianness: Endianness::Big,
        ..Default::default()
    };

    const HDR_FILE_NAME: &str = "resources/minimal.hdr.gz";
    const IMG_FILE_NAME: &str = "resources/minimal.img.gz";
    let obj = InMemNiftiObject::from_file_pair(HDR_FILE_NAME, IMG_FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn f32_nii_gz() {
    let f32_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 11, 11, 11, 1, 1, 1, 1],
        datatype: 16,
        bitpix: 32,
        pixdim: [1., 1., 1., 1., 1., 1., 1., 1.],
        vox_offset: 352.,
        scl_slope: 1.,
        scl_inter: 0.,
        srow_x: [1., 0., 0., 0.],
        srow_y: [0., 1., 0., 0.],
        srow_z: [0., 0., 1., 0.],
        sform_code: 2,
        magic: *b"n+1\0",
        endianness: Endianness::Little,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/f32.nii.gz";
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &f32_hdr);

    assert_eq!(obj.header().sform().unwrap(), XForm::AlignedAnat);

    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Float32);
    assert_eq!(volume.dim(), [11, 11, 11].as_ref());

    assert_eq!(volume.get_f32(&[5, 5, 5]).unwrap(), 1.);
    assert_eq!(volume.get_f32(&[5, 0, 0]).unwrap(), 0.);
    assert_eq!(volume.get_f32(&[0, 5, 0]).unwrap(), 0.);
    assert_eq!(volume.get_f32(&[0, 0, 5]).unwrap(), 0.);
    assert_eq!(volume.get_f32(&[5, 0, 4]).unwrap(), 0.4);
    assert_eq!(volume.get_f32(&[0, 8, 5]).unwrap(), 0.8);
}

#[test]
fn streamed_f32_nii_gz() {
    let f32_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 11, 11, 11, 1, 1, 1, 1],
        datatype: 16,
        bitpix: 32,
        pixdim: [1., 1., 1., 1., 1., 1., 1., 1.],
        vox_offset: 352.,
        scl_slope: 1.,
        scl_inter: 0.,
        srow_x: [1., 0., 0., 0.],
        srow_y: [0., 1., 0., 0.],
        srow_z: [0., 0., 1., 0.],
        sform_code: 2,
        magic: *b"n+1\0",
        endianness: Endianness::Little,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/f32.nii.gz";
    let obj = StreamedNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &f32_hdr);

    assert_eq!(obj.header().sform().unwrap(), XForm::AlignedAnat);

    let volume = obj.into_volume();
    assert_eq!(volume.data_type(), NiftiType::Float32);
    assert_eq!(volume.dim(), [11, 11, 11].as_ref());
    assert_eq!(volume.slice_dim(), &[11, 11]);

    let slices: Vec<_> = volume
        .map(|r| r.expect("slice construction should not fail"))
        .collect();

    for slice in &slices {
        assert_eq!(slice.data_type(), NiftiType::Float32);
        assert_eq!(slice.dim(), &[11, 11]);
    }

    assert_eq!(slices[5].get_f32(&[5, 5]).unwrap(), 1.);
    assert_eq!(slices[0].get_f32(&[5, 0]).unwrap(), 0.);
    assert_eq!(slices[0].get_f32(&[0, 5]).unwrap(), 0.);
    assert_eq!(slices[5].get_f32(&[0, 0]).unwrap(), 0.);
    assert_eq!(slices[4].get_f32(&[5, 0]).unwrap(), 0.4);
    assert_eq!(slices[5].get_f32(&[0, 8]).unwrap(), 0.8);
}

#[test]
fn bad_file_1() {
    let _ = InMemNiftiObject::from_file("resources/fuzz_artifacts/crash-1.nii");
    // must not panic
}
<|endoftext|>


<commit_before>use std::convert::Into;
use std::fmt::{Display, Formatter, Error as FmtError};

use chrono::naive::datetime::NaiveDateTime;
use chrono::naive::time::NaiveTime;
use chrono::naive::date::NaiveDate;
use chrono::Datelike;
use chrono::Timelike;

use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId;

use module_path::ModuleEntryPath;

#[derive(Debug, Clone)]
pub struct DiaryId {
    name: String,
    year: i32,
    month: u32,
    day: u32,
    hour: u32,
    minute: u32,
}

impl DiaryId {

    pub fn new(name: String, y: i32, m: u32, d: u32, h: u32, min: u32) -> DiaryId {
        DiaryId {
            name: name,
            year: y,
            month: m,
            day: d,
            hour: h,
            minute: min,
        }
    }

    pub fn from_datetime<DT: Datelike + Timelike>(diary_name: String, dt: DT) -> DiaryId {
        DiaryId::new(diary_name, dt.year(), dt.month(), dt.day(), dt.hour(), dt.minute())
    }

    pub fn diary_name(&self) -> &String {
        &self.name
    }

    pub fn year(&self) -> i32 {
        self.year
    }

    pub fn month(&self) -> u32 {
        self.month
    }

    pub fn day(&self) -> u32 {
        self.day
    }

    pub fn hour(&self) -> u32 {
        self.hour
    }

    pub fn minute(&self) -> u32 {
        self.minute
    }

    pub fn with_diary_name(mut self, name: String) -> DiaryId {
        self.name = name;
        self
    }

    pub fn with_year(mut self, year: i32) -> DiaryId {
        self.year = year;
        self
    }

    pub fn with_month(mut self, month: u32) -> DiaryId {
        self.month = month;
        self
    }

    pub fn with_day(mut self, day: u32) -> DiaryId {
        self.day = day;
        self
    }

    pub fn with_hour(mut self, hour: u32) -> DiaryId {
        self.hour = hour;
        self
    }

    pub fn with_minute(mut self, minute: u32) -> DiaryId {
        self.minute = minute;
        self
    }

    pub fn now(name: String) -> DiaryId {
        use chrono::offset::local::Local;

        let now = Local::now();
        let now_date = now.date().naive_local();
        let now_time = now.time();
        let dt = NaiveDateTime::new(now_date, now_time);

        DiaryId::new(name, dt.year(), dt.month(), dt.day(), dt.hour(), dt.minute())
    }

}

impl Default for DiaryId {

    /// Create a default DiaryId which is a diaryid for a diary named "default" with
    /// time = 0000-00-00 00:00:00
    fn default() -> DiaryId {
        let dt = NaiveDateTime::new(NaiveDate::from_ymd(0, 0, 0), NaiveTime::from_hms(0, 0, 0));
        DiaryId::from_datetime(String::from("default"), dt)
    }
}

impl IntoStoreId for DiaryId {

    fn into_storeid(self) -> StoreId {
        let s : String = self.into();
        ModuleEntryPath::new(s).into_storeid()
    }

}

impl Into<String> for DiaryId {

    fn into(self) -> String {
        format!("{}/{:0>4}/{:0>2}/{:0>2}/{:0>2}:{:0>2}",
                self.name, self.year, self.month, self.day, self.hour, self.minute)
    }

}

impl Display for DiaryId {

    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
        write!(fmt, "{}/{:0>4}/{:0>2}/{:0>2}/{:0>2}:{:0>2}",
                self.name, self.year, self.month, self.day, self.hour, self.minute)
    }

}

impl Into<NaiveDateTime> for DiaryId {

    fn into(self) -> NaiveDateTime {
        let d = NaiveDate::from_ymd(self.year, self.month, self.day);
        let t = NaiveTime::from_hms(self.hour, self.minute, 0);
        NaiveDateTime::new(d, t)
    }

}

pub trait FromStoreId : Sized {

    fn from_storeid(&StoreId) -> Option<Self>;

}

use std::path::Component;

fn component_to_str<'a>(com: Component<'a>) -> Option<&'a str> {
    match com {
        Component::Normal(s) => Some(s),
        _ => None
    }.and_then(|s| s.to_str())
}

impl FromStoreId for DiaryId {

    fn from_storeid(s: &StoreId) -> Option<DiaryId> {
        use std::str::FromStr;

        let mut cmps   = s.components().rev();
        let (hour, minute) = match cmps.next().and_then(component_to_str)
            .and_then(|time| {
                let mut time = time.split(":");
                let hour     = time.next().and_then(|s| FromStr::from_str(s).ok());
                let minute   = time.next()
                    .and_then(|s| s.split("~").next())
                    .and_then(|s| FromStr::from_str(s).ok());

                debug!("Hour   = {:?}", hour);
                debug!("Minute = {:?}", minute);

                match (hour, minute) {
                    (Some(h), Some(m)) => Some((h, m)),
                    _ => None,
                }
            })
        {
            Some(s) => s,
            None => return None,
        };

        let day   :Option<u32> = cmps.next().and_then(component_to_str).and_then(|s| FromStr::from_str(s).ok());
        let month :Option<u32> = cmps.next().and_then(component_to_str).and_then(|s| FromStr::from_str(s).ok());
        let year  :Option<i32> = cmps.next().and_then(component_to_str).and_then(|s| FromStr::from_str(s).ok());
        let name       = cmps.next().and_then(component_to_str).map(String::from);

        debug!("Day   = {:?}", day);
        debug!("Month = {:?}", month);
        debug!("Year  = {:?}", year);
        debug!("Name  = {:?}", name);

        let day    = if day.is_none()    { return None; } else { day.unwrap() };
        let month  = if month.is_none()  { return None; } else { month.unwrap() };
        let year   = if year.is_none()   { return None; } else { year.unwrap() };
        let name   = if name.is_none()   { return None; } else { name.unwrap() };

        Some(DiaryId::new(name, year, month, day, hour, minute))
    }

}

<commit_msg>Replace unwrap with match<commit_after>use std::convert::Into;
use std::fmt::{Display, Formatter, Error as FmtError};

use chrono::naive::datetime::NaiveDateTime;
use chrono::naive::time::NaiveTime;
use chrono::naive::date::NaiveDate;
use chrono::Datelike;
use chrono::Timelike;

use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId;

use module_path::ModuleEntryPath;

#[derive(Debug, Clone)]
pub struct DiaryId {
    name: String,
    year: i32,
    month: u32,
    day: u32,
    hour: u32,
    minute: u32,
}

impl DiaryId {

    pub fn new(name: String, y: i32, m: u32, d: u32, h: u32, min: u32) -> DiaryId {
        DiaryId {
            name: name,
            year: y,
            month: m,
            day: d,
            hour: h,
            minute: min,
        }
    }

    pub fn from_datetime<DT: Datelike + Timelike>(diary_name: String, dt: DT) -> DiaryId {
        DiaryId::new(diary_name, dt.year(), dt.month(), dt.day(), dt.hour(), dt.minute())
    }

    pub fn diary_name(&self) -> &String {
        &self.name
    }

    pub fn year(&self) -> i32 {
        self.year
    }

    pub fn month(&self) -> u32 {
        self.month
    }

    pub fn day(&self) -> u32 {
        self.day
    }

    pub fn hour(&self) -> u32 {
        self.hour
    }

    pub fn minute(&self) -> u32 {
        self.minute
    }

    pub fn with_diary_name(mut self, name: String) -> DiaryId {
        self.name = name;
        self
    }

    pub fn with_year(mut self, year: i32) -> DiaryId {
        self.year = year;
        self
    }

    pub fn with_month(mut self, month: u32) -> DiaryId {
        self.month = month;
        self
    }

    pub fn with_day(mut self, day: u32) -> DiaryId {
        self.day = day;
        self
    }

    pub fn with_hour(mut self, hour: u32) -> DiaryId {
        self.hour = hour;
        self
    }

    pub fn with_minute(mut self, minute: u32) -> DiaryId {
        self.minute = minute;
        self
    }

    pub fn now(name: String) -> DiaryId {
        use chrono::offset::local::Local;

        let now = Local::now();
        let now_date = now.date().naive_local();
        let now_time = now.time();
        let dt = NaiveDateTime::new(now_date, now_time);

        DiaryId::new(name, dt.year(), dt.month(), dt.day(), dt.hour(), dt.minute())
    }

}

impl Default for DiaryId {

    /// Create a default DiaryId which is a diaryid for a diary named "default" with
    /// time = 0000-00-00 00:00:00
    fn default() -> DiaryId {
        let dt = NaiveDateTime::new(NaiveDate::from_ymd(0, 0, 0), NaiveTime::from_hms(0, 0, 0));
        DiaryId::from_datetime(String::from("default"), dt)
    }
}

impl IntoStoreId for DiaryId {

    fn into_storeid(self) -> StoreId {
        let s : String = self.into();
        ModuleEntryPath::new(s).into_storeid()
    }

}

impl Into<String> for DiaryId {

    fn into(self) -> String {
        format!("{}/{:0>4}/{:0>2}/{:0>2}/{:0>2}:{:0>2}",
                self.name, self.year, self.month, self.day, self.hour, self.minute)
    }

}

impl Display for DiaryId {

    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
        write!(fmt, "{}/{:0>4}/{:0>2}/{:0>2}/{:0>2}:{:0>2}",
                self.name, self.year, self.month, self.day, self.hour, self.minute)
    }

}

impl Into<NaiveDateTime> for DiaryId {

    fn into(self) -> NaiveDateTime {
        let d = NaiveDate::from_ymd(self.year, self.month, self.day);
        let t = NaiveTime::from_hms(self.hour, self.minute, 0);
        NaiveDateTime::new(d, t)
    }

}

pub trait FromStoreId : Sized {

    fn from_storeid(&StoreId) -> Option<Self>;

}

use std::path::Component;

fn component_to_str<'a>(com: Component<'a>) -> Option<&'a str> {
    match com {
        Component::Normal(s) => Some(s),
        _ => None
    }.and_then(|s| s.to_str())
}

impl FromStoreId for DiaryId {

    fn from_storeid(s: &StoreId) -> Option<DiaryId> {
        use std::str::FromStr;

        let mut cmps   = s.components().rev();
        let (hour, minute) = match cmps.next().and_then(component_to_str)
            .and_then(|time| {
                let mut time = time.split(":");
                let hour     = time.next().and_then(|s| FromStr::from_str(s).ok());
                let minute   = time.next()
                    .and_then(|s| s.split("~").next())
                    .and_then(|s| FromStr::from_str(s).ok());

                debug!("Hour   = {:?}", hour);
                debug!("Minute = {:?}", minute);

                match (hour, minute) {
                    (Some(h), Some(m)) => Some((h, m)),
                    _ => None,
                }
            })
        {
            Some(s) => s,
            None => return None,
        };

        let day   :Option<u32> = cmps.next().and_then(component_to_str).and_then(|s| FromStr::from_str(s).ok());
        let month :Option<u32> = cmps.next().and_then(component_to_str).and_then(|s| FromStr::from_str(s).ok());
        let year  :Option<i32> = cmps.next().and_then(component_to_str).and_then(|s| FromStr::from_str(s).ok());
        let name       = cmps.next().and_then(component_to_str).map(String::from);

        debug!("Day   = {:?}", day);
        debug!("Month = {:?}", month);
        debug!("Year  = {:?}", year);
        debug!("Name  = {:?}", name);

        let day    = match day   { None => return None, Some(day)   => day };
        let month  = match month { None => return None, Some(month) => month };
        let year   = match year  { None => return None, Some(year)  => year };
        let name   = match name  { None => return None, Some(name)  => name };

        Some(DiaryId::new(name, year, month, day, hour, minute))
    }

}

<|endoftext|>


<commit_before>//! Global initialization and retrieval of command line arguments.
//!
//! On some platforms these are stored during runtime startup,
//! and on some they are retrieved from the system on demand.

#![allow(dead_code)] // runtime init functions not used during testing

use crate::ffi::OsString;
use crate::marker::PhantomData;
use crate::vec;

/// One-time global initialization.
pub unsafe fn init(argc: isize, argv: *const *const u8) { imp::init(argc, argv) }

/// One-time global cleanup.
pub unsafe fn cleanup() { imp::cleanup() }

/// Returns the command line arguments
pub fn args() -> Args {
    imp::args()
}

pub struct Args {
    iter: vec::IntoIter<OsString>,
    _dont_send_or_sync_me: PhantomData<*mut ()>,
}

impl Args {
    pub fn inner_debug(&self) -> &[OsString] {
        self.iter.as_slice()
    }
}

impl Iterator for Args {
    type Item = OsString;
    fn next(&mut self) -> Option<OsString> { self.iter.next() }
    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
}

impl ExactSizeIterator for Args {
    fn len(&self) -> usize { self.iter.len() }
}

impl DoubleEndedIterator for Args {
    fn next_back(&mut self) -> Option<OsString> { self.iter.next_back() }
}

#[cfg(any(target_os = "linux",
          target_os = "android",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "netbsd",
          target_os = "openbsd",
          target_os = "solaris",
          target_os = "emscripten",
          target_os = "haiku",
          target_os = "l4re",
          target_os = "fuchsia",
          target_os = "redox"))]
mod imp {
    use crate::os::unix::prelude::*;
    use crate::ptr;
    use crate::ffi::{CStr, OsString};
    use crate::marker::PhantomData;
    use super::Args;

    use crate::sys_common::mutex::Mutex;

    static mut ARGC: isize = 0;
    static mut ARGV: *const *const u8 = ptr::null();
    // We never call `ENV_LOCK.init()`, so it is UB to attempt to
    // acquire this mutex reentrantly!
    static LOCK: Mutex = Mutex::new();

    pub unsafe fn init(argc: isize, argv: *const *const u8) {
        let _guard = LOCK.lock();
        ARGC = argc;
        ARGV = argv;
    }

    /// glibc passes argc, argv, and envp to functions in .init_array, as a non-standard extension.
    /// This allows `std::env::args` to work even in a `cdylib`, as it does on macOS and Windows.
    #[cfg(all(target_os = "linux", target_env = "gnu"))]
    #[used]
    #[link_section = ".init_array.00099"]
    static ARGV_INIT_ARRAY: extern "C" fn(
        crate::os::raw::c_int,
        *const *const u8,
        *const *const u8,
    ) = {
        extern "C" fn init_wrapper(
            argc: crate::os::raw::c_int,
            argv: *const *const u8,
            _envp: *const *const u8,
        ) {
            unsafe {
                init(argc as isize, argv);
            }
        }
        init_wrapper
    };

    pub unsafe fn cleanup() {
        let _guard = LOCK.lock();
        ARGC = 0;
        ARGV = ptr::null();
    }

    pub fn args() -> Args {
        Args {
            iter: clone().into_iter(),
            _dont_send_or_sync_me: PhantomData
        }
    }

    fn clone() -> Vec<OsString> {
        unsafe {
            let _guard = LOCK.lock();
            (0..ARGC).map(|i| {
                let cstr = CStr::from_ptr(*ARGV.offset(i) as *const libc::c_char);
                OsStringExt::from_vec(cstr.to_bytes().to_vec())
            }).collect()
        }
    }
}

#[cfg(any(target_os = "macos",
          target_os = "ios"))]
mod imp {
    use crate::ffi::CStr;
    use crate::marker::PhantomData;
    use super::Args;

    pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
    }

    pub fn cleanup() {
    }

    #[cfg(target_os = "macos")]
    pub fn args() -> Args {
        use crate::os::unix::prelude::*;
        extern {
            // These functions are in crt_externs.h.
            fn _NSGetArgc() -> *mut libc::c_int;
            fn _NSGetArgv() -> *mut *mut *mut libc::c_char;
        }

        let vec = unsafe {
            let (argc, argv) = (*_NSGetArgc() as isize,
                                *_NSGetArgv() as *const *const libc::c_char);
            (0.. argc as isize).map(|i| {
                let bytes = CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec();
                OsStringExt::from_vec(bytes)
            }).collect::<Vec<_>>()
        };
        Args {
            iter: vec.into_iter(),
            _dont_send_or_sync_me: PhantomData,
        }
    }

    // As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs
    // and use underscores in their names - they're most probably
    // are considered private and therefore should be avoided
    // Here is another way to get arguments using Objective C
    // runtime
    //
    // In general it looks like:
    // res = Vec::new()
    // let args = [[NSProcessInfo processInfo] arguments]
    // for i in (0..[args count])
    //      res.push([args objectAtIndex:i])
    // res
    #[cfg(target_os = "ios")]
    pub fn args() -> Args {
        use crate::ffi::OsString;
        use crate::mem;
        use crate::str;

        extern {
            fn sel_registerName(name: *const libc::c_uchar) -> Sel;
            fn objc_getClass(class_name: *const libc::c_uchar) -> NsId;
        }

        #[cfg(target_arch="aarch64")]
        extern {
            fn objc_msgSend(obj: NsId, sel: Sel) -> NsId;
            #[link_name="objc_msgSend"]
            fn objc_msgSend_ul(obj: NsId, sel: Sel, i: libc::c_ulong) -> NsId;
        }

        #[cfg(not(target_arch="aarch64"))]
        extern {
            fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId;
            #[link_name="objc_msgSend"]
            fn objc_msgSend_ul(obj: NsId, sel: Sel, ...) -> NsId;
        }

        type Sel = *const libc::c_void;
        type NsId = *const libc::c_void;

        let mut res = Vec::new();

        unsafe {
            let process_info_sel = sel_registerName("processInfo\0".as_ptr());
            let arguments_sel = sel_registerName("arguments\0".as_ptr());
            let utf8_sel = sel_registerName("UTF8String\0".as_ptr());
            let count_sel = sel_registerName("count\0".as_ptr());
            let object_at_sel = sel_registerName("objectAtIndex:\0".as_ptr());

            let klass = objc_getClass("NSProcessInfo\0".as_ptr());
            let info = objc_msgSend(klass, process_info_sel);
            let args = objc_msgSend(info, arguments_sel);

            let cnt: usize = mem::transmute(objc_msgSend(args, count_sel));
            for i in 0..cnt {
                let tmp = objc_msgSend_ul(args, object_at_sel, i as libc::c_ulong);
                let utf_c_str: *const libc::c_char =
                    mem::transmute(objc_msgSend(tmp, utf8_sel));
                let bytes = CStr::from_ptr(utf_c_str).to_bytes();
                res.push(OsString::from(str::from_utf8(bytes).unwrap()))
            }
        }

        Args { iter: res.into_iter(), _dont_send_or_sync_me: PhantomData }
    }
}
<commit_msg>Make std::sys::unix::args::init a no-op on glibc Linux<commit_after>//! Global initialization and retrieval of command line arguments.
//!
//! On some platforms these are stored during runtime startup,
//! and on some they are retrieved from the system on demand.

#![allow(dead_code)] // runtime init functions not used during testing

use crate::ffi::OsString;
use crate::marker::PhantomData;
use crate::vec;

/// One-time global initialization.
pub unsafe fn init(argc: isize, argv: *const *const u8) { imp::init(argc, argv) }

/// One-time global cleanup.
pub unsafe fn cleanup() { imp::cleanup() }

/// Returns the command line arguments
pub fn args() -> Args {
    imp::args()
}

pub struct Args {
    iter: vec::IntoIter<OsString>,
    _dont_send_or_sync_me: PhantomData<*mut ()>,
}

impl Args {
    pub fn inner_debug(&self) -> &[OsString] {
        self.iter.as_slice()
    }
}

impl Iterator for Args {
    type Item = OsString;
    fn next(&mut self) -> Option<OsString> { self.iter.next() }
    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
}

impl ExactSizeIterator for Args {
    fn len(&self) -> usize { self.iter.len() }
}

impl DoubleEndedIterator for Args {
    fn next_back(&mut self) -> Option<OsString> { self.iter.next_back() }
}

#[cfg(any(target_os = "linux",
          target_os = "android",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "netbsd",
          target_os = "openbsd",
          target_os = "solaris",
          target_os = "emscripten",
          target_os = "haiku",
          target_os = "l4re",
          target_os = "fuchsia",
          target_os = "redox"))]
mod imp {
    use crate::os::unix::prelude::*;
    use crate::ptr;
    use crate::ffi::{CStr, OsString};
    use crate::marker::PhantomData;
    use super::Args;

    use crate::sys_common::mutex::Mutex;

    static mut ARGC: isize = 0;
    static mut ARGV: *const *const u8 = ptr::null();
    // We never call `ENV_LOCK.init()`, so it is UB to attempt to
    // acquire this mutex reentrantly!
    static LOCK: Mutex = Mutex::new();

    unsafe fn really_init(argc: isize, argv: *const *const u8) {
        let _guard = LOCK.lock();
        ARGC = argc;
        ARGV = argv;
    }

    #[inline(always)]
    pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
        #[cfg(not(all(target_os = "linux", target_env = "gnu")))]
        really_init(_argc, _argv);
    }

    /// glibc passes argc, argv, and envp to functions in .init_array, as a non-standard extension.
    /// This allows `std::env::args` to work even in a `cdylib`, as it does on macOS and Windows.
    #[cfg(all(target_os = "linux", target_env = "gnu"))]
    #[used]
    #[link_section = ".init_array.00099"]
    static ARGV_INIT_ARRAY: extern "C" fn(
        crate::os::raw::c_int,
        *const *const u8,
        *const *const u8,
    ) = {
        extern "C" fn init_wrapper(
            argc: crate::os::raw::c_int,
            argv: *const *const u8,
            _envp: *const *const u8,
        ) {
            unsafe {
                really_init(argc as isize, argv);
            }
        }
        init_wrapper
    };

    pub unsafe fn cleanup() {
        let _guard = LOCK.lock();
        ARGC = 0;
        ARGV = ptr::null();
    }

    pub fn args() -> Args {
        Args {
            iter: clone().into_iter(),
            _dont_send_or_sync_me: PhantomData
        }
    }

    fn clone() -> Vec<OsString> {
        unsafe {
            let _guard = LOCK.lock();
            (0..ARGC).map(|i| {
                let cstr = CStr::from_ptr(*ARGV.offset(i) as *const libc::c_char);
                OsStringExt::from_vec(cstr.to_bytes().to_vec())
            }).collect()
        }
    }
}

#[cfg(any(target_os = "macos",
          target_os = "ios"))]
mod imp {
    use crate::ffi::CStr;
    use crate::marker::PhantomData;
    use super::Args;

    pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
    }

    pub fn cleanup() {
    }

    #[cfg(target_os = "macos")]
    pub fn args() -> Args {
        use crate::os::unix::prelude::*;
        extern {
            // These functions are in crt_externs.h.
            fn _NSGetArgc() -> *mut libc::c_int;
            fn _NSGetArgv() -> *mut *mut *mut libc::c_char;
        }

        let vec = unsafe {
            let (argc, argv) = (*_NSGetArgc() as isize,
                                *_NSGetArgv() as *const *const libc::c_char);
            (0.. argc as isize).map(|i| {
                let bytes = CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec();
                OsStringExt::from_vec(bytes)
            }).collect::<Vec<_>>()
        };
        Args {
            iter: vec.into_iter(),
            _dont_send_or_sync_me: PhantomData,
        }
    }

    // As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs
    // and use underscores in their names - they're most probably
    // are considered private and therefore should be avoided
    // Here is another way to get arguments using Objective C
    // runtime
    //
    // In general it looks like:
    // res = Vec::new()
    // let args = [[NSProcessInfo processInfo] arguments]
    // for i in (0..[args count])
    //      res.push([args objectAtIndex:i])
    // res
    #[cfg(target_os = "ios")]
    pub fn args() -> Args {
        use crate::ffi::OsString;
        use crate::mem;
        use crate::str;

        extern {
            fn sel_registerName(name: *const libc::c_uchar) -> Sel;
            fn objc_getClass(class_name: *const libc::c_uchar) -> NsId;
        }

        #[cfg(target_arch="aarch64")]
        extern {
            fn objc_msgSend(obj: NsId, sel: Sel) -> NsId;
            #[link_name="objc_msgSend"]
            fn objc_msgSend_ul(obj: NsId, sel: Sel, i: libc::c_ulong) -> NsId;
        }

        #[cfg(not(target_arch="aarch64"))]
        extern {
            fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId;
            #[link_name="objc_msgSend"]
            fn objc_msgSend_ul(obj: NsId, sel: Sel, ...) -> NsId;
        }

        type Sel = *const libc::c_void;
        type NsId = *const libc::c_void;

        let mut res = Vec::new();

        unsafe {
            let process_info_sel = sel_registerName("processInfo\0".as_ptr());
            let arguments_sel = sel_registerName("arguments\0".as_ptr());
            let utf8_sel = sel_registerName("UTF8String\0".as_ptr());
            let count_sel = sel_registerName("count\0".as_ptr());
            let object_at_sel = sel_registerName("objectAtIndex:\0".as_ptr());

            let klass = objc_getClass("NSProcessInfo\0".as_ptr());
            let info = objc_msgSend(klass, process_info_sel);
            let args = objc_msgSend(info, arguments_sel);

            let cnt: usize = mem::transmute(objc_msgSend(args, count_sel));
            for i in 0..cnt {
                let tmp = objc_msgSend_ul(args, object_at_sel, i as libc::c_ulong);
                let utf_c_str: *const libc::c_char =
                    mem::transmute(objc_msgSend(tmp, utf8_sel));
                let bytes = CStr::from_ptr(utf_c_str).to_bytes();
                res.push(OsString::from(str::from_utf8(bytes).unwrap()))
            }
        }

        Args { iter: res.into_iter(), _dont_send_or_sync_me: PhantomData }
    }
}
<|endoftext|>