<commit_before>extern crate ruster_unsafe;
pub use self::ruster_unsafe::{ ERL_NIF_TERM, ErlNifResourceFlags, ErlNifResourceType };

pub mod ruster_export {
    pub use super::ruster_unsafe::*;
}

extern crate libc;
pub use libc::{ c_char, size_t, c_int, c_uint, c_void };

use std::mem;
use std::marker::PhantomData;

mod types;
pub use self::types::{ NifEncoder, NifDecoder };

mod resource;
pub use self::resource::{ open_resource_type_raw, alloc_resource_raw };
pub use self::resource::{ open_struct_resource_type, alloc_struct_resource, get_struct_resource };

mod binary;
pub use self::binary::{ NifBinary, alloc_binary, make_binary, get_binary };

pub struct NifEnv {
    pub env: *mut ruster_unsafe::ErlNifEnv,
}
impl NifEnv {
    unsafe fn as_c_arg(&self) -> *mut ruster_unsafe::ErlNifEnv {
        self.env
    }
}

#[derive(Clone, Copy)]
pub enum NifError {
    BadArg,
    AllocFail,
    Atom(&'static str),
}

#[derive(Clone, Copy)]
pub struct NifTerm<'a> {
    pub term: ERL_NIF_TERM,
    env_life: PhantomData<&'a NifEnv>,
}
impl<'a> NifTerm<'a> {
    pub fn new(_env: &'a NifEnv, inner: ERL_NIF_TERM) -> Self {
        NifTerm {
            term: inner,
            env_life: PhantomData
        }
    }
    unsafe fn as_c_arg(&self) -> ERL_NIF_TERM {
        self.term
    }
}

pub struct NifResourceType {
    pub res: *mut ErlNifResourceType
}
pub struct NifStructResourceType<T> {
    pub res: NifResourceType,
    pub struct_type: PhantomData<T>,
}

// Atoms are a special case of a term. They can be stored and used on all envs regardless of where
// it lives and when it is created.
#[derive(PartialEq, Eq)]
pub struct NifAtom {
    term: ERL_NIF_TERM,
}

pub fn get_tuple<'a>(env: &'a NifEnv, term: NifTerm) -> Result<Vec<NifTerm<'a>>, NifError> {
    let mut arity: c_int = 0;
    let mut array_ptr: *const ERL_NIF_TERM = unsafe { mem::uninitialized() };
    let success = unsafe { ruster_unsafe::enif_get_tuple(env.env, term.term,
                                                         &mut arity as *mut c_int,
                                                         &mut array_ptr as *mut *const ERL_NIF_TERM) };
    if success != 1 {
        return Err(NifError::BadArg);
    }
    let term_array = unsafe { std::slice::from_raw_parts(array_ptr, arity as usize) };
    Ok(term_array.iter().map(|x| { NifTerm::new(env, *x) }).collect::<Vec<NifTerm>>())
}

pub fn decode_type<T: NifDecoder>(term: NifTerm, env: &NifEnv) -> Result<T, NifError> {
    NifDecoder::decode(term, env)
}

#[macro_export]
macro_rules! decode_term_array_to_tuple {
    (@count ()) => { 0 };
    (@count ($_i:ty, $($rest:tt)*)) => { 1 + decode_term_array_to_tuple!(@count ($($rest)*)) };
    (@accum $_env:expr, $_list:expr, $_num:expr, ($(,)*) -> ($($body:tt)*)) => {
        decode_term_array_to_tuple!(@as_expr ($($body)*))
    };
    (@accum $env:expr, $list:expr, $num:expr, ($head:ty, $($tail:tt)*) -> ($($body:tt)*)) => {
        decode_term_array_to_tuple!(@accum $env, $list, ($num+1), ($($tail)*) -> ($($body)* decode_term_array_to_tuple!(@decode_arg $env, $head, $list[$num]),))
    };
    (@as_expr $e:expr) => {$e};
    (@decode_arg $env:expr, $typ:ty, $val:expr) => {
        match $crate::decode_type::<$typ>($val, $env) {
            Ok(val) => val,
            Err(val) => return Err(val),
        }
    };
    ($env:expr, $terms:expr, ($($typs:ty),*)) => {
        {
            let decoder: &Fn(&NifEnv, &[NifTerm]) -> Result<($($typs),*), NifError> = &|env, terms| {
                let num_expr: usize = decode_term_array_to_tuple!(@count ($($typs,)*));
                if $terms.len() != num_expr {
                    Err($crate::NifError::BadArg)
                } else {
                    Ok(decode_term_array_to_tuple!(@accum $env, $terms, 0, ($($typs),*,) -> ()))
                }
            };
            decoder($env, $terms)
        }
    }
}

#[macro_export]
macro_rules! decode_tuple {
    ($env:expr, $term:expr, ($($typs:ty),*)) => {
        {
            let terms = try!($crate::get_tuple($env, $term));
            decode_term_array_to_tuple!($env, &terms[..], ($($typs),*))
        }
    }
}

#[macro_export]
macro_rules! nif_atom {
    ($env:expr, $name:ident) => ({
        const atom_name: &'static str = stringify!($name);
        $crate::ruster_export::enif_make_atom_len(
            $env.env,
            atom_name.as_ptr() as *const u8,
            atom_name.len() as $crate::size_t)
    });
}

pub fn nif_atom<'a>(env: &'a NifEnv, name: &str) -> NifTerm<'a> {
    unsafe {
        NifTerm::new(env, ruster_unsafe::enif_make_atom_len(
            env.env,
            name.as_ptr() as *const u8,
            name.len() as size_t))
    }
}

#[macro_export]
macro_rules! nif_func {
    ($name:ident, $fun:expr) => (
        extern "C" fn $name(r_env: *mut $crate::ruster_export::ErlNifEnv,
                            argc: $crate::c_int,
                            argv: *const $crate::ERL_NIF_TERM) -> $crate::ERL_NIF_TERM {
            use $crate::{ NifEnv, NifTerm, NifError, size_t };
            let env = NifEnv { env: r_env };
            let terms = unsafe { ::std::slice::from_raw_parts(argv, argc as usize) }.iter()
                .map(|x| { NifTerm::new(&env, *x) }).collect::<Vec<NifTerm>>();
            let inner_fun: &for<'a> Fn(&'a NifEnv, &Vec<NifTerm>) -> Result<NifTerm<'a>, NifError> = &$fun;
            let res: Result<NifTerm, NifError> = inner_fun(&env, &terms);
            match res {
                Ok(ret) => ret.term,
                Err(NifError::BadArg) =>
                    unsafe { $crate::ruster_export::enif_make_badarg(r_env) },
                Err(NifError::AllocFail) =>
                    unsafe { $crate::ruster_export::enif_make_badarg(r_env) },
                Err(NifError::Atom(name)) =>
                    unsafe { $crate::ruster_export::enif_make_atom_len(r_env,
                                                               name.as_ptr() as *const u8,
                                                               name.len() as size_t) },
            }
        });
}

#[macro_export]
macro_rules! nif_init_func {
    ($name:expr, $arity:expr, $function:ident, $flags:expr) => {
        $crate::ruster_export::ErlNifFunc {
            name: $name as *const u8,
            arity: $arity,
            function: $function,
            flags: $flags,
        }
    };
    ($name:expr, $arity:expr, $function:ident) => {
        nif_init_func!($name, $arity, $function, 0)
    }
}

#[macro_use(lazy_static)]
extern crate lazy_static;

#[macro_export]
macro_rules! lazy_static_ex {
    ($($args:tt)*) => ( lazy_static!($($args)*); );
}

#[macro_export]
macro_rules! nif_init {
    (@count ()) => { 0 };
    (@count ($_e:expr)) => { 1 };
    (@count ($_e:expr, $($tail:tt)*)) => { 1 + nif_init!(@count ($($tail)*)) };

    ($module:expr, $load:expr, $reload:expr, $upgrade:expr, $unload:expr, [$($func:expr),*]) => {
        const NUM_FUNCS: usize = nif_init!(@count ($($func),*));
        const FUNCS: [$crate::ruster_export::ErlNifFunc; NUM_FUNCS] = [$($func),*];
        static mut NIF_ENTRY: $crate::ruster_export::ErlNifEntry = $crate::ruster_export::ErlNifEntry {
            major: $crate::ruster_export::NIF_MAJOR_VERSION,
            minor: $crate::ruster_export::NIF_MINOR_VERSION,
            name: $module as *const u8,
            num_of_funcs: NUM_FUNCS as $crate::c_int,
            funcs: &FUNCS as *const $crate::ruster_export::ErlNifFunc,
            load: $load,
            reload: $reload,
            upgrade: $upgrade,
            unload: $unload,
            vm_variant: b"beam.vanilla\0" as *const u8,
            options: 0,
        };

        #[no_mangle]
        pub extern "C" fn nif_init() -> *const $crate::ruster_export::ErlNifEntry {
            unsafe { &NIF_ENTRY }
        }
    }
}
<commit_msg>forgot tuple stuff<commit_after>extern crate ruster_unsafe;
pub use self::ruster_unsafe::{ ERL_NIF_TERM, ErlNifResourceFlags, ErlNifResourceType };

pub mod ruster_export {
    pub use super::ruster_unsafe::*;
}

extern crate libc;
pub use libc::{ c_char, size_t, c_int, c_uint, c_void };

use std::mem;
use std::marker::PhantomData;

mod types;
pub use self::types::{ NifEncoder, NifDecoder };

mod resource;
pub use self::resource::{ open_resource_type_raw, alloc_resource_raw };
pub use self::resource::{ open_struct_resource_type, alloc_struct_resource, get_struct_resource };

mod binary;
pub use self::binary::{ NifBinary, alloc_binary, make_binary, get_binary };

#[macro_reexport]
mod tuple;

pub struct NifEnv {
    pub env: *mut ruster_unsafe::ErlNifEnv,
}
impl NifEnv {
    unsafe fn as_c_arg(&self) -> *mut ruster_unsafe::ErlNifEnv {
        self.env
    }
}

#[derive(Clone, Copy)]
pub enum NifError {
    BadArg,
    AllocFail,
    Atom(&'static str),
}

#[derive(Clone, Copy)]
pub struct NifTerm<'a> {
    pub term: ERL_NIF_TERM,
    env_life: PhantomData<&'a NifEnv>,
}
impl<'a> NifTerm<'a> {
    pub fn new(_env: &'a NifEnv, inner: ERL_NIF_TERM) -> Self {
        NifTerm {
            term: inner,
            env_life: PhantomData
        }
    }
    unsafe fn as_c_arg(&self) -> ERL_NIF_TERM {
        self.term
    }
}

pub struct NifResourceType {
    pub res: *mut ErlNifResourceType
}
pub struct NifStructResourceType<T> {
    pub res: NifResourceType,
    pub struct_type: PhantomData<T>,
}

// Atoms are a special case of a term. They can be stored and used on all envs regardless of where
// it lives and when it is created.
#[derive(PartialEq, Eq)]
pub struct NifAtom {
    term: ERL_NIF_TERM,
}

pub fn decode_type<T: NifDecoder>(term: NifTerm, env: &NifEnv) -> Result<T, NifError> {
    NifDecoder::decode(term, env)
}

#[macro_export]
macro_rules! nif_atom {
    ($env:expr, $name:ident) => ({
        const atom_name: &'static str = stringify!($name);
        $crate::ruster_export::enif_make_atom_len(
            $env.env,
            atom_name.as_ptr() as *const u8,
            atom_name.len() as $crate::size_t)
    });
}

pub fn nif_atom<'a>(env: &'a NifEnv, name: &str) -> NifTerm<'a> {
    unsafe {
        NifTerm::new(env, ruster_unsafe::enif_make_atom_len(
            env.env,
            name.as_ptr() as *const u8,
            name.len() as size_t))
    }
}

#[macro_export]
macro_rules! nif_func {
    ($name:ident, $fun:expr) => (
        extern "C" fn $name(r_env: *mut $crate::ruster_export::ErlNifEnv,
                            argc: $crate::c_int,
                            argv: *const $crate::ERL_NIF_TERM) -> $crate::ERL_NIF_TERM {
            use $crate::{ NifEnv, NifTerm, NifError, size_t };
            let env = NifEnv { env: r_env };
            let terms = unsafe { ::std::slice::from_raw_parts(argv, argc as usize) }.iter()
                .map(|x| { NifTerm::new(&env, *x) }).collect::<Vec<NifTerm>>();
            let inner_fun: &for<'a> Fn(&'a NifEnv, &Vec<NifTerm>) -> Result<NifTerm<'a>, NifError> = &$fun;
            let res: Result<NifTerm, NifError> = inner_fun(&env, &terms);
            match res {
                Ok(ret) => ret.term,
                Err(NifError::BadArg) =>
                    unsafe { $crate::ruster_export::enif_make_badarg(r_env) },
                Err(NifError::AllocFail) =>
                    unsafe { $crate::ruster_export::enif_make_badarg(r_env) },
                Err(NifError::Atom(name)) =>
                    unsafe { $crate::ruster_export::enif_make_atom_len(r_env,
                                                               name.as_ptr() as *const u8,
                                                               name.len() as size_t) },
            }
        });
}

#[macro_export]
macro_rules! nif_init_func {
    ($name:expr, $arity:expr, $function:ident, $flags:expr) => {
        $crate::ruster_export::ErlNifFunc {
            name: $name as *const u8,
            arity: $arity,
            function: $function,
            flags: $flags,
        }
    };
    ($name:expr, $arity:expr, $function:ident) => {
        nif_init_func!($name, $arity, $function, 0)
    }
}

#[macro_export]
macro_rules! nif_init {
    (@count ()) => { 0 };
    (@count ($_e:expr)) => { 1 };
    (@count ($_e:expr, $($tail:tt)*)) => { 1 + nif_init!(@count ($($tail)*)) };

    ($module:expr, $load:expr, $reload:expr, $upgrade:expr, $unload:expr, [$($func:expr),*]) => {
        const NUM_FUNCS: usize = nif_init!(@count ($($func),*));
        const FUNCS: [$crate::ruster_export::ErlNifFunc; NUM_FUNCS] = [$($func),*];
        static mut NIF_ENTRY: $crate::ruster_export::ErlNifEntry = $crate::ruster_export::ErlNifEntry {
            major: $crate::ruster_export::NIF_MAJOR_VERSION,
            minor: $crate::ruster_export::NIF_MINOR_VERSION,
            name: $module as *const u8,
            num_of_funcs: NUM_FUNCS as $crate::c_int,
            funcs: &FUNCS as *const $crate::ruster_export::ErlNifFunc,
            load: $load,
            reload: $reload,
            upgrade: $upgrade,
            unload: $unload,
            vm_variant: b"beam.vanilla\0" as *const u8,
            options: 0,
        };

        #[no_mangle]
        pub extern "C" fn nif_init() -> *const $crate::ruster_export::ErlNifEntry {
            unsafe { &NIF_ENTRY }
        }
    }
}
<|endoftext|>


<commit_before>//! FizzBuzz helper library for Rust and Cargo
//!
//! Instructions: Add to your cargo tomato and go!
//!
//! # Example
//!
//! ```
//! use fx::Fx;
//!
//! let sum_of_non_fizz_buzz_values = (1..101)
//!     .map(default)
//!     .fold(0, |a,b| a + if let I(n) = b {
//!         n
//!     } else {
//!         0
//!     });
//!
//! assert!(sum_of_nfizz_buzz_values == 2632);
//! ```

/// Enum representing value status.
pub enum Fx {
    Fizz,
    Buzz,
    FizzBuzz,
    I(u32),
}

impl Fx {
    /// Create new Fx enum using standard FizzBuzz rules.
    pub fn new(n: u32) -> Fx {
        Fx::arbitrary(n, |n| n % 3 == 0, |n| n % 5 == 0)
    }

    /// Create new Fx enum using arbitrary FizzBuzz rules.
    pub fn arbitrary<FA, FB>(n: u32, fa: FA, fb: FB) -> Fx
        where FA: Fn(u32) -> bool,
              FB: Fn(u32) -> bool
    {
        match (n, fa(n), fb(n)) {
            (_, true, true) => Fx::FizzBuzz,
            (_, true, _) => Fx::Fizz,
            (_, _, true) => Fx::Buzz,
            (n, _, _) => Fx::I(n),
        }
    }
}

/// Print Fx value to console; no need to futz with formatting.
/// on the client side.
impl std::fmt::Display for Fx {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            &Fx::FizzBuzz => write!(f, "FizzBuzz"),
            &Fx::Fizz => write!(f, "Fizz"),
            &Fx::Buzz => write!(f, "Buzz"),
            &Fx::I(n) => write!(f, "{}", n),
        }
    }
}

/// Convenience method for creating a new default Fx enum.
pub fn default(n: u32) -> Fx {
    Fx::new(n)
}

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

    #[test]
    fn integers_work() {
        assert!(format!("{}", Fx::new(2)) == "2");
    }

    #[test]
    fn fizz_works() {
        assert!(format!("{}", Fx::new(3)) == "Fizz");
    }

    #[test]
    fn buzz_works() {
        assert!(format!("{}", Fx::new(5)) == "Buzz");
    }

    #[test]
    fn fizz_buzz_works() {
        assert!(format!("{}", Fx::new(15)) == "FizzBuzz");
    }
}
<commit_msg>fixed evil documentation bugs<commit_after>//! FizzBuzz helper library for Rust and Cargo
//!
//! Instructions: Add to your cargo tomato and go!
//!
//! # Example
//!
//! ```
//! use fx::Fx;
//!
//! let sum_of_non_fizz_buzz_values = (1..101)
//!     .map(fx::default)
//!     .fold(0, |a,b| a + if let Fx::I(n) = b {
//!         n
//!     } else {
//!         0
//!     });
//!
//! assert!(sum_of_non_fizz_buzz_values == 2632);
//! ```

/// Enum representing value status.
pub enum Fx {
    Fizz,
    Buzz,
    FizzBuzz,
    I(u32),
}

impl Fx {
    /// Create new Fx enum using standard FizzBuzz rules.
    pub fn new(n: u32) -> Fx {
        Fx::arbitrary(n, |n| n % 3 == 0, |n| n % 5 == 0)
    }

    /// Create new Fx enum using arbitrary FizzBuzz rules.
    pub fn arbitrary<FA, FB>(n: u32, fa: FA, fb: FB) -> Fx
        where FA: Fn(u32) -> bool,
              FB: Fn(u32) -> bool
    {
        match (n, fa(n), fb(n)) {
            (_, true, true) => Fx::FizzBuzz,
            (_, true, _) => Fx::Fizz,
            (_, _, true) => Fx::Buzz,
            (n, _, _) => Fx::I(n),
        }
    }
}

/// Print Fx value to console; no need to futz with formatting.
/// on the client side.
impl std::fmt::Display for Fx {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            &Fx::FizzBuzz => write!(f, "FizzBuzz"),
            &Fx::Fizz => write!(f, "Fizz"),
            &Fx::Buzz => write!(f, "Buzz"),
            &Fx::I(n) => write!(f, "{}", n),
        }
    }
}

/// Convenience method for creating a new default Fx enum.
pub fn default(n: u32) -> Fx {
    Fx::new(n)
}

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

    #[test]
    fn integers_work() {
        assert!(format!("{}", Fx::new(2)) == "2");
    }

    #[test]
    fn fizz_works() {
        assert!(format!("{}", Fx::new(3)) == "Fizz");
    }

    #[test]
    fn buzz_works() {
        assert!(format!("{}", Fx::new(5)) == "Buzz");
    }

    #[test]
    fn fizz_buzz_works() {
        assert!(format!("{}", Fx::new(15)) == "FizzBuzz");
    }
}
<|endoftext|>


<commit_before>/// Extend `Option` with a fallible map method
///
/// This is useful for mapping fallible operations (i.e. operations that)
/// return `Result`, over an optional type. The result will be
/// `Result<Option<U>>`, which makes it easy to handle the errors that
/// originate from inside the closure that's being mapped.
///
/// # Type parameters
///
/// - `T`: The input `Option`'s value type
/// - `U`: The outputs `Option`'s value type
/// - `E`: The possible error during the mapping
pub trait FallibleMapExt<T, U, E> {

    /// Try to apply a fallible map function to the option
    fn try_map<F>(self, f: F) -> Result<Option<U>, E> where
        F: FnOnce(T) -> Result<U, E>;

}

// Implementions

impl<T, U, E> FallibleMapExt<T, U, E> for Option<T> {
    fn try_map<F>(self, f: F) -> Result<Option<U>, E> where
        F: FnOnce(T) -> Result<U, E>
    {
        match self {
            Some(x) => f(x).map(Some),
            None => Ok(None),
        }
    }
}

/// Extend `Option<Result<T>>` and Vec<Result<T>> with a `flip` method that scavenges the inner `Result`
/// type and brings it to the outernmost type for easy error handling.
///
/// This makes easy to `map`, `and_then` etc. with fallible (`Result`-returning)
/// functions over `Option` and then call `flip` to "surface" the `Result` for error handling.
///
/// # Type parameters
///
/// - `T`: The inner value type
/// - `E`: The error type of `Result`
pub trait FlipResultExt<T, E> {
    type ReturnType;

    fn flip(self) -> Self::ReturnType;
}

impl<T, E> FlipResultExt<T, E> for Option<Result<T, E>> {
    type ReturnType = Result<Option<T>, E>;

    fn flip(self) -> Result<Option<T>, E>
    {
        match self {
            Some(r) => r.map(Some),
            None => Ok(None),
        }
    }
}

impl<T, E> FlipResultExt<T, E> for Vec<Result<T, E>> {
    type ReturnType = Result<Vec<T>, E>;
    fn flip(self) -> Result<Vec<T>, E>
    {
        let mut result_vec = Vec::with_capacity(self.len());
        for t in self {
            match t {
                Ok(u) => result_vec.push(u),
                Err(e) => return Err(e),
            }
        }
        Ok(result_vec)
    }
}

impl<T, E> FlipResultExt<T, E> for Vec<Option<T>> {
    type ReturnType = Option<Vec<T>>;
    fn flip(self) -> Option<Vec<T>>
    {
        let mut result_vec = Vec::with_capacity(self.len());
        for t in self {
            match t {
                Some(u) => result_vec.push(u),
                None => return None,
            }
        }
        Some(result_vec)
    }
}

#[cfg(test)]
mod tests {
    use FallibleMapExt;
    use FlipResultExt;

    #[test]
    fn test_try_map_1() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| if true { Err("oh noes") } else { Ok(x + 1) })?
                .try_map(|x| Ok(x + 1))?;

            Ok(x)
        }
        assert_eq!(inner(), Err("oh noes"));
    }

    #[test]
    fn test_try_map_2() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| Ok(x + 1))?;

            Ok(x)
        }
        assert_eq!(inner(), Ok(Some(45)));
    }

    #[test]
    fn test_try_map_3() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| if true { Err("oh noes") } else { Ok(x + 1) })?
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| if true { Err("oh foes") } else { Ok(x + 1) })?;

            Ok(x)
        }
        assert_eq!(inner(), Err("oh noes"));
    }

    #[test]
    fn test_flip_1() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| if true { Err("oh noes") } else { Ok(x + 1) }).flip()?
                .map(|x| Ok(x + 1)).flip()?;

            Ok(x)
        }
        assert_eq!(inner(), Err("oh noes"));
    }

    #[test]
    fn test_flip_2() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| Ok(x + 1)).flip()?;

            Ok(x)
        }
        assert_eq!(inner(), Ok(Some(45)));
    }

    #[test]
    fn test_flip_3() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| if true { Err("oh noes") } else { Ok(x + 1) }).flip()?
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| if true { Err("oh foes") } else { Ok(x + 1) }).flip()?;

            Ok(x)
        }
        assert_eq!(inner(), Err("oh noes"));
    }

    #[test]
    fn test_flip_vec_1() {
        fn inner() -> Result<Vec<i32>, &'static str> {
            let x = vec![42, 100, 99, 1, 42, 10000]
                .into_iter().map(|x| Ok(x + 1)).collect::<Vec<_>>().flip()?;

            Ok(x)
        }
        assert_eq!(inner(), Ok(vec![43, 101, 100, 2, 43, 10001]));
    }

    #[test]
    fn test_flip_vec_2() {
        fn inner() -> Result<Vec<i32>, &'static str> {
            let x = vec![42, 100, 99, 1, 42, 10000]
                .into_iter().map(|x| if true { Err("heatenings") } else { Ok(x + 1) }).collect::<Vec<_>>().flip()?;

            Ok(x)
        }
        assert_eq!(inner(), Err("heatenings"));
    }
}
<commit_msg>E is no longer part of the trait FlipResultExt.<commit_after>/// Extend `Option` with a fallible map method
///
/// This is useful for mapping fallible operations (i.e. operations that)
/// return `Result`, over an optional type. The result will be
/// `Result<Option<U>>`, which makes it easy to handle the errors that
/// originate from inside the closure that's being mapped.
///
/// # Type parameters
///
/// - `T`: The input `Option`'s value type
/// - `U`: The outputs `Option`'s value type
/// - `E`: The possible error during the mapping
pub trait FallibleMapExt<T, U, E> {

    /// Try to apply a fallible map function to the option
    fn try_map<F>(self, f: F) -> Result<Option<U>, E> where
        F: FnOnce(T) -> Result<U, E>;

}

// Implementions

impl<T, U, E> FallibleMapExt<T, U, E> for Option<T> {
    fn try_map<F>(self, f: F) -> Result<Option<U>, E> where
        F: FnOnce(T) -> Result<U, E>
    {
        match self {
            Some(x) => f(x).map(Some),
            None => Ok(None),
        }
    }
}

/// Extend `Option<Result<T>>` and Vec<Result<T>> with a `flip` method that scavenges the inner `Result`
/// type and brings it to the outernmost type for easy error handling.
///
/// This makes easy to `map`, `and_then` etc. with fallible (`Result`-returning)
/// functions over `Option` and then call `flip` to "surface" the `Result` for error handling.
///
/// # Type parameters
///
/// - `T`: The inner value type
/// - `E`: The error type of `Result`
pub trait FlipResultExt<T> {
    type ReturnType;

    fn flip(self) -> Self::ReturnType;
}

impl<T, E> FlipResultExt<T> for Option<Result<T, E>> {
    type ReturnType = Result<Option<T>, E>;

    fn flip(self) -> Result<Option<T>, E>
    {
        match self {
            Some(r) => r.map(Some),
            None => Ok(None),
        }
    }
}

impl<T, E> FlipResultExt<T> for Vec<Result<T, E>> {
    type ReturnType = Result<Vec<T>, E>;
    fn flip(self) -> Result<Vec<T>, E>
    {
        let mut result_vec = Vec::with_capacity(self.len());
        for t in self {
            match t {
                Ok(u) => result_vec.push(u),
                Err(e) => return Err(e),
            }
        }
        Ok(result_vec)
    }
}

impl<T> FlipResultExt<T> for Vec<Option<T>> {
    type ReturnType = Option<Vec<T>>;
    fn flip(self) -> Option<Vec<T>>
    {
        let mut result_vec = Vec::with_capacity(self.len());
        for t in self {
            match t {
                Some(u) => result_vec.push(u),
                None => return None,
            }
        }
        Some(result_vec)
    }
}

#[cfg(test)]
mod tests {
    use FallibleMapExt;
    use FlipResultExt;

    #[test]
    fn test_try_map_1() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| if true { Err("oh noes") } else { Ok(x + 1) })?
                .try_map(|x| Ok(x + 1))?;

            Ok(x)
        }
        assert_eq!(inner(), Err("oh noes"));
    }

    #[test]
    fn test_try_map_2() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| Ok(x + 1))?;

            Ok(x)
        }
        assert_eq!(inner(), Ok(Some(45)));
    }

    #[test]
    fn test_try_map_3() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| if true { Err("oh noes") } else { Ok(x + 1) })?
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| if true { Err("oh foes") } else { Ok(x + 1) })?;

            Ok(x)
        }
        assert_eq!(inner(), Err("oh noes"));
    }

    #[test]
    fn test_flip_1() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| if true { Err("oh noes") } else { Ok(x + 1) }).flip()?
                .map(|x| Ok(x + 1)).flip()?;

            Ok(x)
        }
        assert_eq!(inner(), Err("oh noes"));
    }

    #[test]
    fn test_flip_2() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| Ok(x + 1)).flip()?;

            Ok(x)
        }
        assert_eq!(inner(), Ok(Some(45)));
    }

    #[test]
    fn test_flip_3() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| if true { Err("oh noes") } else { Ok(x + 1) }).flip()?
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| if true { Err("oh foes") } else { Ok(x + 1) }).flip()?;

            Ok(x)
        }
        assert_eq!(inner(), Err("oh noes"));
    }

    #[test]
    fn test_flip_vec_1() {
        fn inner() -> Result<Vec<i32>, &'static str> {
            let x = vec![42, 100, 99, 1, 42, 10000]
                .into_iter().map(|x| Ok(x + 1)).collect::<Vec<_>>().flip()?;

            Ok(x)
        }
        assert_eq!(inner(), Ok(vec![43, 101, 100, 2, 43, 10001]));
    }

    #[test]
    fn test_flip_vec_2() {
        fn inner() -> Result<Vec<i32>, &'static str> {
            let x = vec![42, 100, 99, 1, 42, 10000]
                .into_iter().map(|x| if true { Err("heatenings") } else { Ok(x + 1) }).collect::<Vec<_>>().flip()?;

            Ok(x)
        }
        assert_eq!(inner(), Err("heatenings"));
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::cmp;
use innovation::Innovation;

mod innovation;

trait Gene {
    fn weight_distance(&self, other: &Self) -> f64;
}

enum NodeType {
    Input,
    Output,
    Hidden,
}

struct NodeGene {
    node_type: NodeType,
}

// To avoid node collisions we use Innovation numbers instead. Every newly created node gets it's
// own innovation number.
struct LinkGene {
    // This points to the NodeGene of that innovation
    source_node_gene: Innovation,
    // This points to the NodeGene of that innovation
    target_node_gene: Innovation,
    weight: f64,
    active: bool,
}

impl Gene for LinkGene {
    fn weight_distance(&self, other: &LinkGene) -> f64 {
        self.weight - other.weight
    }
}

// always take excess/disjoint genes if they appear on the fitter parent.
// if they appear on the less fit parent, take them only to a specified
// probability

struct Genome {
    link_genes: BTreeMap<Innovation, LinkGene>,
    node_genes: BTreeMap<Innovation, NodeGene>,
}

struct Coefficients {
    excess: f64,
    disjoint: f64,
    weight: f64,
}

fn genes_compatibility<T: Gene>(genes1: &BTreeMap<Innovation, T>,
                                genes2: &BTreeMap<Innovation, T>,
                                coeff: &Coefficients)
                                -> f64 {
    let max_len = cmp::max(genes1.len(), genes2.len());
    assert!(max_len > 0);

    let range1 = innovation::innovation_range(genes1);
    let range2 = innovation::innovation_range(genes2);

    // calculate the number of excess genes of
    let mut excess = 0;
    let mut disjoint = 0;
    let mut matching = 0;
    let mut weight_dist = 0.0;

    for (innov1, gene) in genes1.iter() {
        if innov1.is_within(&range2) {
            match genes2.get(innov1) {
                Some(other_gene) => {
                    matching += 1;
                    weight_dist += gene.weight_distance(other_gene);
                }
                None => {
                    disjoint += 1;
                }
            }
        } else {
            excess += 1;
        }
    }

    for innov2 in genes2.keys() {
        if innov2.is_within(&range1) {
            if !genes1.contains_key(innov2) {
                disjoint += 1;
            }
        } else {
            excess += 1;
        }
    }

    assert!(2 * matching + disjoint + excess == genes1.len() + genes2.len());

    coeff.excess * (excess as f64) / (max_len as f64) +
    coeff.disjoint * (disjoint as f64) / (max_len as f64) +
    coeff.weight *
    if matching > 0 {
        weight_dist / (matching as f64)
    } else {
        0.0
    }
}
<commit_msg>Implement crossover. Refactor correlation<commit_after>extern crate rand;

use std::collections::BTreeMap;
use std::cmp;
use innovation::Innovation;
use rand::{Rng, Closed01};

mod innovation;

trait Gene: Clone {
    fn weight_distance(&self, other: &Self) -> f64;
}

enum NodeType {
    Input,
    Output,
    Hidden,
}

struct NodeGene {
    node_type: NodeType,
}

// To avoid node collisions we use Innovation numbers instead of node
// ids.
#[derive(Clone)]
struct LinkGene {
    // This points to the NodeGene of that innovation
    source_node_gene: Innovation,
    // This points to the NodeGene of that innovation
    target_node_gene: Innovation,
    weight: f64,
    active: bool,
}

impl Gene for LinkGene {
    fn weight_distance(&self, other: &LinkGene) -> f64 {
        self.weight - other.weight
    }
}

struct Genome {
    link_genes: BTreeMap<Innovation, LinkGene>,
    node_genes: BTreeMap<Innovation, NodeGene>,
}

enum Correlation<'a, T: 'a> {
    Matching(&'a T, &'a T),
    DisjointLeft(&'a T),
    DisjointRight(&'a T),
    ExcessLeft(&'a T),
    ExcessRight(&'a T),
}

/// Correlate the genes in ```genes_left``` with those in ```genes_right```.
fn correlate<'a, T, F>(genes_left: &'a BTreeMap<Innovation, T>,
                       genes_right: &'a BTreeMap<Innovation, T>,
                       f: &mut F)
    where F: FnMut(Innovation, Correlation<'a, T>)
{
    let range_left = innovation::innovation_range(genes_left);
    let range_right = innovation::innovation_range(genes_right);

    for (innov_left, gene_left) in genes_left.iter() {
        if innov_left.is_within(&range_right) {
            match genes_right.get(innov_left) {
                Some(gene_right) => f(*innov_left, Correlation::Matching(gene_left, gene_right)),
                None => f(*innov_left, Correlation::DisjointLeft(gene_left)),
            }
        } else {
            f(*innov_left, Correlation::ExcessLeft(gene_left))
        }
    }

    for (innov_right, gene_right) in genes_right.iter() {
        if innov_right.is_within(&range_left) {
            if !genes_left.contains_key(innov_right) {
                f(*innov_right, Correlation::DisjointRight(gene_right))
            }
        } else {
            f(*innov_right, Correlation::ExcessRight(gene_right))
        }
    }
}

struct CompatibilityCoefficients {
    excess: f64,
    disjoint: f64,
    weight: f64,
}

/// Calculates the compatibility between two gene lists.
fn compatibility<T: Gene>(genes1: &BTreeMap<Innovation, T>,
                              genes2: &BTreeMap<Innovation, T>,
                              coeff: &CompatibilityCoefficients)
                              -> f64 {
    let max_len = cmp::max(genes1.len(), genes2.len());
    assert!(max_len > 0);

    let mut matching = 0;
    let mut disjoint = 0;
    let mut excess = 0;
    let mut weight_dist = 0.0;

    correlate(genes1,
              genes2,
              &mut |_, correlation| {
                  match correlation {
                      Correlation::Matching(gene_left, gene_right) => {
                          matching += 1;
                          weight_dist += gene_left.weight_distance(gene_right).abs();
                      }
                      Correlation::DisjointLeft(_) | Correlation::DisjointRight(_) => {
                          disjoint += 1;
                      }
                      Correlation::ExcessLeft(_) | Correlation::ExcessRight(_) => {
                          excess += 1;
                      }
                  }
              });

    assert!(2 * matching + disjoint + excess == genes1.len() + genes2.len());

    coeff.excess * (excess as f64) / (max_len as f64) +
    coeff.disjoint * (disjoint as f64) / (max_len as f64) +
    coeff.weight *
    if matching > 0 {
        weight_dist / (matching as f64)
    } else {
        0.0
    }
}

/// These describe the probabilities to take a gene from one of the
/// parents during crossover.
/// XXX: It's probably faster to not use floats here.
struct CrossoverProbabilities {
    /// Probability to take a matching gene from the fitter (first) parent.
    prob_match1: Closed01<f32>,

    /// Probability to take a disjoint gene from the fitter (first) parent.
    prob_disjoint1: Closed01<f32>,

    /// Probability to take an excess gene from the fitter (first) parent.
    prob_excess1: Closed01<f32>,

    /// Probability to take a disjoint gene from the less fit parent.
    prob_disjoint2: Closed01<f32>,

    /// Probability to take an excess gene from the less fit parent.
    prob_excess2: Closed01<f32>,
}

fn is_probable<R: Rng>(prob: &Closed01<f32>, rng: &mut R) -> bool {
    if prob.0 < 1.0 {
        let v: f32 = rng.gen(); // half open [0, 1)
        v < prob.0
    } else {
        true
    }
}

/// We assume ```parent1``` to be the fitter parent. Takes gene
/// either from ```parent1``` or ```parent2``` according to
/// the probabilities specified and the relative fitness of the parents.
fn crossover<T: Gene, R: Rng>(parent1: &BTreeMap<Innovation, T>,
                              parent2: &BTreeMap<Innovation, T>,
                              p: &CrossoverProbabilities,
                              rng: &mut R)
                              -> BTreeMap<Innovation, T> {

    let mut offspring = BTreeMap::new();

    correlate(parent1,
              parent2,
              &mut |innov, correlation| {
                  match correlation {
                      Correlation::Matching(gene_left, gene_right) => {
                          if is_probable(&p.prob_match1, rng) {
                              offspring.insert(innov, gene_left.clone());
                          } else {
                              offspring.insert(innov, gene_right.clone());
                          }
                      }

                      Correlation::DisjointLeft(gene_left) => {
                          if is_probable(&p.prob_disjoint1, rng) {
                              offspring.insert(innov, gene_left.clone());
                          }
                      }

                      Correlation::DisjointRight(gene_right) => {
                          if is_probable(&p.prob_disjoint2, rng) {
                              offspring.insert(innov, gene_right.clone());
                          }
                      }

                      Correlation::ExcessLeft(gene_left) => {
                          if is_probable(&p.prob_excess1, rng) {
                              offspring.insert(innov, gene_left.clone());
                          }
                      }

                      Correlation::ExcessRight(gene_right) => {
                          if is_probable(&p.prob_excess2, rng) {
                              offspring.insert(innov, gene_right.clone());
                          }
                      }
                  }
              });

    offspring
}
<|endoftext|>


<commit_before>use super::base::{BaseRand, RAND_MAX};
use std::f64::consts::PI;

pub enum Style {
    Normal,
    Pythagoras,
    Gauss(u32),
    BMgauss(f64, f64, bool),
    Marsaglia(f64, f64, f64, bool),
}

pub enum JumpStyle {
    Static,
    Next,
    Jump,
    DoubleJump,
}

pub struct Rand {
    base: Vec<BaseRand>,
    handle: Option<usize>,
    style: Style,
    jump: JumpStyle,
}

impl Rand {
    /// a lazy way to get a random solver
    pub fn new() -> Self {
        Rand {
            base: vec![BaseRand::new()],
            handle: Some(0),
            style: Style::Normal,
            jump: JumpStyle::Static,
        }
    }

    pub fn set_style(&mut self, style: Style) {
        self.style = style;
    }

    pub fn srand(&mut self, seed: Vec<usize>) {
        for i in 0..self.base.len() {
            self.base[i].srand(seed[i]);
        }
    }

    pub fn lazy_srand(&mut self) {
        for i in 0..self.base.len() {
            self.base[i].lazy_srand();
        }
    }

    pub fn set_function(&mut self, handle: usize, style: &str) {
        self.base[handle].set_function(style);
    }

    /// get a random number
    pub fn rand(&mut self) -> f64 {
        match self.style {
            Style::Normal => self.base() as f64,
            Style::Pythagoras => pythagoras(self),
            Style::Gauss(nsum) => gauss(self, nsum),
            Style::BMgauss(u, v, phase) => {
                let mut _u = u;
                let mut _v = v;
                let mut _phase = phase;
                let _return = bmgauss(self, &mut _u, &mut _v, &mut _phase);
                self.style = Style::BMgauss(_u, _v, _phase);
                _return
            }
            Style::Marsaglia(v1, v2, s, phase) => {
                let mut _v1 = v1;
                let mut _v2 = v2;
                let mut _s = s;
                let mut _phase = phase;
                let _return = marsaglia(self, &mut _v1, &mut _v2, &mut _s, &mut _phase);
                self.style = Style::Marsaglia(_v1, _v2, _s, _phase);
                _return
            }
        }
    }

    pub fn base(&mut self) -> usize {
        match self.handle {
            Some(e) => self.base[e].rand(),
            _ => {
                let mut _base = 0;
                for i in 0..self.base.len() {
                    _base += self.base[i].rand() / self.base.len();
                }
                _base
            }
        }
    }

    pub fn new_base(&mut self) {
        self.base.push(BaseRand::new());
    }

    pub fn del_base(&mut self) -> Option<BaseRand> {
        self.base.pop()
    }

    pub fn jump_style(&mut self, style: JumpStyle) {
        self.jump = style;
    }

    pub fn jump(&mut self) {
        match self.handle {
            Some(e) => {
                match self.jump {
                    JumpStyle::Next => self.handle = Some((e + 1) % self.base.len()),
                    JumpStyle::Jump => {
                        let _jump = self.base();
                        self.handle = Some(_jump % self.base.len());
                    }
                    JumpStyle::DoubleJump => {
                        let _gap = self.base();
                        for _ in 0.._gap {
                            let _jump = self.base();
                            self.handle = Some(_jump % self.base.len());
                        }
                    }
                    _ => {}
                }
            }
            _ => {}
        }
    }
}

fn gauss(base: &mut Rand, nsum: u32) -> f64 {
    let mut x = 0.0;
    for _ in 0..nsum {
        x += base.base() as f64 / RAND_MAX as f64;
    }
    x -= nsum as f64 / 2.0;
    x /= (nsum as f64 / 12.0).sqrt();
    x
}

fn bmgauss(base: &mut Rand, u: &mut f64, v: &mut f64, phase: &mut bool) -> f64 {
    if *phase {
        *phase = false;
        *u = (base.base() + 1) as f64 / (RAND_MAX + 2) as f64;
        *v = base.base() as f64 / (RAND_MAX + 1) as f64;
        (-2.0 * (*u).log10()).sqrt() * (2.0 * PI * (*v)).sin()
    } else {
        *phase = true;
        (-2.0 * (*u).log10()).sqrt() * (2.0 * PI * (*v)).cos()
    }
}

fn marsaglia(base: &mut Rand, v1: &mut f64, v2: &mut f64, s: &mut f64, phase: &mut bool) -> f64 {
    if *phase {
        *phase = false;
        let u1 = base.base() as f64 / RAND_MAX as f64;
        let u2 = base.base() as f64 / RAND_MAX as f64;
        *v1 = 2.0 * u1 - 1.0;
        *v2 = 2.0 * u2 - 1.0;
        *v1 * (-2.0 * (*s).log10() / (*s)).sqrt()
    } else {
        *phase = true;
        *v2 * (-2.0 * (*s).log10() / (*s)).sqrt()
    }
}

fn pythagoras(base: &mut Rand) -> f64 {
    let a = base.base() as f64 / (RAND_MAX + 1) as f64;
    let b = base.base() as f64 / (RAND_MAX + 1) as f64;
    let c_sqr = a * a + b * b;
    c_sqr.sqrt()
}
<commit_msg>Rebuild<commit_after>use super::base::{BaseRand, RAND_MAX};
use std::f64::consts::PI;

pub enum Style {
    Normal,
    Pythagoras,
    Gauss(u32),
    BMgauss(f64, f64, bool),
    Marsaglia(f64, f64, f64, bool),
}

pub enum JumpStyle {
    Static,
    Next,
    Jump,
    DoubleJump,
}

pub struct Rand {
    base: Vec<BaseRand>,
    handle: Option<usize>,
    style: Style,
    jump: JumpStyle,
}

impl Rand {
    /// a lazy way to get a random solver
    pub fn new() -> Self {
        Rand {
            base: vec![BaseRand::new()],
            handle: Some(0),
            style: Style::Normal,
            jump: JumpStyle::Static,
        }
    }

    pub fn set_style(&mut self, style: Style) {
        self.style = style;
    }

    pub fn srand(&mut self, seed: Vec<usize>) {
        for i in 0..self.base.len() {
            self.base[i].srand(seed[i]);
        }
    }

    pub fn lazy_srand(&mut self) {
        for i in 0..self.base.len() {
            self.base[i].lazy_srand();
        }
    }

    pub fn set_function(&mut self, handle: usize, style: &str) {
        self.base[handle].set_function(style);
    }

    /// get a random number
    pub fn rand(&mut self) -> f64 {
        match self.style {
            Style::Normal => self.base() as f64,
            Style::Pythagoras => pythagoras(self),
            Style::Gauss(nsum) => gauss(self, nsum),
            Style::BMgauss(u, v, phase) => {
                let mut _u = u;
                let mut _v = v;
                let mut _phase = phase;
                let _return = bmgauss(self, &mut _u, &mut _v, &mut _phase);
                self.style = Style::BMgauss(_u, _v, _phase);
                _return
            }
            Style::Marsaglia(v1, v2, s, phase) => {
                let mut _v1 = v1;
                let mut _v2 = v2;
                let mut _s = s;
                let mut _phase = phase;
                let _return = marsaglia(self, &mut _v1, &mut _v2, &mut _s, &mut _phase);
                self.style = Style::Marsaglia(_v1, _v2, _s, _phase);
                _return
            }
        }
    }

    pub fn base(&mut self) -> usize {
        match self.handle {
            Some(e) => self.base[e].rand(),
            _ => {
                let mut _base = 0;
                for i in 0..self.base.len() {
                    _base += self.base[i].rand() / self.base.len();
                }
                _base
            }
        }
    }

    pub fn new_base(&mut self) {
        self.base.push(BaseRand::new());
    }

    pub fn del_base(&mut self) -> Option<BaseRand> {
        self.base.pop()
    }

    pub fn jump_style(&mut self, style: JumpStyle) {
        self.jump = style;
    }

    pub fn jump(&mut self) {
        match self.handle {
            Some(e) => {
                match self.jump {
                    JumpStyle::Next => self.handle = Some((e + 1) % self.base.len()),
                    JumpStyle::Jump => {
                        let _jump = self.base();
                        self.handle = Some(_jump % self.base.len());
                    }
                    JumpStyle::DoubleJump => {
                        let _gap = self.base();
                        for _ in 0.._gap {
                            let _jump = self.base();
                            self.handle = Some(_jump % self.base.len());
                        }
                    }
                    _ => {}
                }
            }
            _ => {}
        }
    }
}

fn base64(base: &mut Rand, base_offset: usize, max_offset: usize) -> f64 {
    (base.base() + base_offset) as f64 / (RAND_MAX + base_offset + max_offset) as f64
}

fn gauss(base: &mut Rand, nsum: u32) -> f64 {
    let mut x = 0.0;
    for _ in 0..nsum {
        x += base64(base, 0, 0);
    }
    x -= nsum as f64 / 2.0;
    x /= (nsum as f64 / 12.0).sqrt();
    x
}

fn bmgauss(base: &mut Rand, u: &mut f64, v: &mut f64, phase: &mut bool) -> f64 {
    if *phase {
        *phase = false;
        *u = base64(base, 1, 1);
        *v = base64(base, 0, 1);
        (-2.0 * (*u).log10()).sqrt() * (2.0 * PI * (*v)).sin()
    } else {
        *phase = true;
        (-2.0 * (*u).log10()).sqrt() * (2.0 * PI * (*v)).cos()
    }
}

fn marsaglia(base: &mut Rand, v1: &mut f64, v2: &mut f64, s: &mut f64, phase: &mut bool) -> f64 {
    if *phase {
        *phase = false;
        let u1 = base64(base, 0, 0);
        let u2 = base64(base, 0, 0);
        *v1 = 2.0 * u1 - 1.0;
        *v2 = 2.0 * u2 - 1.0;
        *v1 * (-2.0 * (*s).log10() / (*s)).sqrt()
    } else {
        *phase = true;
        *v2 * (-2.0 * (*s).log10() / (*s)).sqrt()
    }
}

fn pythagoras(base: &mut Rand) -> f64 {
    let a = base64(base, 0, 1);
    let b = base64(base, 0, 1);
    let c_sqr = a * a + b * b;
    c_sqr.sqrt()
}
<|endoftext|>


<commit_before>extern crate tokio_core;
extern crate hyper;
extern crate futures;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate quick_error;

use std::net::SocketAddr;

use futures::future::Either;
use futures::{Future, Stream, BoxFuture};
use hyper::client::{self, HttpConnector};
use tokio_core::net::UdpSocket;
use tokio_core::reactor::Handle;

pub mod measurement;
pub use measurement::Measurement;

// TODO: documentation

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Url(error: hyper::error::ParseError) {
            description(error.description())
            display("Unable to parse URL: {}", error)
            from()
            cause(error)
        }
        Hyper(error: hyper::Error) {
            description(error.description())
            display("Unable to perform HTTP request: {}", error)
            from()
            cause(error)
        }
        Serde(error: serde_json::Error) {
            description(error.description())
            display("Unable to deserialize JSON: {}", error)
            from()
            cause(error)
        }
        BadRequest(what: String) {
            description("The InfluxDB server responded with an error")
            display("The InfluxDB server responded with an error: {}", what)
        }
        AddrParse(error: std::net::AddrParseError) {
            description(error.description())
            display("Unable to parse the address: {}", error)
            from()
            cause(error)
        }
        Udp(error: std::io::Error) {
            description(error.description())
            display("Unable to perform UDP request: {}", error)
            from()
            cause(error)
        }
    }
}

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

pub struct AsyncDb {
    name: String,
    query_endpoint: hyper::Url,
    write_endpoint: hyper::Url,
    client: hyper::Client<HttpConnector>,
}

impl AsyncDb {
    pub fn new(handle: Handle, base_url: &str, name: &str) -> Result<Self> {
        let base_url = hyper::Url::parse(base_url)?;
        let query_endpoint = base_url.join("/query")?;
        let mut write_endpoint = base_url.join("/write")?;
        write_endpoint.query_pairs_mut()
            .append_pair("db", &name);

        let client = hyper::Client::configure().keep_alive(false).build(&handle);

        Ok(AsyncDb {
            name: name.into(),
            query_endpoint: query_endpoint,
            write_endpoint: write_endpoint,
            client: client,
        })
    }

    pub fn add_data<T>(&self, measure: T) -> AddData
        where T: Measurement
    {
        let mut request = client::Request::new(hyper::Method::Post, self.write_endpoint.clone());
        let mut bytes_to_send = String::new();
        measure.to_data(&mut bytes_to_send);
        request.set_body(bytes_to_send.into_bytes());

        let response =
            self.client.request(request)
            .map_err(Error::Hyper)
            .and_then(check_response_code)
            .map(|_| ());

        AddData(Box::new(response))
    }

    pub fn query(&self, query: &str) -> Query {
        let mut query_endpoint = self.query_endpoint.clone();
        query_endpoint.query_pairs_mut()
            .append_pair("db", &self.name)
            .append_pair("q", query);

        let response =
            self.client.get(query_endpoint)
            .map_err(Error::Hyper)
            .and_then(check_response_code)
            .and_then(response_to_json);

        Query(Box::new(response))
    }
}

fn check_response_code(resp: client::Response) -> Box<Future<Item = client::Response, Error = Error>> {
    let f = if resp.status().is_success() {
        Either::A(futures::future::ok(resp))
    } else {
        let e = response_to_json::<InfluxServerError>(resp)
            .and_then(|message| Err(Error::BadRequest(message.error)));
        Either::B(e)
    };

    Box::new(f)
}

fn response_to_json<T>(resp: client::Response) -> Box<Future<Item = T, Error = Error>>
    where T: serde::Deserialize + 'static,
{
    let f =
        resp.body()
        .map_err(Error::Hyper)
        .fold(Vec::new(), |mut acc, chunk| {
            // TODO: Is it the best idea to just build up a big `Vec`?
            // TODO: Is there some way of reusing the vector allocation?
            acc.extend_from_slice(&*chunk);
            futures::future::ok::<_, Error>(acc)
        })
        .and_then(|body| serde_json::from_slice(&body).map_err(Error::Serde));

    Box::new(f)
}

#[must_use = "futures do nothing unless polled"]
pub struct AddData(Box<Future<Item = (), Error = Error>>);

impl Future for AddData {
    type Item = ();
    type Error = Error;

    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        self.0.poll()
    }
}

#[must_use = "futures do nothing unless polled"]
pub struct Query(Box<Future<Item = QueryResponse, Error = Error>>);

impl Future for Query {
    type Item = QueryResponse;
    type Error = Error;

    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        self.0.poll()
    }
}

#[derive(Debug, Deserialize)]
pub struct QueryResponse {
    pub results: Vec<QueryResult>,
}

#[derive(Debug, Deserialize)]
pub struct QueryResult {
    #[serde(default)]
    pub series: Vec<Series>,
    pub error: Option<String>,
    pub statement_id: usize,
}

#[derive(Debug, Deserialize)]
pub struct Series {
    pub name: String,
    pub columns: Vec<String>, // TODO: `time` is always added?
    pub values: Vec<Vec<serde_json::Value>>, // TODO: matches with columns?
    // TODO: Don't expose serde types publically
}

#[derive(Debug, Deserialize)]
pub struct InfluxServerError {
    pub error: String,
}

pub struct AsyncUdpDb {
    handle: Handle,
    my_addr: SocketAddr,
    their_addr: SocketAddr,
}

impl AsyncUdpDb {
    pub fn new(handle: Handle, ip_port: &str) -> Result<Self> {
        Ok(AsyncUdpDb {
            handle: handle,
            my_addr: "0.0.0.0:0".parse()?,
            their_addr: ip_port.parse()?,
        })
    }

    pub fn add_data<T>(&self, measure: T) -> AddDataUdp
        where T: Measurement
    {
        let mut bytes_to_send = String::new();
        measure.to_data(&mut bytes_to_send);

        // TODO: We could consume self like `send_dgram` does, which
        // allows reusing the same socket over and over. The API would
        // be more annoying, but might be like other futures...
        let f = match UdpSocket::bind(&self.my_addr, &self.handle) {
            Ok(socket) => {
                let f = socket.send_dgram(bytes_to_send, self.their_addr)
                    .map(|_| ())
                    .map_err(Error::Udp);
                Either::A(f)
            }
            Err(e) => {
                Either::B(futures::future::err(Error::Udp(e)))
            }
        };

        AddDataUdp(f.boxed())
    }
}

#[must_use = "futures do nothing unless polled"]
pub struct AddDataUdp(BoxFuture<(), Error>);

impl Future for AddDataUdp {
    type Item = ();
    type Error = Error;

    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        self.0.poll()
    }
}
<commit_msg>Add crate-level documentation<commit_after>//! # influxdb
//!
//! influxdb provides an asynchronous Rust interface to an
//! [InfluxDB][] database.
//!
//! This crate supports insertion of strings already in the InfluxDB
//! Line Protocol. The `influxdb-derive` crate provides convenient
//! serialization of Rust structs to this format.
//!
//! [InfluxDB]: https://www.influxdata.com/
//!
//! # Examples
//!
//! To serialize a struct into the InfluxDB Line Protocol format, use the
//! `influxdb-derive` crate's macros as shown below with `MyMeasure`.
//!
//! Then create an instance of `influxdb::AsyncDb` and add instances of
//! your struct. Check out the code in the `examples` directory to see how
//! this code interacts with futures.
//!
//! ```
//! extern crate influxdb;
//! #[macro_use]
//! extern crate influxdb_derive;
//! extern crate tokio_core;
//!
//! use std::time::SystemTime;
//! use influxdb::{Measurement, AsyncDb};
//!
//! // `Measurement` is the trait that `AsyncDb` needs in order to insert
//! #[derive(Measurement)]
//! // The default measurement name will be the struct name; this optional
//! // annotation allows customization of the name sent to InfluxDB.
//! #[influx(rename = "my_measure")]
//! struct MyMeasure {
//!     // Specify which struct fields are InfluxDB tags.
//!     // Tags must be `String`s or `&str`s.
//!     #[influx(tag)]
//!     region: String,
//!     // Specify which struct fields are InfluxDB fields.
//!     // Supported types are integers, floats, strings, and booleans.
//!     // The rename annotation works with struct fields as well.
//!     #[influx(field, rename = "amount")]
//!     count: i32,
//!     // Specify which struct field is the InfluxDB timestamp.
//!     #[influx(timestamp)]
//!     when: SystemTime,
//!     // Struct fields that aren't annotated won't be sent to InfluxDB.
//!     other: i32,
//! }
//!
//! fn main() {
//!     let mut core = tokio_core::reactor::Core::new()
//!         .expect("Unable to create reactor core");
//!
//!     let async_db = AsyncDb::new(
//!         core.handle(),            // A tokio_core handle
//!         "http://localhost:8086/", // URL to InfluxDB
//!         "my_database"             // Name of the database in InfluxDB
//!     ).expect("Unable to create AsyncDb");
//!
//!     let now = SystemTime::now();
//!     let batch = vec![
//!         MyMeasure { region: String::from("us-east"), count: 3, when: now, other: 0 },
//!         MyMeasure { region: String::from("us-west"), count: 20, when: now, other: 1 },
//!     ];
//!
//!     let insert = async_db.add_data(&batch); // Returns a Future
//! }
//! ```

extern crate tokio_core;
extern crate hyper;
extern crate futures;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate quick_error;

use std::net::SocketAddr;

use futures::future::Either;
use futures::{Future, Stream, BoxFuture};
use hyper::client::{self, HttpConnector};
use tokio_core::net::UdpSocket;
use tokio_core::reactor::Handle;

pub mod measurement;
pub use measurement::Measurement;

// TODO: documentation

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Url(error: hyper::error::ParseError) {
            description(error.description())
            display("Unable to parse URL: {}", error)
            from()
            cause(error)
        }
        Hyper(error: hyper::Error) {
            description(error.description())
            display("Unable to perform HTTP request: {}", error)
            from()
            cause(error)
        }
        Serde(error: serde_json::Error) {
            description(error.description())
            display("Unable to deserialize JSON: {}", error)
            from()
            cause(error)
        }
        BadRequest(what: String) {
            description("The InfluxDB server responded with an error")
            display("The InfluxDB server responded with an error: {}", what)
        }
        AddrParse(error: std::net::AddrParseError) {
            description(error.description())
            display("Unable to parse the address: {}", error)
            from()
            cause(error)
        }
        Udp(error: std::io::Error) {
            description(error.description())
            display("Unable to perform UDP request: {}", error)
            from()
            cause(error)
        }
    }
}

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

pub struct AsyncDb {
    name: String,
    query_endpoint: hyper::Url,
    write_endpoint: hyper::Url,
    client: hyper::Client<HttpConnector>,
}

impl AsyncDb {
    pub fn new(handle: Handle, base_url: &str, name: &str) -> Result<Self> {
        let base_url = hyper::Url::parse(base_url)?;
        let query_endpoint = base_url.join("/query")?;
        let mut write_endpoint = base_url.join("/write")?;
        write_endpoint.query_pairs_mut()
            .append_pair("db", &name);

        let client = hyper::Client::configure().keep_alive(false).build(&handle);

        Ok(AsyncDb {
            name: name.into(),
            query_endpoint: query_endpoint,
            write_endpoint: write_endpoint,
            client: client,
        })
    }

    pub fn add_data<T>(&self, measure: T) -> AddData
        where T: Measurement
    {
        let mut request = client::Request::new(hyper::Method::Post, self.write_endpoint.clone());
        let mut bytes_to_send = String::new();
        measure.to_data(&mut bytes_to_send);
        request.set_body(bytes_to_send.into_bytes());

        let response =
            self.client.request(request)
            .map_err(Error::Hyper)
            .and_then(check_response_code)
            .map(|_| ());

        AddData(Box::new(response))
    }

    pub fn query(&self, query: &str) -> Query {
        let mut query_endpoint = self.query_endpoint.clone();
        query_endpoint.query_pairs_mut()
            .append_pair("db", &self.name)
            .append_pair("q", query);

        let response =
            self.client.get(query_endpoint)
            .map_err(Error::Hyper)
            .and_then(check_response_code)
            .and_then(response_to_json);

        Query(Box::new(response))
    }
}

fn check_response_code(resp: client::Response) -> Box<Future<Item = client::Response, Error = Error>> {
    let f = if resp.status().is_success() {
        Either::A(futures::future::ok(resp))
    } else {
        let e = response_to_json::<InfluxServerError>(resp)
            .and_then(|message| Err(Error::BadRequest(message.error)));
        Either::B(e)
    };

    Box::new(f)
}

fn response_to_json<T>(resp: client::Response) -> Box<Future<Item = T, Error = Error>>
    where T: serde::Deserialize + 'static,
{
    let f =
        resp.body()
        .map_err(Error::Hyper)
        .fold(Vec::new(), |mut acc, chunk| {
            // TODO: Is it the best idea to just build up a big `Vec`?
            // TODO: Is there some way of reusing the vector allocation?
            acc.extend_from_slice(&*chunk);
            futures::future::ok::<_, Error>(acc)
        })
        .and_then(|body| serde_json::from_slice(&body).map_err(Error::Serde));

    Box::new(f)
}

#[must_use = "futures do nothing unless polled"]
pub struct AddData(Box<Future<Item = (), Error = Error>>);

impl Future for AddData {
    type Item = ();
    type Error = Error;

    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        self.0.poll()
    }
}

#[must_use = "futures do nothing unless polled"]
pub struct Query(Box<Future<Item = QueryResponse, Error = Error>>);

impl Future for Query {
    type Item = QueryResponse;
    type Error = Error;

    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        self.0.poll()
    }
}

#[derive(Debug, Deserialize)]
pub struct QueryResponse {
    pub results: Vec<QueryResult>,
}

#[derive(Debug, Deserialize)]
pub struct QueryResult {
    #[serde(default)]
    pub series: Vec<Series>,
    pub error: Option<String>,
    pub statement_id: usize,
}

#[derive(Debug, Deserialize)]
pub struct Series {
    pub name: String,
    pub columns: Vec<String>, // TODO: `time` is always added?
    pub values: Vec<Vec<serde_json::Value>>, // TODO: matches with columns?
    // TODO: Don't expose serde types publically
}

#[derive(Debug, Deserialize)]
pub struct InfluxServerError {
    pub error: String,
}

pub struct AsyncUdpDb {
    handle: Handle,
    my_addr: SocketAddr,
    their_addr: SocketAddr,
}

impl AsyncUdpDb {
    pub fn new(handle: Handle, ip_port: &str) -> Result<Self> {
        Ok(AsyncUdpDb {
            handle: handle,
            my_addr: "0.0.0.0:0".parse()?,
            their_addr: ip_port.parse()?,
        })
    }

    pub fn add_data<T>(&self, measure: T) -> AddDataUdp
        where T: Measurement
    {
        let mut bytes_to_send = String::new();
        measure.to_data(&mut bytes_to_send);

        // TODO: We could consume self like `send_dgram` does, which
        // allows reusing the same socket over and over. The API would
        // be more annoying, but might be like other futures...
        let f = match UdpSocket::bind(&self.my_addr, &self.handle) {
            Ok(socket) => {
                let f = socket.send_dgram(bytes_to_send, self.their_addr)
                    .map(|_| ())
                    .map_err(Error::Udp);
                Either::A(f)
            }
            Err(e) => {
                Either::B(futures::future::err(Error::Udp(e)))
            }
        };

        AddDataUdp(f.boxed())
    }
}

#[must_use = "futures do nothing unless polled"]
pub struct AddDataUdp(BoxFuture<(), Error>);

impl Future for AddDataUdp {
    type Item = ();
    type Error = Error;

    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        self.0.poll()
    }
}
<|endoftext|>


<commit_before>use std::hash::{Hash, Hasher};
use std::mem;
use std::ops::{Add, Mul, Neg, Sub};

/// Like f32, but has the additional restriction that the value is *finite*
/// and never NaN.
/// This makes a Real satisfy Total Equality, whereas normal f32 is only
/// PartialEq due to NaNs.
#[derive(Clone, Copy, Debug)]
#[derive(PartialEq, PartialOrd)]
pub struct Real32 {
	value: f32,
}

impl Real32 {
    pub fn new(value: f32) -> Real32 {
        Real32{ value: value }
    }
    pub fn value(&self) -> f32 {
        self.value
    }

    /// return (sin(self), cos(self))
    pub fn sin_cos(&self) -> (Real32, Real32) {
        let sc = self.value().sin_cos();
        (Real32::new(sc.0), Real32::new(sc.1))
    }
}

impl Eq for Real32 {}

impl Hash for Real32 {
    /// Any values that are equal should have the same hash.
    ///
    /// # Examples:
    ///
    /// ```
    /// use libfriendship::real::Real32;
    /// use std::hash::{Hash, Hasher, SipHasher};
    ///
    /// let mut hash_pos = SipHasher::new();
    /// let mut hash_neg = SipHasher::new();
    /// Real32::new(0.0f32).hash(&mut hash_pos);
    /// Real32::new(-0.0f32).hash(&mut hash_neg);
    /// assert_eq!(hash_pos.finish(), hash_neg.finish());
    /// ```
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        // we need to satisfy hash(x) = hash(y) for any x=y.
        // This includes +0.0 == -0.0,
        // so before hashing the bits, force the number to be non-negative:
        let v = self.value.abs();
        // reinterpret the bytes of our float as a u32 & hash that
        state.write_u32(unsafe {
            mem::transmute(v)
        });
    }
}

// Arithmetic traits

impl Add for Real32 {
    type Output = Real32;

    fn add(self, rhs: Real32) -> Real32 {
        Real32::new(self.value() + rhs.value())
    }
}

// Div cannot be safely applied to Reals, as R / 0 doesn't yield a Real
/*impl Div for Real32 {
    type Output = Real32;

    fn div(self, rhs: Real32) -> Real32 {
        Real32::new(self.value() / rhs.value())
    }
}*/

impl Mul for Real32 {
    type Output = Real32;

    fn mul(self, rhs: Real32) -> Real32 {
        Real32::new(self.value() * rhs.value())
    }
}

impl Neg for Real32 {
    type Output = Real32;

    fn neg(self) -> Real32 {
        Real32::new(-self.value())
    }
}

impl Sub for Real32 {
    type Output = Real32;

    fn sub(self, rhs: Real32) -> Real32 {
        Real32::new(self.value() - rhs.value())
    }
}
<commit_msg>Add tests for Real32::new<commit_after>use std::hash::{Hash, Hasher};
use std::mem;
use std::ops::{Add, Mul, Neg, Sub};

/// Like f32, but has the additional restriction that the value is *finite*
/// and never NaN.
/// This makes a Real satisfy Total Equality, whereas normal f32 is only
/// PartialEq due to NaNs.
#[derive(Clone, Copy, Debug)]
#[derive(PartialEq, PartialOrd)]
pub struct Real32 {
	value: f32,
}

impl Real32 {
    /// It should be possible to create a Real from any finite float.
    ///
    /// # Failure Examples:
    ///
    /// ```should_panic
    /// use libfriendship::real::Real32;
    /// println!("Real32({})", 0.0f32 / 0.0f32);
    /// Real32::new(0.0f32 / 0.0f32);
    /// ```
    ///
    /// ```should_panic
    /// use libfriendship::real::Real32;
    /// println!("Real32({})", 1.0f32 / 0.0f32);
    /// Real32::new(1.0f32 / 0.0f32);
    /// ```
    pub fn new(value: f32) -> Real32 {
        assert!(value.is_finite());
        Real32{ value: value }
    }
    pub fn value(&self) -> f32 {
        self.value
    }

    /// return (sin(self), cos(self))
    pub fn sin_cos(&self) -> (Real32, Real32) {
        let sc = self.value().sin_cos();
        (Real32::new(sc.0), Real32::new(sc.1))
    }
}

impl Eq for Real32 {}

impl Hash for Real32 {
    /// Any values that are equal should have the same hash.
    ///
    /// # Examples:
    ///
    /// ```
    /// use libfriendship::real::Real32;
    /// use std::hash::{Hash, Hasher, SipHasher};
    ///
    /// let mut hash_pos = SipHasher::new();
    /// let mut hash_neg = SipHasher::new();
    /// Real32::new(0.0f32).hash(&mut hash_pos);
    /// Real32::new(-0.0f32).hash(&mut hash_neg);
    /// assert_eq!(hash_pos.finish(), hash_neg.finish());
    /// ```
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        // we need to satisfy hash(x) = hash(y) for any x=y.
        // This includes +0.0 == -0.0,
        // so before hashing the bits, force the number to be non-negative:
        let v = self.value.abs();
        // reinterpret the bytes of our float as a u32 & hash that
        state.write_u32(unsafe {
            mem::transmute(v)
        });
    }
}

// Arithmetic traits

impl Add for Real32 {
    type Output = Real32;

    fn add(self, rhs: Real32) -> Real32 {
        Real32::new(self.value() + rhs.value())
    }
}

// Div cannot be safely applied to Reals, as R / 0 doesn't yield a Real
/*impl Div for Real32 {
    type Output = Real32;

    fn div(self, rhs: Real32) -> Real32 {
        Real32::new(self.value() / rhs.value())
    }
}*/

impl Mul for Real32 {
    type Output = Real32;

    fn mul(self, rhs: Real32) -> Real32 {
        Real32::new(self.value() * rhs.value())
    }
}

impl Neg for Real32 {
    type Output = Real32;

    fn neg(self) -> Real32 {
        Real32::new(-self.value())
    }
}

impl Sub for Real32 {
    type Output = Real32;

    fn sub(self, rhs: Real32) -> Real32 {
        Real32::new(self.value() - rhs.value())
    }
}
<|endoftext|>


<commit_before>#![crate_name="gdal"]
#![crate_type="lib"]

extern crate libc;

pub use version::version_info;

mod utils;
pub mod version;
pub mod raster;
pub mod vector;
pub mod geom;

#[derive(Clone, Copy, PartialEq, Debug)]
pub struct GdalError {
    pub desc: &'static str,
}
<commit_msg>crate docs<commit_after>//! [GDAL](http://gdal.org/) bindings for Rust.
//!
//! A high-level API to access the GDAL library, for vector and raster data.
//!
//! ## Use
//!
//! ```
//! use std::path::Path;
//! use gdal::vector::Dataset;
//!
//! let dataset = Dataset::open(Path::new("fixtures/roads.geojson")).unwrap();
//! let layer = dataset.layer(0).unwrap();
//! for feature in layer.features() {
//!     let highway_field = feature.field("highway").unwrap();
//!     let geometry = feature.geometry();
//!     println!("{} {}", highway_field.as_string(), geometry.wkt());
//! }
//! ```

#![crate_name="gdal"]
#![crate_type="lib"]

extern crate libc;

pub use version::version_info;

mod utils;
pub mod version;
pub mod raster;
pub mod vector;
pub mod geom;

#[derive(Clone, Copy, PartialEq, Debug)]
pub struct GdalError {
    pub desc: &'static str,
}
<|endoftext|>


<commit_before>extern crate nom_lua53;

use nom_lua53::{parse_all, ParseResult, Statement, Exp};
use nom_lua53::op::BinOp;

#[derive(PartialEq,Debug)]
pub enum LuaValue {
    Nil,
    Integer(isize),
    Float(f64),
    Boolean(bool),
    Str(String),
}

#[derive(PartialEq,Eq,Debug)]
pub enum LuaError {
    TypeError(String),
    ArithmeticError(String),
}

use LuaError::*;

type Result<T> = std::result::Result<T, LuaError>;

// What do we say? We say "Merci Basile!"
fn lit_to_string(string: &nom_lua53::string::StringLit) -> String {
    return String::from_utf8_lossy(&(string.0)).to_string();
}

fn eval_arithmetic(left_op: &Box<Exp>, right_op: &Box<Exp>,
                   integer: fn(isize, isize) -> Result<LuaValue>,
                   float: fn(f64, f64) -> Result<LuaValue>) -> Result<LuaValue> {

    let left_op = eval_expr(&left_op)?;
    let right_op = eval_expr(&right_op)?;

    match left_op {
        LuaValue::Integer(i) => match right_op {
            LuaValue::Integer(j) => integer(i, j),
            LuaValue::Float(j) => float(i as f64, j),
            _ => Err(TypeError("Trying to do arithmetic on non-numerical values.".to_owned()))
        },
        LuaValue::Float(i) => match right_op {
            LuaValue::Integer(j) => float(i, j as f64),
            LuaValue::Float(j) => float(i, j),
            _ => Err(TypeError("Trying to do arithmetic on non-numerical values.".to_owned()))
        },
        _ => Err(TypeError("Trying to do arithmetic on non-numerical values.".to_owned()))
    }
}

fn eval_binary_expr(left_op: &Box<Exp>, right_op: &Box<Exp>, operator: &BinOp) -> Result<LuaValue> {
    // We cannot yet evaluate the operands as some binary operators are used to shortcut
    // evaluation.
    match *operator {
        BinOp::Plus => eval_arithmetic(left_op, right_op,
                                       |i, j| Ok(LuaValue::Integer(i+j)),
                                       |i, j| Ok(LuaValue::Float(i+j))),
        BinOp::Minus => eval_arithmetic(left_op, right_op,
                                        |i, j| Ok(LuaValue::Integer(i-j)),
                                        |i, j| Ok(LuaValue::Float(i-j))),
        BinOp::Mul => eval_arithmetic(left_op, right_op,
                                      |i, j| Ok(LuaValue::Integer(i*j)),
                                      |i, j| Ok(LuaValue::Float(i*j))),
        BinOp::Div => eval_arithmetic(left_op, right_op,
                                      |i, j| if j == 0 {
                                          Err(ArithmeticError("Dividing by 0".to_owned()))
                                      } else {
                                          Ok(LuaValue::Float((i as f64)/(j as f64)))
                                      },
                                      |i, j| if j == 0. {
                                          Err(ArithmeticError("Dividing by 0".to_owned()))
                                      } else {
                                          Ok(LuaValue::Float(i/j))
                                      }),
        BinOp::Mod => eval_arithmetic(left_op, right_op,
                                      |i, j| if j == 0 {
                                          Err(ArithmeticError("Dividing by 0".to_owned()))
                                      } else {
                                          Ok(LuaValue::Integer(i % j))
                                      },
                                      |i, j| if j == 0. {
                                          Err(ArithmeticError("Dividing by 0".to_owned()))
                                      } else {
                                          Ok(LuaValue::Float(i - (i/j).floor()*j))
                                      }),
        BinOp::IntDiv => eval_arithmetic(left_op, right_op,
                                         |i, j| if j == 0 {
                                             Err(ArithmeticError("Dividing by 0".to_owned()))
                                         } else {
                                             Ok(LuaValue::Integer(i/j))
                                         },
                                         |i, j| if j == 0. {
                                             Err(ArithmeticError("Dividing by 0".to_owned()))
                                         } else {
                                             Ok(LuaValue::Integer((i/j).floor() as isize))
                                         }),
        BinOp::Pow => eval_arithmetic(left_op, right_op,
                                         |i, j| Ok(LuaValue::Float((i as f64).powf(j as f64))),
                                         |i, j| Ok(LuaValue::Float(i.powf(j)))),
        _ => Ok(LuaValue::Nil)
    }
}

fn eval_expr(expr: &Exp) -> Result<LuaValue> {
    match *expr {
        Exp::Nil => Ok(LuaValue::Nil),
        Exp::Bool(val) => Ok(LuaValue::Boolean(val)),
        Exp::Num(val) => Ok(match val {
            nom_lua53::num::Numeral::Float(fl) => LuaValue::Float(fl),
            nom_lua53::num::Numeral::Int(i) => LuaValue::Integer(i),
        }),
        Exp::BinExp(ref left, ref op, ref right) => eval_binary_expr(left, right, &op),
        Exp::Str(ref s) => Ok(LuaValue::Str(lit_to_string(s))),
        _ => Ok(LuaValue::Nil),
    }
}

pub fn eval_file(input: &[u8]) {
    match parse_all(input) {
        ParseResult::Done(blk) => {
            for stmt in blk.stmts {
                println!("{:?}", stmt);
                match stmt {
                    Statement::LVarAssign(ass) => {
                        let values = ass.vals.expect("There should be some values. Why isn't there any value?!");
                        for (var, val) in ass.vars.iter().zip(values.iter()) {
                            let computed_value = eval_expr(val);
                            println!("Assigning {:?} to {:?}", computed_value, var);
                        }
                    }
                    Statement::Assignment(ass) => {
                        println!("Assigning {:?} to {:?}", ass.vals, ass.vars);
                    }
                    _ => {}
                }
            }
        }

        ParseResult::Error(rest, ss) => {
            println!("Error. statements == {:#?}", ss);
            println!("rest == '{}'", String::from_utf8_lossy(rest));
        }
    }
}

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

    use nom_lua53::{parse_all, ParseResult, Statement, Exp};
    use nom_lua53::num::Numeral;
    use nom_lua53::op::BinOp;

    #[test]
    fn addition_test() {
        // 1. + -1. == 0.
        let res = eval_binary_expr(&Box::new(Exp::Num(Numeral::Float(1.0))), &Box::new(Exp::Num(Numeral::Float(-1.0))), &BinOp::Plus).expect("Panicking!");
        assert_eq!(res, LuaValue::Float(0.));

        // 1 + -1. == 0.
        let res = eval_binary_expr(&Box::new(Exp::Num(Numeral::Int(1))), &Box::new(Exp::Num(Numeral::Float(-1.0))), &BinOp::Plus).expect("Panicking!");
        assert_eq!( res, LuaValue::Float(0.));
        // 1 + 3 == 4
        let res = eval_binary_expr(&Box::new(Exp::Num(Numeral::Int(1))), &Box::new(Exp::Num(Numeral::Int(3))), &BinOp::Plus).expect("Panicking!");
        assert_eq!(res, LuaValue::Integer(4));
    }

    #[test]
    fn test_arithmetic_types() {
        eval_binary_expr(&Box::new(Exp::Num(Numeral::Int(1))), &Box::new(Exp::Num(Numeral::Float(-1.0))), &BinOp::Plus).expect("Type error!");

        eval_binary_expr(&Box::new(Exp::Num(Numeral::Float(1.))), &Box::new(Exp::Num(Numeral::Int(-1))), &BinOp::Plus).expect("Type error!");

        let res = eval_binary_expr(&Box::new(Exp::Bool(true)), &Box::new(Exp::Num(Numeral::Int(-1))), &BinOp::Plus).expect_err("No type error, there should be one!");
        assert!(match res { TypeError(_) => true, _ => false })
    }

    #[test]
    fn substraction_test() {
        // 1. - -1. == 2.
        let res = eval_binary_expr(&Box::new(Exp::Num(Numeral::Float(1.0))), &Box::new(Exp::Num(Numeral::Float(-1.0))), &BinOp::Minus).expect("Panicking!");
        assert_eq!(res, LuaValue::Float(2.));

        // 1 - -1. == 2.
        let res = eval_binary_expr(&Box::new(Exp::Num(Numeral::Int(1))), &Box::new(Exp::Num(Numeral::Float(-1.0))), &BinOp::Minus).expect("Panicking!");
        assert_eq!(res, LuaValue::Float(2.));

        // 1 - 3 == -2
        let res = eval_binary_expr(&Box::new(Exp::Num(Numeral::Int(1))), &Box::new(Exp::Num(Numeral::Int(3))), &BinOp::Minus).expect("Panicking!");
        assert_eq!(res, LuaValue::Integer(-2));
    }

    #[test]
    fn multiplication_test() {
        // 1.5 * 2.5. == 3.75.
        let res = eval_binary_expr(&Box::new(Exp::Num(Numeral::Float(1.5))), &Box::new(Exp::Num(Numeral::Float(2.5))), &BinOp::Mul).expect("Panicking!");
        assert_eq!(res, LuaValue::Float(3.75));

        // -2 * 1.25 == -2.5.
        let res = eval_binary_expr(&Box::new(Exp::Num(Numeral::Int(-2))), &Box::new(Exp::Num(Numeral::Float(1.25))), &BinOp::Mul).expect("Panicking!");
        assert_eq!(res, LuaValue::Float(-2.5));

        // 10 * 3 == 30
        let res = eval_binary_expr(&Box::new(Exp::Num(Numeral::Int(10))), &Box::new(Exp::Num(Numeral::Int(3))), &BinOp::Mul).expect("Panicking!");
        assert_eq!(res, LuaValue::Integer(30));
    }
}
<commit_msg>Unify test naming convention<commit_after>extern crate nom_lua53;

use nom_lua53::{parse_all, ParseResult, Statement, Exp};
use nom_lua53::op::BinOp;

#[derive(PartialEq,Debug)]
pub enum LuaValue {
    Nil,
    Integer(isize),
    Float(f64),
    Boolean(bool),
    Str(String),
}

#[derive(PartialEq,Eq,Debug)]
pub enum LuaError {
    TypeError(String),
    ArithmeticError(String),
}

use LuaError::*;

type Result<T> = std::result::Result<T, LuaError>;

// What do we say? We say "Merci Basile!"
fn lit_to_string(string: &nom_lua53::string::StringLit) -> String {
    return String::from_utf8_lossy(&(string.0)).to_string();
}

fn eval_arithmetic(left_op: &Box<Exp>, right_op: &Box<Exp>,
                   integer: fn(isize, isize) -> Result<LuaValue>,
                   float: fn(f64, f64) -> Result<LuaValue>) -> Result<LuaValue> {

    let left_op = eval_expr(&left_op)?;
    let right_op = eval_expr(&right_op)?;

    match left_op {
        LuaValue::Integer(i) => match right_op {
            LuaValue::Integer(j) => integer(i, j),
            LuaValue::Float(j) => float(i as f64, j),
            _ => Err(TypeError("Trying to do arithmetic on non-numerical values.".to_owned()))
        },
        LuaValue::Float(i) => match right_op {
            LuaValue::Integer(j) => float(i, j as f64),
            LuaValue::Float(j) => float(i, j),
            _ => Err(TypeError("Trying to do arithmetic on non-numerical values.".to_owned()))
        },
        _ => Err(TypeError("Trying to do arithmetic on non-numerical values.".to_owned()))
    }
}

fn eval_binary_expr(left_op: &Box<Exp>, right_op: &Box<Exp>, operator: &BinOp) -> Result<LuaValue> {
    // We cannot yet evaluate the operands as some binary operators are used to shortcut
    // evaluation.
    match *operator {
        BinOp::Plus => eval_arithmetic(left_op, right_op,
                                       |i, j| Ok(LuaValue::Integer(i+j)),
                                       |i, j| Ok(LuaValue::Float(i+j))),
        BinOp::Minus => eval_arithmetic(left_op, right_op,
                                        |i, j| Ok(LuaValue::Integer(i-j)),
                                        |i, j| Ok(LuaValue::Float(i-j))),
        BinOp::Mul => eval_arithmetic(left_op, right_op,
                                      |i, j| Ok(LuaValue::Integer(i*j)),
                                      |i, j| Ok(LuaValue::Float(i*j))),
        BinOp::Div => eval_arithmetic(left_op, right_op,
                                      |i, j| if j == 0 {
                                          Err(ArithmeticError("Dividing by 0".to_owned()))
                                      } else {
                                          Ok(LuaValue::Float((i as f64)/(j as f64)))
                                      },
                                      |i, j| if j == 0. {
                                          Err(ArithmeticError("Dividing by 0".to_owned()))
                                      } else {
                                          Ok(LuaValue::Float(i/j))
                                      }),
        BinOp::Mod => eval_arithmetic(left_op, right_op,
                                      |i, j| if j == 0 {
                                          Err(ArithmeticError("Dividing by 0".to_owned()))
                                      } else {
                                          Ok(LuaValue::Integer(i % j))
                                      },
                                      |i, j| if j == 0. {
                                          Err(ArithmeticError("Dividing by 0".to_owned()))
                                      } else {
                                          Ok(LuaValue::Float(i - (i/j).floor()*j))
                                      }),
        BinOp::IntDiv => eval_arithmetic(left_op, right_op,
                                         |i, j| if j == 0 {
                                             Err(ArithmeticError("Dividing by 0".to_owned()))
                                         } else {
                                             Ok(LuaValue::Integer(i/j))
                                         },
                                         |i, j| if j == 0. {
                                             Err(ArithmeticError("Dividing by 0".to_owned()))
                                         } else {
                                             Ok(LuaValue::Integer((i/j).floor() as isize))
                                         }),
        BinOp::Pow => eval_arithmetic(left_op, right_op,
                                         |i, j| Ok(LuaValue::Float((i as f64).powf(j as f64))),
                                         |i, j| Ok(LuaValue::Float(i.powf(j)))),
        _ => Ok(LuaValue::Nil)
    }
}

fn eval_expr(expr: &Exp) -> Result<LuaValue> {
    match *expr {
        Exp::Nil => Ok(LuaValue::Nil),
        Exp::Bool(val) => Ok(LuaValue::Boolean(val)),
        Exp::Num(val) => Ok(match val {
            nom_lua53::num::Numeral::Float(fl) => LuaValue::Float(fl),
            nom_lua53::num::Numeral::Int(i) => LuaValue::Integer(i),
        }),
        Exp::BinExp(ref left, ref op, ref right) => eval_binary_expr(left, right, &op),
        Exp::Str(ref s) => Ok(LuaValue::Str(lit_to_string(s))),
        _ => Ok(LuaValue::Nil),
    }
}

pub fn eval_file(input: &[u8]) {
    match parse_all(input) {
        ParseResult::Done(blk) => {
            for stmt in blk.stmts {
                println!("{:?}", stmt);
                match stmt {
                    Statement::LVarAssign(ass) => {
                        let values = ass.vals.expect("There should be some values. Why isn't there any value?!");
                        for (var, val) in ass.vars.iter().zip(values.iter()) {
                            let computed_value = eval_expr(val);
                            println!("Assigning {:?} to {:?}", computed_value, var);
                        }
                    }
                    Statement::Assignment(ass) => {
                        println!("Assigning {:?} to {:?}", ass.vals, ass.vars);
                    }
                    _ => {}
                }
            }
        }

        ParseResult::Error(rest, ss) => {
            println!("Error. statements == {:#?}", ss);
            println!("rest == '{}'", String::from_utf8_lossy(rest));
        }
    }
}

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

    use nom_lua53::{parse_all, ParseResult, Statement, Exp};
    use nom_lua53::num::Numeral;
    use nom_lua53::op::BinOp;

    #[test]
    fn test_addition() {
        // 1. + -1. == 0.
        let res = eval_binary_expr(&Box::new(Exp::Num(Numeral::Float(1.0))), &Box::new(Exp::Num(Numeral::Float(-1.0))), &BinOp::Plus).expect("Panicking!");
        assert_eq!(res, LuaValue::Float(0.));

        // 1 + -1. == 0.
        let res = eval_binary_expr(&Box::new(Exp::Num(Numeral::Int(1))), &Box::new(Exp::Num(Numeral::Float(-1.0))), &BinOp::Plus).expect("Panicking!");
        assert_eq!( res, LuaValue::Float(0.));
        // 1 + 3 == 4
        let res = eval_binary_expr(&Box::new(Exp::Num(Numeral::Int(1))), &Box::new(Exp::Num(Numeral::Int(3))), &BinOp::Plus).expect("Panicking!");
        assert_eq!(res, LuaValue::Integer(4));
    }

    #[test]
    fn test_arithmetic_types() {
        eval_binary_expr(&Box::new(Exp::Num(Numeral::Int(1))), &Box::new(Exp::Num(Numeral::Float(-1.0))), &BinOp::Plus).expect("Type error!");

        eval_binary_expr(&Box::new(Exp::Num(Numeral::Float(1.))), &Box::new(Exp::Num(Numeral::Int(-1))), &BinOp::Plus).expect("Type error!");

        let res = eval_binary_expr(&Box::new(Exp::Bool(true)), &Box::new(Exp::Num(Numeral::Int(-1))), &BinOp::Plus).expect_err("No type error, there should be one!");
        assert!(match res { TypeError(_) => true, _ => false })
    }

    #[test]
    fn test_substraction() {
        // 1. - -1. == 2.
        let res = eval_binary_expr(&Box::new(Exp::Num(Numeral::Float(1.0))), &Box::new(Exp::Num(Numeral::Float(-1.0))), &BinOp::Minus).expect("Panicking!");
        assert_eq!(res, LuaValue::Float(2.));

        // 1 - -1. == 2.
        let res = eval_binary_expr(&Box::new(Exp::Num(Numeral::Int(1))), &Box::new(Exp::Num(Numeral::Float(-1.0))), &BinOp::Minus).expect("Panicking!");
        assert_eq!(res, LuaValue::Float(2.));

        // 1 - 3 == -2
        let res = eval_binary_expr(&Box::new(Exp::Num(Numeral::Int(1))), &Box::new(Exp::Num(Numeral::Int(3))), &BinOp::Minus).expect("Panicking!");
        assert_eq!(res, LuaValue::Integer(-2));
    }

    #[test]
    fn test_multiplication() {
        // 1.5 * 2.5. == 3.75.
        let res = eval_binary_expr(&Box::new(Exp::Num(Numeral::Float(1.5))), &Box::new(Exp::Num(Numeral::Float(2.5))), &BinOp::Mul).expect("Panicking!");
        assert_eq!(res, LuaValue::Float(3.75));

        // -2 * 1.25 == -2.5.
        let res = eval_binary_expr(&Box::new(Exp::Num(Numeral::Int(-2))), &Box::new(Exp::Num(Numeral::Float(1.25))), &BinOp::Mul).expect("Panicking!");
        assert_eq!(res, LuaValue::Float(-2.5));

        // 10 * 3 == 30
        let res = eval_binary_expr(&Box::new(Exp::Num(Numeral::Int(10))), &Box::new(Exp::Num(Numeral::Int(3))), &BinOp::Mul).expect("Panicking!");
        assert_eq!(res, LuaValue::Integer(30));
    }
}
<|endoftext|>