<commit_before>use std::path::PathBuf;

use std::fmt::{Display, Debug, Formatter};
use std::fmt::Error as FmtError;
use std::result::Result as RResult;
use std::path::Components;

use libimagerror::into::IntoError;

use error::StoreErrorKind as SEK;
use store::Result;
use store::Store;

/// The Index into the Store
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct StoreId {
    base: Option<PathBuf>,
    id:   PathBuf,
}

impl StoreId {

    pub fn new(base: Option<PathBuf>, id: PathBuf) -> Result<StoreId> {
        StoreId::new_baseless(id).map(|mut sid| { sid.base = base; sid })
    }

    pub fn new_baseless(id: PathBuf) -> Result<StoreId> {
        if id.is_absolute() {
            Err(SEK::StoreIdLocalPartAbsoluteError.into_error())
        } else {
            Ok(StoreId {
                base: None,
                id: id
            })
        }
    }

    pub fn without_base(mut self) -> StoreId {
        self.base = None;
        self
    }

    pub fn with_base(mut self, base: PathBuf) -> Self {
        self.base = Some(base);
        self
    }

    pub fn storified(self, store: &Store) -> StoreId {
        StoreId {
            base: Some(store.path().clone()),
            id: self.id
        }
    }

    pub fn exists(&self) -> bool {
        let pb : PathBuf = self.clone().into();
        pb.exists()
    }

    pub fn is_file(&self) -> bool {
        true
    }

    pub fn is_dir(&self) -> bool {
        false
    }

    pub fn to_str(&self) -> Result<String> {
        if self.base.is_some() {
            let mut base = self.base.as_ref().cloned().unwrap();
            base.push(self.id.clone());
            base
        } else {
            self.id.clone()
        }
        .to_str()
        .map(String::from)
        .ok_or(SEK::StoreIdHandlingError.into_error())
    }

    /// Returns the components of the `id` part of the StoreId object.
    ///
    /// Can be used to check whether a StoreId points to an entry in a specific collection of
    /// StoreIds.
    pub fn components(&self) -> Components {
        self.id.components()
    }

    /// Get the _local_ part of a StoreId object, as in "the part from the store root to the entry".
    pub fn local(&self) -> &PathBuf {
        &self.id
    }

}

impl Into<PathBuf> for StoreId {

    fn into(self) -> PathBuf {
        let mut base = self.base.unwrap_or(PathBuf::from("/"));
        base.push(self.id);
        base
    }

}

impl Display for StoreId {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        match self.id.to_str() {
            Some(s) => write!(fmt, "{}", s),
            None    => write!(fmt, "{}", self.id.to_string_lossy()),
        }
    }

}

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> Result<StoreId>;
}

impl IntoStoreId for StoreId {
    fn into_storeid(self) -> Result<StoreId> {
        Ok(self)
    }
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> Result<StoreId> {
        StoreId::new_baseless(self)
    }
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            use $crate::storeid::StoreId;
            use $crate::store::Result;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(name);
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(self) -> Result<$crate::storeid::StoreId> {
                    StoreId::new(None, self.0)
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    iter: Box<Iterator<Item = StoreId>>,
}

impl Debug for StoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "StoreIdIterator")
    }

}

impl StoreIdIterator {

    pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator {
        StoreIdIterator {
            iter: iter,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.iter.next()
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().unwrap().to_str().unwrap(), "test/test");
    }

}
<commit_msg>Add StoreId::from_full_path()<commit_after>use std::ops::Deref;
use std::path::Path;
use std::path::PathBuf;

use std::fmt::{Display, Debug, Formatter};
use std::fmt::Error as FmtError;
use std::result::Result as RResult;
use std::path::Components;

use libimagerror::into::IntoError;

use error::StoreErrorKind as SEK;
use error::MapErrInto;
use store::Result;
use store::Store;

/// The Index into the Store
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct StoreId {
    base: Option<PathBuf>,
    id:   PathBuf,
}

impl StoreId {

    pub fn new(base: Option<PathBuf>, id: PathBuf) -> Result<StoreId> {
        StoreId::new_baseless(id).map(|mut sid| { sid.base = base; sid })
    }

    /// Try to create a StoreId object from a filesystem-absolute path.
    ///
    /// Automatically creates a StoreId object which has a `base` set to `store_part` if stripping
    /// the `store_part` from the `full_path` succeeded.
    ///
    /// Returns a `StoreErrorKind::StoreIdBuildFromFullPathError` if stripping failes.
    pub fn from_full_path<D>(store_part: &PathBuf, full_path: D) -> Result<StoreId>
        where D: Deref<Target = Path>
    {
        let p = try!(
            full_path.strip_prefix(store_part).map_err_into(SEK::StoreIdBuildFromFullPathError)
        );
        StoreId::new(Some(store_part.clone()), PathBuf::from(p))
    }

    pub fn new_baseless(id: PathBuf) -> Result<StoreId> {
        if id.is_absolute() {
            Err(SEK::StoreIdLocalPartAbsoluteError.into_error())
        } else {
            Ok(StoreId {
                base: None,
                id: id
            })
        }
    }

    pub fn without_base(mut self) -> StoreId {
        self.base = None;
        self
    }

    pub fn with_base(mut self, base: PathBuf) -> Self {
        self.base = Some(base);
        self
    }

    pub fn storified(self, store: &Store) -> StoreId {
        StoreId {
            base: Some(store.path().clone()),
            id: self.id
        }
    }

    pub fn exists(&self) -> bool {
        let pb : PathBuf = self.clone().into();
        pb.exists()
    }

    pub fn is_file(&self) -> bool {
        true
    }

    pub fn is_dir(&self) -> bool {
        false
    }

    pub fn to_str(&self) -> Result<String> {
        if self.base.is_some() {
            let mut base = self.base.as_ref().cloned().unwrap();
            base.push(self.id.clone());
            base
        } else {
            self.id.clone()
        }
        .to_str()
        .map(String::from)
        .ok_or(SEK::StoreIdHandlingError.into_error())
    }

    /// Returns the components of the `id` part of the StoreId object.
    ///
    /// Can be used to check whether a StoreId points to an entry in a specific collection of
    /// StoreIds.
    pub fn components(&self) -> Components {
        self.id.components()
    }

    /// Get the _local_ part of a StoreId object, as in "the part from the store root to the entry".
    pub fn local(&self) -> &PathBuf {
        &self.id
    }

}

impl Into<PathBuf> for StoreId {

    fn into(self) -> PathBuf {
        let mut base = self.base.unwrap_or(PathBuf::from("/"));
        base.push(self.id);
        base
    }

}

impl Display for StoreId {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        match self.id.to_str() {
            Some(s) => write!(fmt, "{}", s),
            None    => write!(fmt, "{}", self.id.to_string_lossy()),
        }
    }

}

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> Result<StoreId>;
}

impl IntoStoreId for StoreId {
    fn into_storeid(self) -> Result<StoreId> {
        Ok(self)
    }
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> Result<StoreId> {
        StoreId::new_baseless(self)
    }
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            use $crate::storeid::StoreId;
            use $crate::store::Result;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(name);
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(self) -> Result<$crate::storeid::StoreId> {
                    StoreId::new(None, self.0)
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    iter: Box<Iterator<Item = StoreId>>,
}

impl Debug for StoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "StoreIdIterator")
    }

}

impl StoreIdIterator {

    pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator {
        StoreIdIterator {
            iter: iter,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.iter.next()
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().unwrap().to_str().unwrap(), "test/test");
    }

}
<|endoftext|>


<commit_before>use std;
use libc;
use libc::size_t;
use mdb::types::MDB_val;

pub trait MDBIncomingValue {
    fn to_mdb_value(&self) -> MDB_val;
}

pub trait MDBOutgoingValue {
    fn from_mdb_value(value: &MDB_val) -> Self;
}

impl MDBIncomingValue for Vec<u8> {
    fn to_mdb_value(&self) -> MDB_val {
        unsafe {
            MDB_val {
                mv_data: std::mem::transmute(self.as_ptr()),
                mv_size: self.len() as size_t
            }
        }
    }
}

impl MDBOutgoingValue for Vec<u8> {
    fn from_mdb_value(value: &MDB_val) -> Vec<u8> {
        unsafe {
            std::vec::raw::from_buf(std::mem::transmute(value.mv_data), value.mv_size as uint)
        }
    }
}

impl MDBIncomingValue for ~str {
    fn to_mdb_value(&self) -> MDB_val {
        unsafe {
            let t = self.as_slice();
            MDB_val {
                mv_data: std::mem::transmute(t.as_ptr()),
                mv_size: t.len() as size_t
            }
        }
    }
}

impl<'a> MDBIncomingValue for &'a str {
    fn to_mdb_value(&self) -> MDB_val {
        unsafe {
            let t = self.as_slice();
            MDB_val {
                mv_data: std::mem::transmute(t.as_ptr()),
                mv_size: t.len() as size_t
            }
        }
    }
}

impl MDBIncomingValue for MDB_val {
    fn to_mdb_value(&self) -> MDB_val {
        MDB_val {
            mv_data: (*self).mv_data,
            mv_size: (*self).mv_size
        }
    }
}

impl MDBOutgoingValue for ~str {
    fn from_mdb_value(value: &MDB_val) -> ~str {
        unsafe {
            std::str::raw::from_buf_len(std::mem::transmute(value.mv_data), value.mv_size as uint)
        }
    }
}

impl MDBOutgoingValue for () {
    fn from_mdb_value(_: &MDB_val) {
    }
}

pub trait StateError {
    fn new_state_error(msg: ~str) -> Self;
}

<commit_msg>Up to date with nightly<commit_after>use std;
use libc;
use libc::size_t;
use mdb::types::MDB_val;

pub trait MDBIncomingValue {
    fn to_mdb_value(&self) -> MDB_val;
}

pub trait MDBOutgoingValue {
    fn from_mdb_value(value: &MDB_val) -> Self;
}

impl MDBIncomingValue for Vec<u8> {
    fn to_mdb_value(&self) -> MDB_val {
        unsafe {
            MDB_val {
                mv_data: std::mem::transmute(self.as_ptr()),
                mv_size: self.len() as size_t
            }
        }
    }
}

impl MDBOutgoingValue for Vec<u8> {
    fn from_mdb_value(value: &MDB_val) -> Vec<u8> {
        unsafe {
            std::vec::raw::from_buf(std::mem::transmute(value.mv_data), value.mv_size as uint)
        }
    }
}

impl MDBIncomingValue for ~str {
    fn to_mdb_value(&self) -> MDB_val {
        unsafe {
            let t = self.as_slice();
            MDB_val {
                mv_data: std::mem::transmute(t.as_ptr()),
                mv_size: t.len() as size_t
            }
        }
    }
}

impl MDBIncomingValue for StrBuf {
    fn to_mdb_value(&self) -> MDB_val {
        unsafe {
            let t = self.as_slice();
            MDB_val {
                mv_data: std::mem::transmute(t.as_ptr()),
                mv_size: t.len() as size_t
            }
        }
    }
}

impl<'a> MDBIncomingValue for &'a str {
    fn to_mdb_value(&self) -> MDB_val {
        unsafe {
            let t = self.as_slice();
            MDB_val {
                mv_data: std::mem::transmute(t.as_ptr()),
                mv_size: t.len() as size_t
            }
        }
    }
}

impl MDBIncomingValue for MDB_val {
    fn to_mdb_value(&self) -> MDB_val {
        MDB_val {
            mv_data: (*self).mv_data,
            mv_size: (*self).mv_size
        }
    }
}

impl MDBOutgoingValue for ~str {
    fn from_mdb_value(value: &MDB_val) -> ~str {
        unsafe {
            std::str::raw::from_buf_len(std::mem::transmute(value.mv_data), value.mv_size as uint)
        }
    }
}

impl MDBOutgoingValue for StrBuf {
    fn from_mdb_value(value: &MDB_val) -> StrBuf {
        unsafe {
            std::str::raw::from_buf_len(std::mem::transmute(value.mv_data), value.mv_size as uint).to_strbuf()
        }
    }
}

impl MDBOutgoingValue for () {
    fn from_mdb_value(_: &MDB_val) {
    }
}

pub trait StateError {
    fn new_state_error(msg: ~str) -> Self;
}
<|endoftext|>


<commit_before>use std::ops::Deref;
use std::path::Path;
use std::path::PathBuf;

use std::fmt::{Display, Debug, Formatter};
use std::fmt::Error as FmtError;
use std::result::Result as RResult;
use std::path::Components;

use libimagerror::into::IntoError;

use error::StoreErrorKind as SEK;
use error::MapErrInto;
use store::Result;

/// The Index into the Store
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct StoreId {
    base: Option<PathBuf>,
    id:   PathBuf,
}

impl StoreId {

    pub fn new(base: Option<PathBuf>, id: PathBuf) -> Result<StoreId> {
        StoreId::new_baseless(id).map(|mut sid| { sid.base = base; sid })
    }

    /// Try to create a StoreId object from a filesystem-absolute path.
    ///
    /// Automatically creates a StoreId object which has a `base` set to `store_part` if stripping
    /// the `store_part` from the `full_path` succeeded.
    ///
    /// Returns a `StoreErrorKind::StoreIdBuildFromFullPathError` if stripping failes.
    pub fn from_full_path<D>(store_part: &PathBuf, full_path: D) -> Result<StoreId>
        where D: Deref<Target = Path>
    {
        let p = try!(
            full_path.strip_prefix(store_part).map_err_into(SEK::StoreIdBuildFromFullPathError)
        );
        StoreId::new(Some(store_part.clone()), PathBuf::from(p))
    }

    pub fn new_baseless(id: PathBuf) -> Result<StoreId> {
        if id.is_absolute() {
            Err(SEK::StoreIdLocalPartAbsoluteError.into_error())
        } else {
            Ok(StoreId {
                base: None,
                id: id
            })
        }
    }

    pub fn without_base(mut self) -> StoreId {
        self.base = None;
        self
    }

    pub fn with_base(mut self, base: PathBuf) -> Self {
        self.base = Some(base);
        self
    }

    pub fn exists(&self) -> bool {
        let pb : PathBuf = self.clone().into();
        pb.exists()
    }

    pub fn is_file(&self) -> bool {
        true
    }

    pub fn is_dir(&self) -> bool {
        false
    }

    pub fn to_str(&self) -> Result<String> {
        if self.base.is_some() {
            let mut base = self.base.as_ref().cloned().unwrap();
            base.push(self.id.clone());
            base
        } else {
            self.id.clone()
        }
        .to_str()
        .map(String::from)
        .ok_or(SEK::StoreIdHandlingError.into_error())
    }

    /// Returns the components of the `id` part of the StoreId object.
    ///
    /// Can be used to check whether a StoreId points to an entry in a specific collection of
    /// StoreIds.
    pub fn components(&self) -> Components {
        self.id.components()
    }

    /// Get the _local_ part of a StoreId object, as in "the part from the store root to the entry".
    pub fn local(&self) -> &PathBuf {
        &self.id
    }

}

impl Display for StoreId {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        match self.id.to_str() {
            Some(s) => write!(fmt, "{}", s),
            None    => write!(fmt, "{}", self.id.to_string_lossy()),
        }
    }

}

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> Result<StoreId>;
}

impl IntoStoreId for StoreId {
    fn into_storeid(self) -> Result<StoreId> {
        Ok(self)
    }
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> Result<StoreId> {
        StoreId::new_baseless(self)
    }
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            use $crate::storeid::StoreId;
            use $crate::store::Result;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(name);
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(self) -> Result<$crate::storeid::StoreId> {
                    StoreId::new(None, self.0)
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    iter: Box<Iterator<Item = StoreId>>,
}

impl Debug for StoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "StoreIdIterator")
    }

}

impl StoreIdIterator {

    pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator {
        StoreIdIterator {
            iter: iter,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.iter.next()
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().unwrap().to_str().unwrap(), "test/test");
    }

}
<commit_msg>Add StoreId::into_pathbuf()<commit_after>use std::ops::Deref;
use std::path::Path;
use std::path::PathBuf;

use std::fmt::{Display, Debug, Formatter};
use std::fmt::Error as FmtError;
use std::result::Result as RResult;
use std::path::Components;

use libimagerror::into::IntoError;

use error::StoreErrorKind as SEK;
use error::MapErrInto;
use store::Result;

/// The Index into the Store
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct StoreId {
    base: Option<PathBuf>,
    id:   PathBuf,
}

impl StoreId {

    pub fn new(base: Option<PathBuf>, id: PathBuf) -> Result<StoreId> {
        StoreId::new_baseless(id).map(|mut sid| { sid.base = base; sid })
    }

    /// Try to create a StoreId object from a filesystem-absolute path.
    ///
    /// Automatically creates a StoreId object which has a `base` set to `store_part` if stripping
    /// the `store_part` from the `full_path` succeeded.
    ///
    /// Returns a `StoreErrorKind::StoreIdBuildFromFullPathError` if stripping failes.
    pub fn from_full_path<D>(store_part: &PathBuf, full_path: D) -> Result<StoreId>
        where D: Deref<Target = Path>
    {
        let p = try!(
            full_path.strip_prefix(store_part).map_err_into(SEK::StoreIdBuildFromFullPathError)
        );
        StoreId::new(Some(store_part.clone()), PathBuf::from(p))
    }

    pub fn new_baseless(id: PathBuf) -> Result<StoreId> {
        if id.is_absolute() {
            Err(SEK::StoreIdLocalPartAbsoluteError.into_error())
        } else {
            Ok(StoreId {
                base: None,
                id: id
            })
        }
    }

    pub fn without_base(mut self) -> StoreId {
        self.base = None;
        self
    }

    pub fn with_base(mut self, base: PathBuf) -> Self {
        self.base = Some(base);
        self
    }

    /// Transform the StoreId object into a PathBuf, error if the base of the StoreId is not
    /// specified.
    pub fn into_pathbuf(self) -> Result<PathBuf> {
        self.base
            .ok_or(SEK::StoreIdHasNoBaseError.into_error())
            .map(|mut base| {
                base.push(self.id);
                base
            })
    }

    pub fn exists(&self) -> bool {
        let pb : PathBuf = self.clone().into();
        pb.exists()
    }

    pub fn is_file(&self) -> bool {
        true
    }

    pub fn is_dir(&self) -> bool {
        false
    }

    pub fn to_str(&self) -> Result<String> {
        if self.base.is_some() {
            let mut base = self.base.as_ref().cloned().unwrap();
            base.push(self.id.clone());
            base
        } else {
            self.id.clone()
        }
        .to_str()
        .map(String::from)
        .ok_or(SEK::StoreIdHandlingError.into_error())
    }

    /// Returns the components of the `id` part of the StoreId object.
    ///
    /// Can be used to check whether a StoreId points to an entry in a specific collection of
    /// StoreIds.
    pub fn components(&self) -> Components {
        self.id.components()
    }

    /// Get the _local_ part of a StoreId object, as in "the part from the store root to the entry".
    pub fn local(&self) -> &PathBuf {
        &self.id
    }

}

impl Display for StoreId {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        match self.id.to_str() {
            Some(s) => write!(fmt, "{}", s),
            None    => write!(fmt, "{}", self.id.to_string_lossy()),
        }
    }

}

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> Result<StoreId>;
}

impl IntoStoreId for StoreId {
    fn into_storeid(self) -> Result<StoreId> {
        Ok(self)
    }
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> Result<StoreId> {
        StoreId::new_baseless(self)
    }
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            use $crate::storeid::StoreId;
            use $crate::store::Result;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(name);
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(self) -> Result<$crate::storeid::StoreId> {
                    StoreId::new(None, self.0)
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    iter: Box<Iterator<Item = StoreId>>,
}

impl Debug for StoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "StoreIdIterator")
    }

}

impl StoreIdIterator {

    pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator {
        StoreIdIterator {
            iter: iter,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.iter.next()
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().unwrap().to_str().unwrap(), "test/test");
    }

}
<|endoftext|>


<commit_before>use std::ops::{Add, Sub};

pub struct Vec3 {
  pub i : f64,
  pub j : f64,
  pub k : f64,
}

impl Vec3 {
  pub fn length(&self) -> f64 {
    (self.i * self.i + self.j * self.j + self.k * self.k).sqrt()
  }
}

impl Add for Vec3 {
  type Output = Vec3;
  fn add(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i + other.i, j: self.j + other.j, k: self.k + other.k}
  }
}

impl Sub for Vec3 {
  type Output = Vec3;
  fn sub(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i - other.i, j: self.j - other.j, k: self.k - other.k}
  }
}
<commit_msg>Add implementation of AddAssign<commit_after>use std::ops::{Add, AddAssign, Sub};

pub struct Vec3 {
  pub i : f64,
  pub j : f64,
  pub k : f64,
}

impl Vec3 {
  pub fn length(&self) -> f64 {
    (self.i * self.i + self.j * self.j + self.k * self.k).sqrt()
  }
}

impl Add for Vec3 {
  type Output = Vec3;
  fn add(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i + other.i, j: self.j + other.j, k: self.k + other.k}
  }
}

impl AddAssign for Vec3 {
  fn add_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i + other.i,
      j: self.j + other.j,
      k: self.k + other.k,
    };
  }
}

impl Sub for Vec3 {
  type Output = Vec3;
  fn sub(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i - other.i, j: self.j - other.j, k: self.k - other.k}
  }
}
<|endoftext|>


<commit_before>// Copyright © 2015, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
//! This module contains the public data structures, data types, and procedures exported by the NT
//! console subsystem.
STRUCT!{struct COORD {
    X: ::SHORT,
    Y: ::SHORT,
}}
pub type PCOORD = *mut COORD;
STRUCT!{struct SMALL_RECT {
    Left: ::SHORT,
    Top: ::SHORT,
    Right: ::SHORT,
    Bottom: ::SHORT,
}}
pub type PSMALL_RECT = *mut SMALL_RECT;
STRUCT!{struct KEY_EVENT_RECORD {
    bKeyDown: ::BOOL,
    wRepeatCount: ::WORD,
    wVirtualKeyCode: ::WORD,
    wVirtualScanCode: ::WORD,
    uChar: ::WCHAR, //FIXME - untagged union
    dwControlKeyState: ::DWORD,
}}
pub type PKEY_EVENT_RECORD = *mut KEY_EVENT_RECORD;
pub const RIGHT_ALT_PRESSED: ::DWORD = 0x0001;
pub const LEFT_ALT_PRESSED: ::DWORD = 0x0002;
pub const RIGHT_CTRL_PRESSED: ::DWORD = 0x0004;
pub const LEFT_CTRL_PRESSED: ::DWORD = 0x0008;
pub const SHIFT_PRESSED: ::DWORD = 0x0010;
pub const NUMLOCK_ON: ::DWORD = 0x0020;
pub const SCROLLLOCK_ON: ::DWORD = 0x0040;
pub const CAPSLOCK_ON: ::DWORD = 0x0080;
pub const ENHANCED_KEY: ::DWORD = 0x0100;
pub const NLS_DBCSCHAR: ::DWORD = 0x00010000;
pub const NLS_ALPHANUMERIC: ::DWORD = 0x00000000;
pub const NLS_KATAKANA: ::DWORD = 0x00020000;
pub const NLS_HIRAGANA: ::DWORD = 0x00040000;
pub const NLS_ROMAN: ::DWORD = 0x00400000;
pub const NLS_IME_CONVERSION: ::DWORD = 0x00800000;
pub const NLS_IME_DISABLE: ::DWORD = 0x20000000;
STRUCT!{struct MOUSE_EVENT_RECORD {
    dwMousePosition: COORD,
    dwButtonState: ::DWORD,
    dwControlKeyState: ::DWORD,
    dwEventFlags: ::DWORD,
}}
pub type PMOUSE_EVENT_RECORD = *mut MOUSE_EVENT_RECORD;
pub const FROM_LEFT_1ST_BUTTON_PRESSED: ::DWORD = 0x0001;
pub const RIGHTMOST_BUTTON_PRESSED: ::DWORD = 0x0002;
pub const FROM_LEFT_2ND_BUTTON_PRESSED: ::DWORD = 0x0004;
pub const FROM_LEFT_3RD_BUTTON_PRESSED: ::DWORD = 0x0008;
pub const FROM_LEFT_4TH_BUTTON_PRESSED: ::DWORD = 0x0010;
pub const MOUSE_MOVED: ::DWORD = 0x0001;
pub const DOUBLE_CLICK: ::DWORD = 0x0002;
pub const MOUSE_WHEELED: ::DWORD = 0x0004;
pub const MOUSE_HWHEELED: ::DWORD = 0x0008;
STRUCT!{struct WINDOW_BUFFER_SIZE_RECORD {
    dwSize: COORD,
}}
pub type PWINDOW_BUFFER_SIZE_RECORD = *mut WINDOW_BUFFER_SIZE_RECORD;
STRUCT!{struct MENU_EVENT_RECORD {
    dwCommandId: ::UINT,
}}
pub type PMENU_EVENT_RECORD = *mut MENU_EVENT_RECORD;
STRUCT!{struct FOCUS_EVENT_RECORD {
    bSetFocus: ::BOOL,
}}
pub type PFOCUS_EVENT_RECORD = *mut FOCUS_EVENT_RECORD;
STRUCT!{struct INPUT_RECORD {
    EventType: ::WORD,
    Event: MOUSE_EVENT_RECORD, //FIXME - untagged union
}}
#[test]
fn test_INPUT_RECORD() {
    use std::mem::{size_of, align_of};
    assert!(size_of::<MOUSE_EVENT_RECORD>() >= size_of::<KEY_EVENT_RECORD>());
    assert!(size_of::<MOUSE_EVENT_RECORD>() >= size_of::<WINDOW_BUFFER_SIZE_RECORD>());
    assert!(size_of::<MOUSE_EVENT_RECORD>() >= size_of::<MENU_EVENT_RECORD>());
    assert!(size_of::<MOUSE_EVENT_RECORD>() >= size_of::<FOCUS_EVENT_RECORD>());
    assert!(align_of::<MOUSE_EVENT_RECORD>() >= align_of::<KEY_EVENT_RECORD>());
    assert!(align_of::<MOUSE_EVENT_RECORD>() >= align_of::<WINDOW_BUFFER_SIZE_RECORD>());
    assert!(align_of::<MOUSE_EVENT_RECORD>() >= align_of::<MENU_EVENT_RECORD>());
    assert!(align_of::<MOUSE_EVENT_RECORD>() >= align_of::<FOCUS_EVENT_RECORD>());
}
pub type PINPUT_RECORD = *mut INPUT_RECORD;
pub const KEY_EVENT: ::DWORD = 0x0001;
pub const MOUSE_EVENT: ::DWORD = 0x0002;
pub const WINDOW_BUFFER_SIZE_EVENT: ::DWORD = 0x0004;
pub const MENU_EVENT: ::DWORD = 0x0008;
pub const FOCUS_EVENT: ::DWORD = 0x0010;
STRUCT!{struct CHAR_INFO {
    Char: ::WCHAR, //FIXME - untagged union
    Attributes: ::WORD,
}}
#[test]
fn test_CHAR_INFO() {
    use std::mem::{size_of, align_of};
    assert!(size_of::<::WCHAR>() >= size_of::<::CHAR>());
    assert!(align_of::<::WCHAR>() >= align_of::<::CHAR>());
}
pub type PCHAR_INFO = *mut CHAR_INFO;
pub const FOREGROUND_BLUE: ::DWORD = 0x0001;
pub const FOREGROUND_GREEN: ::DWORD = 0x0002;
pub const FOREGROUND_RED: ::DWORD = 0x0004;
pub const FOREGROUND_INTENSITY: ::DWORD = 0x0008;
pub const BACKGROUND_BLUE: ::DWORD = 0x0010;
pub const BACKGROUND_GREEN: ::DWORD = 0x0020;
pub const BACKGROUND_RED: ::DWORD = 0x0040;
pub const BACKGROUND_INTENSITY: ::DWORD = 0x0080;
pub const COMMON_LVB_LEADING_BYTE: ::DWORD = 0x0100;
pub const COMMON_LVB_TRAILING_BYTE: ::DWORD = 0x0200;
pub const COMMON_LVB_GRID_HORIZONTAL: ::DWORD = 0x0400;
pub const COMMON_LVB_GRID_LVERTICAL: ::DWORD = 0x0800;
pub const COMMON_LVB_GRID_RVERTICAL: ::DWORD = 0x1000;
pub const COMMON_LVB_REVERSE_VIDEO: ::DWORD = 0x4000;
pub const COMMON_LVB_UNDERSCORE: ::DWORD = 0x8000;
pub const COMMON_LVB_SBCSDBCS: ::DWORD = 0x0300;
STRUCT!{struct CONSOLE_SCREEN_BUFFER_INFO {
    dwSize: COORD,
    dwCursorPosition: COORD,
    wAttributes: ::WORD,
    srWindow: SMALL_RECT,
    dwMaximumWindowSize: COORD,
}}
pub type PCONSOLE_SCREEN_BUFFER_INFO = *mut CONSOLE_SCREEN_BUFFER_INFO;
STRUCT!{struct CONSOLE_SCREEN_BUFFER_INFOEX {
    cbSize: ::ULONG,
    dwSize: COORD,
    dwCursorPosition: COORD,
    wAttributes: ::WORD,
    srWindow: SMALL_RECT,
    dwMaximumWindowSize: COORD,
    wPopupAttributes: ::WORD,
    bFullscreenSupported: ::BOOL,
    ColorTable: [::COLORREF; 16],
}}
pub type PCONSOLE_SCREEN_BUFFER_INFOEX = *mut CONSOLE_SCREEN_BUFFER_INFOEX;
STRUCT!{struct CONSOLE_CURSOR_INFO {
    dwSize: ::DWORD,
    bVisible: ::BOOL,
}}
pub type PCONSOLE_CURSOR_INFO = *mut CONSOLE_CURSOR_INFO;
STRUCT!{struct CONSOLE_FONT_INFO {
    nFont: ::DWORD,
    dwFontSize: ::COORD,
}}
pub type PCONSOLE_FONT_INFO = *mut CONSOLE_FONT_INFO;
STRUCT!{struct CONSOLE_FONT_INFOEX {
    cbSize: ::ULONG,
    nFont: ::DWORD,
    dwFontSize: COORD,
    FontFamily: ::UINT,
    FontWeight: ::UINT,
    FaceName: [::WCHAR; ::LF_FACESIZE],
}}
pub type PCONSOLE_FONT_INFOEX = *mut CONSOLE_FONT_INFOEX;
pub const HISTORY_NO_DUP_FLAG: ::DWORD = 0x1;
STRUCT!{struct CONSOLE_HISTORY_INFO {
    cbSize: ::UINT,
    HistoryBufferSize: ::UINT,
    NumberOfHistoryBuffers: ::UINT,
    dwFlags: ::DWORD,
}}
pub type PCONSOLE_HISTORY_INFO = *mut CONSOLE_HISTORY_INFO;
STRUCT!{struct CONSOLE_SELECTION_INFO {
    dwFlags: ::DWORD,
    dwSelectionAnchor: COORD,
    srSelection: SMALL_RECT,
}}
pub type PCONSOLE_SELECTION_INFO = *mut CONSOLE_SELECTION_INFO;
pub const CONSOLE_NO_SELECTION: ::DWORD = 0x0000;
pub const CONSOLE_SELECTION_IN_PROGRESS: ::DWORD = 0x0001;
pub const CONSOLE_SELECTION_NOT_EMPTY: ::DWORD = 0x0002;
pub const CONSOLE_MOUSE_SELECTION: ::DWORD = 0x0004;
pub const CONSOLE_MOUSE_DOWN: ::DWORD = 0x0008;
pub type PHANDLER_ROUTINE = Option<unsafe extern "system" fn(CtrlType: ::DWORD) -> ::BOOL>;
pub const CTRL_C_EVENT: ::DWORD = 0;
pub const CTRL_BREAK_EVENT: ::DWORD = 1;
pub const CTRL_CLOSE_EVENT: ::DWORD = 2;
pub const CTRL_LOGOFF_EVENT: ::DWORD = 5;
pub const CTRL_SHUTDOWN_EVENT: ::DWORD = 6;
pub const ENABLE_PROCESSED_INPUT: ::DWORD = 0x0001;
pub const ENABLE_LINE_INPUT: ::DWORD = 0x0002;
pub const ENABLE_ECHO_INPUT: ::DWORD = 0x0004;
pub const ENABLE_WINDOW_INPUT: ::DWORD = 0x0008;
pub const ENABLE_MOUSE_INPUT: ::DWORD = 0x0010;
pub const ENABLE_INSERT_MODE: ::DWORD = 0x0020;
pub const ENABLE_QUICK_EDIT_MODE: ::DWORD = 0x0040;
pub const ENABLE_EXTENDED_FLAGS: ::DWORD = 0x0080;
pub const ENABLE_AUTO_POSITION: ::DWORD = 0x0100;
pub const ENABLE_PROCESSED_OUTPUT: ::DWORD = 0x0001;
pub const ENABLE_WRAP_AT_EOL_OUTPUT: ::DWORD = 0x0002;
#[cfg(target_arch = "x86")]
pub const CONSOLE_REAL_OUTPUT_HANDLE: *mut ::c_void = 0xFFFFFFFE as *mut ::c_void;
#[cfg(target_arch = "x86_64")]
pub const CONSOLE_REAL_OUTPUT_HANDLE: *mut ::c_void = 0xFFFFFFFFFFFFFFFE as *mut ::c_void;
#[cfg(target_arch = "x86")]
pub const CONSOLE_REAL_INPUT_HANDLE: *mut ::c_void = 0xFFFFFFFD as *mut ::c_void;
#[cfg(target_arch = "x86_64")]
pub const CONSOLE_REAL_INPUT_HANDLE: *mut ::c_void = 0xFFFFFFFFFFFFFFFD as *mut ::c_void;
pub const ATTACH_PARENT_PROCESS: ::DWORD = 0xFFFFFFFF;
STRUCT!{struct CONSOLE_READCONSOLE_CONTROL {
    nLength: ::ULONG,
    nInitialChars: ::ULONG,
    dwCtrlWakeupMask: ::ULONG,
    dwControlKeyState: ::ULONG,
}}
pub type PCONSOLE_READCONSOLE_CONTROL = *mut CONSOLE_READCONSOLE_CONTROL;
pub const CONSOLE_TEXTMODE_BUFFER: ::DWORD = 1;
pub const CONSOLE_FULLSCREEN: ::DWORD = 1;
pub const CONSOLE_FULLSCREEN_HARDWARE: ::DWORD = 2;
pub const CONSOLE_FULLSCREEN_MODE: ::DWORD = 1;
pub const CONSOLE_WINDOWED_MODE: ::DWORD = 2;
<commit_msg>Tweaks to wincon<commit_after>// Copyright © 2015, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
//! This module contains the public data structures, data types, and procedures exported by the NT
//! console subsystem.
STRUCT!{struct COORD {
    X: ::SHORT,
    Y: ::SHORT,
}}
pub type PCOORD = *mut COORD;
STRUCT!{struct SMALL_RECT {
    Left: ::SHORT,
    Top: ::SHORT,
    Right: ::SHORT,
    Bottom: ::SHORT,
}}
pub type PSMALL_RECT = *mut SMALL_RECT;
STRUCT!{struct KEY_EVENT_RECORD {
    bKeyDown: ::BOOL,
    wRepeatCount: ::WORD,
    wVirtualKeyCode: ::WORD,
    wVirtualScanCode: ::WORD,
    UnicodeChar: ::WCHAR,
    dwControlKeyState: ::DWORD,
}}
UNION!{KEY_EVENT_RECORD, UnicodeChar, AsciiChar, AsciiChar_mut, ::CHAR}
pub type PKEY_EVENT_RECORD = *mut KEY_EVENT_RECORD;
pub const RIGHT_ALT_PRESSED: ::DWORD = 0x0001;
pub const LEFT_ALT_PRESSED: ::DWORD = 0x0002;
pub const RIGHT_CTRL_PRESSED: ::DWORD = 0x0004;
pub const LEFT_CTRL_PRESSED: ::DWORD = 0x0008;
pub const SHIFT_PRESSED: ::DWORD = 0x0010;
pub const NUMLOCK_ON: ::DWORD = 0x0020;
pub const SCROLLLOCK_ON: ::DWORD = 0x0040;
pub const CAPSLOCK_ON: ::DWORD = 0x0080;
pub const ENHANCED_KEY: ::DWORD = 0x0100;
pub const NLS_DBCSCHAR: ::DWORD = 0x00010000;
pub const NLS_ALPHANUMERIC: ::DWORD = 0x00000000;
pub const NLS_KATAKANA: ::DWORD = 0x00020000;
pub const NLS_HIRAGANA: ::DWORD = 0x00040000;
pub const NLS_ROMAN: ::DWORD = 0x00400000;
pub const NLS_IME_CONVERSION: ::DWORD = 0x00800000;
pub const NLS_IME_DISABLE: ::DWORD = 0x20000000;
STRUCT!{struct MOUSE_EVENT_RECORD {
    dwMousePosition: COORD,
    dwButtonState: ::DWORD,
    dwControlKeyState: ::DWORD,
    dwEventFlags: ::DWORD,
}}
pub type PMOUSE_EVENT_RECORD = *mut MOUSE_EVENT_RECORD;
pub const FROM_LEFT_1ST_BUTTON_PRESSED: ::DWORD = 0x0001;
pub const RIGHTMOST_BUTTON_PRESSED: ::DWORD = 0x0002;
pub const FROM_LEFT_2ND_BUTTON_PRESSED: ::DWORD = 0x0004;
pub const FROM_LEFT_3RD_BUTTON_PRESSED: ::DWORD = 0x0008;
pub const FROM_LEFT_4TH_BUTTON_PRESSED: ::DWORD = 0x0010;
pub const MOUSE_MOVED: ::DWORD = 0x0001;
pub const DOUBLE_CLICK: ::DWORD = 0x0002;
pub const MOUSE_WHEELED: ::DWORD = 0x0004;
pub const MOUSE_HWHEELED: ::DWORD = 0x0008;
STRUCT!{struct WINDOW_BUFFER_SIZE_RECORD {
    dwSize: COORD,
}}
pub type PWINDOW_BUFFER_SIZE_RECORD = *mut WINDOW_BUFFER_SIZE_RECORD;
STRUCT!{struct MENU_EVENT_RECORD {
    dwCommandId: ::UINT,
}}
pub type PMENU_EVENT_RECORD = *mut MENU_EVENT_RECORD;
STRUCT!{struct FOCUS_EVENT_RECORD {
    bSetFocus: ::BOOL,
}}
pub type PFOCUS_EVENT_RECORD = *mut FOCUS_EVENT_RECORD;
STRUCT!{struct INPUT_RECORD {
    EventType: ::WORD,
    Event: [u32; 4],
}}
UNION!{INPUT_RECORD, Event, KeyEvent, KeyEvent_mut, KEY_EVENT_RECORD}
UNION!{INPUT_RECORD, Event, MouseEvent, MouseEvent_mut, MOUSE_EVENT_RECORD}
UNION!{INPUT_RECORD, Event, WindowBufferSizeEvent, WindowBufferSizeEvent_mut,
    WINDOW_BUFFER_SIZE_RECORD}
UNION!{INPUT_RECORD, Event, MenuEvent, MenuEvent_mut, MENU_EVENT_RECORD}
UNION!{INPUT_RECORD, Event, FocusEvent, FocusEvent_mut, FOCUS_EVENT_RECORD}
pub type PINPUT_RECORD = *mut INPUT_RECORD;
pub const KEY_EVENT: ::WORD = 0x0001;
pub const MOUSE_EVENT: ::WORD = 0x0002;
pub const WINDOW_BUFFER_SIZE_EVENT: ::WORD = 0x0004;
pub const MENU_EVENT: ::WORD = 0x0008;
pub const FOCUS_EVENT: ::WORD = 0x0010;
STRUCT!{struct CHAR_INFO {
    UnicodeChar: ::WCHAR,
    Attributes: ::WORD,
}}
UNION!{CHAR_INFO, UnicodeChar, AsciiChar, AsciiChar_mut, ::CHAR}
pub type PCHAR_INFO = *mut CHAR_INFO;
pub const FOREGROUND_BLUE: ::DWORD = 0x0001;
pub const FOREGROUND_GREEN: ::DWORD = 0x0002;
pub const FOREGROUND_RED: ::DWORD = 0x0004;
pub const FOREGROUND_INTENSITY: ::DWORD = 0x0008;
pub const BACKGROUND_BLUE: ::DWORD = 0x0010;
pub const BACKGROUND_GREEN: ::DWORD = 0x0020;
pub const BACKGROUND_RED: ::DWORD = 0x0040;
pub const BACKGROUND_INTENSITY: ::DWORD = 0x0080;
pub const COMMON_LVB_LEADING_BYTE: ::DWORD = 0x0100;
pub const COMMON_LVB_TRAILING_BYTE: ::DWORD = 0x0200;
pub const COMMON_LVB_GRID_HORIZONTAL: ::DWORD = 0x0400;
pub const COMMON_LVB_GRID_LVERTICAL: ::DWORD = 0x0800;
pub const COMMON_LVB_GRID_RVERTICAL: ::DWORD = 0x1000;
pub const COMMON_LVB_REVERSE_VIDEO: ::DWORD = 0x4000;
pub const COMMON_LVB_UNDERSCORE: ::DWORD = 0x8000;
pub const COMMON_LVB_SBCSDBCS: ::DWORD = 0x0300;
STRUCT!{struct CONSOLE_SCREEN_BUFFER_INFO {
    dwSize: COORD,
    dwCursorPosition: COORD,
    wAttributes: ::WORD,
    srWindow: SMALL_RECT,
    dwMaximumWindowSize: COORD,
}}
pub type PCONSOLE_SCREEN_BUFFER_INFO = *mut CONSOLE_SCREEN_BUFFER_INFO;
STRUCT!{struct CONSOLE_SCREEN_BUFFER_INFOEX {
    cbSize: ::ULONG,
    dwSize: COORD,
    dwCursorPosition: COORD,
    wAttributes: ::WORD,
    srWindow: SMALL_RECT,
    dwMaximumWindowSize: COORD,
    wPopupAttributes: ::WORD,
    bFullscreenSupported: ::BOOL,
    ColorTable: [::COLORREF; 16],
}}
pub type PCONSOLE_SCREEN_BUFFER_INFOEX = *mut CONSOLE_SCREEN_BUFFER_INFOEX;
STRUCT!{struct CONSOLE_CURSOR_INFO {
    dwSize: ::DWORD,
    bVisible: ::BOOL,
}}
pub type PCONSOLE_CURSOR_INFO = *mut CONSOLE_CURSOR_INFO;
STRUCT!{struct CONSOLE_FONT_INFO {
    nFont: ::DWORD,
    dwFontSize: ::COORD,
}}
pub type PCONSOLE_FONT_INFO = *mut CONSOLE_FONT_INFO;
STRUCT!{struct CONSOLE_FONT_INFOEX {
    cbSize: ::ULONG,
    nFont: ::DWORD,
    dwFontSize: COORD,
    FontFamily: ::UINT,
    FontWeight: ::UINT,
    FaceName: [::WCHAR; ::LF_FACESIZE],
}}
pub type PCONSOLE_FONT_INFOEX = *mut CONSOLE_FONT_INFOEX;
pub const HISTORY_NO_DUP_FLAG: ::DWORD = 0x1;
STRUCT!{struct CONSOLE_HISTORY_INFO {
    cbSize: ::UINT,
    HistoryBufferSize: ::UINT,
    NumberOfHistoryBuffers: ::UINT,
    dwFlags: ::DWORD,
}}
pub type PCONSOLE_HISTORY_INFO = *mut CONSOLE_HISTORY_INFO;
STRUCT!{struct CONSOLE_SELECTION_INFO {
    dwFlags: ::DWORD,
    dwSelectionAnchor: COORD,
    srSelection: SMALL_RECT,
}}
pub type PCONSOLE_SELECTION_INFO = *mut CONSOLE_SELECTION_INFO;
pub const CONSOLE_NO_SELECTION: ::DWORD = 0x0000;
pub const CONSOLE_SELECTION_IN_PROGRESS: ::DWORD = 0x0001;
pub const CONSOLE_SELECTION_NOT_EMPTY: ::DWORD = 0x0002;
pub const CONSOLE_MOUSE_SELECTION: ::DWORD = 0x0004;
pub const CONSOLE_MOUSE_DOWN: ::DWORD = 0x0008;
pub type PHANDLER_ROUTINE = Option<unsafe extern "system" fn(CtrlType: ::DWORD) -> ::BOOL>;
pub const CTRL_C_EVENT: ::DWORD = 0;
pub const CTRL_BREAK_EVENT: ::DWORD = 1;
pub const CTRL_CLOSE_EVENT: ::DWORD = 2;
pub const CTRL_LOGOFF_EVENT: ::DWORD = 5;
pub const CTRL_SHUTDOWN_EVENT: ::DWORD = 6;
pub const ENABLE_PROCESSED_INPUT: ::DWORD = 0x0001;
pub const ENABLE_LINE_INPUT: ::DWORD = 0x0002;
pub const ENABLE_ECHO_INPUT: ::DWORD = 0x0004;
pub const ENABLE_WINDOW_INPUT: ::DWORD = 0x0008;
pub const ENABLE_MOUSE_INPUT: ::DWORD = 0x0010;
pub const ENABLE_INSERT_MODE: ::DWORD = 0x0020;
pub const ENABLE_QUICK_EDIT_MODE: ::DWORD = 0x0040;
pub const ENABLE_EXTENDED_FLAGS: ::DWORD = 0x0080;
pub const ENABLE_AUTO_POSITION: ::DWORD = 0x0100;
pub const ENABLE_PROCESSED_OUTPUT: ::DWORD = 0x0001;
pub const ENABLE_WRAP_AT_EOL_OUTPUT: ::DWORD = 0x0002;
pub const CONSOLE_REAL_OUTPUT_HANDLE: *mut ::c_void = -2isize as *mut ::c_void;
pub const CONSOLE_REAL_INPUT_HANDLE: *mut ::c_void = -3isize as *mut ::c_void;
pub const ATTACH_PARENT_PROCESS: ::DWORD = 0xFFFFFFFF;
STRUCT!{struct CONSOLE_READCONSOLE_CONTROL {
    nLength: ::ULONG,
    nInitialChars: ::ULONG,
    dwCtrlWakeupMask: ::ULONG,
    dwControlKeyState: ::ULONG,
}}
pub type PCONSOLE_READCONSOLE_CONTROL = *mut CONSOLE_READCONSOLE_CONTROL;
pub const CONSOLE_TEXTMODE_BUFFER: ::DWORD = 1;
pub const CONSOLE_FULLSCREEN: ::DWORD = 1;
pub const CONSOLE_FULLSCREEN_HARDWARE: ::DWORD = 2;
pub const CONSOLE_FULLSCREEN_MODE: ::DWORD = 1;
pub const CONSOLE_WINDOWED_MODE: ::DWORD = 2;
<|endoftext|>


<commit_before>//!
//! This module is an attempt to provide a friendly, rust-esque interface to
//! Apple's Audio Unit API.
//!
//! Learn more about the Audio Unit API here:
//! https://developer.apple.com/library/mac/documentation/MusicAudio/Conceptual/AudioUnitProgrammingGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40003278-CH1-SW2
//!

use bindings::audio_unit as au;
use error::{Error, AudioUnitError};
use libc;
use self::stream_format::StreamFormat;
use std::mem;
use std::ptr;

pub mod audio_format;
pub mod stream_format;

/// Represents the input and output scope.
#[derive(Copy, Clone, Debug)]
pub enum Scope {
    Output = 0,
    Input  = 1,
}

/// Represents the input and output elements .
#[derive(Copy, Clone, Debug)]
pub enum Element {
    Output = 0,
    Input  = 1,
}

/// Represents the different types of Audio Units.
#[derive(Copy, Clone, Debug)]
pub enum Type {
    Output          = 1635086197,
    MusicDevice     = 1635085685,
    MusicEffect     = 1635085670,
    FormatConverter = 1635083875,
    Effect          = 1635083896,
    Mixer           = 1635085688,
    Panner          = 1635086446,
    Generator       = 1635084142,
    OfflineEffect   = 1635086188,
    MidiProcessor   = 1635085673,
}

/// Represents the different audio unit sub types.
#[derive(Copy, Clone, Debug)]
pub enum SubType {
    GenericOutput        = 1734700658,
    HalOutput            = 1634230636,
    DefaultOutput        = 1684366880,
    SystemOutput         = 1937339168,
    VoiceProcessingIO    = 1987078511,
    DLSSynth             = 1684828960,
    Sampler              = 1935764848,
    MIDISynth            = 1836284270,
    AUConverter          = 1668247158,
    Varispeed            = 1986097769,
    DeferredRenderer     = 1684366962,
    Splitter             = 1936747636,
    Merger               = 1835364967,
    NewTimePitch         = 1853191280,
    AUiPodTimeOther      = 1768977519,
    RoundTripAAC         = 1918984547,
    PeakLimiter          = 1819112562,
    DynamicsProcessor    = 1684237680,
    LowPassFilter        = 1819304307,
    HighPassFilter       = 1752195443,
    BandPassFilter       = 1651532147,
    HighShelfFilter      = 1752393830,
    LowShelfFilter       = 1819502694,
    ParametricEQ         = 1886217585,
    Distortion           = 1684632436,
    Delay                = 1684368505,
    SampleDelay          = 1935961209,
    GraphicEQ            = 1735550321,
    MultiBandCompressor  = 1835232624,
    MatrixReverb         = 1836213622,
    Pitch                = 1953329268,
    AUFilter             = 1718185076,
    NetSend              = 1853058660,
    RogerBeep            = 1919903602,
    NBandEQ              = 1851942257,
    MultiChannelMixer    = 1835232632,
    MatrixMixer          = 1836608888,
    SpatialMixer         = 862217581,
    StereoMixer          = 1936554098,
    Mixer3D              = 862219640,
    SphericalHeadPanner  = 1936746610,
    VectorPanner         = 1986158963,
    SoundFieldPanner     = 1634558569,
    HRTFPanner           = 1752331366,
    NetReceive           = 1852990326,
    ScheduledSoundPlayer = 1936945260,
    AudioFilePlayer      = 1634103404,
}

pub type NumFrames = usize;

/// A type representing a render callback (aka "Input Procedure")
/// If set on an AudioUnit, this will be called every time the AudioUnit requests audio.
/// The first arg is [frames[channels]]; the second is the number of frames to render.
pub type RenderCallback = FnMut(&mut[&mut[f32]], NumFrames) -> Result<(), String>;

/// A rust representation of the au::AudioUnit, including a pointer to the current rendering callback.
pub struct AudioUnit {
    instance: au::AudioUnit,
    callback: Option<*mut libc::c_void>
}

macro_rules! try_os_status {
    ($expr:expr) => (try!(Error::from_os_status($expr)))
}

impl AudioUnit {

    /// Construct a new AudioUnit.
    pub fn new(au_type: Type, sub_type: SubType) -> Result<AudioUnit, Error> {

        // A description of the audio unit we desire.
        let desc = au::AudioComponentDescription {
            componentType         : au_type as libc::c_uint,
            componentSubType      : sub_type as libc::c_uint,
            componentManufacturer : au::kAudioUnitManufacturer_Apple,
            componentFlags        : 0,
            componentFlagsMask    : 0,
        };

        unsafe {
            // Find the default audio unit for the description.
            let component = match au::AudioComponentFindNext(ptr::null_mut(), &desc as *const _) {
                component if component.is_null() => return Err(Error::NoMatchingDefaultAudioUnitFound),
                component                        => component,
            };

            // Get an instance of the default audio unit using the component.
            let mut instance: au::AudioUnit = mem::uninitialized();

            try_os_status!(au::AudioComponentInstanceNew(component, &mut instance as *mut au::AudioUnit));
            // Initialise the audio unit!
            try_os_status!(au::AudioUnitInitialize(instance));
            Ok(AudioUnit {
                instance: instance,
                callback: None
            })
        }
    }

    fn free_render_callback(&self) {
        if let Some(callback) = self.callback {
            // Here, we transfer ownership of the callback back to the current scope so that it
            // is dropped and cleaned up. Without this line, we would leak the Boxed callback.
            let _: Box<Box<RenderCallback>> = unsafe { mem::transmute(callback) };
        }
    }

    /// Pass a render callback (aka "Input Procedure") to the audio unit.
    pub fn render_callback(&mut self, f: Option<Box<RenderCallback>>) -> Result<(), Error>
    {
        unsafe {
            // Setup render callback. Notice that we relinquish ownership of the Callback
            // here so that it can be used as the C render callback via a void pointer.
            // We do however store the *mut so that we can transmute back to a
            // Box<Box<RenderCallback>> within our AudioUnit's Drop implementation
            // (otherwise it would leak). The double-boxing is due to incompleteness with
            // Rust's FnMut implemetation and is necessary to be able to transmute to the
            // correct pointer size.
            let callback_ptr: *mut libc::c_void = match f {
                Some(x) => mem::transmute(Box::new(x)),
                _ => ptr::null_mut()
            };
            let render_callback = au::AURenderCallbackStruct {
                inputProc: Some(input_proc),
                inputProcRefCon: callback_ptr
            };

            try_os_status!(au::AudioUnitSetProperty(
                self.instance,
                au::kAudioUnitProperty_SetRenderCallback,
                Scope::Input as libc::c_uint,
                Element::Output as libc::c_uint,
                &render_callback as *const _ as *const libc::c_void,
                mem::size_of::<au::AURenderCallbackStruct>() as u32));

            self.free_render_callback();
            self.callback = if !callback_ptr.is_null() { Some(callback_ptr) } else { None };
            Ok(())
        }
    }

    /// Start the audio unit.
    pub fn start(&self) -> Result<(), Error> {
        unsafe { try_os_status!(au::AudioOutputUnitStart(self.instance)); }
        Ok(())
    }

    /// Stop the audio unit.
    pub fn stop(&self) -> Result<(), Error> {
        unsafe { try_os_status!(au::AudioOutputUnitStop(self.instance)); }
        Ok(())
    }

    /// Set the audio unit's sample rate.
    pub fn set_sample_rate(&self, sample_rate: f64) -> Result<(), Error> {
        unsafe {
            try_os_status!(au::AudioUnitSetProperty(
                self.instance,
                au::kAudioUnitProperty_SampleRate,
                au::kAudioUnitScope_Input,
                0,
                &sample_rate as *const _ as *const libc::c_void,
                mem::size_of::<f64>() as u32));
            Ok(())
        }
    }

    /// Get the audio unit's sample rate.
    pub fn sample_rate(&self) -> Result<f64, Error> {
        unsafe {
            let mut sample_rate: f64 = 0.0;
            let mut size: u32 = mem::size_of::<f64>() as u32;
            try_os_status!(au::AudioUnitGetProperty(
                self.instance,
                au::kAudioUnitProperty_SampleRate,
                au::kAudioUnitScope_Input,
                0,
                &mut sample_rate as *mut _ as *mut libc::c_void,
                &mut size as *mut _));
            Ok(sample_rate)
        }
    }

    /// Return the current Stream Format for the AudioUnit.
    pub fn stream_format(&self) -> Result<StreamFormat, Error> {
        unsafe {
            let mut asbd: au::AudioStreamBasicDescription = mem::uninitialized();
            let mut size = ::std::mem::size_of::<au::AudioStreamBasicDescription>() as u32;
            try_os_status!(au::AudioUnitGetProperty(
                self.instance,
                au::kAudioUnitProperty_StreamFormat,
                Scope::Output as libc::c_uint,
                Element::Output as libc::c_uint,
                &mut asbd as *mut _ as *mut libc::c_void,
                &mut size as *mut au::UInt32));
            Ok(StreamFormat::from_asbd(asbd))
        }
    }

}

impl Drop for AudioUnit {
    fn drop(&mut self) {
        unsafe {
            use error;
            use std::error::Error;
            if let Err(err) = self.stop() {
                panic!("{:?}", err.description());
            }
            if let Err(err) = error::Error::from_os_status(au::AudioUnitUninitialize(self.instance)) {
                panic!("{:?}", err.description());
            }
            self.free_render_callback();
        }
    }
}

/// Callback procedure that will be called each time our audio_unit requests audio.
extern "C" fn input_proc(in_ref_con: *mut libc::c_void,
                         _io_action_flags: *mut au::AudioUnitRenderActionFlags,
                         _in_time_stamp: *const au::AudioTimeStamp,
                         _in_bus_number: au::UInt32,
                         in_number_frames: au::UInt32,
                         io_data: *mut au::AudioBufferList) -> au::OSStatus {
    let callback: *mut Box<RenderCallback> = in_ref_con as *mut _;
    unsafe {
        let num_channels = (*io_data).mNumberBuffers as usize;

        // FIXME: We shouldn't need a Vec for this, it should probably be something like
        // `&[&mut [f32]]` instead.
        let mut channels: Vec<&mut [f32]> =
            (0..num_channels)
                .map(|i| {
                    let slice_ptr = (*io_data).mBuffers[i].mData as *mut libc::c_float;
                    ::std::slice::from_raw_parts_mut(slice_ptr, in_number_frames as usize)
                })
                .collect();

        match (*callback)(&mut channels[..], in_number_frames as usize) {
            Ok(()) => 0 as au::OSStatus,
            Err(description) => {
                use std::io::Write;
                writeln!(::std::io::stderr(), "{:?}", description).unwrap();
                AudioUnitError::NoConnection as au::OSStatus
            },
        }
    }
}
<commit_msg>Added set_stream_format to AudioUnit<commit_after>//!
//! This module is an attempt to provide a friendly, rust-esque interface to
//! Apple's Audio Unit API.
//!
//! Learn more about the Audio Unit API here:
//! https://developer.apple.com/library/mac/documentation/MusicAudio/Conceptual/AudioUnitProgrammingGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40003278-CH1-SW2
//!

use bindings::audio_unit as au;
use error::{Error, AudioUnitError};
use libc;
use self::stream_format::StreamFormat;
use std::mem;
use std::ptr;

pub mod audio_format;
pub mod stream_format;

/// Represents the input and output scope.
#[derive(Copy, Clone, Debug)]
pub enum Scope {
    Output = 0,
    Input  = 1,
}

/// Represents the input and output elements .
#[derive(Copy, Clone, Debug)]
pub enum Element {
    Output = 0,
    Input  = 1,
}

/// Represents the different types of Audio Units.
#[derive(Copy, Clone, Debug)]
pub enum Type {
    Output          = 1635086197,
    MusicDevice     = 1635085685,
    MusicEffect     = 1635085670,
    FormatConverter = 1635083875,
    Effect          = 1635083896,
    Mixer           = 1635085688,
    Panner          = 1635086446,
    Generator       = 1635084142,
    OfflineEffect   = 1635086188,
    MidiProcessor   = 1635085673,
}

/// Represents the different audio unit sub types.
#[derive(Copy, Clone, Debug)]
pub enum SubType {
    GenericOutput        = 1734700658,
    HalOutput            = 1634230636,
    DefaultOutput        = 1684366880,
    SystemOutput         = 1937339168,
    VoiceProcessingIO    = 1987078511,
    DLSSynth             = 1684828960,
    Sampler              = 1935764848,
    MIDISynth            = 1836284270,
    AUConverter          = 1668247158,
    Varispeed            = 1986097769,
    DeferredRenderer     = 1684366962,
    Splitter             = 1936747636,
    Merger               = 1835364967,
    NewTimePitch         = 1853191280,
    AUiPodTimeOther      = 1768977519,
    RoundTripAAC         = 1918984547,
    PeakLimiter          = 1819112562,
    DynamicsProcessor    = 1684237680,
    LowPassFilter        = 1819304307,
    HighPassFilter       = 1752195443,
    BandPassFilter       = 1651532147,
    HighShelfFilter      = 1752393830,
    LowShelfFilter       = 1819502694,
    ParametricEQ         = 1886217585,
    Distortion           = 1684632436,
    Delay                = 1684368505,
    SampleDelay          = 1935961209,
    GraphicEQ            = 1735550321,
    MultiBandCompressor  = 1835232624,
    MatrixReverb         = 1836213622,
    Pitch                = 1953329268,
    AUFilter             = 1718185076,
    NetSend              = 1853058660,
    RogerBeep            = 1919903602,
    NBandEQ              = 1851942257,
    MultiChannelMixer    = 1835232632,
    MatrixMixer          = 1836608888,
    SpatialMixer         = 862217581,
    StereoMixer          = 1936554098,
    Mixer3D              = 862219640,
    SphericalHeadPanner  = 1936746610,
    VectorPanner         = 1986158963,
    SoundFieldPanner     = 1634558569,
    HRTFPanner           = 1752331366,
    NetReceive           = 1852990326,
    ScheduledSoundPlayer = 1936945260,
    AudioFilePlayer      = 1634103404,
}

pub type NumFrames = usize;

/// A type representing a render callback (aka "Input Procedure")
/// If set on an AudioUnit, this will be called every time the AudioUnit requests audio.
/// The first arg is [frames[channels]]; the second is the number of frames to render.
pub type RenderCallback = FnMut(&mut[&mut[f32]], NumFrames) -> Result<(), String>;

/// A rust representation of the au::AudioUnit, including a pointer to the current rendering callback.
pub struct AudioUnit {
    instance: au::AudioUnit,
    callback: Option<*mut libc::c_void>
}

macro_rules! try_os_status {
    ($expr:expr) => (try!(Error::from_os_status($expr)))
}

impl AudioUnit {

    /// Construct a new AudioUnit.
    pub fn new(au_type: Type, sub_type: SubType) -> Result<AudioUnit, Error> {

        // A description of the audio unit we desire.
        let desc = au::AudioComponentDescription {
            componentType         : au_type as libc::c_uint,
            componentSubType      : sub_type as libc::c_uint,
            componentManufacturer : au::kAudioUnitManufacturer_Apple,
            componentFlags        : 0,
            componentFlagsMask    : 0,
        };

        unsafe {
            // Find the default audio unit for the description.
            let component = match au::AudioComponentFindNext(ptr::null_mut(), &desc as *const _) {
                component if component.is_null() => return Err(Error::NoMatchingDefaultAudioUnitFound),
                component                        => component,
            };

            // Get an instance of the default audio unit using the component.
            let mut instance: au::AudioUnit = mem::uninitialized();

            try_os_status!(au::AudioComponentInstanceNew(component, &mut instance as *mut au::AudioUnit));
            // Initialise the audio unit!
            try_os_status!(au::AudioUnitInitialize(instance));
            Ok(AudioUnit {
                instance: instance,
                callback: None
            })
        }
    }

    fn free_render_callback(&self) {
        if let Some(callback) = self.callback {
            // Here, we transfer ownership of the callback back to the current scope so that it
            // is dropped and cleaned up. Without this line, we would leak the Boxed callback.
            let _: Box<Box<RenderCallback>> = unsafe { mem::transmute(callback) };
        }
    }

    /// Pass a render callback (aka "Input Procedure") to the audio unit.
    pub fn render_callback(&mut self, f: Option<Box<RenderCallback>>) -> Result<(), Error>
    {
        unsafe {
            // Setup render callback. Notice that we relinquish ownership of the Callback
            // here so that it can be used as the C render callback via a void pointer.
            // We do however store the *mut so that we can transmute back to a
            // Box<Box<RenderCallback>> within our AudioUnit's Drop implementation
            // (otherwise it would leak). The double-boxing is due to incompleteness with
            // Rust's FnMut implemetation and is necessary to be able to transmute to the
            // correct pointer size.
            let callback_ptr: *mut libc::c_void = match f {
                Some(x) => mem::transmute(Box::new(x)),
                _ => ptr::null_mut()
            };
            let render_callback = au::AURenderCallbackStruct {
                inputProc: Some(input_proc),
                inputProcRefCon: callback_ptr
            };

            try_os_status!(au::AudioUnitSetProperty(
                self.instance,
                au::kAudioUnitProperty_SetRenderCallback,
                Scope::Input as libc::c_uint,
                Element::Output as libc::c_uint,
                &render_callback as *const _ as *const libc::c_void,
                mem::size_of::<au::AURenderCallbackStruct>() as u32));

            self.free_render_callback();
            self.callback = if !callback_ptr.is_null() { Some(callback_ptr) } else { None };
            Ok(())
        }
    }

    /// Start the audio unit.
    pub fn start(&self) -> Result<(), Error> {
        unsafe { try_os_status!(au::AudioOutputUnitStart(self.instance)); }
        Ok(())
    }

    /// Stop the audio unit.
    pub fn stop(&self) -> Result<(), Error> {
        unsafe { try_os_status!(au::AudioOutputUnitStop(self.instance)); }
        Ok(())
    }

    /// Set the audio unit's sample rate.
    pub fn set_sample_rate(&self, sample_rate: f64) -> Result<(), Error> {
        unsafe {
            try_os_status!(au::AudioUnitSetProperty(
                self.instance,
                au::kAudioUnitProperty_SampleRate,
                au::kAudioUnitScope_Input,
                0,
                &sample_rate as *const _ as *const libc::c_void,
                mem::size_of::<f64>() as u32));
            Ok(())
        }
    }

    /// Get the audio unit's sample rate.
    pub fn sample_rate(&self) -> Result<f64, Error> {
        unsafe {
            let mut sample_rate: f64 = 0.0;
            let mut size: u32 = mem::size_of::<f64>() as u32;
            try_os_status!(au::AudioUnitGetProperty(
                self.instance,
                au::kAudioUnitProperty_SampleRate,
                au::kAudioUnitScope_Input,
                0,
                &mut sample_rate as *mut _ as *mut libc::c_void,
                &mut size as *mut _));
            Ok(sample_rate)
        }
    }

    /// Sets the current Stream Format for the AudioUnit.
    pub fn set_stream_format(&self, stream_format: StreamFormat) -> Result<(), Error> {
        unsafe {
            let mut asbd = stream_format.to_asbd();
            try_os_status!(au::AudioUnitSetProperty(
                self.instance,
                au::kAudioUnitProperty_StreamFormat,
                au::kAudioUnitScope_Input,
                0,
                &mut asbd as *mut _ as *mut libc::c_void,
                mem::size_of::<au::AudioStreamBasicDescription>() as u32));
            Ok(())
        }
    }

    /// Return the current Stream Format for the AudioUnit.
    pub fn stream_format(&self) -> Result<StreamFormat, Error> {
        unsafe {
            let mut asbd: au::AudioStreamBasicDescription = mem::uninitialized();
            let mut size = ::std::mem::size_of::<au::AudioStreamBasicDescription>() as u32;
            try_os_status!(au::AudioUnitGetProperty(
                self.instance,
                au::kAudioUnitProperty_StreamFormat,
                Scope::Output as libc::c_uint,
                Element::Output as libc::c_uint,
                &mut asbd as *mut _ as *mut libc::c_void,
                &mut size as *mut au::UInt32));
            Ok(StreamFormat::from_asbd(asbd))
        }
    }

}

impl Drop for AudioUnit {
    fn drop(&mut self) {
        unsafe {
            use error;
            use std::error::Error;
            if let Err(err) = self.stop() {
                panic!("{:?}", err.description());
            }
            if let Err(err) = error::Error::from_os_status(au::AudioUnitUninitialize(self.instance)) {
                panic!("{:?}", err.description());
            }
            self.free_render_callback();
        }
    }
}

/// Callback procedure that will be called each time our audio_unit requests audio.
extern "C" fn input_proc(in_ref_con: *mut libc::c_void,
                         _io_action_flags: *mut au::AudioUnitRenderActionFlags,
                         _in_time_stamp: *const au::AudioTimeStamp,
                         _in_bus_number: au::UInt32,
                         in_number_frames: au::UInt32,
                         io_data: *mut au::AudioBufferList) -> au::OSStatus {
    let callback: *mut Box<RenderCallback> = in_ref_con as *mut _;
    unsafe {
        let num_channels = (*io_data).mNumberBuffers as usize;

        // FIXME: We shouldn't need a Vec for this, it should probably be something like
        // `&[&mut [f32]]` instead.
        let mut channels: Vec<&mut [f32]> =
            (0..num_channels)
                .map(|i| {
                    let slice_ptr = (*io_data).mBuffers[i].mData as *mut libc::c_float;
                    ::std::slice::from_raw_parts_mut(slice_ptr, in_number_frames as usize)
                })
                .collect();

        match (*callback)(&mut channels[..], in_number_frames as usize) {
            Ok(()) => 0 as au::OSStatus,
            Err(description) => {
                use std::io::Write;
                writeln!(::std::io::stderr(), "{:?}", description).unwrap();
                AudioUnitError::NoConnection as au::OSStatus
            },
        }
    }
}
<|endoftext|>


<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate docopt;
extern crate csv;
extern crate rustc_serialize;
extern crate mimir;
#[macro_use]
extern crate log;
extern crate geo;

use std::path::Path;
use mimir::rubber::Rubber;
use mimir::objects::Admin;
use std::fs;
use std::rc::Rc;
use std::collections::BTreeMap;

type AdminFromInsee = BTreeMap<String, Rc<Admin>>;

#[derive(RustcDecodable, RustcEncodable)]
pub struct Bano {
    pub id: String,
    pub nb: String,
    pub street: String,
    pub zip: String,
    pub city: String,
    pub src: String,
    pub lat: f64,
    pub lon: f64,
}

impl Bano {
    pub fn insee(&self) -> &str {
        assert!(self.id.len() >= 5);
        self.id[..5].trim_left_matches('0')
    }
    pub fn fantoir(&self) -> &str {
        assert!(self.id.len() >= 10);
        &self.id[..10]
    }
    pub fn into_addr(self, admins: &AdminFromInsee) -> mimir::Addr {
        let street_name = format!("{} ({})", self.street, self.city);
        let addr_name = format!("{} {}", self.nb, self.street);
        let addr_label = format!("{} ({})", addr_name, self.city);
        let street_id = format!("street:{}", self.fantoir().to_string());
        let admin = admins.get(&format!("admin:fr:{}", self.insee()));

        let street = mimir::Street {
            id: street_id,
            street_name: self.street,
            label: street_name.to_string(),
            administrative_regions: admin.map_or(vec![], |a| vec![a.clone()]),
            weight: 1,
            zip_codes: vec![self.zip.clone()],
            coord: mimir::Coord::new(self.lat, self.lon),
        };
        mimir::Addr {
            id: format!("addr:{};{}", self.lon, self.lat),
            house_number: self.nb,
            street: street,
            label: addr_label,
            coord: mimir::Coord::new(self.lat, self.lon),
            weight: 1,
            zip_codes: vec![self.zip.clone()],
        }
    }
}

fn index_bano<I>(cnx_string: &str, dataset: &str, files: I)
    where I: Iterator<Item = std::path::PathBuf>
{
    let doc_type = "addr";
    let mut rubber = Rubber::new(cnx_string);

    let mut admins_by_insee = AdminFromInsee::new();
    rubber.get_admins_from_dataset(dataset)
                        .map(|admins| {
                            for a in admins {
                                admins_by_insee.insert(a.id.to_string(), Rc::new(a));
                            }
                        })
                        .map_err(|err| {
        info!("Administratives regions not found in elasticsearch db for dataset {}. (error: {})", dataset, err)
    });

    let addr_index = rubber.make_index(doc_type, dataset).unwrap();
    info!("Add data in elasticsearch db.");
    for f in files {
        info!("importing {:?}...", &f);
        let mut rdr = csv::Reader::from_file(&f).unwrap().has_headers(false);

        let iter = rdr.decode().map(|r| {
            let b: Bano = r.unwrap();
            b.into_addr(&admins_by_insee)
        });
        match rubber.bulk_index(&addr_index, iter) {
            Err(e) => panic!("failed to bulk insert file {:?} because: {}", &f, e),
            Ok(nb) => info!("importing {:?}: {} addresses added.", &f, nb),
        }
    }
    rubber.publish_index(doc_type, dataset, addr_index).unwrap();
}

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_input: String,
    flag_connection_string: String,
    flag_dataset: String,
}

static USAGE: &'static str = "
Usage:
    bano2mimir --input=<input> [--connection-string=<connection-string>] [--dataset=<dataset>]

    -i, --input=<input>           Bano files. Can be either a directory or a file.
    -c, --connection-string=<connection-string>
                                  Elasticsearch parameters, [default: http://localhost:9200/munin]
    -d, --dataset=<dataset>       Name of the dataset, [default: fr]
";

fn main() {
    mimir::logger_init().unwrap();
    info!("importing bano into Mimir");

    let args: Args = docopt::Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());

    let file_path = Path::new(&args.flag_input);
    if file_path.is_dir() {
        let paths: std::fs::ReadDir = fs::read_dir(&args.flag_input).unwrap();
        index_bano(&args.flag_connection_string,
                   &args.flag_dataset,
                   paths.map(|p| p.unwrap().path()));
    } else {
        index_bano(&args.flag_connection_string,
                   &args.flag_dataset,
                   std::iter::once(std::path::PathBuf::from(&args.flag_input)));
    }
}
<commit_msg>refacto<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate docopt;
extern crate csv;
extern crate rustc_serialize;
extern crate mimir;
#[macro_use]
extern crate log;
extern crate geo;

use std::path::Path;
use mimir::rubber::Rubber;
use mimir::objects::Admin;
use std::fs;
use std::rc::Rc;
use std::collections::BTreeMap;

type AdminFromInsee = BTreeMap<String, Rc<Admin>>;

#[derive(RustcDecodable, RustcEncodable)]
pub struct Bano {
    pub id: String,
    pub nb: String,
    pub street: String,
    pub zip: String,
    pub city: String,
    pub src: String,
    pub lat: f64,
    pub lon: f64,
}

impl Bano {
    pub fn insee(&self) -> &str {
        assert!(self.id.len() >= 5);
        self.id[..5].trim_left_matches('0')
    }
    pub fn fantoir(&self) -> &str {
        assert!(self.id.len() >= 10);
        &self.id[..10]
    }
    pub fn into_addr(self, admins: &AdminFromInsee) -> mimir::Addr {
        let street_name = format!("{} ({})", self.street, self.city);
        let addr_name = format!("{} {}", self.nb, self.street);
        let addr_label = format!("{} ({})", addr_name, self.city);
        let street_id = format!("street:{}", self.fantoir().to_string());
        let admin = admins.get(&format!("admin:fr:{}", self.insee()));

        let street = mimir::Street {
            id: street_id,
            street_name: self.street,
            label: street_name.to_string(),
            administrative_regions: admin.map_or(vec![], |a| vec![a.clone()]),
            weight: 1,
            zip_codes: vec![self.zip.clone()],
            coord: mimir::Coord::new(self.lat, self.lon),
        };
        mimir::Addr {
            id: format!("addr:{};{}", self.lon, self.lat),
            house_number: self.nb,
            street: street,
            label: addr_label,
            coord: mimir::Coord::new(self.lat, self.lon),
            weight: 1,
            zip_codes: vec![self.zip.clone()],
        }
    }
}

fn index_bano<I>(cnx_string: &str, dataset: &str, files: I)
    where I: Iterator<Item = std::path::PathBuf>
{
    let doc_type = "addr";
    let mut rubber = Rubber::new(cnx_string);

    let admins_by_insee = rubber.get_admins_from_dataset(dataset)
        .unwrap_or_else(|err| {
            info!("Administratives regions not found in es db for dataset {}. (error: {})",
                  dataset,
                  err);
            vec![]
        })
        .into_iter()
        .fold(AdminFromInsee::new(), |mut a_by_insee, a| {
            a_by_insee.insert(a.id.to_string(), Rc::new(a));
            a_by_insee
        });

    let addr_index = rubber.make_index(doc_type, dataset).unwrap();
    info!("Add data in elasticsearch db.");
    for f in files {
        info!("importing {:?}...", &f);
        let mut rdr = csv::Reader::from_file(&f).unwrap().has_headers(false);

        let iter = rdr.decode().map(|r| {
            let b: Bano = r.unwrap();
            b.into_addr(&admins_by_insee)
        });
        match rubber.bulk_index(&addr_index, iter) {
            Err(e) => panic!("failed to bulk insert file {:?} because: {}", &f, e),
            Ok(nb) => info!("importing {:?}: {} addresses added.", &f, nb),
        }
    }
    rubber.publish_index(doc_type, dataset, addr_index).unwrap();
}

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_input: String,
    flag_connection_string: String,
    flag_dataset: String,
}

static USAGE: &'static str = "
Usage:
    bano2mimir --input=<input> [--connection-string=<connection-string>] [--dataset=<dataset>]

    -i, --input=<input>           Bano files. Can be either a directory or a file.
    -c, --connection-string=<connection-string>
                                  Elasticsearch parameters, [default: http://localhost:9200/munin]
    -d, --dataset=<dataset>       Name of the dataset, [default: fr]
";

fn main() {
    mimir::logger_init().unwrap();
    info!("importing bano into Mimir");

    let args: Args = docopt::Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());

    let file_path = Path::new(&args.flag_input);
    if file_path.is_dir() {
        let paths: std::fs::ReadDir = fs::read_dir(&args.flag_input).unwrap();
        index_bano(&args.flag_connection_string,
                   &args.flag_dataset,
                   paths.map(|p| p.unwrap().path()));
    } else {
        index_bano(&args.flag_connection_string,
                   &args.flag_dataset,
                   std::iter::once(std::path::PathBuf::from(&args.flag_input)));
    }
}
<|endoftext|>