<commit_before>//! Low-level bindings for Perl XS API.
//!
//! This can be used to create Perl extensions, and to write programs that embed the perl
//! interpreter.
//!
//! Contents of this crate is automatically generated at build time to match specific Perl version
//! installed in the system. Expect type definitions, constants, available functions and their
//! signatures to change between different perl interpreters.
//!
//! API bindings are organized in layers:
//!
//!  - `fn_bindings` module provides raw prototypes for perl functions;
//!  - `fn_wrappers` module provides wrappers around the API to help with exception handling;
//!  - `Perl` type encapsulates exception handling and optional context pointer present in some
//!    builds of perl.

#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]

use std::mem;
use std::panic;
use std::any::Any;
use std::os::raw::c_int;

include!(concat!(env!("OUT_DIR"), "/perl_sys.rs"));

struct Carrier(c_int);

fn panic_with_code(code: c_int) -> ! {
    panic::resume_unwind(Box::new(Carrier(code)))
}

/// Resume a perl exception.
///
/// This function should be used in pair with `catch_unwind()` for functions that are called by the
/// interpreter (xsubs, opcode checkers and such) to prevent panics from unwinding through the C
/// code.
///
/// If `err` contains a perl exception caught by one of the wrappers, pass control to perl to resume
/// handling of this exception. In this case this function never returns. This interrupts normal
/// control flow expected by the language and prevents destructors for rust values on stack from
/// running.
///
/// If `err` is any other value, it is returned unmodified.
pub unsafe fn try_rethrow(perl: Perl, err: Box<Any>) -> Box<Any> {
    if let Some(&Carrier(code)) = err.downcast_ref() {
        mem::drop(err);
        perl.ouroboros_xcpt_rethrow(code);
        unreachable!();
    }
    err
}

/// Macro to handle the implicit context parameter.
///
/// See [documentation](http://perldoc.perl.org/perlguts.html#Background-and-PERL_IMPLICIT_CONTEXT)
/// for more information about the implicit context. This macro implements equivalent of `pTHX` and
/// `aTHX` macros in C.
///
/// # Defining functions
///
/// First two forms are used to define functions:
///
/// ```ignore
/// pthx! {
///     fn foo(my_perl, arg: IV) -> IV {
///         let my_perl = perl_sys::initialize(my_perl);
///         // ...
///     }
/// }
/// ```
///
/// Under perls without implicit context, `foo` will take one parameter and `my_perl` will have unit
/// type and value (unlike C, the context variable is always present). Under perls with implicit
/// context, `foo` will take two parameters and `my_perl` will be an actual pointer.
///
/// # Calling functions
///
/// Last form of this macro is for calling functions that take implicit context parameter:
///
/// ```ignore
/// pthx!(foo(my_perl, arg));
/// ```
///
/// This simply removes first parameter under perls without implicit context.
#[cfg(perl_multiplicity)]
#[macro_export]
macro_rules! pthx {
    ($( #[$me:meta] )* fn $id:ident ( $ctx:ident $(, $pid:ident : $pty:ty )* ) -> $rty:ty $body:block) => ($( #[$me] )* pub extern "C" fn $id ($ctx: *mut $crate::types::PerlInterpreter $(, $pid : $pty )*) -> $rty $body);
    ($( #[$me:meta] )* fn $id:ident ( $ctx:ident $(, $pid:ident : $pty:ty )* ) $body:block) => ($( #[$me] )* pub extern "C" fn $id ($ctx: *mut $crate::types::PerlInterpreter $(, $pid : $pty )*) $body);

    ($id:ident ( $ctx:expr $(, $p:expr )* $(,)* )) => ($id($ctx $(, $p )*));
}

#[cfg(not(perl_multiplicity))]
#[macro_export]
macro_rules! pthx {
    ($(#[$me:meta])* fn $id:ident ( $ctx:ident $(, $pid:ident : $pty:ty )* ) -> $rty:ty $body:block) => ($(#[$me])* pub extern "C" fn $id ($( $pid : $pty ),*) -> $rty { let $ctx = (); $body });
    ($(#[$me:meta])* fn $id:ident ( $ctx:ident $(, $pid:ident : $pty:ty )* ) $body:block) => ($(#[$me])* pub extern "C" fn $id ($( $pid : $pty ),*) { let $ctx = (); $body });

    ($id:ident ( $ctx:expr $(, $p:expr ),* $(,)* )) => ($id($( $p ),*));
}

#[test]
fn test_svttype() {
    use consts::*;
    /* These relations are documented in perlguts */
    assert!(SVt_PVIV < SVt_PVAV);
    assert!(SVt_PVMG < SVt_PVAV);
}

#[test]
fn test_alignment() {
    use std::mem::align_of;
    assert_eq!(align_of::<*mut u8>(), align_of::<types::OuroborosStack>());
}
<commit_msg>Fix pthx macro<commit_after>//! Low-level bindings for Perl XS API.
//!
//! This can be used to create Perl extensions, and to write programs that embed the perl
//! interpreter.
//!
//! Contents of this crate is automatically generated at build time to match specific Perl version
//! installed in the system. Expect type definitions, constants, available functions and their
//! signatures to change between different perl interpreters.
//!
//! API bindings are organized in layers:
//!
//!  - `fn_bindings` module provides raw prototypes for perl functions;
//!  - `fn_wrappers` module provides wrappers around the API to help with exception handling;
//!  - `Perl` type encapsulates exception handling and optional context pointer present in some
//!    builds of perl.

#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]

use std::mem;
use std::panic;
use std::any::Any;
use std::os::raw::c_int;

include!(concat!(env!("OUT_DIR"), "/perl_sys.rs"));

struct Carrier(c_int);

fn panic_with_code(code: c_int) -> ! {
    panic::resume_unwind(Box::new(Carrier(code)))
}

/// Resume a perl exception.
///
/// This function should be used in pair with `catch_unwind()` for functions that are called by the
/// interpreter (xsubs, opcode checkers and such) to prevent panics from unwinding through the C
/// code.
///
/// If `err` contains a perl exception caught by one of the wrappers, pass control to perl to resume
/// handling of this exception. In this case this function never returns. This interrupts normal
/// control flow expected by the language and prevents destructors for rust values on stack from
/// running.
///
/// If `err` is any other value, it is returned unmodified.
pub unsafe fn try_rethrow(perl: Perl, err: Box<Any>) -> Box<Any> {
    if let Some(&Carrier(code)) = err.downcast_ref() {
        mem::drop(err);
        perl.ouroboros_xcpt_rethrow(code);
        unreachable!();
    }
    err
}

/// Macro to handle the implicit context parameter.
///
/// See [documentation](http://perldoc.perl.org/perlguts.html#Background-and-PERL_IMPLICIT_CONTEXT)
/// for more information about the implicit context. This macro implements equivalent of `pTHX` and
/// `aTHX` macros in C.
///
/// # Defining functions
///
/// First two forms are used to define functions:
///
/// ```ignore
/// pthx! {
///     fn foo(my_perl, arg: IV) -> IV {
///         let my_perl = perl_sys::initialize(my_perl);
///         // ...
///     }
/// }
/// ```
///
/// Under perls without implicit context, `foo` will take one parameter and `my_perl` will have unit
/// type and value (unlike C, the context variable is always present). Under perls with implicit
/// context, `foo` will take two parameters and `my_perl` will be an actual pointer.
///
/// # Calling functions
///
/// Last form of this macro is for calling functions that take implicit context parameter:
///
/// ```ignore
/// pthx!(foo(my_perl, arg));
/// ```
///
/// This simply removes first parameter under perls without implicit context.
#[cfg(perl_multiplicity)]
#[macro_export]
macro_rules! pthx {
    ($( #[$me:meta] )* fn $id:ident ( $ctx:ident $(, $pid:ident : $pty:ty )* ) -> $rty:ty $body:block) => ($( #[$me] )* pub extern "C" fn $id ($ctx: *mut $crate::types::PerlInterpreter $(, $pid : $pty )*) -> $rty $body);
    ($( #[$me:meta] )* fn $id:ident ( $ctx:ident $(, $pid:ident : $pty:ty )* ) $body:block) => ($( #[$me] )* pub extern "C" fn $id ($ctx: *mut $crate::types::PerlInterpreter $(, $pid : $pty )*) $body);

    ($id:ident ( $ctx:expr $(, $p:expr )* $(,)* )) => ($id($ctx $(, $p )*));
}

#[cfg(not(perl_multiplicity))]
#[macro_export]
macro_rules! pthx {
    ($(#[$me:meta])* fn $id:ident ( $ctx:ident $(, $pid:ident : $pty:ty )* ) -> $rty:ty $body:block) => ($(#[$me])* pub extern "C" fn $id ($( $pid : $pty ),*) -> $rty { let $ctx = (); $body });
    ($(#[$me:meta])* fn $id:ident ( $ctx:ident $(, $pid:ident : $pty:ty )* ) $body:block) => ($(#[$me])* pub extern "C" fn $id ($( $pid : $pty ),*) { let $ctx = (); $body });

    ($id:ident ( $ctx:expr $(, $p:expr )* $(,)* )) => ($id($( $p ),*));
}

#[test]
fn test_svttype() {
    use consts::*;
    /* These relations are documented in perlguts */
    assert!(SVt_PVIV < SVt_PVAV);
    assert!(SVt_PVMG < SVt_PVAV);
}

#[test]
fn test_alignment() {
    use std::mem::align_of;
    assert_eq!(align_of::<*mut u8>(), align_of::<types::OuroborosStack>());
}
<|endoftext|>


<commit_before>//! This crate allows one-liners to read from a terminal
//! A minimal example to get an i32 from the command line is
//!
//! ```rust,ignore
//! #[macro_use] extern crate text_io;
//! fn main() {
//!     let i: i32 = read!();
//! }
//! ```
//!
//! The `read!()` macro will always read until the next ascii whitespace character
//! (`\n`, `\r`, `\t` or space).
//!
//! Any type that implements the `FromStr` trait can be read with the `read!` macro.
//!
//! # Advanced
//! Text parsing can be done similar to `println!` by adding a format string
//! to the macro:
//!
//! ```rust,ignore
//! let i: i32 = read!("The answer: {}!");
//! ```
//!
//! This will read `"The answer: "`, then an integer, then an exclamation mark. Any deviation from
//! the format string will result in a panic.
//!
//! Note: only a single value can be read per `read!` invocation.

/// All text input is handled through this macro
#[macro_export]
macro_rules! read(
    () => { read!("{}") };
    ($text:expr) => {{
        let value;
        scan!($text, value);
        value
    }};
    ($text:expr, $input:expr) => {{
        let value;
        scan!($input => $text, value);
        value
    }};
);

/// This macro allows to pass several variables so multiple values can be read
#[macro_export]
macro_rules! scan(
    ($text:expr, $($arg:expr),*) => { scan!(::std::io::stdin().bytes().map(|c| c.unwrap()) => $text, $($arg),*) };
    ($input:expr => $text:expr, $($arg:expr),*) => {{
        use ::std::io::Read;
        use ::std::str::FromStr;
        // typesafe macros :)
        let text: &'static str = $text;
        let stdin: &mut Iterator<Item = u8> = &mut ($input);

        let mut text = text.bytes();
        $(
        loop { match text.next() {
            Some(b'{') => match text.next() {
                Some(b'{') => assert_eq!(Some(b'{'), stdin.next()),
                Some(b'}') => {
                    let s: Vec<u8> = match text.next() {
                        Some(c) => stdin.take_while(|&ch| ch != c).collect(),
                        None => stdin.take_while(|ch| !b"\t\r\n ".contains(ch)).collect(),
                    };
                    let s = match ::std::str::from_utf8(&s) {
                        Ok(s) => s,
                        Err(e) => {
                            let n = e.valid_up_to();
                            if n == 0 {
                                panic!("input was not valid utf8: {:?}", s);
                            } else {
                                panic!("input was only partially valid utf8: \"{}\" followed by {:?}",
                                       ::std::str::from_utf8(&s[..n]).unwrap(), &s[n..]);
                            }
                        }
                    };
                    $arg = FromStr::from_str(s).expect(&format!("could not parse {} as target type of {}", s, stringify!($arg)));
                    break;
                }
                Some(_) => panic!("found bad curly brace"),
                None => panic!("found single open curly brace at the end of the format string"),
            },
            Some(c) => assert_eq!(Some(c), stdin.next()),
            None => panic!("Bad read! format string: did not contain {{}}"),
        } }
        )*
        for c in text {
            assert_eq!(Some(c), stdin.next());
        }
    }};
);
<commit_msg>allow compilation time checks<commit_after>//! This crate allows one-liners to read from a terminal
//! A minimal example to get an i32 from the command line is
//!
//! ```rust,ignore
//! #[macro_use] extern crate text_io;
//! fn main() {
//!     let i: i32 = read!();
//! }
//! ```
//!
//! The `read!()` macro will always read until the next ascii whitespace character
//! (`\n`, `\r`, `\t` or space).
//!
//! Any type that implements the `FromStr` trait can be read with the `read!` macro.
//!
//! # Advanced
//! Text parsing can be done similar to `println!` by adding a format string
//! to the macro:
//!
//! ```rust,ignore
//! let i: i32 = read!("The answer: {}!");
//! ```
//!
//! This will read `"The answer: "`, then an integer, then an exclamation mark. Any deviation from
//! the format string will result in a panic.
//!
//! Note: only a single value can be read per `read!` invocation.

/// All text input is handled through this macro
#[macro_export]
macro_rules! read(
    () => { read!("{}") };
    ($text:expr) => {{
        let value;
        scan!($text, value);
        value
    }};
    ($text:expr, $input:expr) => {{
        let value;
        scan!($input => $text, value);
        value
    }};
);

/// This macro allows to pass several variables so multiple values can be read
#[macro_export]
macro_rules! scan(
    ($text:expr, $($arg:expr),*) => {
        scan!(::std::io::stdin().bytes().map(|c| c.unwrap()) => $text, $($arg),*) ;
        format_args!($text, $($arg),*);
    };
    ($input:expr => $text:expr, $($arg:expr),*) => {{
        use ::std::io::Read;
        use ::std::str::FromStr;
        // typesafe macros :)
        let text: &'static str = $text;
        let stdin: &mut Iterator<Item = u8> = &mut ($input);

        let mut text = text.bytes();
        $(
        loop { match text.next() {
            Some(b'{') => match text.next() {
                Some(b'{') => assert_eq!(Some(b'{'), stdin.next()),
                Some(b'}') => {
                    let s: Vec<u8> = match text.next() {
                        Some(c) => stdin.take_while(|&ch| ch != c).collect(),
                        None => stdin.take_while(|ch| !b"\t\r\n ".contains(ch)).collect(),
                    };
                    let s = match ::std::str::from_utf8(&s) {
                        Ok(s) => s,
                        Err(e) => {
                            let n = e.valid_up_to();
                            if n == 0 {
                                panic!("input was not valid utf8: {:?}", s);
                            } else {
                                panic!("input was only partially valid utf8: \"{}\" followed by {:?}",
                                       ::std::str::from_utf8(&s[..n]).unwrap(), &s[n..]);
                            }
                        }
                    };
                    $arg = FromStr::from_str(s).expect(&format!("could not parse {} as target type of {}", s, stringify!($arg)));
                    break;
                }
                Some(_) => panic!("found bad curly brace"),
                None => panic!("found single open curly brace at the end of the format string"),
            },
            Some(c) => assert_eq!(Some(c), stdin.next()),
            None => panic!("Bad read! format string: did not contain {{}}"),
        } }
        )*
        for c in text {
            assert_eq!(Some(c), stdin.next());
        }
        format_args!($text, $($arg),*);
    }};
);
<|endoftext|>


<commit_before>use std::iter::repeat;

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

    #[test]
    fn zeros_creates_zero_filled_vector_of_correct_size_and_length() {
        let a1 = zeros(vec![0]);
        assert_eq!(a1.dimensions, vec![0]);
        assert_eq!(a1.data, vec![]);

        let a2 = zeros(vec![1]);
        assert_eq!(a2.dimensions, vec![1]);
        assert_eq!(a2.data, vec![0]);

        let a3 = zeros(vec![10]);
        assert_eq!(a3.dimensions, vec![10]);
        assert_eq!(a3.data, vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);

        let a4 = zeros(vec![1, 2, 3]);
        assert_eq!(a4.dimensions, vec![1, 2, 3]);
        assert_eq!(a4.data, vec![0, 0, 0, 0, 0, 0]);
    }

    #[test]
    fn index_test_1() {
        let array1 = QArray {
            dimensions: vec![1, 1, 1],
            data: vec![1],
        };

        assert_eq!(index(&array1, vec![0, 0, 0]), 0);
    }

    #[test]
    fn index_test_2() {
        let array2 = QArray {
            dimensions: vec![2, 2, 1],
            data: vec![1, 2, 3, 4],
        };

        assert_eq!(index(&array2, vec![1, 0, 0]), 1);
        assert_eq!(index(&array2, vec![0, 1, 0]), 2);
    }

    #[test]
    fn index_test_3() {
        let array3 = QArray {
            dimensions: vec![2, 4, 3],
            data: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
                       22, 23, 24],
        };

        assert_eq!(index(&array3, vec![1, 2, 1]), 13);
        assert_eq!(index(&array3, vec![0, 2, 2]), 20);
    }

    #[test]
    fn test_1d_vec_to_qarray() {
        let v = vec![1, 2, 3];
        let array = v.to_qarray();

        assert_eq!(array.dimensions, vec![3]);
        assert_eq!(array.data, vec![1, 2, 3]);
    }

    #[test]
    fn test_2d_vec_to_qarray() {
        let v1 = vec![vec![1, 2], vec![3, 4]];
        let array1 = v1.to_qarray();

        assert_eq!(array1.dimensions, vec![2, 2]);
        assert_eq!(array1.data, vec![1, 2, 3, 4]);

        let v2 = vec![vec![1, 2, 3], vec![4, 5, 6]];
        let array2 = v2.to_qarray();

        assert_eq!(array2.dimensions, vec![2, 3]);
        assert_eq!(array2.data, vec![1, 2, 3, 4, 5, 6]);
    }

    #[test]
    fn test_3d_vec_to_qarray() {
        let v = vec![vec![vec![1, 2], vec![3, 4]], vec![vec![5, 6], vec![7, 8]]];
        let array = v.to_qarray();

        assert_eq!(array.dimensions, vec![2, 2, 2]);
        assert_eq!(array.data, vec![1, 2, 3, 4, 5, 6, 7, 8]);
    }
}

/// Return a new QArray of the given dimensions, filled with zeroes.
///
/// ```
/// use quota::zeros;
/// let qarray = zeros(vec![1, 2, 3]);
/// assert_eq!(qarray.dimensions, vec![1, 2, 3]);
/// assert_eq!(qarray.data, vec![0, 0, 0, 0, 0, 0])
/// ```
pub fn zeros(dimensions: Vec<usize>) -> QArray {
    let data = repeat(0).take(dimensions.iter().sum()).collect::<Vec<isize>>();
    QArray { dimensions, data }
}

#[derive(Debug)]
pub struct QArray {
    pub dimensions: Vec<usize>,
    pub data: Vec<isize>,
}

pub fn index(array: &QArray, coordinates: Vec<usize>) -> usize {
    coordinates
        .into_iter()
        .enumerate()
        .map(|(idx, coord)| {
                 array
                     .dimensions
                     .iter()
                     .take(idx)
                     .fold(coord, |acc, x| acc * x)
             })
        .fold(0, |acc, x| acc + x)
}

trait ToQArray {
    fn to_qarray(&self) -> QArray;
}

impl ToQArray for Vec<isize> {
    fn to_qarray(&self) -> QArray {
        QArray {
            dimensions: vec![self.len()],
            data: self.clone(),
        }
    }
}

impl ToQArray for Vec<Vec<isize>> {
    fn to_qarray(&self) -> QArray {
        let l1 = self.len();
        let l2 = match self.first() {
            Some(fst) => fst.len(),
            None => 0,
        };
        let dimensions = vec![l1, l2];

        let mut data = Vec::new();

        for row in self {
            for e in row {
                data.push(*e);
            }
        }

        QArray { dimensions, data }
    }
}

impl ToQArray for Vec<Vec<Vec<isize>>> {
    fn to_qarray(&self) -> QArray {
        let l1 = self.len();
        let (l2, l3) = match self.first() {
            Some(fst) => match fst.first() {
                Some(ffst) => (fst.len(), ffst.len()),
                None => (fst.len(), 0)
            },
            None => (0, 0)
        };
        let dimensions = vec![l1, l2, l3];

        let mut data = Vec::new();

        for row in self {
            for col in row {
                for e in col {
                    data.push(*e)
                }
            }
        };

        QArray { dimensions, data }
    }
}
<commit_msg>Make `index` return the element at the given coordinates<commit_after>use std::iter::repeat;

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

    #[test]
    fn zeros_creates_zero_filled_vector_of_correct_size_and_length() {
        let a1 = zeros(vec![0]);
        assert_eq!(a1.dimensions, vec![0]);
        assert_eq!(a1.data, vec![]);

        let a2 = zeros(vec![1]);
        assert_eq!(a2.dimensions, vec![1]);
        assert_eq!(a2.data, vec![0]);

        let a3 = zeros(vec![10]);
        assert_eq!(a3.dimensions, vec![10]);
        assert_eq!(a3.data, vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);

        let a4 = zeros(vec![1, 2, 3]);
        assert_eq!(a4.dimensions, vec![1, 2, 3]);
        assert_eq!(a4.data, vec![0, 0, 0, 0, 0, 0]);
    }

    #[test]
    fn index_test_1() {
        let array = QArray {
            dimensions: vec![1, 1, 1],
            data: vec![1],
        };

        assert_eq!(array.index(vec![0, 0, 0].as_slice()), Some(1));
    }

    #[test]
    fn index_test_2() {
        let array = QArray {
            dimensions: vec![2, 2, 1],
            data: vec![1, 2, 3, 4],
        };

        assert_eq!(array.index(vec![1, 0, 0].as_slice()), Some(2));
        assert_eq!(array.index(vec![0, 1, 0].as_slice()), Some(3));
    }

    #[test]
    fn index_test_3() {
        let array = QArray {
            dimensions: vec![2, 4, 3],
            data: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
                       22, 23, 24],
        };

        assert_eq!(array.index(vec![1, 2, 1].as_slice()), Some(14));
        assert_eq!(array.index(vec![0, 2, 2].as_slice()), Some(21));
    }

    #[test]
    fn test_1d_vec_to_qarray() {
        let v = vec![1, 2, 3];
        let array = v.to_qarray();

        assert_eq!(array.dimensions, vec![3]);
        assert_eq!(array.data, vec![1, 2, 3]);
    }

    #[test]
    fn test_2d_vec_to_qarray() {
        let v1 = vec![vec![1, 2], vec![3, 4]];
        let array1 = v1.to_qarray();

        assert_eq!(array1.dimensions, vec![2, 2]);
        assert_eq!(array1.data, vec![1, 2, 3, 4]);

        let v2 = vec![vec![1, 2, 3], vec![4, 5, 6]];
        let array2 = v2.to_qarray();

        assert_eq!(array2.dimensions, vec![2, 3]);
        assert_eq!(array2.data, vec![1, 2, 3, 4, 5, 6]);
    }

    #[test]
    fn test_3d_vec_to_qarray() {
        let v = vec![vec![vec![1, 2], vec![3, 4]], vec![vec![5, 6], vec![7, 8]]];
        let array = v.to_qarray();

        assert_eq!(array.dimensions, vec![2, 2, 2]);
        assert_eq!(array.data, vec![1, 2, 3, 4, 5, 6, 7, 8]);
    }
}

/// Return a new QArray of the given dimensions, filled with zeroes.
///
/// ```
/// use quota::zeros;
/// let qarray = zeros(vec![1, 2, 3]);
/// assert_eq!(qarray.dimensions, vec![1, 2, 3]);
/// assert_eq!(qarray.data, vec![0, 0, 0, 0, 0, 0])
/// ```
pub fn zeros(dimensions: Vec<usize>) -> QArray {
    let data = repeat(0).take(dimensions.iter().sum()).collect::<Vec<isize>>();
    QArray { dimensions, data }
}

#[derive(Debug)]
pub struct QArray {
    pub dimensions: Vec<usize>,
    pub data: Vec<isize>,
}

impl QArray {
    /// Return the element at the given coordinates.
    /// If the coordinates don't specify a single element (e.g. 2D coordinates
    /// are given for a 3D array), or the coordinates are invalid,
    /// this function will return None.
    ///
    /// ```
    /// use quota::*;
    ///
    /// let qarray = zeros(vec![2, 2]);
    /// assert_eq!(qarray.index(vec![0, 0].as_slice()), Some(0));
    /// assert_eq!(qarray.index(vec![1, 1].as_slice()), Some(0));
    /// assert_eq!(qarray.index(vec![3, 3].as_slice()), None);
    /// assert_eq!(qarray.index(vec![1].as_slice()), None);
    /// ```
    pub fn index(&self, coordinates: &[usize]) -> Option<isize> {
        // Check that the coordinates are valid
        // The number of coordinates should match the dimensions of the array.
        // Each coordinate should be less than the length of the array
        // in that dimension.
        if coordinates.len() != self.dimensions.len() { return None }
        for (coord, dim) in coordinates.iter().zip(self.dimensions.as_slice()) {
            if *coord >= *dim { return None }
        }

        return Some(self.data[offset(self, coordinates)])
    }
}

fn offset(array: &QArray, coordinates: &[usize]) -> usize {
    coordinates
        .into_iter()
        .enumerate()
        .map(|(idx, coord)| {
                 array
                     .dimensions
                     .iter()
                     .take(idx)
                     .fold(*coord, |acc, x| acc * x)
             })
        .fold(0, |acc, x| acc + x)
}

trait ToQArray {
    fn to_qarray(&self) -> QArray;
}

impl ToQArray for Vec<isize> {
    fn to_qarray(&self) -> QArray {
        QArray {
            dimensions: vec![self.len()],
            data: self.clone(),
        }
    }
}

impl ToQArray for Vec<Vec<isize>> {
    fn to_qarray(&self) -> QArray {
        let l1 = self.len();
        let l2 = match self.first() {
            Some(fst) => fst.len(),
            None => 0,
        };
        let dimensions = vec![l1, l2];

        let mut data = Vec::new();

        for row in self {
            for e in row {
                data.push(*e);
            }
        }

        QArray { dimensions, data }
    }
}

impl ToQArray for Vec<Vec<Vec<isize>>> {
    fn to_qarray(&self) -> QArray {
        let l1 = self.len();
        let (l2, l3) = match self.first() {
            Some(fst) => match fst.first() {
                Some(ffst) => (fst.len(), ffst.len()),
                None => (fst.len(), 0)
            },
            None => (0, 0)
        };
        let dimensions = vec![l1, l2, l3];

        let mut data = Vec::new();

        for row in self {
            for col in row {
                for e in col {
                    data.push(*e)
                }
            }
        };

        QArray { dimensions, data }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Keegan McAllister.
// Copyright 2016 Corey Farwell.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// See `LICENSE` in this repository.

use std::io::{self, Read};
use std::{panic, process};

/// Utility that reads a `Vec` of bytes from standard input (stdin)
/// and passes it to `closure`. All panics that occur within
/// `closure` will be treated as aborts. This is done so that
/// AFL considers a panic to be a crash.
///
/// # Examples
///
/// ```no_run
/// extern crate afl;
/// # struct Image;
/// # impl Image {
/// #     fn parse(_: &[u8]) {}
/// # }
///
/// fn main() {
///     afl::read_stdio_bytes(|read| {
///         Image::parse(&read)
///     })
/// }
/// ```
pub fn read_stdio_bytes<F>(closure: F)
where
    F: Fn(Vec<u8>) + panic::RefUnwindSafe,
{
    let mut input = vec![];
    let result = io::stdin().read_to_end(&mut input);
    if result.is_err() {
        return;
    }
    let was_panic = panic::catch_unwind(|| {
        closure(input);
    });
    if was_panic.is_err() {
        process::abort();
    }
}

/// Utility that reads a `String` from standard input (stdin) and
/// passes it to `closure`. If a `String` cannot be constructed from
/// the data provided by standard input, `closure` will _not_ be
/// called. All panics that occur within `closure` will be treated as
/// aborts. This is done so that AFL considers a panic to be a crash.
///
/// # Examples
///
/// ```no_run
/// extern crate afl;
/// # struct Url;
/// # impl Url {
/// #     fn parse(_: &str) {}
/// # }
///
/// fn main() {
///     afl::read_stdio_string(|string| {
///         Url::parse(&string)
///     })
/// }
/// ```
pub fn read_stdio_string<F>(closure: F)
where
    F: Fn(String) + panic::RefUnwindSafe,
{
    let mut input = String::new();
    let result = io::stdin().read_to_string(&mut input);
    if result.is_err() {
        return;
    }
    let was_panic = panic::catch_unwind(|| {
        closure(input);
    });
    if was_panic.is_err() {
        process::abort();
    }
}

// those functions are provided by the afl-llvm-rt static library
extern "C" {
    fn __afl_persistent_loop(counter: usize) -> isize;
    fn __afl_manual_init();
}

pub fn fuzz<F>(closure: F) where F: Fn(&[u8]) + std::panic::RefUnwindSafe {
    // this marker strings needs to be in the produced executable for
    // afl-fuzz to detect `persistent mode` and `defered mode`
    static PERSIST_MARKER: &'static str = "##SIG_AFL_PERSISTENT##\0";
    static DEFERED_MARKER: &'static str = "##SIG_AFL_DEFER_FORKSRV##\0";

    // we now need a fake instruction to prevent the compiler from optimizing out
    // those marker strings
    unsafe{std::ptr::read_volatile(&PERSIST_MARKER)}; // hack used in https://github.com/bluss/bencher for black_box()
    unsafe{std::ptr::read_volatile(&DEFERED_MARKER)};
    // unsafe { asm!("" : : "r"(&PERSIST_MARKER)) }; // hack used in nightly's back_box(), requires feature asm
    // unsafe { asm!("" : : "r"(&DEFERED_MARKER)) };

    // sets panic hook to abort
    std::panic::set_hook(Box::new(|_| {
        std::process::abort();
    }));

    let mut input = vec![];

    // initialize forkserver there
    unsafe{__afl_manual_init()};

    while unsafe{__afl_persistent_loop(1000)} != 0 {
        // get buffer from AFL through stdin
        let result = io::stdin().read_to_end(&mut input);
        if result.is_err() {
            return;
        }

        // We still catch unwinding panics just in case the fuzzed code modifies
        // the panic hook.
        // If so, the fuzzer will be unable to tell different bugs appart and you will
        // only be able to find one bug at a time before fixing it to then find a new one.
        let did_panic = std::panic::catch_unwind(|| {
            closure(&input);
        }).is_err();

        if did_panic {
            // hopefully the custom panic hook will be called before and abort the
            // process before the stack frames are unwinded.
            std::process::abort();
        }
        input.clear();
    }
}

#[cfg(test)]
mod test {
    /*
    use std::path::PathBuf;
    use std::process::{Command, Stdio};
    use std::thread;
    use std::time;

    extern crate libc;
    extern crate tempdir;

    fn target_path() -> PathBuf {
        if PathBuf::from("../target/debug/cargo-afl-fuzz").exists() {
            PathBuf::from("../target/debug/")
        } else if PathBuf::from("target/debug/cargo-afl-fuzz").exists() {
            PathBuf::from("target/debug/")
        } else {
            panic!("Could not find cargo-afl-fuzz!");
        }
    }

    #[test]
    fn test_cargo_afl_fuzz() {
        let temp_dir = tempdir::TempDir::new("aflrs").expect("Could not create temporary directory");
        let temp_dir_path = temp_dir.path();
        let mut child = Command::new(target_path().join("cargo-afl-fuzz"))
            .stdout(Stdio::inherit())
            .stderr(Stdio::inherit())
            .arg("-i")
            .arg(".")
            .arg("-o")
            .arg(temp_dir_path)
            .arg(target_path().join("examples").join("hello"))
            .spawn()
            .expect("Could not run cargo-afl-fuzz");
        thread::sleep(time::Duration::from_secs(7));
        child.kill().unwrap();
        assert!(temp_dir_path.join("fuzzer_stats").is_file());
    }
    */
}
<commit_msg>Document fuzz function<commit_after>// Copyright 2015 Keegan McAllister.
// Copyright 2016 Corey Farwell.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// See `LICENSE` in this repository.

use std::io::{self, Read};
use std::{panic, process};

/// Utility that reads a `Vec` of bytes from standard input (stdin)
/// and passes it to `closure`. All panics that occur within
/// `closure` will be treated as aborts. This is done so that
/// AFL considers a panic to be a crash.
///
/// # Examples
///
/// ```no_run
/// extern crate afl;
/// # struct Image;
/// # impl Image {
/// #     fn parse(_: &[u8]) {}
/// # }
///
/// fn main() {
///     afl::read_stdio_bytes(|read| {
///         Image::parse(&read)
///     })
/// }
/// ```
pub fn read_stdio_bytes<F>(closure: F)
where
    F: Fn(Vec<u8>) + panic::RefUnwindSafe,
{
    let mut input = vec![];
    let result = io::stdin().read_to_end(&mut input);
    if result.is_err() {
        return;
    }
    let was_panic = panic::catch_unwind(|| {
        closure(input);
    });
    if was_panic.is_err() {
        process::abort();
    }
}

/// Utility that reads a `String` from standard input (stdin) and
/// passes it to `closure`. If a `String` cannot be constructed from
/// the data provided by standard input, `closure` will _not_ be
/// called. All panics that occur within `closure` will be treated as
/// aborts. This is done so that AFL considers a panic to be a crash.
///
/// # Examples
///
/// ```no_run
/// extern crate afl;
/// # struct Url;
/// # impl Url {
/// #     fn parse(_: &str) {}
/// # }
///
/// fn main() {
///     afl::read_stdio_string(|string| {
///         Url::parse(&string)
///     })
/// }
/// ```
pub fn read_stdio_string<F>(closure: F)
where
    F: Fn(String) + panic::RefUnwindSafe,
{
    let mut input = String::new();
    let result = io::stdin().read_to_string(&mut input);
    if result.is_err() {
        return;
    }
    let was_panic = panic::catch_unwind(|| {
        closure(input);
    });
    if was_panic.is_err() {
        process::abort();
    }
}

// those functions are provided by the afl-llvm-rt static library
extern "C" {
    fn __afl_persistent_loop(counter: usize) -> isize;
    fn __afl_manual_init();
}

/// Fuzz a closure by passing it a `&[u8]`
///
/// This slice contains a "random" quantity of "random" data.
///
/// ```rust,should_panic
/// # extern crate afl;
/// # use afl::fuzz;
/// # fn main() {
/// fuzz(|data|{
///     if data.len() != 6 {return}
///     if data[0] != b'q' {return}
///     if data[1] != b'w' {return}
///     if data[2] != b'e' {return}
///     if data[3] != b'r' {return}
///     if data[4] != b't' {return}
///     if data[5] != b'y' {return}
///     panic!("BOOM")
/// });
/// # }
/// ```
pub fn fuzz<F>(closure: F) where F: Fn(&[u8]) + std::panic::RefUnwindSafe {
    // this marker strings needs to be in the produced executable for
    // afl-fuzz to detect `persistent mode` and `defered mode`
    static PERSIST_MARKER: &'static str = "##SIG_AFL_PERSISTENT##\0";
    static DEFERED_MARKER: &'static str = "##SIG_AFL_DEFER_FORKSRV##\0";

    // we now need a fake instruction to prevent the compiler from optimizing out
    // those marker strings
    unsafe{std::ptr::read_volatile(&PERSIST_MARKER)}; // hack used in https://github.com/bluss/bencher for black_box()
    unsafe{std::ptr::read_volatile(&DEFERED_MARKER)};
    // unsafe { asm!("" : : "r"(&PERSIST_MARKER)) }; // hack used in nightly's back_box(), requires feature asm
    // unsafe { asm!("" : : "r"(&DEFERED_MARKER)) };

    // sets panic hook to abort
    std::panic::set_hook(Box::new(|_| {
        std::process::abort();
    }));

    let mut input = vec![];

    // initialize forkserver there
    unsafe{__afl_manual_init()};

    while unsafe{__afl_persistent_loop(1000)} != 0 {
        // get buffer from AFL through stdin
        let result = io::stdin().read_to_end(&mut input);
        if result.is_err() {
            return;
        }

        // We still catch unwinding panics just in case the fuzzed code modifies
        // the panic hook.
        // If so, the fuzzer will be unable to tell different bugs appart and you will
        // only be able to find one bug at a time before fixing it to then find a new one.
        let did_panic = std::panic::catch_unwind(|| {
            closure(&input);
        }).is_err();

        if did_panic {
            // hopefully the custom panic hook will be called before and abort the
            // process before the stack frames are unwinded.
            std::process::abort();
        }
        input.clear();
    }
}

#[cfg(test)]
mod test {
    /*
    use std::path::PathBuf;
    use std::process::{Command, Stdio};
    use std::thread;
    use std::time;

    extern crate libc;
    extern crate tempdir;

    fn target_path() -> PathBuf {
        if PathBuf::from("../target/debug/cargo-afl-fuzz").exists() {
            PathBuf::from("../target/debug/")
        } else if PathBuf::from("target/debug/cargo-afl-fuzz").exists() {
            PathBuf::from("target/debug/")
        } else {
            panic!("Could not find cargo-afl-fuzz!");
        }
    }

    #[test]
    fn test_cargo_afl_fuzz() {
        let temp_dir = tempdir::TempDir::new("aflrs").expect("Could not create temporary directory");
        let temp_dir_path = temp_dir.path();
        let mut child = Command::new(target_path().join("cargo-afl-fuzz"))
            .stdout(Stdio::inherit())
            .stderr(Stdio::inherit())
            .arg("-i")
            .arg(".")
            .arg("-o")
            .arg(temp_dir_path)
            .arg(target_path().join("examples").join("hello"))
            .spawn()
            .expect("Could not run cargo-afl-fuzz");
        thread::sleep(time::Duration::from_secs(7));
        child.kill().unwrap();
        assert!(temp_dir_path.join("fuzzer_stats").is_file());
    }
    */
}
<|endoftext|>


<commit_before>#![crate_id = "graphics"]
#![deny(missing_doc)]

//! A library for 2D graphics that works with multiple back-ends.
//!
//! To implement your own back-end, use the BackEnd trait.
//!
//! ## Usage
//!
//! To draw to the back-end, you need a context.
//! The context contains the information necessary to perform the drawing.
//! Unlike other graphics libraries, this library is not bound to the back-end.
//! You do not have to specify which back-end to use before doing the actual drawing.
//!
//! For example, assuming we have a back-end called `back_end`:
//!
//! ```
//! Context::new().rect(x, y, w, h).rgba(r, g, b, a).fill(&mut back_end);
//! ```
//!
//! ## Important!
//!
//! Because the context is built using borrowed pointers,
//! it is not possible to do two or more steps at a time and assign it to a variable:
//!
//! ```
//! // ERROR: Borrowed value does not live long enough
//! let rect = Context::new().rect(x, y, w, h);
//! ```
//!
//! This is because the lifetime of the first step only lives inside the expression.
//! To solve this problem, break the statement into two parts, one for each step:
//!
//! ```
//! let c = Context::new();
//! let rect = c.rect(x, y, w, h);
//! ```
//!
//! This is only the case when you are assigning the context to a variable.

extern crate std;

pub use AddColor = add_color::AddColor;
pub use AddEllipse = add_ellipse::AddEllipse;
pub use AddImage = add_image::AddImage;
pub use AddPolygon = add_polygon::AddPolygon;
pub use AddPolygons = add_polygons::AddPolygons;
pub use AddRectangle = add_rectangle::AddRectangle;
pub use AddRound = add_round::AddRound;
pub use AddRoundBorder = add_round_border::AddRoundBorder;
pub use AddTween = add_tween::AddTween;
pub use BackEnd = back_end::BackEnd;
pub use Clear = clear::Clear;
pub use ColorContext = color_context::ColorContext;
pub use Context = context::Context;
pub use Draw = draw::Draw;
pub use EllipseContext = ellipse_context::EllipseContext;
pub use EllipseColorContext = ellipse_color_context::EllipseColorContext;
pub use Fill = fill::Fill;
pub use ImageRectangleContext = image_rectangle_context::ImageRectangleContext;
pub use ImageRectangleColorContext = image_rectangle_color_context::ImageRectangleColorContext;
pub use LineContext = line_context::LineContext;
pub use LineColorContext = line_color_context::LineColorContext;
pub use PolygonContext = polygon_context::PolygonContext;
pub use PolygonColorContext = polygon_color_context::PolygonColorContext;
pub use RectangleContext = rectangle_context::RectangleContext;
pub use RectangleColorContext = rectangle_color_context::RectangleColorContext;
pub use RelativeColor = relative_color::RelativeColor;
pub use RelativeRectangle = relative_rectangle::RelativeRectangle;
pub use RelativeTransform2d = relative_transform2d::RelativeTransform2d;
pub use RoundBorderLineContext = round_border_line_context::RoundBorderLineContext;
pub use RoundBorderLineColorContext = round_border_line_color_context::RoundBorderLineColorContext;
pub use RoundRectangleContext = round_rectangle_context::RoundRectangleContext;
pub use RoundRectangleColorContext = round_rectangle_color_context::RoundRectangleColorContext;
pub use TweenContext = tween_context::TweenContext;
pub use TweenColorContext = tween_color_context::TweenColorContext;
pub use TweenPolygonsContext = tween_polygons_context::TweenPolygonsContext;
pub use TweenPolygonsColorContext = tween_polygons_color_context::TweenPolygonsColorContext;
pub use View = view::View;

mod internal;
mod context;
mod back_end;
mod relative_transform2d;
mod add_color;
mod add_ellipse;
mod add_image;
mod add_polygon;
mod add_polygons;
mod add_rectangle;
mod add_round;
mod add_round_border;
mod add_tween;
mod relative_color;
mod relative_rectangle;
mod draw;
mod fill;
mod clear;
mod color_context;
mod ellipse_context;
mod ellipse_color_context;
mod image_rectangle_context;
mod image_rectangle_color_context;
mod line_context;
mod line_color_context;
mod polygon_context;
mod polygon_color_context;
mod rectangle_context;
mod rectangle_color_context;
mod round_border_line_context;
mod round_border_line_color_context;
mod round_rectangle_context;
mod round_rectangle_color_context;
mod tween_context;
mod tween_color_context;
mod tween_polygons_context;
mod tween_polygons_color_context;
mod view;
pub mod vecmath;
pub mod triangulation;
pub mod interpolation;
pub mod modular_index;

/// [red, green, blue, alpha]
pub type Color = [f32, ..4];

/// [x1, y1, x2, y2]
pub type Line = [f64, ..4];

/// [x, y, dir_x, dir_y]
pub type Ray = [f64, ..4];

/// [radius, width]
pub type RoundBorder = [f64, ..2];

/// [m00, m01, m02, m10, m11, m12]
///
/// The first 3 numbers transforms `x`,
/// the last 3 numbers transforms `y`:
///
/// ```
/// tx = m00 * x + m01 * y + m02;
/// ty = m10 * x + m11 * y + m12;
/// ```
pub type Matrix2d = [f64, ..6];

/// [x, y, w, h]
pub type PixelRectangle = [u32, ..4];

/// [x, y, w, h]
pub type Rectangle = [f64, ..4];

/// [x1, y1, x2, y2, x3, y3]
pub type Triangle = [f64, ..6];

/// [x, y]
pub type Vec2d = [f64, ..2];

/// A structure that might contain a value or a borrowed value.
/// This is to used as building block to create data structure
/// that is partially based on an existing structure.
pub enum Field<'a, T> {
    /// Contains a value.
    Value(T),
    /// Contains a borrowed pointer.
    Borrowed(&'a T),
}

impl<'a, T> Field<'a, T> {
    /// Gets a read only value.
    #[inline(always)]
    pub fn get(&'a self) -> &'a T {
        match *self {
            Value(ref val) => val,
            Borrowed(rval) => rval,
        }
    }
}

/// Represents an image.
///
/// Images are often packed together in sprite sheets.
/// For this reason it refers to a rectangle within a texture.
///
/// The texture is a unique identifier recognized by the back-end.
/// An image contains the size of a texture to be able to
/// compute normalized coordinates.
///
/// There is no garbage collection of textures,
/// this responsibility is given to the back-end.
pub struct Image {
    /// A unique identifier of the texture, recognizable by back-end.
    pub texture_id: uint,
    /// The pixel width of the texture.
    pub texture_width: u32,
    /// The pixel height of the texture.
    pub texture_height: u32,
    /// The source rectangle in the texture.
    pub source_rect: PixelRectangle,
}

<commit_msg>Arranged `mod` alphabetically<commit_after>#![crate_id = "graphics"]
#![deny(missing_doc)]

//! A library for 2D graphics that works with multiple back-ends.
//!
//! To implement your own back-end, use the BackEnd trait.
//!
//! ## Usage
//!
//! To draw to the back-end, you need a context.
//! The context contains the information necessary to perform the drawing.
//! Unlike other graphics libraries, this library is not bound to the back-end.
//! You do not have to specify which back-end to use before doing the actual drawing.
//!
//! For example, assuming we have a back-end called `back_end`:
//!
//! ```
//! Context::new().rect(x, y, w, h).rgba(r, g, b, a).fill(&mut back_end);
//! ```
//!
//! ## Important!
//!
//! Because the context is built using borrowed pointers,
//! it is not possible to do two or more steps at a time and assign it to a variable:
//!
//! ```
//! // ERROR: Borrowed value does not live long enough
//! let rect = Context::new().rect(x, y, w, h);
//! ```
//!
//! This is because the lifetime of the first step only lives inside the expression.
//! To solve this problem, break the statement into two parts, one for each step:
//!
//! ```
//! let c = Context::new();
//! let rect = c.rect(x, y, w, h);
//! ```
//!
//! This is only the case when you are assigning the context to a variable.

extern crate std;

pub use AddColor = add_color::AddColor;
pub use AddEllipse = add_ellipse::AddEllipse;
pub use AddImage = add_image::AddImage;
pub use AddPolygon = add_polygon::AddPolygon;
pub use AddPolygons = add_polygons::AddPolygons;
pub use AddRectangle = add_rectangle::AddRectangle;
pub use AddRound = add_round::AddRound;
pub use AddRoundBorder = add_round_border::AddRoundBorder;
pub use AddTween = add_tween::AddTween;
pub use BackEnd = back_end::BackEnd;
pub use Clear = clear::Clear;
pub use ColorContext = color_context::ColorContext;
pub use Context = context::Context;
pub use Draw = draw::Draw;
pub use EllipseContext = ellipse_context::EllipseContext;
pub use EllipseColorContext = ellipse_color_context::EllipseColorContext;
pub use Fill = fill::Fill;
pub use ImageRectangleContext = image_rectangle_context::ImageRectangleContext;
pub use ImageRectangleColorContext = image_rectangle_color_context::ImageRectangleColorContext;
pub use LineContext = line_context::LineContext;
pub use LineColorContext = line_color_context::LineColorContext;
pub use PolygonContext = polygon_context::PolygonContext;
pub use PolygonColorContext = polygon_color_context::PolygonColorContext;
pub use RectangleContext = rectangle_context::RectangleContext;
pub use RectangleColorContext = rectangle_color_context::RectangleColorContext;
pub use RelativeColor = relative_color::RelativeColor;
pub use RelativeRectangle = relative_rectangle::RelativeRectangle;
pub use RelativeTransform2d = relative_transform2d::RelativeTransform2d;
pub use RoundBorderLineContext = round_border_line_context::RoundBorderLineContext;
pub use RoundBorderLineColorContext = round_border_line_color_context::RoundBorderLineColorContext;
pub use RoundRectangleContext = round_rectangle_context::RoundRectangleContext;
pub use RoundRectangleColorContext = round_rectangle_color_context::RoundRectangleColorContext;
pub use TweenContext = tween_context::TweenContext;
pub use TweenColorContext = tween_color_context::TweenColorContext;
pub use TweenPolygonsContext = tween_polygons_context::TweenPolygonsContext;
pub use TweenPolygonsColorContext = tween_polygons_color_context::TweenPolygonsColorContext;
pub use View = view::View;

mod add_color;
mod add_ellipse;
mod add_image;
mod add_polygon;
mod add_polygons;
mod add_rectangle;
mod add_round;
mod add_round_border;
mod add_tween;
mod back_end;
mod clear;
mod color_context;
mod context;
mod draw;
mod ellipse_color_context;
mod ellipse_context;
mod fill;
mod image_rectangle_color_context;
mod image_rectangle_context;
mod internal;
mod line_color_context;
mod line_context;
mod polygon_color_context;
mod polygon_context;
mod rectangle_color_context;
mod rectangle_context;
mod relative_color;
mod relative_rectangle;
mod relative_transform2d;
mod round_border_line_color_context;
mod round_border_line_context;
mod round_rectangle_color_context;
mod round_rectangle_context;
mod tween_color_context;
mod tween_context;
mod tween_polygons_color_context;
mod tween_polygons_context;
mod view;

pub mod interpolation;
pub mod modular_index;
pub mod triangulation;
pub mod vecmath;

/// [red, green, blue, alpha]
pub type Color = [f32, ..4];

/// [x1, y1, x2, y2]
pub type Line = [f64, ..4];

/// [x, y, dir_x, dir_y]
pub type Ray = [f64, ..4];

/// [radius, width]
pub type RoundBorder = [f64, ..2];

/// [m00, m01, m02, m10, m11, m12]
///
/// The first 3 numbers transforms `x`,
/// the last 3 numbers transforms `y`:
///
/// ```
/// tx = m00 * x + m01 * y + m02;
/// ty = m10 * x + m11 * y + m12;
/// ```
pub type Matrix2d = [f64, ..6];

/// [x, y, w, h]
pub type PixelRectangle = [u32, ..4];

/// [x, y, w, h]
pub type Rectangle = [f64, ..4];

/// [x1, y1, x2, y2, x3, y3]
pub type Triangle = [f64, ..6];

/// [x, y]
pub type Vec2d = [f64, ..2];

/// A structure that might contain a value or a borrowed value.
/// This is to used as building block to create data structure
/// that is partially based on an existing structure.
pub enum Field<'a, T> {
    /// Contains a value.
    Value(T),
    /// Contains a borrowed pointer.
    Borrowed(&'a T),
}

impl<'a, T> Field<'a, T> {
    /// Gets a read only value.
    #[inline(always)]
    pub fn get(&'a self) -> &'a T {
        match *self {
            Value(ref val) => val,
            Borrowed(rval) => rval,
        }
    }
}

/// Represents an image.
///
/// Images are often packed together in sprite sheets.
/// For this reason it refers to a rectangle within a texture.
///
/// The texture is a unique identifier recognized by the back-end.
/// An image contains the size of a texture to be able to
/// compute normalized coordinates.
///
/// There is no garbage collection of textures,
/// this responsibility is given to the back-end.
pub struct Image {
    /// A unique identifier of the texture, recognizable by back-end.
    pub texture_id: uint,
    /// The pixel width of the texture.
    pub texture_width: u32,
    /// The pixel height of the texture.
    pub texture_height: u32,
    /// The source rectangle in the texture.
    pub source_rect: PixelRectangle,
}

<|endoftext|>


<commit_before>//! A library for using the Monzo API
//!
//! This library wraps over the Monzo API in a future aware manner.
//!
//! Example usage:
//!
//! ```rust,no_run
//! extern crate monzo;
//! extern crate tokio_core;
//!
//! let mut core = tokio_core::reactor::Core::new().unwrap();
//! let monzo = monzo::Client::new(&core.handle(), "<access_token>");
//! let work = monzo.balance("<account_id>".into());
//! let response = core.run(work).unwrap();
//! println!("Balance: {} {}", response.balance, response.currency);
//! println!("Spent today: {}", response.spend_today);
//! ```

#![crate_name = "monzo"]
#![deny(missing_docs,
        missing_debug_implementations,
        missing_copy_implementations,
        trivial_casts,
        trivial_numeric_casts,
        unsafe_code,
        unused_extern_crates,
        unused_import_braces,
        unused_qualifications)]

#[macro_use]
extern crate error_chain;
extern crate futures;
extern crate hyper;
extern crate hyper_tls;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate tokio_core;
extern crate url;

use futures::{Future, Stream};
use hyper::{Body, Method, Request, Uri, Chunk, StatusCode};
use hyper::header::{Authorization, Bearer};
use std::collections::HashMap;
use std::string::String;
use tokio_core::reactor::Handle;
use url::Url;

/// Identifier for an account.
pub type AccountId = String;
/// Identifier for a transaction.
pub type TransactionId = String;
/// Identifier of a merchant.
pub type MerchantId = String;
/// Holds an ISO 4217 currency code.
pub type Currency = String;

/// Accounts represent a store of funds, and have a list of transactions.
#[derive(Debug, Deserialize)]
pub struct Account {
    /// The account id.
    pub id: AccountId,
    /// Description of the account.
    pub description: String,
    /// The timestamp in UTC when the account was created.
    // TODO: Change to date type?
    pub created: String,
}

/// Response to the list accounts future.
#[derive(Debug, Deserialize)]
pub struct Accounts {
    /// List of accounts owned by the currenty authorized user.
    pub accounts: Vec<Account>,
}

/// Response to the balance future if successful.
#[derive(Debug, Deserialize)]
pub struct Balance {
    /// The currently available balance of the account, as a 64bit integer in minor units of the
    /// currency, eg. pennies for GBP, or cents for EUR and USD.
    pub balance: i64,
    /// The ISO 4217 currency code.
    pub currency: Currency,
    /// The amount spent from this account today (considered from approx 4am onwards), in minor
    /// units of the currency.
    pub spend_today: i64,
}

/// Describes a transaction.
#[derive(Debug, Deserialize)]
pub struct Transaction {
    /// Balance in the account after the transaction.
    pub account_balance: i64,
    /// The amount of the transaction in minor units of currency. For example pennies in the case
    /// of GBP. A negative amount indicates a debit (most card transactions will have a negative
    /// amount).
    pub amount: i64,
    /// The timestamp in UTC when the transaction was created.
    // TODO: Change to date type?
    pub created: String,
    /// The ISO 4217 currency code.
    pub currency: Currency,
    /// Description of the transaction.
    pub description: String,
    /// The transaction id.
    pub id: TransactionId,
    /// This contains the merchant_id of the merchant that this transaction was made at.
    pub merchant: Option<MerchantId>,
    /// Key-value annotations made for transaction. Metadata is private to your application.
    pub metadata: HashMap<String, String>,
    /// Notes attached to the transaction.
    pub notes: String,
    /// Top-ups to an account are represented as transactions with a positive amount and
    /// is_load = true. Other transactions such as refunds, reversals or chargebacks may have a
    /// positive amount but is_load = false
    pub is_load: bool,
    /// The timestamp in UTC at which the transaction settled. In most cases, this happens 24-48
    /// hours after created. If this field is not present, the transaction is authorised but not
    /// yet “complete”.
    pub settled: String,
    /// The category can be set for each transaction by the user. Over time we learn which merchant
    /// goes in which category and auto-assign the category of a transaction. If the user hasn’t
    /// set a category, we’ll return the default category of the merchant on this transactions.
    /// Top-ups have category mondo. Valid values are general, eating_out, expenses, transport,
    /// cash, bills, entertainment, shopping, holidays, groceries.
    pub category: String,
    /// This is only present on declined transactions! Valid values are INSUFFICIENT_FUNDS,
    /// CARD_INACTIVE, CARD_BLOCKED or OTHER.
    // TODO: Make this an enum?
    pub decline_reason: Option<String>,
}

/// Response to the transaction future if successful.
#[derive(Debug, Deserialize)]
pub struct Transactions {
    /// List of transactions.
    pub transactions: Vec<Transaction>,
}

/// Response to the futures in case of an error.
#[derive(Debug, Deserialize)]
pub struct Error {
    /// The HTTP response code.
    pub code: Option<String>,
    /// Short description of the error.
    // TODO; Maybe make this an enum since the documentation says it can only contain a certain set
    // of values.
    pub error: Option<String>,
    /// Longer description of the error.
    pub error_description: Option<String>,
    /// Additional information.
    pub message: Option<String>,
}

const ACCOUNT_ID: &'static str = "account_id";

/// Errors for this crate using error_chain.
pub mod errors {
    #![allow(missing_docs)]
    error_chain! {
        errors {
            /// When the Monzo API returns an error response code with more detailed information.
            BadResponse(statuscode: ::hyper::StatusCode, error: ::Error)
        }
        foreign_links {
            BadJsonResponse(::serde_json::Error);
            NetworkError(::hyper::Error);
        }
    }
}

/// The main interface for this crate.
#[derive(Debug)]
pub struct Client {
    client: hyper::client::Client<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>,
    access_token: String,
    base_url: Url,
}

/// The main interface for this crate.
impl Client {
    /// Creates a new Monzo client.
    pub fn new(handle: &Handle, access_token: &str) -> Client {
        Client::new_with_base_url(
            handle,
            access_token,
            "https://api.monzo.com".parse().unwrap(),
        )
    }

    /// Creates a new Monzo client with another base url. Useful for tests.
    pub fn new_with_base_url(handle: &Handle, access_token: &str, base_url: Url) -> Client {
        Client {
            client: ::hyper::Client::configure()
                .connector(::hyper_tls::HttpsConnector::new(4, handle).unwrap())
                .build(handle),
            access_token: access_token.into(),
            base_url: base_url,
        }
    }

    fn create_request(&self, uri: Uri) -> Request<Body> {
        let mut req: Request<Body> = Request::new(Method::Get, uri);
        req.headers_mut().set(Authorization(
            Bearer { token: self.access_token.clone() },
        ));
        req
    }

    fn make_request<T: 'static, F: 'static>(
        &self,
        uri: Uri,
        response_handler: F,
    ) -> Box<Future<Item = T, Error = errors::Error>>
    where
        F: Fn(Chunk) -> Result<T, errors::Error>,
    {
        let request = self.create_request(uri);
        let response: hyper::client::FutureResponse = self.client.request(request);
        let future = response
            .map_err(|err: hyper::Error| -> errors::Error { err.into() })
            .and_then(|res| {
                let status = res.status().clone();
                res.body()
                    .concat2()
                    .map_err(|err: hyper::Error| err.into())
                    .and_then(move |body: Chunk| {
                        match status {
                            StatusCode::Ok => {}
                            _ => {
                                let error: Error = serde_json::from_slice(&body)?;
                                return Err(errors::ErrorKind::BadResponse(status, error).into());
                            }
                        };
                        response_handler(body)
                    })
            });

        Box::new(future)
    }

    /// Returns a list of accounts owned by the currently authorised user.
    pub fn accounts(&self) -> Box<Future<Item = Accounts, Error = errors::Error>> {
        let mut url = self.base_url.clone();
        url.path_segments_mut().unwrap().push("accounts");
        let uri: Uri = url.into_string().parse().unwrap();

        self.make_request(uri, |body| {
            let a: Accounts = serde_json::from_slice(&body)?;
            Ok(a)
        })
    }

    /// Retrieve information about an account’s balance.
    pub fn balance(
        &self,
        account_id: AccountId,
    ) -> Box<Future<Item = Balance, Error = errors::Error>> {
        let mut url = self.base_url.clone();
        url.path_segments_mut().unwrap().push("balance");
        url.query_pairs_mut().append_pair(ACCOUNT_ID, &account_id);
        let uri: Uri = url.into_string().parse().unwrap();

        self.make_request(uri, |body| {
            let b: Balance = serde_json::from_slice(&body)?;
            Ok(b)
        })
    }

    /// Returns a list of transactions on the user’s account.
    pub fn transactions(
        &self,
        account_id: AccountId,
    ) -> Box<Future<Item = Transactions, Error = errors::Error>> {
        let mut url = self.base_url.clone();
        url.path_segments_mut().unwrap().push("transactions");
        url.query_pairs_mut().append_pair(ACCOUNT_ID, &account_id);
        let uri: Uri = url.into_string().parse().unwrap();

        self.make_request(uri, |body| {
            let t: Transactions = serde_json::from_slice(&body)?;
            Ok(t)
        })
    }
}
<commit_msg>Fix lint warnings<commit_after>//! A library for using the Monzo API
//!
//! This library wraps over the Monzo API in a future aware manner.
//!
//! Example usage:
//!
//! ```rust,no_run
//! extern crate monzo;
//! extern crate tokio_core;
//!
//! let mut core = tokio_core::reactor::Core::new().unwrap();
//! let monzo = monzo::Client::new(&core.handle(), "<access_token>");
//! let work = monzo.balance("<account_id>".into());
//! let response = core.run(work).unwrap();
//! println!("Balance: {} {}", response.balance, response.currency);
//! println!("Spent today: {}", response.spend_today);
//! ```

#![crate_name = "monzo"]
#![deny(missing_docs,
        missing_debug_implementations,
        missing_copy_implementations,
        trivial_casts,
        trivial_numeric_casts,
        unsafe_code,
        unused_extern_crates,
        unused_import_braces,
        unused_qualifications)]

#[macro_use]
extern crate error_chain;
extern crate futures;
extern crate hyper;
extern crate hyper_tls;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate tokio_core;
extern crate url;

use futures::{Future, Stream};
use hyper::{Body, Method, Request, Uri, Chunk, StatusCode};
use hyper::header::{Authorization, Bearer};
use std::collections::HashMap;
use std::string::String;
use tokio_core::reactor::Handle;
use url::Url;

/// Identifier for an account.
pub type AccountId = String;
/// Identifier for a transaction.
pub type TransactionId = String;
/// Identifier of a merchant.
pub type MerchantId = String;
/// Holds an ISO 4217 currency code.
pub type Currency = String;

/// Accounts represent a store of funds, and have a list of transactions.
#[derive(Debug, Deserialize)]
pub struct Account {
    /// The account id.
    pub id: AccountId,
    /// Description of the account.
    pub description: String,
    /// The timestamp in UTC when the account was created.
    // TODO: Change to date type?
    pub created: String,
}

/// Response to the list accounts future.
#[derive(Debug, Deserialize)]
pub struct Accounts {
    /// List of accounts owned by the currenty authorized user.
    pub accounts: Vec<Account>,
}

/// Response to the balance future if successful.
#[derive(Debug, Deserialize)]
pub struct Balance {
    /// The currently available balance of the account, as a 64bit integer in minor units of the
    /// currency, eg. pennies for GBP, or cents for EUR and USD.
    pub balance: i64,
    /// The ISO 4217 currency code.
    pub currency: Currency,
    /// The amount spent from this account today (considered from approx 4am onwards), in minor
    /// units of the currency.
    pub spend_today: i64,
}

/// Describes a transaction.
#[derive(Debug, Deserialize)]
pub struct Transaction {
    /// Balance in the account after the transaction.
    pub account_balance: i64,
    /// The amount of the transaction in minor units of currency. For example pennies in the case
    /// of GBP. A negative amount indicates a debit (most card transactions will have a negative
    /// amount).
    pub amount: i64,
    /// The timestamp in UTC when the transaction was created.
    // TODO: Change to date type?
    pub created: String,
    /// The ISO 4217 currency code.
    pub currency: Currency,
    /// Description of the transaction.
    pub description: String,
    /// The transaction id.
    pub id: TransactionId,
    /// This contains the merchant_id of the merchant that this transaction was made at.
    pub merchant: Option<MerchantId>,
    /// Key-value annotations made for transaction. Metadata is private to your application.
    pub metadata: HashMap<String, String>,
    /// Notes attached to the transaction.
    pub notes: String,
    /// Top-ups to an account are represented as transactions with a positive amount and
    /// is_load = true. Other transactions such as refunds, reversals or chargebacks may have a
    /// positive amount but is_load = false
    pub is_load: bool,
    /// The timestamp in UTC at which the transaction settled. In most cases, this happens 24-48
    /// hours after created. If this field is not present, the transaction is authorised but not
    /// yet “complete”.
    pub settled: String,
    /// The category can be set for each transaction by the user. Over time we learn which merchant
    /// goes in which category and auto-assign the category of a transaction. If the user hasn’t
    /// set a category, we’ll return the default category of the merchant on this transactions.
    /// Top-ups have category mondo. Valid values are general, eating_out, expenses, transport,
    /// cash, bills, entertainment, shopping, holidays, groceries.
    pub category: String,
    /// This is only present on declined transactions! Valid values are INSUFFICIENT_FUNDS,
    /// CARD_INACTIVE, CARD_BLOCKED or OTHER.
    // TODO: Make this an enum?
    pub decline_reason: Option<String>,
}

/// Response to the transaction future if successful.
#[derive(Debug, Deserialize)]
pub struct Transactions {
    /// List of transactions.
    pub transactions: Vec<Transaction>,
}

/// Response to the futures in case of an error.
#[derive(Debug, Deserialize)]
pub struct Error {
    /// The HTTP response code.
    pub code: Option<String>,
    /// Short description of the error.
    // TODO; Maybe make this an enum since the documentation says it can only contain a certain set
    // of values.
    pub error: Option<String>,
    /// Longer description of the error.
    pub error_description: Option<String>,
    /// Additional information.
    pub message: Option<String>,
}

const ACCOUNT_ID: &'static str = "account_id";

/// Errors for this crate using `error_chain`.
pub mod errors {
    error_chain! {
        errors {
            #[doc = "When the Monzo API returns an error response code with more detailed \
            information."]
            BadResponse(statuscode: ::hyper::StatusCode, error: ::Error)
        }
        foreign_links {
            BadJsonResponse(::serde_json::Error)
            #[doc = "When the Monzo API returns invalid or unexpected json content."];
            NetworkError(::hyper::Error) #[doc = "Returned on network failure."];
        }
    }
}

/// The main interface for this crate.
#[derive(Debug)]
pub struct Client {
    client: hyper::client::Client<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>,
    access_token: String,
    base_url: Url,
}

/// The main interface for this crate.
impl Client {
    /// Creates a new Monzo client.
    pub fn new(handle: &Handle, access_token: &str) -> Client {
        Client::new_with_base_url(
            handle,
            access_token,
            "https://api.monzo.com".parse().unwrap(),
        )
    }

    /// Creates a new Monzo client with another base url. Useful for tests.
    pub fn new_with_base_url(handle: &Handle, access_token: &str, base_url: Url) -> Client {
        Client {
            client: ::hyper::Client::configure()
                .connector(::hyper_tls::HttpsConnector::new(4, handle).unwrap())
                .build(handle),
            access_token: access_token.into(),
            base_url: base_url,
        }
    }

    fn create_request(&self, uri: Uri) -> Request<Body> {
        let mut req: Request<Body> = Request::new(Method::Get, uri);
        req.headers_mut().set(Authorization(
            Bearer { token: self.access_token.clone() },
        ));
        req
    }

    fn make_request<T: 'static, F: 'static>(
        &self,
        uri: Uri,
        response_handler: F,
    ) -> Box<Future<Item = T, Error = errors::Error>>
    where
        F: Fn(Chunk) -> Result<T, errors::Error>,
    {
        let request = self.create_request(uri);
        let response: hyper::client::FutureResponse = self.client.request(request);
        let future = response
            .map_err(|err: hyper::Error| -> errors::Error { err.into() })
            .and_then(|res| {
                let status = res.status();
                res.body()
                    .concat2()
                    .map_err(|err: hyper::Error| err.into())
                    .and_then(move |body: Chunk| {
                        match status {
                            StatusCode::Ok => {}
                            _ => {
                                let error: Error = serde_json::from_slice(&body)?;
                                return Err(errors::ErrorKind::BadResponse(status, error).into());
                            }
                        };
                        response_handler(body)
                    })
            });

        Box::new(future)
    }

    /// Returns a list of accounts owned by the currently authorised user.
    pub fn accounts(&self) -> Box<Future<Item = Accounts, Error = errors::Error>> {
        let mut url = self.base_url.clone();
        url.path_segments_mut().unwrap().push("accounts");
        let uri: Uri = url.into_string().parse().unwrap();

        self.make_request(uri, |body| {
            let a: Accounts = serde_json::from_slice(&body)?;
            Ok(a)
        })
    }

    /// Retrieve information about an account’s balance.
    pub fn balance(
        &self,
        account_id: AccountId,
    ) -> Box<Future<Item = Balance, Error = errors::Error>> {
        let mut url = self.base_url.clone();
        url.path_segments_mut().unwrap().push("balance");
        url.query_pairs_mut().append_pair(ACCOUNT_ID, &account_id);
        let uri: Uri = url.into_string().parse().unwrap();

        self.make_request(uri, |body| {
            let b: Balance = serde_json::from_slice(&body)?;
            Ok(b)
        })
    }

    /// Returns a list of transactions on the user’s account.
    pub fn transactions(
        &self,
        account_id: AccountId,
    ) -> Box<Future<Item = Transactions, Error = errors::Error>> {
        let mut url = self.base_url.clone();
        url.path_segments_mut().unwrap().push("transactions");
        url.query_pairs_mut().append_pair(ACCOUNT_ID, &account_id);
        let uri: Uri = url.into_string().parse().unwrap();

        self.make_request(uri, |body| {
            let t: Transactions = serde_json::from_slice(&body)?;
            Ok(t)
        })
    }
}
<|endoftext|>


<commit_before>mod key;
mod rangeset;

use key::Key;
use rangeset::{Range, RangeSet};
use std::collections::HashMap;

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
struct VKeyMarker;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
struct EKeyMarker;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
struct FKeyMarker;
pub type VKey = Key<VKeyMarker>;
pub type EKey = Key<EKeyMarker>;
pub type FKey = Key<FKeyMarker>;
pub type FaceLen = u32;

/// Editable mesh with persistent adjacency data. Modeled loosely
/// after Blender's BMesh:
///
/// http://wiki.blender.org/index.php/Dev:2.6/Source/Modeling/BMesh/Design
pub struct Mesh<VData, EData, FData> {
    verts: HashMap<VKey, Vert<VData>>,
    edges: HashMap<EKey, Edge<EData>>,
    faces: HashMap<FKey, Face<FData>>,

    vert_range_set: RangeSet,
    edge_range_set: RangeSet,
    face_range_set: RangeSet
}

// TODO
fn new_key_range_set() -> RangeSet {
    RangeSet::new(Range::new(0, 0xffffffff - 1))
}

impl<VData: Clone, EData: Clone, FData: Clone> Mesh<VData, EData, FData> {
    pub fn new() -> Mesh<VData, EData, FData> {
        Mesh {
            verts: HashMap::new(),
            edges: HashMap::new(),
            faces: HashMap::new(),

            vert_range_set: new_key_range_set(),
            edge_range_set: new_key_range_set(),
            face_range_set: new_key_range_set()
        }
    }

    /// Return the edge between two verts, or None if no such edge
    /// exists.
    pub fn find_edge(&self, vk0: VKey, vk1: VKey) -> Option<EKey> {
        for ek in self.verts[&vk0].edges.iter() {
            if self.edges[ek].is_vert_adjacent(vk1) {
                return Some(*ek)
            }
        }
        None
    }

    /// Get all faces adjacent to the specified vertex. The order is
    /// arbitrary.
    pub fn vert_adjacent_faces(&self, vk: VKey) -> Vec<FKey> {
        let mut adj = Vec::new();
        for ek in self.verts[&vk].edges.iter() {
            for fk in self.edges[ek].faces.iter() {
                if !adj.contains(fk) {
                    adj.push(*fk);
                }
            }
        }
        adj
    }

    /// Add a new isolated vertex and return its key. Fail and return
    /// None if there are no more vertex keys available.
    pub fn add_vert(&mut self, vdata: VData) -> Option<VKey> {
        if let Some(val) = self.vert_range_set.take_any_one() {
            let vkey = VKey::new(val);
            self.verts.insert(vkey, Vert::new(vdata));
            Some(vkey)
        } else {
            None
        }
    }

    pub fn add_edge(&mut self, vk0: VKey, vk1: VKey, edata: EData) -> Option<EKey> {
        // TODO(nicholasbishop): check that the verts are in the mesh,
        if vk0 == vk1 {
            None
        } else if let Some(ek) = self.find_edge(vk0, vk1) {
            Some(ek)
        } else {
            if let Some(val) = self.edge_range_set.take_any_one() {
                let ekey = EKey::new(val);
                self.verts.get_mut(&vk0).unwrap().push_edge(ekey);
                self.verts.get_mut(&vk1).unwrap().push_edge(ekey);
                self.edges.insert(ekey, Edge::new(vk0, vk1, edata));
                Some(ekey)
            } else {
                None
            }
        }
    }

    pub fn add_face(&mut self, vk: &[VKey], edata: EData, fdata: FData) -> Option<FKey> {
        let mut loops = Vec::with_capacity(vk.len());
        for i in 0..vk.len() {
            let vk0 = vk[i];
            let vk1 = vk[if i < (vk.len() - 1) { i + 1 } else { 0 }];
            // TODO(nicholasbishop): do more checking up front so that
            // edges don't get created on failure, or delete them after.
            if let Some(ek) = self.add_edge(vk0, vk1, edata.clone()) {
                loops.push(Loop { vert: vk0, edge: ek });
            } else {
                // Error: failed to create edge
                return None;
            }
        }
        if let Some(val) = self.face_range_set.take_any_one() {
            let fk = FKey::new(val);
            for lp in loops.iter() {
                self.edges.get_mut(&lp.edge).unwrap().push_face(fk);
            }
            self.faces.insert(fk, Face::new(loops, fdata));
            Some(fk)
        } else {
            None
        }
    }
}

pub struct Vert<VData> {
    vdata: VData,
    edges: Vec<EKey>
}

impl<VData> Vert<VData> {
    fn new(vdata: VData) -> Vert<VData> {
        Vert { vdata: vdata, edges: Vec::new() }
    }

    /// Check if the edge is in the set of edges adjacent to this vert.
    pub fn is_edge_adjacent(&self, ek: EKey) -> bool {
        self.edges.contains(&ek)
    }

    /// Add edge to set of edges adjacent to the vert. Does nothing if
    /// the edge is already in the set.
    fn push_edge(&mut self, ek: EKey) {
        if !self.is_edge_adjacent(ek) {
            self.edges.push(ek);
        }
    }
}

pub struct Edge<EData> {
    edata: EData,
    verts: [VKey; 2],
    faces: Vec<FKey>
}

impl<EData> Edge<EData> {
    fn new(vk0: VKey, vk1: VKey, edata: EData) -> Edge<EData> {
        Edge { edata: edata, verts: [vk0, vk1], faces: Vec::new() }
    }

    /// Check if the vert is one of the two verts adjacent to this edge.
    fn is_vert_adjacent(&self, vk: VKey) -> bool {
        self.verts.contains(&vk)
    }

    /// Check if the face is in the set of edges adjacent to this edge.
    pub fn is_face_adjacent(&self, fk: FKey) -> bool {
        self.faces.contains(&fk)
    }

    /// Add face to set of faces adjacent to the edge. Does nothing if
    /// the face is already in the set.
    fn push_face(&mut self, fk: FKey) {
        if !self.is_face_adjacent(fk) {
            self.faces.push(fk);
        }
    }
}

pub struct Loop {
    vert: VKey,
    edge: EKey,
}

pub struct Face<FData> {
    fdata: FData,
    loops: Vec<Loop>
}

impl<FData> Face<FData> {
    fn new(loops: Vec<Loop>, fdata: FData) -> Face<FData> {
        Face { fdata: fdata, loops: loops }
    }
}

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

    // Placeholder for vert/edge/face data
    const DAT: () = ();

    #[test]
    fn test_add_vert() {
        let mut mesh = Mesh::<_, (), ()>::new();
        assert!(mesh.add_vert(DAT).is_some());
        assert!(!mesh.verts.is_empty());
    }

    #[test]
    fn test_add_edge() {
        let mut mesh = Mesh::<_, _, ()>::new();
        let a = mesh.add_vert(DAT).unwrap();
        let b = mesh.add_vert(DAT).unwrap();

        // Add a valid edge
        let e = mesh.add_edge(a, b, DAT).unwrap();
        assert!(mesh.verts[&a].edges.contains(&e));
        assert!(mesh.verts[&b].edges.contains(&e));

        // Edge from a vertex to the same vertex is not allowed
        assert!(mesh.add_edge(a, a, DAT).is_none());

        // Duplicate edge should return the existing edge
        assert_eq!(mesh.add_edge(a, b, DAT).unwrap(), e);
        assert_eq!(mesh.add_edge(b, a, DAT).unwrap(), e);
    }

    #[test]
    fn test_add_face() {
        let mut mesh = Mesh::new();
        let a = mesh.add_vert(DAT).unwrap();
        let b = mesh.add_vert(DAT).unwrap();
        let c = mesh.add_vert(DAT).unwrap();

        // Add a valid triangle
        let fk = mesh.add_face(&[a, b, c], DAT, DAT).unwrap();
        assert_eq!(mesh.edges.len(), 3);
        for lp in mesh.faces[&fk].loops.iter() {
            assert!(mesh.edges[&lp.edge].is_face_adjacent(fk));
        }

        // Add an invalid triangle with invalid edge
        assert!(mesh.add_face(&[a, b, b], DAT, DAT).is_none());
    }

    #[test]
    fn test_vert_adjacent_faces() {
        // Create a bow-tie mesh
        let mut mesh = Mesh::new();
        let middle = mesh.add_vert(DAT).unwrap();
        let l0 = mesh.add_vert(DAT).unwrap();
        let l1 = mesh.add_vert(DAT).unwrap();
        let r0 = mesh.add_vert(DAT).unwrap();
        let r1 = mesh.add_vert(DAT).unwrap();
        let fk0 = mesh.add_face(&[middle, l0, l1], DAT, DAT).unwrap();
        let fk1 = mesh.add_face(&[middle, r0, r1], DAT, DAT).unwrap();

        let adj = mesh.vert_adjacent_faces(middle);
        assert_eq!(adj.len(), 2);
        assert!(adj.contains(&fk0));
        assert!(adj.contains(&fk1));
    }

    #[test]
    fn test_ngon() {
        let mut mesh = Mesh::new();
        let a = mesh.add_vert(DAT).unwrap();
        let b = mesh.add_vert(DAT).unwrap();
        let c = mesh.add_vert(DAT).unwrap();
        let d = mesh.add_vert(DAT).unwrap();
        let e = mesh.add_vert(DAT).unwrap();

        let fk = mesh.add_face(&[a, b, c, d, e], DAT, DAT).unwrap();
        let face = &mesh.faces[&fk];

        assert_eq!(face.loops.len(), 5);
    }
}
<commit_msg>Add accessor<commit_after>mod key;
mod rangeset;

use key::Key;
use rangeset::{Range, RangeSet};
use std::collections::HashMap;

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
struct VKeyMarker;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
struct EKeyMarker;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
struct FKeyMarker;
pub type VKey = Key<VKeyMarker>;
pub type EKey = Key<EKeyMarker>;
pub type FKey = Key<FKeyMarker>;
pub type FaceLen = u32;

/// Editable mesh with persistent adjacency data. Modeled loosely
/// after Blender's BMesh:
///
/// http://wiki.blender.org/index.php/Dev:2.6/Source/Modeling/BMesh/Design
pub struct Mesh<VData, EData, FData> {
    verts: HashMap<VKey, Vert<VData>>,
    edges: HashMap<EKey, Edge<EData>>,
    faces: HashMap<FKey, Face<FData>>,

    vert_range_set: RangeSet,
    edge_range_set: RangeSet,
    face_range_set: RangeSet
}

// TODO
fn new_key_range_set() -> RangeSet {
    RangeSet::new(Range::new(0, 0xffffffff - 1))
}

impl<VData: Clone, EData: Clone, FData: Clone> Mesh<VData, EData, FData> {
    pub fn new() -> Mesh<VData, EData, FData> {
        Mesh {
            verts: HashMap::new(),
            edges: HashMap::new(),
            faces: HashMap::new(),

            vert_range_set: new_key_range_set(),
            edge_range_set: new_key_range_set(),
            face_range_set: new_key_range_set()
        }
    }

    pub fn vert_data(&self, vk: VKey) -> Option<&VData> {
        self.verts.get(&vk).map(|v| &v.vdata)
    }

    pub fn edge_data(&self, ek: EKey) -> Option<&EData> {
        self.edges.get(&ek).map(|e| &e.edata)
    }

    pub fn face_data(&self, fk: FKey) -> Option<&FData> {
        self.faces.get(&fk).map(|f| &f.fdata)
    }

    pub fn vert_data_mut(&mut self, vk: VKey) -> Option<&mut VData> {
        self.verts.get_mut(&vk).map(|v| &mut v.vdata)
    }

    pub fn edge_data_mut(&mut self, ek: EKey) -> Option<&mut EData> {
        self.edges.get_mut(&ek).map(|e| &mut e.edata)
    }

    pub fn face_data_mut(&mut self, fk: FKey) -> Option<&mut FData> {
        self.faces.get_mut(&fk).map(|f| &mut f.fdata)
    }

    /// Return the edge between two verts, or None if no such edge
    /// exists.
    pub fn find_edge(&self, vk0: VKey, vk1: VKey) -> Option<EKey> {
        for ek in self.verts[&vk0].edges.iter() {
            if self.edges[ek].is_vert_adjacent(vk1) {
                return Some(*ek)
            }
        }
        None
    }

    /// Get all faces adjacent to the specified vertex. The order is
    /// arbitrary.
    pub fn vert_adjacent_faces(&self, vk: VKey) -> Vec<FKey> {
        let mut adj = Vec::new();
        for ek in self.verts[&vk].edges.iter() {
            for fk in self.edges[ek].faces.iter() {
                if !adj.contains(fk) {
                    adj.push(*fk);
                }
            }
        }
        adj
    }

    /// Add a new isolated vertex and return its key. Fail and return
    /// None if there are no more vertex keys available.
    pub fn add_vert(&mut self, vdata: VData) -> Option<VKey> {
        if let Some(val) = self.vert_range_set.take_any_one() {
            let vkey = VKey::new(val);
            self.verts.insert(vkey, Vert::new(vdata));
            Some(vkey)
        } else {
            None
        }
    }

    pub fn add_edge(&mut self, vk0: VKey, vk1: VKey, edata: EData) -> Option<EKey> {
        // TODO(nicholasbishop): check that the verts are in the mesh,
        if vk0 == vk1 {
            None
        } else if let Some(ek) = self.find_edge(vk0, vk1) {
            Some(ek)
        } else {
            if let Some(val) = self.edge_range_set.take_any_one() {
                let ekey = EKey::new(val);
                self.verts.get_mut(&vk0).unwrap().push_edge(ekey);
                self.verts.get_mut(&vk1).unwrap().push_edge(ekey);
                self.edges.insert(ekey, Edge::new(vk0, vk1, edata));
                Some(ekey)
            } else {
                None
            }
        }
    }

    pub fn add_face(&mut self, vk: &[VKey], edata: EData, fdata: FData) -> Option<FKey> {
        let mut loops = Vec::with_capacity(vk.len());
        for i in 0..vk.len() {
            let vk0 = vk[i];
            let vk1 = vk[if i < (vk.len() - 1) { i + 1 } else { 0 }];
            // TODO(nicholasbishop): do more checking up front so that
            // edges don't get created on failure, or delete them after.
            if let Some(ek) = self.add_edge(vk0, vk1, edata.clone()) {
                loops.push(Loop { vert: vk0, edge: ek });
            } else {
                // Error: failed to create edge
                return None;
            }
        }
        if let Some(val) = self.face_range_set.take_any_one() {
            let fk = FKey::new(val);
            for lp in loops.iter() {
                self.edges.get_mut(&lp.edge).unwrap().push_face(fk);
            }
            self.faces.insert(fk, Face::new(loops, fdata));
            Some(fk)
        } else {
            None
        }
    }
}

pub struct Vert<VData> {
    pub vdata: VData,
    edges: Vec<EKey>
}

impl<VData> Vert<VData> {
    fn new(vdata: VData) -> Vert<VData> {
        Vert { vdata: vdata, edges: Vec::new() }
    }

    /// Check if the edge is in the set of edges adjacent to this vert.
    pub fn is_edge_adjacent(&self, ek: EKey) -> bool {
        self.edges.contains(&ek)
    }

    /// Add edge to set of edges adjacent to the vert. Does nothing if
    /// the edge is already in the set.
    fn push_edge(&mut self, ek: EKey) {
        if !self.is_edge_adjacent(ek) {
            self.edges.push(ek);
        }
    }
}

pub struct Edge<EData> {
    pub edata: EData,
    verts: [VKey; 2],
    faces: Vec<FKey>
}

impl<EData> Edge<EData> {
    fn new(vk0: VKey, vk1: VKey, edata: EData) -> Edge<EData> {
        Edge { edata: edata, verts: [vk0, vk1], faces: Vec::new() }
    }

    /// Check if the vert is one of the two verts adjacent to this edge.
    fn is_vert_adjacent(&self, vk: VKey) -> bool {
        self.verts.contains(&vk)
    }

    /// Check if the face is in the set of edges adjacent to this edge.
    pub fn is_face_adjacent(&self, fk: FKey) -> bool {
        self.faces.contains(&fk)
    }

    /// Add face to set of faces adjacent to the edge. Does nothing if
    /// the face is already in the set.
    fn push_face(&mut self, fk: FKey) {
        if !self.is_face_adjacent(fk) {
            self.faces.push(fk);
        }
    }
}

pub struct Loop {
    vert: VKey,
    edge: EKey,
}

pub struct Face<FData> {
    pub fdata: FData,
    loops: Vec<Loop>
}

impl<FData> Face<FData> {
    fn new(loops: Vec<Loop>, fdata: FData) -> Face<FData> {
        Face { fdata: fdata, loops: loops }
    }
}

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

    // Placeholder for vert/edge/face data
    const DAT: () = ();

    #[test]
    fn test_add_vert() {
        let mut mesh = Mesh::<_, (), ()>::new();
        assert!(mesh.add_vert(DAT).is_some());
        assert!(!mesh.verts.is_empty());
    }

    #[test]
    fn test_add_edge() {
        let mut mesh = Mesh::<_, _, ()>::new();
        let a = mesh.add_vert(DAT).unwrap();
        let b = mesh.add_vert(DAT).unwrap();

        // Add a valid edge
        let e = mesh.add_edge(a, b, DAT).unwrap();
        assert!(mesh.verts[&a].edges.contains(&e));
        assert!(mesh.verts[&b].edges.contains(&e));

        // Edge from a vertex to the same vertex is not allowed
        assert!(mesh.add_edge(a, a, DAT).is_none());

        // Duplicate edge should return the existing edge
        assert_eq!(mesh.add_edge(a, b, DAT).unwrap(), e);
        assert_eq!(mesh.add_edge(b, a, DAT).unwrap(), e);
    }

    #[test]
    fn test_add_face() {
        let mut mesh = Mesh::new();
        let a = mesh.add_vert(DAT).unwrap();
        let b = mesh.add_vert(DAT).unwrap();
        let c = mesh.add_vert(DAT).unwrap();

        // Add a valid triangle
        let fk = mesh.add_face(&[a, b, c], DAT, DAT).unwrap();
        assert_eq!(mesh.edges.len(), 3);
        for lp in mesh.faces[&fk].loops.iter() {
            assert!(mesh.edges[&lp.edge].is_face_adjacent(fk));
        }

        // Add an invalid triangle with invalid edge
        assert!(mesh.add_face(&[a, b, b], DAT, DAT).is_none());
    }

    #[test]
    fn test_vert_adjacent_faces() {
        // Create a bow-tie mesh
        let mut mesh = Mesh::new();
        let middle = mesh.add_vert(DAT).unwrap();
        let l0 = mesh.add_vert(DAT).unwrap();
        let l1 = mesh.add_vert(DAT).unwrap();
        let r0 = mesh.add_vert(DAT).unwrap();
        let r1 = mesh.add_vert(DAT).unwrap();
        let fk0 = mesh.add_face(&[middle, l0, l1], DAT, DAT).unwrap();
        let fk1 = mesh.add_face(&[middle, r0, r1], DAT, DAT).unwrap();

        let adj = mesh.vert_adjacent_faces(middle);
        assert_eq!(adj.len(), 2);
        assert!(adj.contains(&fk0));
        assert!(adj.contains(&fk1));
    }

    #[test]
    fn test_ngon() {
        let mut mesh = Mesh::new();
        let a = mesh.add_vert(DAT).unwrap();
        let b = mesh.add_vert(DAT).unwrap();
        let c = mesh.add_vert(DAT).unwrap();
        let d = mesh.add_vert(DAT).unwrap();
        let e = mesh.add_vert(DAT).unwrap();

        let fk = mesh.add_face(&[a, b, c, d, e], DAT, DAT).unwrap();
        let face = &mesh.faces[&fk];

        assert_eq!(face.loops.len(), 5);
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use self::rand::seq::SliceRandom;

/// Convenience function to generate a new petname from default word lists.
pub fn petname(words: u8, separator: &str) -> String {
    Petnames::default().generate(&mut rand::thread_rng(), words, separator)
}

/// Word lists and the logic to combine them into _petnames_.
///
/// A _petname_ with `n` words will contain, in order:
///
///   * 1 adjective when `n >= 2`, otherwise 0 adjectives.
///   * `n - 2` adverbs when `n >= 2`.
///   * 1 name / noun.
///
pub struct Petnames<'a> {
    pub adjectives: Vec<&'a str>,
    pub adverbs: Vec<&'a str>,
    pub names: Vec<&'a str>,
}

impl<'a> Petnames<'a> {
    /// Constructs a new `Petnames` from the default (small) word lists.
    pub fn default() -> Petnames<'a> {
        Self::small()
    }

    /// Constructs a new `Petnames` from the small word lists.
    pub fn small() -> Petnames<'a> {
        Self::init(
            include_str!("../words/small/adjectives.txt"),
            include_str!("../words/small/adverbs.txt"),
            include_str!("../words/small/names.txt"),
        )
    }

    /// Constructs a new `Petnames` from the medium word lists.
    pub fn medium() -> Petnames<'a> {
        Self::init(
            include_str!("../words/medium/adjectives.txt"),
            include_str!("../words/medium/adverbs.txt"),
            include_str!("../words/medium/names.txt"),
        )
    }

    /// Constructs a new `Petnames` from the large word lists.
    pub fn large() -> Petnames<'a> {
        Self::init(
            include_str!("../words/large/adjectives.txt"),
            include_str!("../words/large/adverbs.txt"),
            include_str!("../words/large/names.txt"),
        )
    }

    fn init(adjectives: &'a str, adverbs: &'a str, names: &'a str) -> Petnames<'a> {
        Self {
            adjectives: adjectives.split_whitespace().collect(),
            adverbs: adverbs.split_whitespace().collect(),
            names: names.split_whitespace().collect(),
        }
    }

    /// Generate a new petname.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate rand;
    /// # extern crate petname;
    /// let mut rng = rand::thread_rng();
    /// petname::Petnames::default().generate(&mut rng, 7, ":");
    /// ```
    pub fn generate<RNG>(&self, rng: &mut RNG, words: u8, separator: &str) -> String
    where
        RNG: rand::Rng,
    {
        // Adverbs all the way, finishing with adjective then name.
        let mut parts = Vec::with_capacity(words as usize);
        for num in (0..words).rev() {
            parts.push(*match num {
                0 => self.names.choose(rng).unwrap(),
                1 => self.adjectives.choose(rng).unwrap(),
                _ => self.adverbs.choose(rng).unwrap(),
            });
        }
        parts.join(separator)
    }
}

#[cfg(test)]
mod tests {

    use super::{petname, rand, Petnames};

    #[test]
    fn default_petnames_has_adjectives() {
        let petnames = Petnames::default();
        assert_ne!(petnames.adjectives.len(), 0);
    }

    #[test]
    fn default_petnames_has_adverbs() {
        let petnames = Petnames::default();
        assert_ne!(petnames.adverbs.len(), 0);
    }

    #[test]
    fn default_petnames_has_names() {
        let petnames = Petnames::default();
        assert_ne!(petnames.names.len(), 0);
    }

    #[test]
    fn generate_uses_adverb_adjective_name() {
        let petnames = Petnames {
            adjectives: vec!["adjective"],
            adverbs: vec!["adverb"],
            names: vec!["name"],
        };
        assert_eq!(
            petnames.generate(&mut rand::thread_rng(), 3, "-"),
            "adverb-adjective-name"
        );
    }

    #[test]
    fn petname_renders_desired_number_of_words() {
        assert_eq!(petname(7, "-").split("-").count(), 7);
    }

    #[test]
    fn petname_renders_with_desired_separator() {
        assert_eq!(petname(7, "@").split("@").count(), 7);
    }
}
<commit_msg>Add std::default::Default impl for Petnames.<commit_after>extern crate rand;

use self::rand::seq::SliceRandom;

/// Convenience function to generate a new petname from default word lists.
pub fn petname(words: u8, separator: &str) -> String {
    Petnames::default().generate(&mut rand::thread_rng(), words, separator)
}

/// Word lists and the logic to combine them into _petnames_.
///
/// A _petname_ with `n` words will contain, in order:
///
///   * 1 adjective when `n >= 2`, otherwise 0 adjectives.
///   * `n - 2` adverbs when `n >= 2`.
///   * 1 name / noun.
///
pub struct Petnames<'a> {
    pub adjectives: Vec<&'a str>,
    pub adverbs: Vec<&'a str>,
    pub names: Vec<&'a str>,
}

impl<'a> Petnames<'a> {
    /// Constructs a new `Petnames` from the default (small) word lists.
    pub fn default() -> Petnames<'a> {
        Self::small()
    }

    /// Constructs a new `Petnames` from the small word lists.
    pub fn small() -> Petnames<'a> {
        Self::init(
            include_str!("../words/small/adjectives.txt"),
            include_str!("../words/small/adverbs.txt"),
            include_str!("../words/small/names.txt"),
        )
    }

    /// Constructs a new `Petnames` from the medium word lists.
    pub fn medium() -> Petnames<'a> {
        Self::init(
            include_str!("../words/medium/adjectives.txt"),
            include_str!("../words/medium/adverbs.txt"),
            include_str!("../words/medium/names.txt"),
        )
    }

    /// Constructs a new `Petnames` from the large word lists.
    pub fn large() -> Petnames<'a> {
        Self::init(
            include_str!("../words/large/adjectives.txt"),
            include_str!("../words/large/adverbs.txt"),
            include_str!("../words/large/names.txt"),
        )
    }

    fn init(adjectives: &'a str, adverbs: &'a str, names: &'a str) -> Petnames<'a> {
        Self {
            adjectives: adjectives.split_whitespace().collect(),
            adverbs: adverbs.split_whitespace().collect(),
            names: names.split_whitespace().collect(),
        }
    }

    /// Generate a new petname.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate rand;
    /// # extern crate petname;
    /// let mut rng = rand::thread_rng();
    /// petname::Petnames::default().generate(&mut rng, 7, ":");
    /// ```
    pub fn generate<RNG>(&self, rng: &mut RNG, words: u8, separator: &str) -> String
    where
        RNG: rand::Rng,
    {
        // Adverbs all the way, finishing with adjective then name.
        let mut parts = Vec::with_capacity(words as usize);
        for num in (0..words).rev() {
            parts.push(*match num {
                0 => self.names.choose(rng).unwrap(),
                1 => self.adjectives.choose(rng).unwrap(),
                _ => self.adverbs.choose(rng).unwrap(),
            });
        }
        parts.join(separator)
    }
}

impl<'a> Default for Petnames<'a> {
    fn default() -> Self { Self::default() }
}

#[cfg(test)]
mod tests {

    use super::{petname, rand, Petnames};

    #[test]
    fn default_petnames_has_adjectives() {
        let petnames = Petnames::default();
        assert_ne!(petnames.adjectives.len(), 0);
    }

    #[test]
    fn default_petnames_has_adverbs() {
        let petnames = Petnames::default();
        assert_ne!(petnames.adverbs.len(), 0);
    }

    #[test]
    fn default_petnames_has_names() {
        let petnames = Petnames::default();
        assert_ne!(petnames.names.len(), 0);
    }

    #[test]
    fn generate_uses_adverb_adjective_name() {
        let petnames = Petnames {
            adjectives: vec!["adjective"],
            adverbs: vec!["adverb"],
            names: vec!["name"],
        };
        assert_eq!(
            petnames.generate(&mut rand::thread_rng(), 3, "-"),
            "adverb-adjective-name"
        );
    }

    #[test]
    fn petname_renders_desired_number_of_words() {
        assert_eq!(petname(7, "-").split("-").count(), 7);
    }

    #[test]
    fn petname_renders_with_desired_separator() {
        assert_eq!(petname(7, "@").split("@").count(), 7);
    }
}
<|endoftext|>