<commit_before>// Copyright 2016-2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The binomial distribution.

use Rng;
use distributions::Distribution;
use distributions::log_gamma::log_gamma;
use std::f64::consts::PI;

/// The binomial distribution `Binomial(n, p)`.
///
/// This distribution has density function:
/// `f(k) = n!/(k! (n-k)!) p^k (1-p)^(n-k)` for `k >= 0`.
///
/// # Example
///
/// ```rust
/// use rand::distributions::{Binomial, Distribution};
///
/// let bin = Binomial::new(20, 0.3);
/// let v = bin.sample(&mut rand::thread_rng());
/// println!("{} is from a binomial distribution", v);
/// ```
#[derive(Clone, Copy, Debug)]
pub struct Binomial {
    n: u64, // number of trials
    p: f64, // probability of success
}

impl Binomial {
    /// Construct a new `Binomial` with the given shape parameters
    /// `n`, `p`. Panics if `p <= 0` or `p >= 1`.
    pub fn new(n: u64, p: f64) -> Binomial {
        assert!(p > 0.0, "Binomial::new called with p <= 0");
        assert!(p < 1.0, "Binomial::new called with p >= 1");
        Binomial { n: n, p: p }
    }
}

impl Distribution<u64> for Binomial {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u64 {
        // binomial distribution is symmetrical with respect to p -> 1-p, k -> n-k
        // switch p so that it is less than 0.5 - this allows for lower expected values
        // we will just invert the result at the end
        let p = if self.p <= 0.5 {
            self.p
        } else {
            1.0 - self.p
        };

        // expected value of the sample
        let expected = self.n as f64 * p;

        let result =
            // for low expected values we just simulate n drawings
            if expected < 25.0 {
                let mut lresult = 0.0;
                for _ in 0 .. self.n {
                    if rng.gen::<f64>() < p {
                        lresult += 1.0;
                    }
                }
                lresult
            }
            // high expected value - do the rejection method
            else {
                // prepare some cached values
                let float_n = self.n as f64;
                let ln_fact_n = log_gamma(float_n + 1.0);
                let pc = 1.0 - p;
                let log_p = p.ln();
                let log_pc = pc.ln();
                let sq = (expected * (2.0 * pc)).sqrt();

                let mut lresult;

                loop {
                    let mut comp_dev: f64;
                    // we use the lorentzian distribution as the comparison distribution
                    // f(x) ~ 1/(1+x/^2)
                    loop {
                        // draw from the lorentzian distribution
                        comp_dev = (PI*rng.gen::<f64>()).tan();
                        // shift the peak of the comparison ditribution
                        lresult = expected + sq * comp_dev;
                        // repeat the drawing until we are in the range of possible values
                        if lresult >= 0.0 && lresult < float_n + 1.0 {
                            break;
                        }
                    }

                    // the result should be discrete
                    lresult = lresult.floor();

                    let log_binomial_dist = ln_fact_n - log_gamma(lresult+1.0) -
                        log_gamma(float_n - lresult + 1.0) + lresult*log_p + (float_n - lresult)*log_pc;
                    // this is the binomial probability divided by the comparison probability
                    // we will generate a uniform random value and if it is larger than this,
                    // we interpret it as a value falling out of the distribution and repeat
                    let comparison_coeff = (log_binomial_dist.exp() * sq) * (1.2 * (1.0 + comp_dev*comp_dev));

                    if comparison_coeff >= rng.gen() {
                        break;
                    }
                }

                lresult
            };

        // invert the result for p < 0.5
        if p != self.p {
            self.n - result as u64
        } else {
            result as u64
        }
    }
}

#[cfg(test)]
mod test {
    use distributions::Distribution;
    use super::Binomial;

    #[test]
    fn test_binomial() {
        let binomial = Binomial::new(150, 0.1);
        let mut rng = ::test::rng(123);
        let mut sum = 0;
        for _ in 0..1000 {
            sum += binomial.sample(&mut rng);
        }
        let avg = (sum as f64) / 1000.0;
        println!("Binomial average: {}", avg);
        assert!((avg - 15.0).abs() < 0.5); // not 100% certain, but probable enough
    }

    #[test]
    #[should_panic]
    fn test_binomial_invalid_lambda_zero() {
        Binomial::new(20, 0.0);
    }

    #[test]
    #[should_panic]
    fn test_binomial_invalid_lambda_neg() {
        Binomial::new(20, -10.0);
    }
}
<commit_msg>Use `gen_bool` in Binomial distribution<commit_after>// Copyright 2016-2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The binomial distribution.

use Rng;
use distributions::Distribution;
use distributions::log_gamma::log_gamma;
use std::f64::consts::PI;

/// The binomial distribution `Binomial(n, p)`.
///
/// This distribution has density function:
/// `f(k) = n!/(k! (n-k)!) p^k (1-p)^(n-k)` for `k >= 0`.
///
/// # Example
///
/// ```rust
/// use rand::distributions::{Binomial, Distribution};
///
/// let bin = Binomial::new(20, 0.3);
/// let v = bin.sample(&mut rand::thread_rng());
/// println!("{} is from a binomial distribution", v);
/// ```
#[derive(Clone, Copy, Debug)]
pub struct Binomial {
    n: u64, // number of trials
    p: f64, // probability of success
}

impl Binomial {
    /// Construct a new `Binomial` with the given shape parameters
    /// `n`, `p`. Panics if `p <= 0` or `p >= 1`.
    pub fn new(n: u64, p: f64) -> Binomial {
        assert!(p > 0.0, "Binomial::new called with p <= 0");
        assert!(p < 1.0, "Binomial::new called with p >= 1");
        Binomial { n: n, p: p }
    }
}

impl Distribution<u64> for Binomial {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u64 {
        // binomial distribution is symmetrical with respect to p -> 1-p, k -> n-k
        // switch p so that it is less than 0.5 - this allows for lower expected values
        // we will just invert the result at the end
        let p = if self.p <= 0.5 {
            self.p
        } else {
            1.0 - self.p
        };

        // expected value of the sample
        let expected = self.n as f64 * p;

        let result =
            // for low expected values we just simulate n drawings
            if expected < 25.0 {
                let mut lresult = 0.0;
                for _ in 0 .. self.n {
                    if rng.gen_bool(p) {
                        lresult += 1.0;
                    }
                }
                lresult
            }
            // high expected value - do the rejection method
            else {
                // prepare some cached values
                let float_n = self.n as f64;
                let ln_fact_n = log_gamma(float_n + 1.0);
                let pc = 1.0 - p;
                let log_p = p.ln();
                let log_pc = pc.ln();
                let sq = (expected * (2.0 * pc)).sqrt();

                let mut lresult;

                loop {
                    let mut comp_dev: f64;
                    // we use the lorentzian distribution as the comparison distribution
                    // f(x) ~ 1/(1+x/^2)
                    loop {
                        // draw from the lorentzian distribution
                        comp_dev = (PI*rng.gen::<f64>()).tan();
                        // shift the peak of the comparison ditribution
                        lresult = expected + sq * comp_dev;
                        // repeat the drawing until we are in the range of possible values
                        if lresult >= 0.0 && lresult < float_n + 1.0 {
                            break;
                        }
                    }

                    // the result should be discrete
                    lresult = lresult.floor();

                    let log_binomial_dist = ln_fact_n - log_gamma(lresult+1.0) -
                        log_gamma(float_n - lresult + 1.0) + lresult*log_p + (float_n - lresult)*log_pc;
                    // this is the binomial probability divided by the comparison probability
                    // we will generate a uniform random value and if it is larger than this,
                    // we interpret it as a value falling out of the distribution and repeat
                    let comparison_coeff = (log_binomial_dist.exp() * sq) * (1.2 * (1.0 + comp_dev*comp_dev));

                    if comparison_coeff >= rng.gen() {
                        break;
                    }
                }

                lresult
            };

        // invert the result for p < 0.5
        if p != self.p {
            self.n - result as u64
        } else {
            result as u64
        }
    }
}

#[cfg(test)]
mod test {
    use distributions::Distribution;
    use super::Binomial;

    #[test]
    fn test_binomial() {
        let binomial = Binomial::new(150, 0.1);
        let mut rng = ::test::rng(123);
        let mut sum = 0;
        for _ in 0..1000 {
            sum += binomial.sample(&mut rng);
        }
        let avg = (sum as f64) / 1000.0;
        println!("Binomial average: {}", avg);
        assert!((avg - 15.0).abs() < 0.5); // not 100% certain, but probable enough
    }

    #[test]
    #[should_panic]
    fn test_binomial_invalid_lambda_zero() {
        Binomial::new(20, 0.0);
    }

    #[test]
    #[should_panic]
    fn test_binomial_invalid_lambda_neg() {
        Binomial::new(20, -10.0);
    }
}
<|endoftext|>


<commit_before>// Rust Bitcoin Library
// Written in 2014 by
//   Andrew Poelstra <apoelstra@wpsoftware.net>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # Macros
//!
//! Macros available to users of the Bitcoin library

#![macro_escape]

#[macro_export]
macro_rules! nu_select(
  ($($name:pat from $rx:expr => $code:expr),+) => ({
    nu_select!{ $($name from $rx using recv => $code),+ }
  });
  ($($name:pat from $rx:expr using $meth:ident => $code:expr),+) => ({
    use rustrt::local::Local;
    use rustrt::task::Task;
    use sync::comm::Packet;

    let task: Box<Task> = Local::take();

    // Is anything already ready to receive? Grab it without waiting.
    $(
      if (&$rx as &Packet).can_recv() {
        let $name = $rx.$meth();
        $code
      }
    )else+
    else {

      // Start selecting on as many as we need to before getting a bite.
      // Keep count of how many, since we need to abort every selection
      // that we started.
      let mut started_count = 0;
      let packets = [ $( &$rx as &Packet, )+ ];
      task.deschedule(packets.len(), |task| {
        match packets[started_count].start_selection(task) {
          Ok(()) => {
            started_count += 1;
            Ok(())
          }
          Err(task) => Err(task)
        }
      });

      let mut i = -1;
      $(
        // Abort every one, but only react to the first
        if { i += 1; i < started_count } &&
           // If start_selection() failed, abort_selection() will fail too,
           // but it still counts as "data available". FIXME: should we swap
           // the following two conditions so that packets[started_count - 1].
           // abort_selection() is never called?
           (packets[i].abort_selection() || i == started_count - 1) {
          // Abort the remainder, ignoring their return values
          i += 1;
          while i < started_count {
            packets[i].abort_selection();
            i += 1;
          }
          // React to the first
          let $name = $rx.$meth();
          $code
        }
      )else+
    else {
      println!("i = {} , started_count {}", i, started_count);
      fail!("we didn't find the ready receiver, but we should have had one"); }
    }
  })
)

<commit_msg>Move Local::take() into a scope where it is guaranteed to be used<commit_after>// Rust Bitcoin Library
// Written in 2014 by
//   Andrew Poelstra <apoelstra@wpsoftware.net>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # Macros
//!
//! Macros available to users of the Bitcoin library

#![macro_escape]

#[macro_export]
macro_rules! nu_select(
  ($($name:pat from $rx:expr => $code:expr),+) => ({
    nu_select!{ $($name from $rx using recv => $code),+ }
  });
  ($($name:pat from $rx:expr using $meth:ident => $code:expr),+) => ({
    use rustrt::local::Local;
    use rustrt::task::Task;
    use sync::comm::Packet;

    // Is anything already ready to receive? Grab it without waiting.
    $(
      if (&$rx as &Packet).can_recv() {
        let $name = $rx.$meth();
        $code
      }
    )else+
    else {

      // Start selecting on as many as we need to before getting a bite.
      // Keep count of how many, since we need to abort every selection
      // that we started.
      let mut started_count = 0;
      let packets = [ $( &$rx as &Packet, )+ ];

      let task: Box<Task> = Local::take();
      task.deschedule(packets.len(), |task| {
        match packets[started_count].start_selection(task) {
          Ok(()) => {
            started_count += 1;
            Ok(())
          }
          Err(task) => Err(task)
        }
      });

      let mut i = -1;
      $(
        // Abort every one, but only react to the first
        if { i += 1; i < started_count } &&
           // If start_selection() failed, abort_selection() will fail too,
           // but it still counts as "data available". FIXME: should we swap
           // the following two conditions so that packets[started_count - 1].
           // abort_selection() is never called?
           (packets[i].abort_selection() || i == started_count - 1) {
          // Abort the remainder, ignoring their return values
          i += 1;
          while i < started_count {
            packets[i].abort_selection();
            i += 1;
          }
          // React to the first
          let $name = $rx.$meth();
          $code
        }
      )else+
    else {
      println!("i = {} , started_count {}", i, started_count);
      fail!("we didn't find the ready receiver, but we should have had one"); }
    }
  })
)

<|endoftext|>


<commit_before>//! This module provides two utility macros for testing custom derives. They can
//! be used together to eliminate some of the boilerplate required in order to
//! declare and test custom derive implementations.

// Re-exports used by the decl_derive! and test_derive!
pub use proc_macro::TokenStream;
pub use proc_macro2::TokenStream as TokenStream2;
pub use syn::{parse, parse_str, DeriveInput};

/// The `decl_derive!` macro declares a custom derive wrapper. It will parse the
/// incoming `TokenStream` into a `synstructure::Structure` object, and pass it
/// into the inner function.
///
/// Your inner function should take a `synstructure::Structure` by value, and
/// return a type implementing `synstructure::MacroResult`, for example:
///
/// ```
/// # extern crate quote;
/// # extern crate proc_macro;
/// # extern crate proc_macro2;
/// # extern crate synstructure;
/// # extern crate syn;
/// fn derive_simple(input: synstructure::Structure) -> proc_macro2::TokenStream {
///     unimplemented!()
/// }
///
/// fn derive_result(input: synstructure::Structure)
///     -> syn::Result<proc_macro2::TokenStream>
/// {
///     unimplemented!()
/// }
/// ```
///
/// # Usage
///
/// ### Without Attributes
/// ```
/// # #[macro_use] extern crate quote;
/// # extern crate proc_macro2;
/// # extern crate synstructure;
/// # fn main() {}
/// fn derive_interesting(_input: synstructure::Structure) -> proc_macro2::TokenStream {
///     quote! { ... }
/// }
///
/// # const _IGNORE: &'static str = stringify! {
/// decl_derive!([Interesting] => derive_interesting);
/// # };
/// ```
///
/// ### With Attributes
/// ```
/// # #[macro_use] extern crate quote;
/// # extern crate proc_macro2;
/// # extern crate synstructure;
/// # fn main() {}
/// fn derive_interesting(_input: synstructure::Structure) -> proc_macro2::TokenStream {
///     quote! { ... }
/// }
///
/// # const _IGNORE: &'static str = stringify! {
/// decl_derive!([Interesting, attributes(interesting_ignore)] => derive_interesting);
/// # };
/// ```
#[macro_export]
macro_rules! decl_derive {
    // XXX: Switch to using this variant everywhere?
    ([$derives:ident $($derive_t:tt)*] => $inner:path) => {
        #[proc_macro_derive($derives $($derive_t)*)]
        #[allow(non_snake_case)]
        pub fn $derives(
            i: $crate::macros::TokenStream
        ) -> $crate::macros::TokenStream {
            match $crate::macros::parse::<$crate::macros::DeriveInput>(i) {
                Ok(p) => {
                    match $crate::Structure::try_new(&p) {
                        Ok(s) => $crate::MacroResult::into_stream($inner(s)),
                        Err(e) => e.to_compile_error().into(),
                    }
                }
                Err(e) => e.to_compile_error().into(),
            }
        }
    };
}

/// The `decl_attribute!` macro declares a custom attribute wrapper. It will
/// parse the incoming `TokenStream` into a `synstructure::Structure` object,
/// and pass it into the inner function.
///
/// Your inner function should have the following type:
///
/// ```
/// # extern crate quote;
/// # extern crate proc_macro2;
/// # extern crate synstructure;
/// fn attribute(
///     attr: proc_macro2::TokenStream,
///     structure: synstructure::Structure,
/// ) -> proc_macro2::TokenStream {
///     unimplemented!()
/// }
/// ```
///
/// # Usage
///
/// ```
/// # #[macro_use] extern crate quote;
/// # extern crate proc_macro2;
/// # extern crate synstructure;
/// # fn main() {}
/// fn attribute_interesting(
///     _attr: proc_macro2::TokenStream,
///     _structure: synstructure::Structure,
/// ) -> proc_macro2::TokenStream {
///     quote! { ... }
/// }
///
/// # const _IGNORE: &'static str = stringify! {
/// decl_attribute!([interesting] => attribute_interesting);
/// # };
/// ```
/// ```
#[macro_export]
macro_rules! decl_attribute {
    ([$attribute:ident] => $inner:path) => {
        #[proc_macro_attribute]
        pub fn $attribute(
            attr: $crate::macros::TokenStream,
            i: $crate::macros::TokenStream,
        ) -> $crate::macros::TokenStream {
            match $crate::macros::parse::<$crate::macros::DeriveInput>(i) {
                Ok(p) => match $crate::Structure::try_new(&p) {
                    Ok(s) => $crate::MacroResult::into_stream($inner(attr.into(), s)),
                    Err(e) => e.to_compile_error().into(),
                },
                Err(e) => e.to_compile_error().into(),
            }
        }
    };
}

/// Run a test on a custom derive. This macro expands both the original struct
/// and the expansion to ensure that they compile correctly, and confirms that
/// feeding the original struct into the named derive will produce the written
/// output.
///
/// You can add `no_build` to the end of the macro invocation to disable
/// checking that the written code compiles. This is useful in contexts where
/// the procedural macro cannot depend on the crate where it is used during
/// tests.
///
/// # Usage
///
/// ```
/// # #[macro_use] extern crate quote;
/// # extern crate proc_macro2;
/// # #[macro_use] extern crate synstructure;
/// # extern crate syn;
/// fn test_derive_example(_s: synstructure::Structure)
///     -> Result<proc_macro2::TokenStream, syn::Error>
/// {
///     Ok(quote! { const YOUR_OUTPUT: &'static str = "here"; })
/// }
///
/// fn main() {
///     test_derive!{
///         test_derive_example {
///             struct A;
///         }
///         expands to {
///             const YOUR_OUTPUT: &'static str = "here";
///         }
///     }
/// }
/// ```
#[macro_export]
macro_rules! test_derive {
    ($name:path { $($i:tt)* } expands to { $($o:tt)* }) => {
        {
            #[allow(dead_code)]
            fn ensure_compiles() {
                $($i)*
                $($o)*
            }

            test_derive!($name { $($i)* } expands to { $($o)* } no_build);
        }
    };

    ($name:path { $($i:tt)* } expands to { $($o:tt)* } no_build) => {
        {
            let i = stringify!( $($i)* );
            let parsed = $crate::macros::parse_str::<$crate::macros::DeriveInput>(i)
                .expect(concat!(
                    "Failed to parse input to `#[derive(",
                    stringify!($name),
                    ")]`",
                ));

            let raw_res = $name($crate::Structure::new(&parsed));
            let res = $crate::MacroResult::into_result(raw_res)
                .expect(concat!(
                    "Procedural macro failed for `#[derive(",
                    stringify!($name),
                    ")]`",
                ));

            let expected = stringify!( $($o)* )
                .parse::<$crate::macros::TokenStream2>()
                .expect("output should be a valid TokenStream");
            let mut expected_toks = $crate::macros::TokenStream2::from(expected);
            if res.to_string() != expected_toks.to_string() {
                panic!("\
test_derive failed:
expected:
```
{}
```

got:
```
{}
```\n",
                    $crate::unpretty_print(&expected_toks),
                    $crate::unpretty_print(&res),
                );
            }
        }
    };
}

/// A helper macro for declaring relatively straightforward derive
/// implementations. It provides mechanisms for operating over structures
/// performing modifications on each field etc.
///
/// This macro doesn't define the actual derive, but rather the implementation
/// method. Use `decl_derive!` to generate the implementation wrapper.
///
/// # Stability Warning
///
/// This is an unstable experimental macro API, which may be changed or removed
/// in a future version. I'm not yet confident enough that this API is useful
/// enough to warrant its complexity and inclusion in `synstructure`.
///
/// # Caveat
///
/// The `quote!` macro from `quote` must be imported in the calling crate, as
/// this macro depends on it.
///
/// # Note
///
/// This feature is implemented behind the `simple-derive` feature, and is only
/// available when that feature is enabled.
///
/// # Example
///
/// ```
/// extern crate syn;
/// #[macro_use]
/// extern crate quote;
/// #[macro_use]
/// extern crate synstructure;
/// extern crate proc_macro2;
/// # const _IGNORE: &'static str = stringify! {
/// decl_derive!([Interest] => derive_interest);
/// # };
///
/// simple_derive! {
///     // This macro implements the `Interesting` method exported by the `aa`
///     // crate. It will explicitly add an `extern crate` invocation to import the
///     // crate into the expanded context.
///     derive_interest impl synstructure_test_traits::Interest {
///         // A "filter" block can be added. It evaluates its body with the (s)
///         // variable bound to a mutable reference to the input `Structure`
///         // object.
///         //
///         // This block can be used to perform general transformations, such as
///         // filtering out fields which should be ignored by all methods and for
///         // the purposes of binding type parameters.
///         filter(s) {
///             s.filter(|bi| bi.ast().ident != Some(syn::Ident::new("a",
///                 proc_macro2::Span::call_site())));
///         }
///
///         // This is an implementation of a method in the implemented crate. The
///         // return value should be the series of match patterns to destructure
///         // the `self` argument with.
///         fn interesting(&self as s) -> bool {
///             s.fold(false, |acc, bi| {
///                 quote!(#acc || synstructure_test_traits::Interest::interesting(#bi))
///             })
///         }
///     }
/// }
///
/// fn main() {
///     test_derive!{
///         derive_interest {
///             struct A<T> {
///                 x: i32,
///                 a: bool, // Will be ignored by filter
///                 c: T,
///             }
///         }
///         expands to {
///             #[allow(non_upper_case_globals)]
///             #[doc(hidden)]
///             const _DERIVE_synstructure_test_traits_Interest_FOR_A: () = {
///                 extern crate synstructure_test_traits;
///                 impl<T> synstructure_test_traits::Interest for A<T>
///                     where T: synstructure_test_traits::Interest
///                 {
///                     fn interesting(&self) -> bool {
///                         match *self {
///                             A {
///                                 x: ref __binding_0,
///                                 c: ref __binding_2,
///                                 ..
///                             } => {
///                                 false ||
///                                     synstructure_test_traits::Interest::interesting(__binding_0) ||
///                                     synstructure_test_traits::Interest::interesting(__binding_2)
///                             }
///                         }
///                     }
///                 }
///             };
///         }
///     }
/// }
/// ```
#[cfg(feature = "simple-derive")]
#[macro_export]
macro_rules! simple_derive {
    // entry point
    (
        $iname:ident impl $path:path { $($rest:tt)* }
    ) => {
        simple_derive!(__I [$iname, $path] { $($rest)* } [] []);
    };

    // Adding a filter block
    (
        __I $opt:tt {
            filter($s:ident) {
                $($body:tt)*
            }
            $($rest:tt)*
        } [$($done:tt)*] [$($filter:tt)*]
    ) => {
        simple_derive!(
            __I $opt { $($rest)* } [$($done)*] [
                $($filter)*
                [
                    st_name = $s,
                    body = {
                        $($body)*
                    },
                ]
            ]
        );
    };

    // &self bound method
    (
        __I $opt:tt {
            fn $fn_name:ident (&self as $s:ident $($params:tt)*) $(-> $t:ty)* {
                $($body:tt)*
            }
            $($rest:tt)*
        } [$($done:tt)*] [$($filter:tt)*]
    ) => {
        simple_derive!(
            __I $opt { $($rest)* } [
                $($done)*
                [
                    st_name = $s,
                    bind_style = Ref,
                    body = { $($body)* },
                    result = result,
                    expanded = {
                        fn $fn_name(&self $($params)*) $(-> $t)* {
                            match *self { #result }
                        }
                    },
                ]
            ] [$($filter)*]
        );
    };

    // &mut self bound method
    (
        __I $opt:tt {
            fn $fn_name:ident (&mut self as $s:ident $($params:tt)*) $(-> $t:ty)* {
                $($body:tt)*
            }
            $($rest:tt)*
        } [$($done:tt)*] [$($filter:tt)*]
    ) => {
        simple_derive!(
            __I $opt { $($rest)* } [
                $($done)*
                [
                    st_name = $s,
                    bind_style = RefMut,
                    body = { $($body)* },
                    result = result,
                    expanded = {
                        fn $fn_name(&mut self $($params)*) $(-> $t)* {
                            match *self { #result }
                        }
                    },
                ]
            ] [$($filter)*]
        );
    };

    // self bound method
    (
        __I $opt:tt {
            fn $fn_name:ident (self as $s:ident $($params:tt)*) $(-> $t:ty)* {
                $($body:tt)*
            }
            $($rest:tt)*
        } [$($done:tt)*] [$($filter:tt)*]
    ) => {
        simple_derive!(
            __I $opt { $($rest)* } [
                $($done)*
                [
                    st_name = $s,
                    bind_style = Move,
                    body = { $($body)* },
                    result = result,
                    expanded = {
                        fn $fn_name(self $($params)*) $(-> $t)* {
                            match self { #result }
                        }
                    },
                ]
            ] [$($filter)*]
        );
    };

    // XXX: Static methods?

    // codegen after data collection
    (
        __I [$iname:ident, $path:path] {} [$(
            [
                st_name = $st_name:ident,
                bind_style = $bind_style:ident,
                body = $body:tt,
                result = $result:ident,
                expanded = { $($expanded:tt)* },
            ]
        )*] [$(
            [
                st_name = $filter_st_name:ident,
                body = $filter_body:tt,
            ]
        )*]
    ) => {
        fn $iname(mut st: $crate::Structure) -> $crate::macros::TokenStream2 {
            let _ = &mut st; // Silence the unused mut warning

            // Filter/transform the `Structure` object before cloning it for
            // individual methods.
            $(
                {
                    let $filter_st_name = &mut st;
                    $filter_body
                }
            )*

            // Clone the `Structure` object and set the correct binding style,
            // then perform method specific expansion.
            $(
                let $result = {
                    let mut $st_name = st.clone();
                    $st_name.bind_with(|_| ::synstructure::BindStyle::$bind_style);
                    let $result = {
                        $body
                    };
                    quote!{ $($expanded)* }
                };
            )*

            st.bound_impl(quote!($path), quote!{
                $(#$result)*
            })
        }
    }
}
<commit_msg>Use :: prefixed paths<commit_after>//! This module provides two utility macros for testing custom derives. They can
//! be used together to eliminate some of the boilerplate required in order to
//! declare and test custom derive implementations.

// Re-exports used by the decl_derive! and test_derive!
pub use proc_macro::TokenStream;
pub use proc_macro2::TokenStream as TokenStream2;
pub use syn::{parse, parse_str, DeriveInput};

/// The `decl_derive!` macro declares a custom derive wrapper. It will parse the
/// incoming `TokenStream` into a `synstructure::Structure` object, and pass it
/// into the inner function.
///
/// Your inner function should take a `synstructure::Structure` by value, and
/// return a type implementing `synstructure::MacroResult`, for example:
///
/// ```
/// # extern crate quote;
/// # extern crate proc_macro;
/// # extern crate proc_macro2;
/// # extern crate synstructure;
/// # extern crate syn;
/// fn derive_simple(input: synstructure::Structure) -> proc_macro2::TokenStream {
///     unimplemented!()
/// }
///
/// fn derive_result(input: synstructure::Structure)
///     -> syn::Result<proc_macro2::TokenStream>
/// {
///     unimplemented!()
/// }
/// ```
///
/// # Usage
///
/// ### Without Attributes
/// ```
/// # #[macro_use] extern crate quote;
/// # extern crate proc_macro2;
/// # extern crate synstructure;
/// # fn main() {}
/// fn derive_interesting(_input: synstructure::Structure) -> proc_macro2::TokenStream {
///     quote! { ... }
/// }
///
/// # const _IGNORE: &'static str = stringify! {
/// decl_derive!([Interesting] => derive_interesting);
/// # };
/// ```
///
/// ### With Attributes
/// ```
/// # #[macro_use] extern crate quote;
/// # extern crate proc_macro2;
/// # extern crate synstructure;
/// # fn main() {}
/// fn derive_interesting(_input: synstructure::Structure) -> proc_macro2::TokenStream {
///     quote! { ... }
/// }
///
/// # const _IGNORE: &'static str = stringify! {
/// decl_derive!([Interesting, attributes(interesting_ignore)] => derive_interesting);
/// # };
/// ```
#[macro_export]
macro_rules! decl_derive {
    // XXX: Switch to using this variant everywhere?
    ([$derives:ident $($derive_t:tt)*] => $inner:path) => {
        #[proc_macro_derive($derives $($derive_t)*)]
        #[allow(non_snake_case)]
        pub fn $derives(
            i: $crate::macros::TokenStream
        ) -> $crate::macros::TokenStream {
            match $crate::macros::parse::<$crate::macros::DeriveInput>(i) {
                Ok(p) => {
                    match $crate::Structure::try_new(&p) {
                        Ok(s) => $crate::MacroResult::into_stream($inner(s)),
                        Err(e) => e.to_compile_error().into(),
                    }
                }
                Err(e) => e.to_compile_error().into(),
            }
        }
    };
}

/// The `decl_attribute!` macro declares a custom attribute wrapper. It will
/// parse the incoming `TokenStream` into a `synstructure::Structure` object,
/// and pass it into the inner function.
///
/// Your inner function should have the following type:
///
/// ```
/// # extern crate quote;
/// # extern crate proc_macro2;
/// # extern crate synstructure;
/// fn attribute(
///     attr: proc_macro2::TokenStream,
///     structure: synstructure::Structure,
/// ) -> proc_macro2::TokenStream {
///     unimplemented!()
/// }
/// ```
///
/// # Usage
///
/// ```
/// # #[macro_use] extern crate quote;
/// # extern crate proc_macro2;
/// # extern crate synstructure;
/// # fn main() {}
/// fn attribute_interesting(
///     _attr: proc_macro2::TokenStream,
///     _structure: synstructure::Structure,
/// ) -> proc_macro2::TokenStream {
///     quote! { ... }
/// }
///
/// # const _IGNORE: &'static str = stringify! {
/// decl_attribute!([interesting] => attribute_interesting);
/// # };
/// ```
/// ```
#[macro_export]
macro_rules! decl_attribute {
    ([$attribute:ident] => $inner:path) => {
        #[proc_macro_attribute]
        pub fn $attribute(
            attr: $crate::macros::TokenStream,
            i: $crate::macros::TokenStream,
        ) -> $crate::macros::TokenStream {
            match $crate::macros::parse::<$crate::macros::DeriveInput>(i) {
                Ok(p) => match $crate::Structure::try_new(&p) {
                    Ok(s) => $crate::MacroResult::into_stream($inner(attr.into(), s)),
                    Err(e) => e.to_compile_error().into(),
                },
                Err(e) => e.to_compile_error().into(),
            }
        }
    };
}

/// Run a test on a custom derive. This macro expands both the original struct
/// and the expansion to ensure that they compile correctly, and confirms that
/// feeding the original struct into the named derive will produce the written
/// output.
///
/// You can add `no_build` to the end of the macro invocation to disable
/// checking that the written code compiles. This is useful in contexts where
/// the procedural macro cannot depend on the crate where it is used during
/// tests.
///
/// # Usage
///
/// ```
/// # #[macro_use] extern crate quote;
/// # extern crate proc_macro2;
/// # #[macro_use] extern crate synstructure;
/// # extern crate syn;
/// fn test_derive_example(_s: synstructure::Structure)
///     -> Result<proc_macro2::TokenStream, syn::Error>
/// {
///     Ok(quote! { const YOUR_OUTPUT: &'static str = "here"; })
/// }
///
/// fn main() {
///     test_derive!{
///         test_derive_example {
///             struct A;
///         }
///         expands to {
///             const YOUR_OUTPUT: &'static str = "here";
///         }
///     }
/// }
/// ```
#[macro_export]
macro_rules! test_derive {
    ($name:path { $($i:tt)* } expands to { $($o:tt)* }) => {
        {
            #[allow(dead_code)]
            fn ensure_compiles() {
                $($i)*
                $($o)*
            }

            $crate::test_derive!($name { $($i)* } expands to { $($o)* } no_build);
        }
    };

    ($name:path { $($i:tt)* } expands to { $($o:tt)* } no_build) => {
        {
            let i = stringify!( $($i)* );
            let parsed = $crate::macros::parse_str::<$crate::macros::DeriveInput>(i)
                .expect(concat!(
                    "Failed to parse input to `#[derive(",
                    stringify!($name),
                    ")]`",
                ));

            let raw_res = $name($crate::Structure::new(&parsed));
            let res = $crate::MacroResult::into_result(raw_res)
                .expect(concat!(
                    "Procedural macro failed for `#[derive(",
                    stringify!($name),
                    ")]`",
                ));

            let expected = stringify!( $($o)* )
                .parse::<$crate::macros::TokenStream2>()
                .expect("output should be a valid TokenStream");
            let mut expected_toks = $crate::macros::TokenStream2::from(expected);
            if res.to_string() != expected_toks.to_string() {
                panic!("\
test_derive failed:
expected:
```
{}
```

got:
```
{}
```\n",
                    $crate::unpretty_print(&expected_toks),
                    $crate::unpretty_print(&res),
                );
            }
        }
    };
}

/// A helper macro for declaring relatively straightforward derive
/// implementations. It provides mechanisms for operating over structures
/// performing modifications on each field etc.
///
/// This macro doesn't define the actual derive, but rather the implementation
/// method. Use `decl_derive!` to generate the implementation wrapper.
///
/// # Stability Warning
///
/// This is an unstable experimental macro API, which may be changed or removed
/// in a future version. I'm not yet confident enough that this API is useful
/// enough to warrant its complexity and inclusion in `synstructure`.
///
/// # Caveat
///
/// The `quote!` macro from `quote` must be imported in the calling crate, as
/// this macro depends on it.
///
/// # Note
///
/// This feature is implemented behind the `simple-derive` feature, and is only
/// available when that feature is enabled.
///
/// # Example
///
/// ```
/// extern crate syn;
/// #[macro_use]
/// extern crate quote;
/// #[macro_use]
/// extern crate synstructure;
/// extern crate proc_macro2;
/// # const _IGNORE: &'static str = stringify! {
/// decl_derive!([Interest] => derive_interest);
/// # };
///
/// simple_derive! {
///     // This macro implements the `Interesting` method exported by the `aa`
///     // crate. It will explicitly add an `extern crate` invocation to import the
///     // crate into the expanded context.
///     derive_interest impl synstructure_test_traits::Interest {
///         // A "filter" block can be added. It evaluates its body with the (s)
///         // variable bound to a mutable reference to the input `Structure`
///         // object.
///         //
///         // This block can be used to perform general transformations, such as
///         // filtering out fields which should be ignored by all methods and for
///         // the purposes of binding type parameters.
///         filter(s) {
///             s.filter(|bi| bi.ast().ident != Some(syn::Ident::new("a",
///                 proc_macro2::Span::call_site())));
///         }
///
///         // This is an implementation of a method in the implemented crate. The
///         // return value should be the series of match patterns to destructure
///         // the `self` argument with.
///         fn interesting(&self as s) -> bool {
///             s.fold(false, |acc, bi| {
///                 quote!(#acc || synstructure_test_traits::Interest::interesting(#bi))
///             })
///         }
///     }
/// }
///
/// fn main() {
///     test_derive!{
///         derive_interest {
///             struct A<T> {
///                 x: i32,
///                 a: bool, // Will be ignored by filter
///                 c: T,
///             }
///         }
///         expands to {
///             #[allow(non_upper_case_globals)]
///             #[doc(hidden)]
///             const _DERIVE_synstructure_test_traits_Interest_FOR_A: () = {
///                 extern crate synstructure_test_traits;
///                 impl<T> synstructure_test_traits::Interest for A<T>
///                     where T: synstructure_test_traits::Interest
///                 {
///                     fn interesting(&self) -> bool {
///                         match *self {
///                             A {
///                                 x: ref __binding_0,
///                                 c: ref __binding_2,
///                                 ..
///                             } => {
///                                 false ||
///                                     synstructure_test_traits::Interest::interesting(__binding_0) ||
///                                     synstructure_test_traits::Interest::interesting(__binding_2)
///                             }
///                         }
///                     }
///                 }
///             };
///         }
///     }
/// }
/// ```
#[cfg(feature = "simple-derive")]
#[macro_export]
macro_rules! simple_derive {
    // entry point
    (
        $iname:ident impl $path:path { $($rest:tt)* }
    ) => {
        $crate::simple_derive!(__I [$iname, $path] { $($rest)* } [] []);
    };

    // Adding a filter block
    (
        __I $opt:tt {
            filter($s:ident) {
                $($body:tt)*
            }
            $($rest:tt)*
        } [$($done:tt)*] [$($filter:tt)*]
    ) => {
        $crate::simple_derive!(
            __I $opt { $($rest)* } [$($done)*] [
                $($filter)*
                [
                    st_name = $s,
                    body = {
                        $($body)*
                    },
                ]
            ]
        );
    };

    // &self bound method
    (
        __I $opt:tt {
            fn $fn_name:ident (&self as $s:ident $($params:tt)*) $(-> $t:ty)* {
                $($body:tt)*
            }
            $($rest:tt)*
        } [$($done:tt)*] [$($filter:tt)*]
    ) => {
        $crate::simple_derive!(
            __I $opt { $($rest)* } [
                $($done)*
                [
                    st_name = $s,
                    bind_style = Ref,
                    body = { $($body)* },
                    result = result,
                    expanded = {
                        fn $fn_name(&self $($params)*) $(-> $t)* {
                            match *self { #result }
                        }
                    },
                ]
            ] [$($filter)*]
        );
    };

    // &mut self bound method
    (
        __I $opt:tt {
            fn $fn_name:ident (&mut self as $s:ident $($params:tt)*) $(-> $t:ty)* {
                $($body:tt)*
            }
            $($rest:tt)*
        } [$($done:tt)*] [$($filter:tt)*]
    ) => {
        $crate::simple_derive!(
            __I $opt { $($rest)* } [
                $($done)*
                [
                    st_name = $s,
                    bind_style = RefMut,
                    body = { $($body)* },
                    result = result,
                    expanded = {
                        fn $fn_name(&mut self $($params)*) $(-> $t)* {
                            match *self { #result }
                        }
                    },
                ]
            ] [$($filter)*]
        );
    };

    // self bound method
    (
        __I $opt:tt {
            fn $fn_name:ident (self as $s:ident $($params:tt)*) $(-> $t:ty)* {
                $($body:tt)*
            }
            $($rest:tt)*
        } [$($done:tt)*] [$($filter:tt)*]
    ) => {
        $crate::simple_derive!(
            __I $opt { $($rest)* } [
                $($done)*
                [
                    st_name = $s,
                    bind_style = Move,
                    body = { $($body)* },
                    result = result,
                    expanded = {
                        fn $fn_name(self $($params)*) $(-> $t)* {
                            match self { #result }
                        }
                    },
                ]
            ] [$($filter)*]
        );
    };

    // XXX: Static methods?

    // codegen after data collection
    (
        __I [$iname:ident, $path:path] {} [$(
            [
                st_name = $st_name:ident,
                bind_style = $bind_style:ident,
                body = $body:tt,
                result = $result:ident,
                expanded = { $($expanded:tt)* },
            ]
        )*] [$(
            [
                st_name = $filter_st_name:ident,
                body = $filter_body:tt,
            ]
        )*]
    ) => {
        fn $iname(mut st: $crate::Structure) -> $crate::macros::TokenStream2 {
            let _ = &mut st; // Silence the unused mut warning

            // Filter/transform the `Structure` object before cloning it for
            // individual methods.
            $(
                {
                    let $filter_st_name = &mut st;
                    $filter_body
                }
            )*

            // Clone the `Structure` object and set the correct binding style,
            // then perform method specific expansion.
            $(
                let $result = {
                    let mut $st_name = st.clone();
                    $st_name.bind_with(|_| $crate::BindStyle::$bind_style);
                    let $result = {
                        $body
                    };
                    $crate::quote!{ $($expanded)* }
                };
            )*

            st.bound_impl($crate::quote!($path), $crate::quote!{
                $(#$result)*
            })
        }
    }
}
<|endoftext|>


<commit_before>use super::vector3::Vector3;
use std::ops;

///Implements a matrix 3 x 3
#[derive(Clone, PartialEq, Debug)]
pub struct Matrix3x3 {
    pub r1: Vector3,
    pub r2: Vector3,
    pub r3: Vector3,
}

impl Matrix3x3 {

    ///Creates a new Matrix3x3 from 3 vector3 rows
    pub fn new(r1: Vector3, r2: Vector3, r3: Vector3) -> Matrix3x3 {
        Matrix3x3 {r1: r1, r2: r2, r3: r3}
    }

    ///Creates a new Matrix3x3 from 9 indexed floats
    pub fn new_idx(n1: f32, n2: f32, n3: f32, n4: f32, n5: f32, n6: f32, n7: f32, n8: f32, n9: f32)
                                                                                -> Matrix3x3 {

        Matrix3x3 {r1: Vector3::new(n1, n2, n3),
                   r2: Vector3::new(n4, n5, n6),
                   r3: Vector3::new(n7, n8, n9)}
    }

    pub fn det(self) -> f32 {
        (self.r1.x * self.r2.y * self.r3.z +
            self.r1.y * self.r2.z * self.r3.x +
            self.r1.z * self.r2.x * self.r3.y)
        - (self.r1.z * self.r2.y * self.r3.x +
            self.r1.y * self.r2.x * self.r3.z +
            self.r1.x * self.r2.z * self.r3.y)
    }
}

impl ops::Mul<Vector3> for Matrix3x3 {
    type Output = Vector3;

    ///Implements the transform matrix of a vector 3 into another vector 3.
    fn mul(self, vec: Vector3) -> Vector3 {
        Vector3 {x: self.r1 * vec.clone(),
            y: self.r2 * vec.clone(),
            z: self.r3 * vec.clone()}
    }
}

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

    #[test]
    fn matrix_created_new_from_3_vector3() {
        let actual = Matrix3x3::new(Vector3::new(1f32, 2f32, 3f32),
                                        Vector3::new(1f32, 2f32, 3f32),
                                        Vector3::new(1f32, 2f32, 3f32));
        let expected = Matrix3x3 {r1: Vector3::new(1f32, 2f32, 3f32),
                                        r2: Vector3::new(1f32, 2f32, 3f32),
                                        r3: Vector3::new(1f32, 2f32, 3f32)};
        assert_eq!(expected, actual);
    }

    #[test]
    fn matrix_created_new_from_9_floats() {
        let actual = Matrix3x3::new_idx(1f32, 1f32, 1f32, 1f32, 1f32, 1f32,
                                    1f32, 1f32, 1f32);
        let expected = Matrix3x3 {r1: Vector3::new(1f32, 1f32, 1f32),
                                            r2: Vector3::new(1f32, 1f32, 1f32),
                                            r3: Vector3::new(1f32, 1f32, 1f32)};
        assert_eq!(expected, actual);
    }

    #[test]
    fn vector_transform_by_matrix() {
        let vec = Vector3::new(1f32, 2f32, 3f32);
        let matrix = Matrix3x3::new_idx(1f32, 2f32, 3f32,
                                        4f32, 5f32, 6f32, 7f32, 8f32, 9f32);
        let actual = matrix * vec;
        let expected = Vector3::new(14f32, 32f32, 50f32);
        assert_eq!(expected, actual);
    }

    #[test]
    fn seq_maxtrix_det() {
        let matrix = Matrix3x3::new_idx(1f32, 2f32, 3f32,
                                        4f32, 5f32, 6f32, 7f32, 8f32, 5f32);
        let actual = matrix.det();
        let expected = 12f32;
        assert_eq!(expected, actual);
    }
}<commit_msg>multiplication of matrix value<commit_after>use super::vector3::Vector3;
use std::ops;

///Implements a matrix 3 x 3
#[derive(Clone, PartialEq, Debug)]
pub struct Matrix3x3 {
    pub r1: Vector3,
    pub r2: Vector3,
    pub r3: Vector3,
}

impl Matrix3x3 {

    ///Creates a new Matrix3x3 from 3 vector3 rows
    pub fn new(r1: Vector3, r2: Vector3, r3: Vector3) -> Matrix3x3 {
        Matrix3x3 {r1: r1, r2: r2, r3: r3}
    }

    ///Creates a new Matrix3x3 from 9 indexed floats
    pub fn new_idx(n1: f32, n2: f32, n3: f32, n4: f32, n5: f32, n6: f32, n7: f32, n8: f32, n9: f32)
                                                                                -> Matrix3x3 {

        Matrix3x3 {r1: Vector3::new(n1, n2, n3),
                   r2: Vector3::new(n4, n5, n6),
                   r3: Vector3::new(n7, n8, n9)}
    }

    #[allow(dead_code, non_snake_case)]
    pub fn IDENTITY() -> Matrix3x3 {
        Matrix3x3::new_idx(1f32, 0f32, 0f32, 0f32, 1f32, 0f32,
                           0f32, 0f32, 1f32)
    }

    ///Matrix 3x3 determinant
    pub fn det(self) -> f32 {
        (self.r1.x * self.r2.y * self.r3.z +
            self.r1.y * self.r2.z * self.r3.x +
            self.r1.z * self.r2.x * self.r3.y)
        - (self.r1.z * self.r2.y * self.r3.x +
            self.r1.y * self.r2.x * self.r3.z +
            self.r1.x * self.r2.z * self.r3.y)
    }
}

impl ops::Add for Matrix3x3 {
    type Output = Matrix3x3;

    ///Implements the Matrix 3x3 '+' trait
    fn add(self, new: Matrix3x3) -> Matrix3x3 {
        Matrix3x3::new(
            Vector3::new(self.r1.x + new.r1.x, self.r1.y + new.r1.y, self.r1.z + new.r1.z),
            Vector3::new(self.r2.x + new.r2.x, self.r2.y + new.r2.y, self.r2.z + new.r2.z),
            Vector3::new(self.r3.x + new.r3.x, self.r3.y + new.r3.y, self.r3.z + new.r3.z)
        )
    }
}

impl ops::Mul<Vector3> for Matrix3x3 {
    type Output = Vector3;

    ///Implements the transform matrix of a vector 3 into another vector 3.
    fn mul(self, vec: Vector3) -> Vector3 {
        Vector3 {x: self.r1 * vec.clone(),
            y: self.r2 * vec.clone(),
            z: self.r3 * vec.clone()}
    }
}

impl ops::Mul<f32> for Matrix3x3 {
    type Output = Matrix3x3;

    ///Implements the Matrix 3x3 '*' trait for `Matrix3x3 * f32` so that `(identity * value).det() == valueˆ3`.
    fn mul(self, value: f32) -> Matrix3x3 {
        Matrix3x3::new(
            Vector3::new(self.r1.x * value, self.r1.y * value, self.r1.z * value),
            Vector3::new(self.r2.x * value, self.r2.y * value, self.r2.z * value),
            Vector3::new(self.r3.x * value, self.r3.y * value, self.r3.z * value)
        )
    }
}

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

    #[test]
    fn matrix_created_new_from_3_vector3() {
        let actual = Matrix3x3::new(Vector3::new(1f32, 2f32, 3f32),
                                        Vector3::new(1f32, 2f32, 3f32),
                                        Vector3::new(1f32, 2f32, 3f32));
        let expected = Matrix3x3 {r1: Vector3::new(1f32, 2f32, 3f32),
                                        r2: Vector3::new(1f32, 2f32, 3f32),
                                        r3: Vector3::new(1f32, 2f32, 3f32)};
        assert_eq!(expected, actual);
    }

    #[test]
    fn matrix_created_new_from_9_floats() {
        let actual = Matrix3x3::new_idx(1f32, 1f32, 1f32, 1f32, 1f32, 1f32,
                                    1f32, 1f32, 1f32);
        let expected = Matrix3x3 {r1: Vector3::new(1f32, 1f32, 1f32),
                                            r2: Vector3::new(1f32, 1f32, 1f32),
                                            r3: Vector3::new(1f32, 1f32, 1f32)};
        assert_eq!(expected, actual);
    }

    #[test]
    fn vector_transform_by_matrix() {
        let vec = Vector3::new(1f32, 2f32, 3f32);
        let matrix = Matrix3x3::new_idx(1f32, 2f32, 3f32,
                                        4f32, 5f32, 6f32, 7f32, 8f32, 9f32);
        let actual = matrix * vec;
        let expected = Vector3::new(14f32, 32f32, 50f32);
        assert_eq!(expected, actual);
    }

    #[test]
    fn seq_maxtrix_det() {
        let matrix = Matrix3x3::new_idx(1f32, 2f32, 3f32,
                                        4f32, 5f32, 6f32, 7f32, 8f32, 5f32);
        let actual = matrix.det();
        let expected = 12f32;
        assert_eq!(expected, actual);
    }

    #[test]
    fn identity_matrix_has_det_1() {
        let identity = Matrix3x3::IDENTITY();
        assert_eq!(1f32, identity.det());
    }

    #[test]
    fn identity_plus_identity_has_det_8() {
        let identities = Matrix3x3::IDENTITY() + Matrix3x3::IDENTITY();
        assert_eq!(8f32, identities.det());
    }

    #[test]
    fn det_of_identity_times_3_is_27() {
        let identity_3 = Matrix3x3::IDENTITY() * 3f32;
        assert_eq!(27f32, identity_3.det());
    }
}<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

//! The portable PortAudio API.

use libc::c_double;
use std::ptr;
use ffi;

pub use self::error::Error;
pub use self::stream::Stream;
pub use self::types::{
    DeviceIndex,
    DeviceInfo,
    Frames,
    HostApiIndex,
    HostApiInfo,
    HostApiTypeId,
    HostErrorInfo,
    SampleFormat,
    StreamAvailable,
    stream_callback_flags,
    StreamCallbackFlags,
    StreamCallbackTimeInfo,
    StreamCallbackResult,
    stream_flags,
    StreamFlags,
    StreamInfo,
    StreamParameters,
    Time,
    FRAMES_PER_BUFFER_UNSPECIFIED,
    NO_DEVICE,
    USE_HOST_API_SPECIFIC_DEVICE_SPECIFICATION,
};

pub mod error;
pub mod device;
pub mod host;
pub mod stream;
mod types;

/// Retrieve the release number of the currently running PortAudio build.
pub fn get_version() -> i32 {
    unsafe {
        ffi::Pa_GetVersion()
    }
}

/// Retrieve a textual description of the current PortAudio build.
pub fn get_version_text() -> String {
    unsafe {
        ffi::c_str_to_string(&ffi::Pa_GetVersionText())
    }
}

/// Translate the supplied PortAudio error code into a human readable message.
///
/// # Arguments
/// * error_code - The error code
///
/// Return the error as a string.
pub fn get_error_text(error_code: Error) -> String {
    unsafe {
        ffi::c_str_to_string(&ffi::Pa_GetErrorText(error_code))
    }
}

/// Library initialization function - call this before using PortAudio.
/// This function initializes internal data structures and prepares underlying
/// host APIs for use. With the exception of get_version(), get_version_text(),
/// and get_error_text(), this function MUST be called before using any other
/// PortAudio API functions.
///
/// Note that if initialize() returns an error code, Pa_Terminate() should NOT be
/// called.
///
/// Return NoError if successful, otherwise an error code indicating the cause
/// of failure.
pub fn initialize() -> Result<(), Error> {
    unsafe {
        match ffi::Pa_Initialize() {
            Error::NoError => Ok(()),
            err => Err(err),
        }
    }
}

/// Library termination function - call this when finished using PortAudio.
/// This function deallocates all resources allocated by PortAudio since it was
/// initialized by a call to initialize(). In cases where initialise() has been
/// called multiple times, each call must be matched with a corresponding call to
/// terminate(). The final matching call to terminate() will automatically close
/// any PortAudio streams that are still open.
///
/// terminate() MUST be called before exiting a program which uses PortAudio.
/// Failure to do so may result in serious resource leaks, such as audio devices
/// not being available until the next reboot.
///
/// Return NoError if successful, otherwise an error code indicating the cause
/// of failure.
pub fn terminate() -> Result<(), Error> {
    unsafe {
        match ffi::Pa_Terminate() {
            Error::NoError => Ok(()),
            err => Err(err),
        }
    }
}

/// Return information about the last host error encountered.
/// The error information returned by get_last_host_error_info() will never be
/// modified asynchronously by errors occurring in other PortAudio owned threads
/// (such as the thread that manages the stream callback.)
///
/// This function is provided as a last resort, primarily to enhance debugging
/// by providing clients with access to all available error information.
///
/// Return a pointer to an immuspacespacespacele structure constraining
/// information about the host error. The values in this structure will only be
/// valid if a PortAudio function has previously returned the
/// UnanticipatedHostError error code.
pub fn get_last_host_error_info() -> HostErrorInfo {
    let c_error = unsafe { ffi::Pa_GetLastHostErrorInfo() };
    HostErrorInfo::wrap(c_error)
}

/// Determine whether it would be possible to open a stream with the specified
/// parameters.
///
/// # Arguments
/// * input_parameters - A structure that describes the input parameters used to
/// open a stream.
/// The suggestedLatency field is ignored. See StreamParameters for a
/// description of these parameters. inputParameters must be None for output-only
/// streams.
/// * output_parameters - A structure that describes the output parameters used to
/// open a stream. The suggestedLatency field is ignored. See StreamParameters
/// for a description of these parameters. outputParameters must be None for
/// input-only streams.
/// * sample_rate - The required sampleRate. For full-duplex streams it is the
/// sample rate for both input and output.
///
/// Return 0 if the format is supported, and an error code indicating why the
/// format is not supported otherwise. The constant PaFormatIsSupported is
/// provided to compare with the return value for success.
pub fn is_format_supported(maybe_input_parameters: Option<&StreamParameters>,
                           maybe_output_parameters: Option<&StreamParameters>,
                           sample_rate : f64) -> Result<(), Error> {
    let c_input = maybe_input_parameters.map(StreamParameters::unwrap).as_ref().map(|input| input as *const _);
    let c_output = maybe_output_parameters.map(StreamParameters::unwrap).as_ref().map(|output| output as *const _);
    if c_input.is_none() && c_output.is_none() {
        Err(Error::InvalidDevice)
    } else {
        unsafe {
            match ffi::Pa_IsFormatSupported(c_input.unwrap_or(ptr::null()),
                                            c_output.unwrap_or(ptr::null()),
                                            sample_rate as c_double) {
                Error::NoError => Ok(()),
                err => Err(err),
            }
        }
    }
}

/// Retrieve the size of a given sample format in bytes.
///
/// Return the size in bytes of a single sample in the specified format,
/// or SampleFormatNotSupported if the format is not supported.
pub fn get_sample_size(format: SampleFormat) -> Result<(), Error> {
    match unsafe {
        ffi::Pa_GetSampleSize(format as u64)
    } {
        Error::NoError => Ok(()),
        err => Err(err),
    }
}

/// Put the caller to sleep for at least 'msec' milliseconds.
/// This function is provided only as a convenience for authors of portable code
/// (such as the tests and examples in the PortAudio distribution.)
///
/// The function may sleep longer than requested so don't rely on this for
/// accurate musical timing.
pub fn sleep(m_sec : i32) -> () {
    unsafe {
        ffi::Pa_Sleep(m_sec)
    }
}

mod private {

    use num::{FromPrimitive, ToPrimitive};
    use std::ops::{Add, Sub, Mul, Div};
    use super::types::SampleFormat;

    /// internal private trait for Sample format management
    pub trait SamplePrivate: ::std::default::Default + Copy + Clone + ::std::fmt::Debug
                             + ToPrimitive + FromPrimitive + Add + Sub + Mul + Div {
        /// return the size of a sample format
        fn size<S: SamplePrivate>() -> usize {
            ::std::mem::size_of::<S>()
        }
        /// get the sample format
        fn to_sample_format() -> SampleFormat;
    }

}

impl private::SamplePrivate for f32 {
    fn to_sample_format() -> SampleFormat { SampleFormat::Float32 }
}

impl private::SamplePrivate for i32 {
    fn to_sample_format() -> SampleFormat { SampleFormat::Int32 }
}

impl private::SamplePrivate for u8 {
    fn to_sample_format() -> SampleFormat { SampleFormat::UInt8 }
}

impl private::SamplePrivate for i8 {
    fn to_sample_format() -> SampleFormat { SampleFormat::Int8 }
}

/// public trait to constraint pa::Stream for specific types
pub trait Sample: private::SamplePrivate {
    /// Retrieve the SampleFormat variant associated with the type.
    fn sample_format_for<S: Sample>() -> SampleFormat {
        S::to_sample_format()
    }
    /// Retrieve the SampleFormat variant associated with the type.
    fn sample_format(&self) -> SampleFormat { Self::to_sample_format() }
}

impl Sample for f32 {}
impl Sample for i32 {}
impl Sample for i8 {}
impl Sample for u8 {}
<commit_msg>Introduce PortAudio type (WIP)<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

//! The portable PortAudio API.

use ffi;
use libc::c_double;
use std::ptr;
use std::marker::PhantomData;

pub use self::error::Error;
pub use self::stream::Stream;
pub use self::types::{
    DeviceIndex,
    DeviceInfo,
    Frames,
    HostApiIndex,
    HostApiInfo,
    HostApiTypeId,
    HostErrorInfo,
    SampleFormat,
    StreamAvailable,
    stream_callback_flags,
    StreamCallbackFlags,
    StreamCallbackTimeInfo,
    StreamCallbackResult,
    stream_flags,
    StreamFlags,
    StreamInfo,
    StreamParameters,
    Time,
    FRAMES_PER_BUFFER_UNSPECIFIED,
    NO_DEVICE,
    USE_HOST_API_SPECIFIC_DEVICE_SPECIFICATION,
};

pub mod error;
pub mod device;
pub mod host;
pub mod stream;
mod types;

/// A type-safe wrapper around the PortAudio API.
///
/// We use a type here instead of pure functions in order to ensure correct intialisation and
/// termination of the underlying PortAudio instance.
#[derive(Debug)]
pub struct PortAudio {
    /// This is solely used for checking whether or not the PortAudio API has already been
    /// terminated manually (via the `PortAudio::terminate` method) when `Drop::drop` is called.
    is_terminated: bool,
}

impl PortAudio {

    /// Construct a **PortAudio** instance.
    ///
    /// This calls PortAudio's `Pa_Initialize` function which initializes internal data structures
    /// and prepares underlying host APIs for use.
    ///
    /// Using the C API, a user would normally have to call `Pa_Terminate` when shutting down
    /// PortAudio, however this **PortAudio** type will automatically take care of this when
    /// `Drop`ped.
    ///
    /// It is safe to simultaneously construct more than one **PortAudio** instance, however this
    /// is rarely necessary.
    pub fn new() -> Result<Self, Error> {
        unsafe {
            match ffi::Pa_Initialize() {
                Error::NoError => Ok(PortAudio { is_terminated: false }),
                err => Err(err),
            }
        }
    }

    /// Takes ownership of `self` and terminates the PortAudio API using `Pa_Terminate`.
    ///
    /// This function deallocates all resources allocated by PortAudio since it was constructed.
    ///
    /// **Calling this method is optional**. It is only necessary if you require handling any
    /// PortAudio termination errors. Otherwise, `Pa_Terminate` will be called and all necessary
    /// cleanup will occur automatically when this **PortAudio** instance is **Drop**ped.
    pub fn terminate(mut self) -> Result<(), Error> {
        self.is_terminated = true;
        terminate()
    }

}

impl Drop for PortAudio {
    fn drop(&mut self) {
        if !self.is_terminated {
            terminate();
        }
    }
}

/// Retrieve the release number of the currently running PortAudio build.
pub fn get_version() -> i32 {
    unsafe {
        ffi::Pa_GetVersion()
    }
}

/// Retrieve a textual description of the current PortAudio build.
pub fn get_version_text() -> String {
    unsafe {
        ffi::c_str_to_string(&ffi::Pa_GetVersionText())
    }
}

/// Translate the supplied PortAudio error code into a human readable message.
///
/// # Arguments
/// * error_code - The error code
///
/// Return the error as a string.
pub fn get_error_text(error_code: Error) -> String {
    unsafe {
        ffi::c_str_to_string(&ffi::Pa_GetErrorText(error_code))
    }
}

// /// Library initialization function - call this before using PortAudio.
// /// This function initializes internal data structures and prepares underlying
// /// host APIs for use. With the exception of get_version(), get_version_text(),
// /// and get_error_text(), this function MUST be called before using any other
// /// PortAudio API functions.
// ///
// /// Note that if initialize() returns an error code, Pa_Terminate() should NOT be
// /// called.
// ///
// /// Return NoError if successful, otherwise an error code indicating the cause
// /// of failure.
// fn initialize() -> Result<(), Error> {
//     unsafe {
//         match ffi::Pa_Initialize() {
//             Error::NoError => Ok(()),
//             err => Err(err),
//         }
//     }
// }

/// Library termination function - call this when finished using PortAudio.
/// This function deallocates all resources allocated by PortAudio since it was
/// initialized by a call to initialize(). In cases where initialise() has been
/// called multiple times, each call must be matched with a corresponding call to
/// terminate(). The final matching call to terminate() will automatically close
/// any PortAudio streams that are still open.
///
/// terminate() MUST be called before exiting a program which uses PortAudio.
/// Failure to do so may result in serious resource leaks, such as audio devices
/// not being available until the next reboot.
///
/// **Note:** The above resource management is automatically handled by the
/// **PortAudio** type.
///
/// Return NoError if successful, otherwise an error code indicating the cause
/// of failure.
fn terminate() -> Result<(), Error> {
    unsafe {
        match ffi::Pa_Terminate() {
            Error::NoError => Ok(()),
            err => Err(err),
        }
    }
}

/// Return information about the last host error encountered.
/// The error information returned by get_last_host_error_info() will never be
/// modified asynchronously by errors occurring in other PortAudio owned threads
/// (such as the thread that manages the stream callback.)
///
/// This function is provided as a last resort, primarily to enhance debugging
/// by providing clients with access to all available error information.
///
/// Return a pointer to an immuspacespacespacele structure constraining
/// information about the host error. The values in this structure will only be
/// valid if a PortAudio function has previously returned the
/// UnanticipatedHostError error code.
pub fn get_last_host_error_info() -> HostErrorInfo {
    let c_error = unsafe { ffi::Pa_GetLastHostErrorInfo() };
    HostErrorInfo::wrap(c_error)
}

/// Determine whether it would be possible to open a stream with the specified
/// parameters.
///
/// # Arguments
/// * input_parameters - A structure that describes the input parameters used to
/// open a stream.
/// The suggestedLatency field is ignored. See StreamParameters for a
/// description of these parameters. inputParameters must be None for output-only
/// streams.
/// * output_parameters - A structure that describes the output parameters used to
/// open a stream. The suggestedLatency field is ignored. See StreamParameters
/// for a description of these parameters. outputParameters must be None for
/// input-only streams.
/// * sample_rate - The required sampleRate. For full-duplex streams it is the
/// sample rate for both input and output.
///
/// Return 0 if the format is supported, and an error code indicating why the
/// format is not supported otherwise. The constant PaFormatIsSupported is
/// provided to compare with the return value for success.
pub fn is_format_supported(maybe_input_parameters: Option<&StreamParameters>,
                           maybe_output_parameters: Option<&StreamParameters>,
                           sample_rate : f64) -> Result<(), Error> {
    let c_input = maybe_input_parameters.map(StreamParameters::unwrap).as_ref().map(|input| input as *const _);
    let c_output = maybe_output_parameters.map(StreamParameters::unwrap).as_ref().map(|output| output as *const _);
    if c_input.is_none() && c_output.is_none() {
        Err(Error::InvalidDevice)
    } else {
        unsafe {
            match ffi::Pa_IsFormatSupported(c_input.unwrap_or(ptr::null()),
                                            c_output.unwrap_or(ptr::null()),
                                            sample_rate as c_double) {
                Error::NoError => Ok(()),
                err => Err(err),
            }
        }
    }
}

/// Retrieve the size of a given sample format in bytes.
///
/// Return the size in bytes of a single sample in the specified format,
/// or SampleFormatNotSupported if the format is not supported.
pub fn get_sample_size(format: SampleFormat) -> Result<(), Error> {
    match unsafe {
        ffi::Pa_GetSampleSize(format as u64)
    } {
        Error::NoError => Ok(()),
        err => Err(err),
    }
}

/// Put the caller to sleep for at least 'msec' milliseconds.
/// This function is provided only as a convenience for authors of portable code
/// (such as the tests and examples in the PortAudio distribution.)
///
/// The function may sleep longer than requested so don't rely on this for
/// accurate musical timing.
pub fn sleep(m_sec : i32) -> () {
    unsafe {
        ffi::Pa_Sleep(m_sec)
    }
}

mod private {

    use num::{FromPrimitive, ToPrimitive};
    use std::ops::{Add, Sub, Mul, Div};
    use super::types::SampleFormat;

    /// internal private trait for Sample format management
    pub trait SamplePrivate: ::std::default::Default + Copy + Clone + ::std::fmt::Debug
                             + ToPrimitive + FromPrimitive + Add + Sub + Mul + Div {
        /// return the size of a sample format
        fn size<S: SamplePrivate>() -> usize {
            ::std::mem::size_of::<S>()
        }
        /// get the sample format
        fn to_sample_format() -> SampleFormat;
    }

}

impl private::SamplePrivate for f32 {
    fn to_sample_format() -> SampleFormat { SampleFormat::Float32 }
}

impl private::SamplePrivate for i32 {
    fn to_sample_format() -> SampleFormat { SampleFormat::Int32 }
}

impl private::SamplePrivate for u8 {
    fn to_sample_format() -> SampleFormat { SampleFormat::UInt8 }
}

impl private::SamplePrivate for i8 {
    fn to_sample_format() -> SampleFormat { SampleFormat::Int8 }
}

/// public trait to constraint pa::Stream for specific types
pub trait Sample: private::SamplePrivate {
    /// Retrieve the SampleFormat variant associated with the type.
    fn sample_format_for<S: Sample>() -> SampleFormat {
        S::to_sample_format()
    }
    /// Retrieve the SampleFormat variant associated with the type.
    fn sample_format(&self) -> SampleFormat { Self::to_sample_format() }
}

impl Sample for f32 {}
impl Sample for i32 {}
impl Sample for i8 {}
impl Sample for u8 {}
<|endoftext|>


<commit_before>use super::models::{LanguageModel, WordVec};
use self::Token::*;
use super::mayberef::MaybeRef::{self, Val, Ref};
use std::fmt::{Display, Formatter, Error};

pub fn parse(expr: &str, model: &LanguageModel) -> Result<WordVec, String> {
    expression(&mut Tokens::from(expr.chars()), model).map(|w| w.take())
}

#[derive(PartialEq, Eq, Debug, Clone)]
enum Token {
    RParen,
    LParen,
    Plus,
    Minus,
    Word(String),
    Invalid(char),
}

impl Display for Token {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        let invalid;
        fmt.write_str(match *self {
            RParen => ")",
            LParen => "(",
            Plus => "+",
            Minus => "-",
            Word(ref w) => &*w,
            Invalid(w) => {
                invalid = w.to_string();
                &*invalid
            },
        })
    }
}

fn expression<'a, I>(tokens: &mut Tokens<I>, model: &'a LanguageModel)
    -> Result<MaybeRef<'a, WordVec>, String>
    where I: Iterator<Item = char>
{
    let token = try!(tokens.next().ok_or("An expression may not be empty"));
    match token {
        LParen => {
            let vec = try!(expression(tokens, model));
            let rparen = try!(tokens.next().ok_or("Unbalanced parentheses"));
            if rparen != RParen {
                return Err(format!("Expected ')', found '{}'", rparen))
            }
            rhs(vec, tokens, model)
        },
        Word(word) => {
            let vec = try!(model.get(&*word).ok_or_else(||
                format!("'{}' is not present in the language model", &word)
            ));
            rhs(Ref(vec), tokens, model)
        },
        _ => Err(format!("An expression may not start with '{}'", token)),
    }
}

fn rhs<'a, I>(lhs: MaybeRef<'a, WordVec>, tokens: &mut Tokens<I>, model: &LanguageModel)
    -> Result<MaybeRef<'a, WordVec>, String>
    where I: Iterator<Item = char>
{
    match tokens.peek() {
        Some(&RParen) | None => return Ok(lhs),
        _ => {}
    }

    let token = tokens.next().unwrap();
    match token {
        Plus => Ok(Val(lhs.take() + &*try!(expression(tokens, model)))),
        Minus => Ok(Val(lhs.take() - &*try!(expression(tokens, model)))),
        Word(_) | LParen => Err(format!("'{}' found in invalid position", token)),
        Invalid(s) => Err(format!("'{}' could not be tokenized", s)),
        RParen => unreachable!(),
    }
}

fn atom<'a, I>(tokens: &mut Tokens<I>, model: &'a LanguageModel)
    -> Result<MaybeRef<'a, WordVec>, String>
    where I: Iterator<Item = char>
{
    {
        let token = try!(tokens.peek().ok_or("Invalid end of expression"));
        match *token {
            Plus | Minus | Invalid(_) | RParen => {
                return Err(format!("Invalid token {}", token));
            }
            _ => {},
        }
    }

    let token = tokens.next().unwrap();
    match token {
        LParen => {
            let expr = try!(expression(tokens, model));
            match tokens.next() {
                Some(RParen) => Ok(expr),
                Some(t) => Err(format!("Expected ')', found '{}'", t)),
                None => Err("Unclosed parentheses".to_string()),
            }
        }
        Word(word) =>  {
            let vec = try!(model.get(&*word).ok_or_else(||
                format!("'{}' is not present in the language model", &word)
            ));
            Ok(Ref(vec))
        }
        _ => unreachable!(),
    }
}

struct Tokens<I> {
    iter: I,
    next_char: Option<Option<char>>,
    next_token: Option<Option<Token>>
}

impl<I> Tokens<I> where I: Iterator<Item = char> {
    fn from(iter: I) -> Tokens<I> {
        Tokens {
            iter: iter,
            next_char: None,
            next_token: None,
        }
    }

    fn get_next_token(&mut self) -> Option<Token> {
        while let Some(' ') = self.peek_char() {
            self.take();
        }

        match self.peek_char() {
            Some('a'...'z') => return Some(self.word()),
            // Some('0'..'9') | Some('.') => return Some(self.number()),
            None => return None,
            _ => {}
        }

        Some(match self.take().unwrap() {
            '+' => Plus,
            '-' => Minus,
            '(' => LParen,
            ')' => RParen,
            c => Invalid(c),
        })
    }

    fn peek(&mut self) -> Option<&Token> {
        if let Some(ref t) = self.next_token {
            return t.as_ref();
        }

        self.next_token = Some(self.get_next_token());
        return self.next_token.as_ref().unwrap().as_ref();
    }

    fn peek_char(&mut self) -> Option<char> {
        match self.next_char {
            Some(x) => x,
            None => {
                let next = self.iter.next();
                self.next_char = Some(next);
                next
            }
        }
    }

    fn take(&mut self) -> Option<char> {
        self.peek_char();
        self.next_char.take().unwrap()
    }

    fn word(&mut self) -> Token {
        let mut token = String::new();
        while let Some('a'...'z') = self.peek_char() {
            token.push(self.take().unwrap());
        }

        Word(token)
    }

}

impl<I> Iterator for Tokens<I> where I: Iterator<Item = char> {
    type Item = Token;

    fn next(&mut self) -> Option<Token> {
        self.peek();
        self.next_token.take().unwrap()
    }
}

mod test {
    use super::Tokens;
    use super::Token::*;

    #[test]
    fn single_character() {
        let c = Tokens::from("a".chars()).next().unwrap();
        assert_eq!(c, Word("a".to_string()));
    }

    #[test]
    fn single_token() {
        let s = Tokens::from("abc".chars()).next().unwrap();
        assert_eq!(s, Word("abc".to_string()));
    }

    #[test]
    fn two_tokens() {
        let s = Tokens::from("abc def".chars()).collect::<Vec<_>>();
        assert_eq!(s, vec![Word("abc".to_string()), Word("def".to_string())]);
    }

    #[test]
    fn plus_tokens() {
        let s = Tokens::from("   abc  +def".chars()).collect::<Vec<_>>();
        assert_eq!(s, vec![Word("abc".to_string()), Plus, Word("def".to_string())]);
    }

    #[test]
    fn bracket_tokens() {
        let s = Tokens::from(" ()  (abc  +)def".chars()).collect::<Vec<_>>();
        assert_eq!(s, vec![LParen, RParen, LParen, Word("abc".to_string()),
            Plus, RParen, Word("def".to_string())]);
    }

    #[test]
    fn test_associativity() {
        use super::parse;
        use super::super::models::{WordVec, LanguageModel, LanguageModelBuilder};

        let words = vec!("a".to_string(), "b".to_string(), "c".to_string());
        let mut builder = LanguageModelBuilder::new(1, words);

        {
            let mut acc = builder.new_file();
            let text = "x x a a b a c b x x";
            for word in text.split(' ') {
                acc.add_word(word.to_string());
            }
        }

        let model = builder.build();
        assert_eq!(parse("a - b + c", &model).unwrap(), parse("(a - b) + c", &model).unwrap());
    }
}<commit_msg>Integrate the new parser phase, correcting the failing test.<commit_after>use super::models::{LanguageModel, WordVec};
use self::Token::*;
use super::mayberef::MaybeRef::{self, Val, Ref};
use std::fmt::{Display, Formatter, Error};

pub fn parse(expr: &str, model: &LanguageModel) -> Result<WordVec, String> {
    expression(&mut Tokens::from(expr.chars()), model).map(|w| w.take())
}

#[derive(PartialEq, Eq, Debug, Clone)]
enum Token {
    RParen,
    LParen,
    Plus,
    Minus,
    Word(String),
    Invalid(char),
}

impl Token {
    fn apply_addop(&self, lhs: WordVec, rhs: &WordVec) -> Result<WordVec, String> {
        match *self {
            Plus => Ok(lhs + rhs),
            Minus => Ok(lhs - rhs),
            _ => Err(format!("Internal error: tried calling add using {}", self)),
        }
    }
}

impl Display for Token {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        let invalid;
        fmt.write_str(match *self {
            RParen => ")",
            LParen => "(",
            Plus => "+",
            Minus => "-",
            Word(ref w) => &*w,
            Invalid(w) => {
                invalid = w.to_string();
                &*invalid
            },
        })
    }
}

fn expression<'a, I>(tokens: &mut Tokens<I>, model: &'a LanguageModel)
    -> Result<MaybeRef<'a, WordVec>, String>
    where I: Iterator<Item = char>
{
    let token = try!(tokens.next().ok_or("An expression may not be empty"));
    match token {
        LParen => {
            let vec = try!(expression(tokens, model));
            let rparen = try!(tokens.next().ok_or("Unbalanced parentheses"));
            if rparen != RParen {
                return Err(format!("Expected ')', found '{}'", rparen))
            }
            rhs(vec, tokens, model)
        },
        Word(word) => {
            let vec = try!(model.get(&*word).ok_or_else(||
                format!("'{}' is not present in the language model", &word)
            ));
            rhs(Ref(vec), tokens, model)
        },
        _ => Err(format!("An expression may not start with '{}'", token)),
    }
}

fn rhs<'a, I>(lhs: MaybeRef<'a, WordVec>, tokens: &mut Tokens<I>, model: &LanguageModel)
    -> Result<MaybeRef<'a, WordVec>, String>
    where I: Iterator<Item = char>
{
    match tokens.peek() {
        Some(&RParen) | None => return Ok(lhs),
        _ => {}
    }

    let token = tokens.next().unwrap();
    match token {
        Plus | Minus => {
            let lhs = lhs.take();
            let atom = try!(atom(tokens, model));
            let result = try!(token.apply_addop(lhs, &*atom));
            rhs(Val(result), tokens, model)
        }
        Word(_) | LParen => Err(format!("'{}' found in invalid position", token)),
        Invalid(s) => Err(format!("'{}' could not be tokenized", s)),
        RParen => unreachable!(),
    }
}

fn atom<'a, I>(tokens: &mut Tokens<I>, model: &'a LanguageModel)
    -> Result<MaybeRef<'a, WordVec>, String>
    where I: Iterator<Item = char>
{
    {
        let token = try!(tokens.peek().ok_or("Invalid end of expression"));
        match *token {
            Plus | Minus | Invalid(_) | RParen => {
                return Err(format!("Invalid token {}", token));
            }
            _ => {},
        }
    }

    let token = tokens.next().unwrap();
    match token {
        LParen => {
            let expr = try!(expression(tokens, model));
            match tokens.next() {
                Some(RParen) => Ok(expr),
                Some(t) => Err(format!("Expected ')', found '{}'", t)),
                None => Err("Unclosed parentheses".to_string()),
            }
        }
        Word(word) =>  {
            let vec = try!(model.get(&*word).ok_or_else(||
                format!("'{}' is not present in the language model", &word)
            ));
            Ok(Ref(vec))
        }
        _ => unreachable!(),
    }
}

struct Tokens<I> {
    iter: I,
    next_char: Option<Option<char>>,
    next_token: Option<Option<Token>>
}

impl<I> Tokens<I> where I: Iterator<Item = char> {
    fn from(iter: I) -> Tokens<I> {
        Tokens {
            iter: iter,
            next_char: None,
            next_token: None,
        }
    }

    fn get_next_token(&mut self) -> Option<Token> {
        while let Some(' ') = self.peek_char() {
            self.take();
        }

        match self.peek_char() {
            Some('a'...'z') => return Some(self.word()),
            // Some('0'..'9') | Some('.') => return Some(self.number()),
            None => return None,
            _ => {}
        }

        Some(match self.take().unwrap() {
            '+' => Plus,
            '-' => Minus,
            '(' => LParen,
            ')' => RParen,
            c => Invalid(c),
        })
    }

    fn peek(&mut self) -> Option<&Token> {
        if let Some(ref t) = self.next_token {
            return t.as_ref();
        }

        self.next_token = Some(self.get_next_token());
        return self.next_token.as_ref().unwrap().as_ref();
    }

    fn peek_char(&mut self) -> Option<char> {
        match self.next_char {
            Some(x) => x,
            None => {
                let next = self.iter.next();
                self.next_char = Some(next);
                next
            }
        }
    }

    fn take(&mut self) -> Option<char> {
        self.peek_char();
        self.next_char.take().unwrap()
    }

    fn word(&mut self) -> Token {
        let mut token = String::new();
        while let Some('a'...'z') = self.peek_char() {
            token.push(self.take().unwrap());
        }

        Word(token)
    }

}

impl<I> Iterator for Tokens<I> where I: Iterator<Item = char> {
    type Item = Token;

    fn next(&mut self) -> Option<Token> {
        self.peek();
        self.next_token.take().unwrap()
    }
}

mod test {
    use super::Tokens;
    use super::Token::*;

    #[test]
    fn single_character() {
        let c = Tokens::from("a".chars()).next().unwrap();
        assert_eq!(c, Word("a".to_string()));
    }

    #[test]
    fn single_token() {
        let s = Tokens::from("abc".chars()).next().unwrap();
        assert_eq!(s, Word("abc".to_string()));
    }

    #[test]
    fn two_tokens() {
        let s = Tokens::from("abc def".chars()).collect::<Vec<_>>();
        assert_eq!(s, vec![Word("abc".to_string()), Word("def".to_string())]);
    }

    #[test]
    fn plus_tokens() {
        let s = Tokens::from("   abc  +def".chars()).collect::<Vec<_>>();
        assert_eq!(s, vec![Word("abc".to_string()), Plus, Word("def".to_string())]);
    }

    #[test]
    fn bracket_tokens() {
        let s = Tokens::from(" ()  (abc  +)def".chars()).collect::<Vec<_>>();
        assert_eq!(s, vec![LParen, RParen, LParen, Word("abc".to_string()),
            Plus, RParen, Word("def".to_string())]);
    }

    #[test]
    fn test_associativity() {
        use super::parse;
        use super::super::models::{WordVec, LanguageModel, LanguageModelBuilder};

        let words = vec!("a".to_string(), "b".to_string(), "c".to_string());
        let mut builder = LanguageModelBuilder::new(1, words);

        {
            let mut acc = builder.new_file();
            let text = "x x a a b a c b x x";
            for word in text.split(' ') {
                acc.add_word(word.to_string());
            }
        }

        let model = builder.build();
        assert_eq!(parse("a - b + c", &model).unwrap(), parse("(a - b) + c", &model).unwrap());
    }
}<|endoftext|>


<commit_before>extern crate byteorder;

use std::error;
use std::fmt;
use std::io;
use std::mem;

use self::byteorder::{ByteOrder, BigEndian, LittleEndian};

use super::Catalog;

/// Represents an error encountered while parsing an MO file.
#[derive(Debug)]
pub enum Error {
    /// An incorrect magic number has been encountered
    BadMagic,
    /// An unexpected EOF occured
    Eof,
    /// An I/O error occured
    Io(io::Error),
}
use Error::*;

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            BadMagic => "bad magic number",
            Eof => "unxpected end of file",
            Io(ref err) => err.description(),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let self_err: &error::Error = self;
        write!(fmt, "{}", self_err.description())
    }
}

impl From<io::Error> for Error {
    fn from(inner: io::Error) -> Error {
        Io(inner)
    }
}

/// According to the given magic number of a MO file,
/// returns the function which reads a `u32` in the relevant endianness.
fn get_read_u32_fn(magic: &[u8]) -> Option<fn(&[u8]) -> u32> {
    if magic == [0xde, 0x12, 0x04, 0x95] {
        Some(LittleEndian::read_u32)
    } else if magic == [0x95, 0x04, 0x12, 0xde] {
        Some(BigEndian::read_u32)
    } else {
        None
    }
}

fn parse_catalog<R: io::Read>(mut file: R) -> Result<Catalog, Error> {
    let mut magic = [0u8; 4];
    let n = try!(file.read(&mut magic));
    if n != 4 {
        return Err(Eof);
    }
    let read_u32 = match get_read_u32_fn(&magic) {
        Some(f) => f,
        None => return Err(BadMagic),
    };
    Ok(Catalog::new())
}

#[test]
fn test_get_read_u32_fn() {
    assert!(get_read_u32_fn(&[]).is_none());
    assert!(get_read_u32_fn(&[0xde, 0x12, 0x04, 0x95, 0x00]).is_none());

    {
        let le_ptr: *const ();
        let ret_ptr;
        unsafe {
            le_ptr = mem::transmute(LittleEndian::read_u32);
            ret_ptr = mem::transmute(get_read_u32_fn(&[0xde, 0x12, 0x04, 0x95]).unwrap());
        }
        assert_eq!(le_ptr, ret_ptr);
    }

    {
        let be_ptr: *const ();
        let ret_ptr;
        unsafe {
            be_ptr = mem::transmute(BigEndian::read_u32);
            ret_ptr = mem::transmute(get_read_u32_fn(&[0x95, 0x04, 0x12, 0xde]).unwrap());
        }
        assert_eq!(be_ptr, ret_ptr);
    }
}

#[test]
fn test_parse_catalog() {
    macro_rules! assert_variant {
        ($value:expr, $variant:path) => {
            match $value {
                $variant => (),
                _ => panic!("Expected {}, got {}", stringify!($variant), $value),
            }
        };
    }

    {
        let reader: &[u8] = &[1u8, 2, 3];
        let err = parse_catalog(reader).unwrap_err();
        assert_variant!(err, Eof);
    }

    {
        let reader: &[u8] = &[1u8, 2, 3, 4];
        let err = parse_catalog(reader).unwrap_err();
        assert_variant!(err, BadMagic);
    }

    {
        let reader: &[u8] = &[0x95, 0x04, 0x12, 0xde];
        assert!(parse_catalog(reader).is_ok());
    }

    {
        let reader: &[u8] = &[0xde, 0x12, 0x04, 0x95];
        assert!(parse_catalog(reader).is_ok());
    }
}
<commit_msg>Read the entire file into memory<commit_after>extern crate byteorder;

use std::error;
use std::fmt;
use std::io;
use std::mem;

use self::byteorder::{ByteOrder, BigEndian, LittleEndian};

use super::Catalog;

/// Represents an error encountered while parsing an MO file.
#[derive(Debug)]
pub enum Error {
    /// An incorrect magic number has been encountered
    BadMagic,
    /// An unexpected EOF occured
    Eof,
    /// An I/O error occured
    Io(io::Error),
}
use Error::*;

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            BadMagic => "bad magic number",
            Eof => "unxpected end of file",
            Io(ref err) => err.description(),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let self_err: &error::Error = self;
        write!(fmt, "{}", self_err.description())
    }
}

impl From<io::Error> for Error {
    fn from(inner: io::Error) -> Error {
        Io(inner)
    }
}

/// According to the given magic number of a MO file,
/// returns the function which reads a `u32` in the relevant endianness.
fn get_read_u32_fn(magic: &[u8]) -> Option<fn(&[u8]) -> u32> {
    if magic == [0xde, 0x12, 0x04, 0x95] {
        Some(LittleEndian::read_u32)
    } else if magic == [0x95, 0x04, 0x12, 0xde] {
        Some(BigEndian::read_u32)
    } else {
        None
    }
}

fn parse_catalog<R: io::Read>(mut file: R) -> Result<Catalog, Error> {
    let mut contents = vec![];
    let n = try!(file.read_to_end(&mut contents));
    if n < 28 {
        return Err(Eof);
    }
    let read_u32 = match get_read_u32_fn(&contents[0..4]) {
        Some(f) => f,
        None => return Err(BadMagic),
    };
    Ok(Catalog::new())
}

#[test]
fn test_get_read_u32_fn() {
    assert!(get_read_u32_fn(&[]).is_none());
    assert!(get_read_u32_fn(&[0xde, 0x12, 0x04, 0x95, 0x00]).is_none());

    {
        let le_ptr: *const ();
        let ret_ptr;
        unsafe {
            le_ptr = mem::transmute(LittleEndian::read_u32);
            ret_ptr = mem::transmute(get_read_u32_fn(&[0xde, 0x12, 0x04, 0x95]).unwrap());
        }
        assert_eq!(le_ptr, ret_ptr);
    }

    {
        let be_ptr: *const ();
        let ret_ptr;
        unsafe {
            be_ptr = mem::transmute(BigEndian::read_u32);
            ret_ptr = mem::transmute(get_read_u32_fn(&[0x95, 0x04, 0x12, 0xde]).unwrap());
        }
        assert_eq!(be_ptr, ret_ptr);
    }
}

#[test]
fn test_parse_catalog() {
    macro_rules! assert_variant {
        ($value:expr, $variant:path) => {
            match $value {
                $variant => (),
                _ => panic!("Expected {}, got {}", stringify!($variant), $value),
            }
        };
    }

    let fluff: &[u8] = &[0; 24]; // zeros to pad our magic test cases to satisfy the length requirements

    {
        let mut reader = vec![1u8, 2, 3];
        reader.extend(fluff);
        let err = parse_catalog(&reader[..]).unwrap_err();
        assert_variant!(err, Eof);
    }

    {
        let mut reader = vec![1u8, 2, 3, 4];
        reader.extend(fluff);
        let err = parse_catalog(&reader[..]).unwrap_err();
        assert_variant!(err, BadMagic);
    }

    {
        let mut reader = vec![0x95, 0x04, 0x12, 0xde];
        reader.extend(fluff);
        assert!(parse_catalog(&reader[..]).is_ok());
    }

    {
        let mut reader = vec![0xde, 0x12, 0x04, 0x95];
        reader.extend(fluff);
        assert!(parse_catalog(&reader[..]).is_ok());
    }
}
<|endoftext|>