<commit_before>//! Different types of delay for retryable operations.

use std::time::Duration;
use std::u64::MAX as U64_MAX;

use rand::{
    distributions::{Distribution, Uniform},
    random,
    rngs::ThreadRng,
    thread_rng,
};

/// Each retry increases the delay since the last exponentially.
#[derive(Debug)]
pub struct Exponential {
    base: u64,
    current: u64,
}

impl Exponential {
    /// Create a new `Exponential` using the given millisecond duration as the initial delay.
    pub fn from_millis(base: u64) -> Self {
        Exponential {
            base,
            current: base,
        }
    }
}

impl Iterator for Exponential {
    type Item = Duration;

    fn next(&mut self) -> Option<Duration> {
        let duration = Duration::from_millis(self.current);

        if let Some(next) = self.current.checked_mul(self.base) {
            self.current = next;
        } else {
            self.current = U64_MAX;
        }

        Some(duration)
    }
}

/// Each retry uses a delay which is the sum of the two previous delays.
///
/// Depending on the problem at hand, a fibonacci delay strategy might
/// perform better and lead to better throughput than the `Exponential`
/// strategy.
///
/// See ["A Performance Comparison of Different Backoff Algorithms under Different Rebroadcast Probabilities for MANETs."](http://www.comp.leeds.ac.uk/ukpew09/papers/12.pdf)
/// for more details.
#[derive(Debug)]
pub struct Fibonacci {
    curr: u64,
    next: u64,
}

impl Fibonacci {
    /// Create a new `Fibonacci` using the given duration in milliseconds.
    pub fn from_millis(millis: u64) -> Fibonacci {
        Fibonacci {
            curr: millis,
            next: millis,
        }
    }
}

impl Iterator for Fibonacci {
    type Item = Duration;

    fn next(&mut self) -> Option<Duration> {
        let duration = Duration::from_millis(self.curr);

        if let Some(next_next) = self.curr.checked_add(self.next) {
            self.curr = self.next;
            self.next = next_next;
        } else {
            self.curr = self.next;
            self.next = U64_MAX;
        }

        Some(duration)
    }
}

#[test]
fn fibonacci() {
    let mut iter = Fibonacci::from_millis(10);
    assert_eq!(iter.next(), Some(Duration::from_millis(10)));
    assert_eq!(iter.next(), Some(Duration::from_millis(10)));
    assert_eq!(iter.next(), Some(Duration::from_millis(20)));
    assert_eq!(iter.next(), Some(Duration::from_millis(30)));
    assert_eq!(iter.next(), Some(Duration::from_millis(50)));
    assert_eq!(iter.next(), Some(Duration::from_millis(80)));
}

#[test]
fn fibonacci_saturated() {
    let mut iter = Fibonacci::from_millis(U64_MAX);
    assert_eq!(iter.next(), Some(Duration::from_millis(U64_MAX)));
    assert_eq!(iter.next(), Some(Duration::from_millis(U64_MAX)));
}

/// Each retry uses a fixed delay.
#[derive(Debug)]
pub struct Fixed {
    duration: Duration,
}

impl Fixed {
    /// Create a new `Fixed` using the given duration in milliseconds.
    pub fn from_millis(millis: u64) -> Self {
        Fixed {
            duration: Duration::from_millis(millis),
        }
    }
}

impl Iterator for Fixed {
    type Item = Duration;

    fn next(&mut self) -> Option<Duration> {
        Some(self.duration)
    }
}

impl From<Duration> for Fixed {
    fn from(delay: Duration) -> Self {
        Self {
            duration: delay.into(),
        }
    }
}

/// Each retry happens immediately without any delay.
#[derive(Debug)]
pub struct NoDelay;

impl Iterator for NoDelay {
    type Item = Duration;

    fn next(&mut self) -> Option<Duration> {
        Some(Duration::default())
    }
}

/// Each retry uses a duration randomly chosen from a range.
#[derive(Debug)]
pub struct Range {
    distribution: Uniform<u64>,
    rng: ThreadRng,
}

impl Range {
    /// Create a new `Range` between the given millisecond durations, excluding the maximum value.
    ///
    /// # Panics
    ///
    /// Panics if the minimum is greater than or equal to the maximum.
    pub fn from_millis_exclusive(minimum: u64, maximum: u64) -> Self {
        Range {
            distribution: Uniform::new(minimum, maximum),
            rng: thread_rng(),
        }
    }

    /// Create a new `Range` between the given millisecond durations, including the maximum value.
    ///
    /// # Panics
    ///
    /// Panics if the minimum is greater than or equal to the maximum.
    pub fn from_millis_inclusive(minimum: u64, maximum: u64) -> Self {
        Range {
            distribution: Uniform::new_inclusive(minimum, maximum),
            rng: thread_rng(),
        }
    }
}

impl Iterator for Range {
    type Item = Duration;

    fn next(&mut self) -> Option<Duration> {
        Some(Duration::from_millis(
            self.distribution.sample(&mut self.rng),
        ))
    }
}

/// Apply full random jitter to a duration.
pub fn jitter(duration: Duration) -> Duration {
    let jitter = random::<f64>();
    let secs = ((duration.as_secs() as f64) * jitter).ceil() as u64;
    let nanos = ((f64::from(duration.subsec_nanos())) * jitter).ceil() as u32;
    Duration::new(secs, nanos)
}
<commit_msg>implement From for some std's corresponding types<commit_after>//! Different types of delay for retryable operations.

use std::ops::{Range as StdRange, RangeInclusive};
use std::time::Duration;
use std::u64::MAX as U64_MAX;

use rand::{
    distributions::{Distribution, Uniform},
    random,
    rngs::ThreadRng,
    thread_rng,
};

/// Each retry increases the delay since the last exponentially.
#[derive(Debug)]
pub struct Exponential {
    base: u64,
    current: u64,
}

impl Exponential {
    /// Create a new `Exponential` using the given millisecond duration as the initial delay.
    pub fn from_millis(base: u64) -> Self {
        Exponential {
            base,
            current: base,
        }
    }
}

impl Iterator for Exponential {
    type Item = Duration;

    fn next(&mut self) -> Option<Duration> {
        let duration = Duration::from_millis(self.current);

        if let Some(next) = self.current.checked_mul(self.base) {
            self.current = next;
        } else {
            self.current = U64_MAX;
        }

        Some(duration)
    }
}

impl From<Duration> for Exponential {
    fn from(duration: Duration) -> Self {
        Self::from_millis(duration.as_millis() as u64)
    }
}

/// Each retry uses a delay which is the sum of the two previous delays.
///
/// Depending on the problem at hand, a fibonacci delay strategy might
/// perform better and lead to better throughput than the `Exponential`
/// strategy.
///
/// See ["A Performance Comparison of Different Backoff Algorithms under Different Rebroadcast Probabilities for MANETs."](http://www.comp.leeds.ac.uk/ukpew09/papers/12.pdf)
/// for more details.
#[derive(Debug)]
pub struct Fibonacci {
    curr: u64,
    next: u64,
}

impl Fibonacci {
    /// Create a new `Fibonacci` using the given duration in milliseconds.
    pub fn from_millis(millis: u64) -> Fibonacci {
        Fibonacci {
            curr: millis,
            next: millis,
        }
    }
}

impl Iterator for Fibonacci {
    type Item = Duration;

    fn next(&mut self) -> Option<Duration> {
        let duration = Duration::from_millis(self.curr);

        if let Some(next_next) = self.curr.checked_add(self.next) {
            self.curr = self.next;
            self.next = next_next;
        } else {
            self.curr = self.next;
            self.next = U64_MAX;
        }

        Some(duration)
    }
}

impl From<Duration> for Fibonacci {
    fn from(duration: Duration) -> Self {
        Self::from_millis(duration.as_millis() as u64)
    }
}

#[test]
fn fibonacci() {
    let mut iter = Fibonacci::from_millis(10);
    assert_eq!(iter.next(), Some(Duration::from_millis(10)));
    assert_eq!(iter.next(), Some(Duration::from_millis(10)));
    assert_eq!(iter.next(), Some(Duration::from_millis(20)));
    assert_eq!(iter.next(), Some(Duration::from_millis(30)));
    assert_eq!(iter.next(), Some(Duration::from_millis(50)));
    assert_eq!(iter.next(), Some(Duration::from_millis(80)));
}

#[test]
fn fibonacci_saturated() {
    let mut iter = Fibonacci::from_millis(U64_MAX);
    assert_eq!(iter.next(), Some(Duration::from_millis(U64_MAX)));
    assert_eq!(iter.next(), Some(Duration::from_millis(U64_MAX)));
}

/// Each retry uses a fixed delay.
#[derive(Debug)]
pub struct Fixed {
    duration: Duration,
}

impl Fixed {
    /// Create a new `Fixed` using the given duration in milliseconds.
    pub fn from_millis(millis: u64) -> Self {
        Fixed {
            duration: Duration::from_millis(millis),
        }
    }
}

impl Iterator for Fixed {
    type Item = Duration;

    fn next(&mut self) -> Option<Duration> {
        Some(self.duration)
    }
}

impl From<Duration> for Fixed {
    fn from(delay: Duration) -> Self {
        Self {
            duration: delay.into(),
        }
    }
}

/// Each retry happens immediately without any delay.
#[derive(Debug)]
pub struct NoDelay;

impl Iterator for NoDelay {
    type Item = Duration;

    fn next(&mut self) -> Option<Duration> {
        Some(Duration::default())
    }
}

/// Each retry uses a duration randomly chosen from a range.
#[derive(Debug)]
pub struct Range {
    distribution: Uniform<u64>,
    rng: ThreadRng,
}

impl Range {
    /// Create a new `Range` between the given millisecond durations, excluding the maximum value.
    ///
    /// # Panics
    ///
    /// Panics if the minimum is greater than or equal to the maximum.
    pub fn from_millis_exclusive(minimum: u64, maximum: u64) -> Self {
        Range {
            distribution: Uniform::new(minimum, maximum),
            rng: thread_rng(),
        }
    }

    /// Create a new `Range` between the given millisecond durations, including the maximum value.
    ///
    /// # Panics
    ///
    /// Panics if the minimum is greater than or equal to the maximum.
    pub fn from_millis_inclusive(minimum: u64, maximum: u64) -> Self {
        Range {
            distribution: Uniform::new_inclusive(minimum, maximum),
            rng: thread_rng(),
        }
    }
}

impl Iterator for Range {
    type Item = Duration;

    fn next(&mut self) -> Option<Duration> {
        Some(Duration::from_millis(
            self.distribution.sample(&mut self.rng),
        ))
    }
}

impl From<StdRange<Duration>> for Range {
    fn from(range: StdRange<Duration>) -> Self {
        Self::from_millis_exclusive(range.start.as_millis() as u64, range.end.as_millis() as u64)
    }
}

impl From<RangeInclusive<Duration>> for Range {
    fn from(range: RangeInclusive<Duration>) -> Self {
        Self::from_millis_inclusive(
            range.start().as_millis() as u64,
            range.end().as_millis() as u64,
        )
    }
}

/// Apply full random jitter to a duration.
pub fn jitter(duration: Duration) -> Duration {
    let jitter = random::<f64>();
    let secs = ((duration.as_secs() as f64) * jitter).ceil() as u64;
    let nanos = ((f64::from(duration.subsec_nanos())) * jitter).ceil() as u32;
    Duration::new(secs, nanos)
}
<|endoftext|>


<commit_before>//! choice combinators

#[macro_use]
mod macros;

use error::ErrorKind;
use error::ParseError;
use internal::{Err, IResult};

pub fn or<I: Clone, O, E: ParseError<I>, F, G>(f: F, g: G) -> impl Fn(I) -> IResult<I, O, E>
where
  F: Fn(I) -> IResult<I, O, E>,
  G: Fn(I) -> IResult<I, O, E>,
{
  move |i: I| match f(i.clone()) {
    Err(Err::Error(e)) => g(i).map_err(|e2| match e2 {
      Err::Error(e2) => Err::Error(e.or(e2)),
      e2 => e2,
    }),
    res => res,
  }
}

/// helper trait for arguments to [alt]
pub trait Alt<I, O, E> {
  fn choice(&self, input: I) -> IResult<I, O, E>;
}

/// tests a list of parsers one by one until one succeeds
///
/// It takes as argument a tuple of parsers.
///
/// ```rust
/// # #[macro_use] extern crate nom;
/// # use nom::{Err,error::ErrorKind, Needed, IResult};
/// use nom::character::complete::{alpha1, digit1};
/// use nom::branch::alt;
/// # fn main() {
/// fn parser(input: &str) -> IResult<&str, &str> {
///   alt((alpha1, digit1))(input)
/// };
///
/// // the first parser, alpha1, recognizes the input
/// assert_eq!(parser("abc"), Ok(("", "abc")));
///
/// // the first parser returns an error, so alt tries the second one
/// assert_eq!(parser("123456"), Ok(("", "123456")));
///
/// // both parsers failed, and with the default error type, alt will return the last error
/// assert_eq!(parser(" "), Err(Err::Error(error_position!(" ", ErrorKind::Digit))));
/// # }
/// ```
///
/// with a custom error type, it is possible to have alt return the error of the parser
/// that went the farthest in the input data
pub fn alt<I: Clone, O, E: ParseError<I>, List: Alt<I, O, E>>(l: List) -> impl Fn(I) -> IResult<I, O, E> {
  move |i: I| l.choice(i)
}

/// helper trait for arguments to [permutation]
pub trait Permutation<I, O, E> {
  fn permutation(&self, input: I) -> IResult<I, O, E>;
}

/// applies a list of parsers in any order
///
/// permutation will succeed if all of the child parsers succeeded.
/// It takes as argument a tuple of parsers, and returns a
/// tuple of the parser results.
///
/// ```rust
/// # #[macro_use] extern crate nom;
/// # use nom::{Err,error::ErrorKind, Needed, IResult};
/// use nom::character::complete::{alpha1, digit1};
/// use nom::branch::permutation;
/// # fn main() {
/// fn parser(input: &str) -> IResult<&str, (&str, &str)> {
///   permutation((alpha1, digit1))(input)
/// };
///
/// // permutation recognizes alphabetic characters then digit
/// assert_eq!(parser("abc123"), Ok(("", ("abc", "123"))));
///
/// // but also in inverse order
/// assert_eq!(parser("123abc"), Ok(("", ("abc", "123"))));
///
/// // it will fail if one of the parsers failed
/// assert_eq!(parser("abc;"), Err(Err::Error(error_position!(";", ErrorKind::Permutation))));
/// # }
/// ```
pub fn permutation<I: Clone, O, E: ParseError<I>, List: Permutation<I, O, E>>(l: List) -> impl Fn(I) -> IResult<I, O, E> {
  move |i: I| l.permutation(i)
}

macro_rules! alt_trait(
  ($first:ident $second:ident $($id: ident)+) => (
    alt_trait!(__impl $first $second; $($id)+);
  );
  (__impl $($current:ident)*; $head:ident $($id: ident)+) => (
    alt_trait_impl!($($current)*);

    alt_trait!(__impl $($current)* $head; $($id)+);
  );
  (__impl $($current:ident)*; $head:ident) => (
    alt_trait_impl!($($current)*);
    alt_trait_impl!($($current)* $head);
  );
);

macro_rules! alt_trait_impl(
  ($($id:ident)+) => (
    impl<
      Input: Clone, Output, Error: ParseError<Input>,
      $($id: Fn(Input) -> IResult<Input, Output, Error>),+
    > Alt<Input, Output, Error> for ( $($id),+ ) {

      fn choice(&self, input: Input) -> IResult<Input, Output, Error> {
        let mut err = None;
        alt_trait_inner!(0, self, input, err, $($id)+);

        Err(Err::Error(Error::append(input, ErrorKind::Alt, err.unwrap())))
      }
    }
  );
);

macro_rules! alt_trait_inner(
  ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident $($id:ident)+) => (
    match $self.$it($input.clone()) {
      Err(Err::Error(e)) => {
        if $err.is_none() {
          $err = Some(e);
        } else {
          $err = Some($err.unwrap().or(e));
        }
        succ!($it, alt_trait_inner!($self, $input, $err, $($id)+))
      },
      res => return res,
    }
  );
  ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident) => (
    match $self.$it($input.clone()) {
      Err(Err::Error(e)) => {
        if $err.is_none() {
          $err = Some(e);
        } else {
          $err = Some($err.unwrap().or(e));
        }
      },
      res => return res,
    }
  );
);

alt_trait!(A B C D E F G H I J K L M N O P Q R S T U);

macro_rules! permutation_trait(
  ($name1:ident $ty1:ident, $name2:ident $ty2:ident) => (
    permutation_trait_impl!($name1 $ty1, $name2 $ty2);
  );
  ($name1:ident $ty1:ident, $name2: ident $ty2:ident, $($name:ident $ty:ident),*) => (
    permutation_trait!(__impl $name1 $ty1, $name2 $ty2; $($name $ty),*);
  );
  (__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident, $($name2:ident $ty2:ident),*) => (
    permutation_trait_impl!($($name $ty),+);
    permutation_trait!(__impl $($name $ty),+ , $name1 $ty1; $($name2 $ty2),*);
  );
  (__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident) => (
    permutation_trait_impl!($($name $ty),+);
    permutation_trait_impl!($($name $ty),+, $name1 $ty1);
  );
);

macro_rules! permutation_trait_impl(
  ($($name:ident $ty: ident),+) => (
    impl<
      Input: Clone, $($ty),+ , Error: ParseError<Input>,
      $($name: Fn(Input) -> IResult<Input, $ty, Error>),+
    > Permutation<Input, ( $($ty),+ ), Error> for ( $($name),+ ) {

      fn permutation(&self, mut input: Input) -> IResult<Input, ( $($ty),+ ), Error> {
        let mut res = permutation_init!((), $($name),+);

        loop {
          let mut all_done = true;
          permutation_trait_inner!(0, self, input, res, all_done, $($name)+);

          //if we reach that part, it means none of the parsers were able to read anything
          if !all_done {
            //FIXME: should wrap the error returned by the child parser
            return Err(Err::Error(error_position!(input, ErrorKind::Permutation)));
          }
          break;
        }

        if let Some(unwrapped_res) = { permutation_trait_unwrap!(0, (), res, $($name),+) } {
          Ok((input, unwrapped_res))
        } else {
          Err(Err::Error(error_position!(input, ErrorKind::Permutation)))
        }
      }
    }
  );
);

macro_rules! permutation_trait_inner(
  ($it:tt, $self:expr, $input:ident, $res:expr, $all_done:expr, $head:ident $($id:ident)+) => ({
    if $res.$it.is_none() {
      match $self.$it($input.clone()) {
        Ok((i,o))     => {
          $input = i;
          $res.$it = Some(o);
          continue;
        },
        Err(Err::Error(_)) => {
          $all_done = false;
        },
        Err(e) => {
          return Err(e);
        }
      };
    }
    succ!($it, permutation_trait_inner!($self, $input, $res, $all_done, $($id)*));
  });
  ($it:tt, $self:expr, $input:ident, $res:expr, $all_done:expr, $head:ident) => ({
    if $res.$it.is_none() {
      match $self.$it($input.clone()) {
        Ok((i,o))     => {
          $input = i;
          $res.$it = Some(o);
          continue;
        },
        Err(Err::Error(_)) => {
          $all_done = false;
        },
        Err(e) => {
          return Err(e);
        }
      };
    }
  });
);

macro_rules! permutation_trait_unwrap (
  ($it:tt,  (), $res:ident, $e:ident, $($name:ident),+) => ({
    let res = $res.$it;
    if res.is_some() {
      succ!($it, permutation_trait_unwrap!((res.unwrap()), $res, $($name),+))
    } else {
      $crate::lib::std::option::Option::None
    }
  });

  ($it:tt, ($($parsed:expr),*), $res:ident, $e:ident, $($name:ident),+) => ({
    let res = $res.$it;
    if res.is_some() {
      succ!($it, permutation_trait_unwrap!(($($parsed),* , res.unwrap()), $res, $($name),+))
    } else {
      $crate::lib::std::option::Option::None
    }
  });

  ($it:tt, ($($parsed:expr),*), $res:ident, $name:ident) => ({
    let res = $res.$it;
    if res.is_some() {
      $crate::lib::std::option::Option::Some(($($parsed),* , res.unwrap() ))
    } else {
      $crate::lib::std::option::Option::None
    }
  });
);

permutation_trait!(FnA A, FnB B, FnC C, FnD D, FnE E, FnF F, FnG G, FnH H, FnI I, FnJ J, FnK K, FnL L, FnM M, FnN N, FnO O, FnP P, FnQ Q, FnR R, FnS S, FnT T, FnU U);
<commit_msg>remove the or combinator<commit_after>//! choice combinators

#[macro_use]
mod macros;

use error::ErrorKind;
use error::ParseError;
use internal::{Err, IResult};

/// helper trait for arguments to [alt]
pub trait Alt<I, O, E> {
  fn choice(&self, input: I) -> IResult<I, O, E>;
}

/// tests a list of parsers one by one until one succeeds
///
/// It takes as argument a tuple of parsers.
///
/// ```rust
/// # #[macro_use] extern crate nom;
/// # use nom::{Err,error::ErrorKind, Needed, IResult};
/// use nom::character::complete::{alpha1, digit1};
/// use nom::branch::alt;
/// # fn main() {
/// fn parser(input: &str) -> IResult<&str, &str> {
///   alt((alpha1, digit1))(input)
/// };
///
/// // the first parser, alpha1, recognizes the input
/// assert_eq!(parser("abc"), Ok(("", "abc")));
///
/// // the first parser returns an error, so alt tries the second one
/// assert_eq!(parser("123456"), Ok(("", "123456")));
///
/// // both parsers failed, and with the default error type, alt will return the last error
/// assert_eq!(parser(" "), Err(Err::Error(error_position!(" ", ErrorKind::Digit))));
/// # }
/// ```
///
/// with a custom error type, it is possible to have alt return the error of the parser
/// that went the farthest in the input data
pub fn alt<I: Clone, O, E: ParseError<I>, List: Alt<I, O, E>>(l: List) -> impl Fn(I) -> IResult<I, O, E> {
  move |i: I| l.choice(i)
}

/// helper trait for arguments to [permutation]
pub trait Permutation<I, O, E> {
  fn permutation(&self, input: I) -> IResult<I, O, E>;
}

/// applies a list of parsers in any order
///
/// permutation will succeed if all of the child parsers succeeded.
/// It takes as argument a tuple of parsers, and returns a
/// tuple of the parser results.
///
/// ```rust
/// # #[macro_use] extern crate nom;
/// # use nom::{Err,error::ErrorKind, Needed, IResult};
/// use nom::character::complete::{alpha1, digit1};
/// use nom::branch::permutation;
/// # fn main() {
/// fn parser(input: &str) -> IResult<&str, (&str, &str)> {
///   permutation((alpha1, digit1))(input)
/// };
///
/// // permutation recognizes alphabetic characters then digit
/// assert_eq!(parser("abc123"), Ok(("", ("abc", "123"))));
///
/// // but also in inverse order
/// assert_eq!(parser("123abc"), Ok(("", ("abc", "123"))));
///
/// // it will fail if one of the parsers failed
/// assert_eq!(parser("abc;"), Err(Err::Error(error_position!(";", ErrorKind::Permutation))));
/// # }
/// ```
pub fn permutation<I: Clone, O, E: ParseError<I>, List: Permutation<I, O, E>>(l: List) -> impl Fn(I) -> IResult<I, O, E> {
  move |i: I| l.permutation(i)
}

macro_rules! alt_trait(
  ($first:ident $second:ident $($id: ident)+) => (
    alt_trait!(__impl $first $second; $($id)+);
  );
  (__impl $($current:ident)*; $head:ident $($id: ident)+) => (
    alt_trait_impl!($($current)*);

    alt_trait!(__impl $($current)* $head; $($id)+);
  );
  (__impl $($current:ident)*; $head:ident) => (
    alt_trait_impl!($($current)*);
    alt_trait_impl!($($current)* $head);
  );
);

macro_rules! alt_trait_impl(
  ($($id:ident)+) => (
    impl<
      Input: Clone, Output, Error: ParseError<Input>,
      $($id: Fn(Input) -> IResult<Input, Output, Error>),+
    > Alt<Input, Output, Error> for ( $($id),+ ) {

      fn choice(&self, input: Input) -> IResult<Input, Output, Error> {
        let mut err = None;
        alt_trait_inner!(0, self, input, err, $($id)+);

        Err(Err::Error(Error::append(input, ErrorKind::Alt, err.unwrap())))
      }
    }
  );
);

macro_rules! alt_trait_inner(
  ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident $($id:ident)+) => (
    match $self.$it($input.clone()) {
      Err(Err::Error(e)) => {
        if $err.is_none() {
          $err = Some(e);
        } else {
          $err = Some($err.unwrap().or(e));
        }
        succ!($it, alt_trait_inner!($self, $input, $err, $($id)+))
      },
      res => return res,
    }
  );
  ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident) => (
    match $self.$it($input.clone()) {
      Err(Err::Error(e)) => {
        if $err.is_none() {
          $err = Some(e);
        } else {
          $err = Some($err.unwrap().or(e));
        }
      },
      res => return res,
    }
  );
);

alt_trait!(A B C D E F G H I J K L M N O P Q R S T U);

macro_rules! permutation_trait(
  ($name1:ident $ty1:ident, $name2:ident $ty2:ident) => (
    permutation_trait_impl!($name1 $ty1, $name2 $ty2);
  );
  ($name1:ident $ty1:ident, $name2: ident $ty2:ident, $($name:ident $ty:ident),*) => (
    permutation_trait!(__impl $name1 $ty1, $name2 $ty2; $($name $ty),*);
  );
  (__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident, $($name2:ident $ty2:ident),*) => (
    permutation_trait_impl!($($name $ty),+);
    permutation_trait!(__impl $($name $ty),+ , $name1 $ty1; $($name2 $ty2),*);
  );
  (__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident) => (
    permutation_trait_impl!($($name $ty),+);
    permutation_trait_impl!($($name $ty),+, $name1 $ty1);
  );
);

macro_rules! permutation_trait_impl(
  ($($name:ident $ty: ident),+) => (
    impl<
      Input: Clone, $($ty),+ , Error: ParseError<Input>,
      $($name: Fn(Input) -> IResult<Input, $ty, Error>),+
    > Permutation<Input, ( $($ty),+ ), Error> for ( $($name),+ ) {

      fn permutation(&self, mut input: Input) -> IResult<Input, ( $($ty),+ ), Error> {
        let mut res = permutation_init!((), $($name),+);

        loop {
          let mut all_done = true;
          permutation_trait_inner!(0, self, input, res, all_done, $($name)+);

          //if we reach that part, it means none of the parsers were able to read anything
          if !all_done {
            //FIXME: should wrap the error returned by the child parser
            return Err(Err::Error(error_position!(input, ErrorKind::Permutation)));
          }
          break;
        }

        if let Some(unwrapped_res) = { permutation_trait_unwrap!(0, (), res, $($name),+) } {
          Ok((input, unwrapped_res))
        } else {
          Err(Err::Error(error_position!(input, ErrorKind::Permutation)))
        }
      }
    }
  );
);

macro_rules! permutation_trait_inner(
  ($it:tt, $self:expr, $input:ident, $res:expr, $all_done:expr, $head:ident $($id:ident)+) => ({
    if $res.$it.is_none() {
      match $self.$it($input.clone()) {
        Ok((i,o))     => {
          $input = i;
          $res.$it = Some(o);
          continue;
        },
        Err(Err::Error(_)) => {
          $all_done = false;
        },
        Err(e) => {
          return Err(e);
        }
      };
    }
    succ!($it, permutation_trait_inner!($self, $input, $res, $all_done, $($id)*));
  });
  ($it:tt, $self:expr, $input:ident, $res:expr, $all_done:expr, $head:ident) => ({
    if $res.$it.is_none() {
      match $self.$it($input.clone()) {
        Ok((i,o))     => {
          $input = i;
          $res.$it = Some(o);
          continue;
        },
        Err(Err::Error(_)) => {
          $all_done = false;
        },
        Err(e) => {
          return Err(e);
        }
      };
    }
  });
);

macro_rules! permutation_trait_unwrap (
  ($it:tt,  (), $res:ident, $e:ident, $($name:ident),+) => ({
    let res = $res.$it;
    if res.is_some() {
      succ!($it, permutation_trait_unwrap!((res.unwrap()), $res, $($name),+))
    } else {
      $crate::lib::std::option::Option::None
    }
  });

  ($it:tt, ($($parsed:expr),*), $res:ident, $e:ident, $($name:ident),+) => ({
    let res = $res.$it;
    if res.is_some() {
      succ!($it, permutation_trait_unwrap!(($($parsed),* , res.unwrap()), $res, $($name),+))
    } else {
      $crate::lib::std::option::Option::None
    }
  });

  ($it:tt, ($($parsed:expr),*), $res:ident, $name:ident) => ({
    let res = $res.$it;
    if res.is_some() {
      $crate::lib::std::option::Option::Some(($($parsed),* , res.unwrap() ))
    } else {
      $crate::lib::std::option::Option::None
    }
  });
);

permutation_trait!(FnA A, FnB B, FnC C, FnD D, FnE E, FnF F, FnG G, FnH H, FnI I, FnJ J, FnK K, FnL L, FnM M, FnN N, FnO O, FnP P, FnQ Q, FnR R, FnS S, FnT T, FnU U);
<|endoftext|>


<commit_before>//! A flash simulator
//!
//! This module is capable of simulating the type of NOR flash commonly used in microcontrollers.
//! These generally can be written as individual bytes, but must be erased in larger units.

#[macro_use] extern crate error_chain;
mod pdump;

use std::fs::File;
use std::io::Write;
use std::iter::Enumerate;
use std::path::Path;
use std::slice;
use pdump::HexDump;

error_chain! {
    errors {
        OutOfBounds(t: String) {
            description("Offset is out of bounds")
            display("Offset out of bounds: {}", t)
        }
        Write(t: String) {
            description("Invalid write")
            display("Invalid write: {}", t)
        }
    }
}

pub trait Flash {
    fn erase(&mut self, offset: usize, len: usize) -> Result<()>;
    fn write(&mut self, offset: usize, payload: &[u8]) -> Result<()>;
    fn read(&self, offset: usize, data: &mut [u8]) -> Result<()>;

    fn sector_iter(&self) -> SectorIter;
    fn device_size(&self) -> usize;
}

fn ebounds<T: AsRef<str>>(message: T) -> ErrorKind {
    ErrorKind::OutOfBounds(message.as_ref().to_owned())
}

#[allow(dead_code)]
fn ewrite<T: AsRef<str>>(message: T) -> ErrorKind {
    ErrorKind::Write(message.as_ref().to_owned())
}

/// An emulated flash device.  It is represented as a block of bytes, and a list of the sector
/// mapings.
#[derive(Clone)]
pub struct SimFlash {
    data: Vec<u8>,
    write_safe: Vec<bool>,
    sectors: Vec<usize>,
    // Alignment required for writes.
    align: usize,
}

impl SimFlash {
    /// Given a sector size map, construct a flash device for that.
    pub fn new(sectors: Vec<usize>, align: usize) -> SimFlash {
        // Verify that the alignment is a positive power of two.
        assert!(align > 0);
        assert!(align & (align - 1) == 0);

        let total = sectors.iter().sum();
        SimFlash {
            data: vec![0xffu8; total],
            write_safe: vec![true; total],
            sectors: sectors,
            align: align,
        }
    }

    #[allow(dead_code)]
    pub fn dump(&self) {
        self.data.dump();
    }

    /// Dump this image to the given file.
    #[allow(dead_code)]
    pub fn write_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
        let mut fd = File::create(path).chain_err(|| "Unable to write image file")?;
        fd.write_all(&self.data).chain_err(|| "Unable to write to image file")?;
        Ok(())
    }

    // Scan the sector map, and return the base and offset within a sector for this given byte.
    // Returns None if the value is outside of the device.
    fn get_sector(&self, offset: usize) -> Option<(usize, usize)> {
        let mut offset = offset;
        for (sector, &size) in self.sectors.iter().enumerate() {
            if offset < size {
                return Some((sector, offset));
            }
            offset -= size;
        }
        return None;
    }

}

impl Flash for SimFlash {
    /// The flash drivers tend to erase beyond the bounds of the given range.  Instead, we'll be
    /// strict, and make sure that the passed arguments are exactly at a sector boundary, otherwise
    /// return an error.
    fn erase(&mut self, offset: usize, len: usize) -> Result<()> {
        let (_start, slen) = self.get_sector(offset).ok_or_else(|| ebounds("start"))?;
        let (end, elen) = self.get_sector(offset + len - 1).ok_or_else(|| ebounds("end"))?;

        if slen != 0 {
            bail!(ebounds("offset not at start of sector"));
        }
        if elen != self.sectors[end] - 1 {
            bail!(ebounds("end not at start of sector"));
        }

        for x in &mut self.data[offset .. offset + len] {
            *x = 0xff;
        }

        for x in &mut self.write_safe[offset .. offset + len] {
            *x = true;
        }

        Ok(())
    }

    /// We restrict to only allowing writes of values that are:
    ///
    /// 1. being written to for the first time
    /// 2. being written to after being erased
    ///
    /// This emulates a flash device which starts out erased, with the
    /// added restriction that repeated writes to the same location
    /// are disallowed, even if they would be safe to do.
    fn write(&mut self, offset: usize, payload: &[u8]) -> Result<()> {
        if offset + payload.len() > self.data.len() {
            panic!("Write outside of device");
        }

        // Verify the alignment (which must be a power of two).
        if offset & (self.align - 1) != 0 {
            panic!("Misaligned write address");
        }

        if payload.len() & (self.align - 1) != 0 {
            panic!("Write length not multiple of alignment");
        }

        for (i, x) in &mut self.write_safe[offset .. offset + payload.len()].iter_mut().enumerate() {
            if !(*x) {
                panic!("Write to unerased location at 0x{:x}", offset + i);
            }
            *x = false;
        }

        let mut sub = &mut self.data[offset .. offset + payload.len()];
        sub.copy_from_slice(payload);
        Ok(())
    }

    /// Read is simple.
    fn read(&self, offset: usize, data: &mut [u8]) -> Result<()> {
        if offset + data.len() > self.data.len() {
            bail!(ebounds("Read outside of device"));
        }

        let sub = &self.data[offset .. offset + data.len()];
        data.copy_from_slice(sub);
        Ok(())
    }

    /// An iterator over each sector in the device.
    fn sector_iter(&self) -> SectorIter {
        SectorIter {
            iter: self.sectors.iter().enumerate(),
            base: 0,
        }
    }

    fn device_size(&self) -> usize {
        self.data.len()
    }
}

/// It is possible to iterate over the sectors in the device, each element returning this.
#[derive(Debug, Clone)]
pub struct Sector {
    /// Which sector is this, starting from 0.
    pub num: usize,
    /// The offset, in bytes, of the start of this sector.
    pub base: usize,
    /// The length, in bytes, of this sector.
    pub size: usize,
}

pub struct SectorIter<'a> {
    iter: Enumerate<slice::Iter<'a, usize>>,
    base: usize,
}

impl<'a> Iterator for SectorIter<'a> {
    type Item = Sector;

    fn next(&mut self) -> Option<Sector> {
        match self.iter.next() {
            None => None,
            Some((num, &size)) => {
                let base = self.base;
                self.base += size;
                Some(Sector {
                    num: num,
                    base: base,
                    size: size,
                })
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::{Flash, SimFlash, Error, ErrorKind, Result, Sector};

    #[test]
    fn test_flash() {
        // NXP-style, uniform sectors.
        let mut f1 = SimFlash::new(vec![4096usize; 256], 1);
        test_device(&mut f1);

        // STM style, non-uniform sectors
        let mut f2 = SimFlash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 64 * 1024,
                                128 * 1024, 128 * 1024, 128 * 1024], 1);
        test_device(&mut f2);
    }

    fn test_device(flash: &mut Flash) {
        let sectors: Vec<Sector> = flash.sector_iter().collect();

        flash.erase(0, sectors[0].size).unwrap();
        let flash_size = flash.device_size();
        flash.erase(0, flash_size).unwrap();
        assert!(flash.erase(0, sectors[0].size - 1).is_bounds());

        // Verify that write and erase do something.
        flash.write(0, &[0]).unwrap();
        let mut buf = [0; 4];
        flash.read(0, &mut buf).unwrap();
        assert_eq!(buf, [0, 0xff, 0xff, 0xff]);

        flash.erase(0, sectors[0].size).unwrap();
        flash.read(0, &mut buf).unwrap();
        assert_eq!(buf, [0xff; 4]);

        // Program the first and last byte of each sector, verify that has been done, and then
        // erase to verify the erase boundaries.
        for sector in &sectors {
            let byte = [(sector.num & 127) as u8];
            flash.write(sector.base, &byte).unwrap();
            flash.write(sector.base + sector.size - 1, &byte).unwrap();
        }

        // Verify the above
        let mut buf = Vec::new();
        for sector in &sectors {
            let byte = (sector.num & 127) as u8;
            buf.resize(sector.size, 0);
            flash.read(sector.base, &mut buf).unwrap();
            assert_eq!(buf.first(), Some(&byte));
            assert_eq!(buf.last(), Some(&byte));
            assert!(buf[1..buf.len()-1].iter().all(|&x| x == 0xff));
        }
    }

    // Helper checks for the result type.
    trait EChecker {
        fn is_bounds(&self) -> bool;
    }

    impl<T> EChecker for Result<T> {

        fn is_bounds(&self) -> bool {
            match *self {
                Err(Error(ErrorKind::OutOfBounds(_), _)) => true,
                _ => false,
            }
        }
    }
}
<commit_msg>Add configurable simulation of bad memory writes<commit_after>//! A flash simulator
//!
//! This module is capable of simulating the type of NOR flash commonly used in microcontrollers.
//! These generally can be written as individual bytes, but must be erased in larger units.

#[macro_use] extern crate log;
#[macro_use] extern crate error_chain;
extern crate rand;
mod pdump;

use rand::distributions::{IndependentSample, Range};
use std::fs::File;
use std::io::Write;
use std::iter::Enumerate;
use std::path::Path;
use std::slice;
use pdump::HexDump;

error_chain! {
    errors {
        OutOfBounds(t: String) {
            description("Offset is out of bounds")
            display("Offset out of bounds: {}", t)
        }
        Write(t: String) {
            description("Invalid write")
            display("Invalid write: {}", t)
        }
        SimulatedFail(t: String) {
            description("Write failed by chance")
            display("Failed write: {}", t)
        }
    }
}

pub trait Flash {
    fn erase(&mut self, offset: usize, len: usize) -> Result<()>;
    fn write(&mut self, offset: usize, payload: &[u8]) -> Result<()>;
    fn read(&self, offset: usize, data: &mut [u8]) -> Result<()>;

    fn add_bad_region(&mut self, offset: usize, len: usize, rate: f32) -> Result<()>;
    fn reset_bad_regions(&mut self);

    fn sector_iter(&self) -> SectorIter;
    fn device_size(&self) -> usize;
}

fn ebounds<T: AsRef<str>>(message: T) -> ErrorKind {
    ErrorKind::OutOfBounds(message.as_ref().to_owned())
}

#[allow(dead_code)]
fn ewrite<T: AsRef<str>>(message: T) -> ErrorKind {
    ErrorKind::Write(message.as_ref().to_owned())
}

#[allow(dead_code)]
fn esimulatedwrite<T: AsRef<str>>(message: T) -> ErrorKind {
    ErrorKind::SimulatedFail(message.as_ref().to_owned())
}

/// An emulated flash device.  It is represented as a block of bytes, and a list of the sector
/// mapings.
#[derive(Clone)]
pub struct SimFlash {
    data: Vec<u8>,
    write_safe: Vec<bool>,
    sectors: Vec<usize>,
    bad_region: Vec<(usize, usize, f32)>,
    // Alignment required for writes.
    align: usize,
}

impl SimFlash {
    /// Given a sector size map, construct a flash device for that.
    pub fn new(sectors: Vec<usize>, align: usize) -> SimFlash {
        // Verify that the alignment is a positive power of two.
        assert!(align > 0);
        assert!(align & (align - 1) == 0);

        let total = sectors.iter().sum();
        SimFlash {
            data: vec![0xffu8; total],
            write_safe: vec![true; total],
            sectors: sectors,
            bad_region: Vec::new(),
            align: align,
        }
    }

    #[allow(dead_code)]
    pub fn dump(&self) {
        self.data.dump();
    }

    /// Dump this image to the given file.
    #[allow(dead_code)]
    pub fn write_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
        let mut fd = File::create(path).chain_err(|| "Unable to write image file")?;
        fd.write_all(&self.data).chain_err(|| "Unable to write to image file")?;
        Ok(())
    }

    // Scan the sector map, and return the base and offset within a sector for this given byte.
    // Returns None if the value is outside of the device.
    fn get_sector(&self, offset: usize) -> Option<(usize, usize)> {
        let mut offset = offset;
        for (sector, &size) in self.sectors.iter().enumerate() {
            if offset < size {
                return Some((sector, offset));
            }
            offset -= size;
        }
        return None;
    }

}

impl Flash for SimFlash {
    /// The flash drivers tend to erase beyond the bounds of the given range.  Instead, we'll be
    /// strict, and make sure that the passed arguments are exactly at a sector boundary, otherwise
    /// return an error.
    fn erase(&mut self, offset: usize, len: usize) -> Result<()> {
        let (_start, slen) = self.get_sector(offset).ok_or_else(|| ebounds("start"))?;
        let (end, elen) = self.get_sector(offset + len - 1).ok_or_else(|| ebounds("end"))?;

        if slen != 0 {
            bail!(ebounds("offset not at start of sector"));
        }
        if elen != self.sectors[end] - 1 {
            bail!(ebounds("end not at start of sector"));
        }

        for x in &mut self.data[offset .. offset + len] {
            *x = 0xff;
        }

        for x in &mut self.write_safe[offset .. offset + len] {
            *x = true;
        }

        Ok(())
    }

    /// We restrict to only allowing writes of values that are:
    ///
    /// 1. being written to for the first time
    /// 2. being written to after being erased
    ///
    /// This emulates a flash device which starts out erased, with the
    /// added restriction that repeated writes to the same location
    /// are disallowed, even if they would be safe to do.
    fn write(&mut self, offset: usize, payload: &[u8]) -> Result<()> {
        for &(off, len, rate) in &self.bad_region {
            if offset >= off && (offset + payload.len()) <= (off + len) {
                let mut rng = rand::thread_rng();
                let between = Range::new(0., 1.);
                if between.ind_sample(&mut rng) < rate {
                    bail!(esimulatedwrite(
                        format!("Ignoring write to {:#x}-{:#x}", off, off + len)));
                }
            }
        }

        if offset + payload.len() > self.data.len() {
            panic!("Write outside of device");
        }

        // Verify the alignment (which must be a power of two).
        if offset & (self.align - 1) != 0 {
            panic!("Misaligned write address");
        }

        if payload.len() & (self.align - 1) != 0 {
            panic!("Write length not multiple of alignment");
        }

        for (i, x) in &mut self.write_safe[offset .. offset + payload.len()].iter_mut().enumerate() {
            if !(*x) {
                panic!("Write to unerased location at 0x{:x}", offset + i);
            }
            *x = false;
        }

        let mut sub = &mut self.data[offset .. offset + payload.len()];
        sub.copy_from_slice(payload);
        Ok(())
    }

    /// Read is simple.
    fn read(&self, offset: usize, data: &mut [u8]) -> Result<()> {
        if offset + data.len() > self.data.len() {
            bail!(ebounds("Read outside of device"));
        }

        let sub = &self.data[offset .. offset + data.len()];
        data.copy_from_slice(sub);
        Ok(())
    }

    /// Adds a new flash bad region. Writes to this area fail with a chance
    /// given by `rate`.
    fn add_bad_region(&mut self, offset: usize, len: usize, rate: f32) -> Result<()> {
        if rate < 0.0 || rate > 1.0 {
            bail!(ebounds("Invalid rate"));
        }

        info!("Adding new bad region {:#x}-{:#x}", offset, offset + len);
        self.bad_region.push((offset, len, rate));

        Ok(())
    }

    fn reset_bad_regions(&mut self) {
        self.bad_region.clear();
    }

    /// An iterator over each sector in the device.
    fn sector_iter(&self) -> SectorIter {
        SectorIter {
            iter: self.sectors.iter().enumerate(),
            base: 0,
        }
    }

    fn device_size(&self) -> usize {
        self.data.len()
    }
}

/// It is possible to iterate over the sectors in the device, each element returning this.
#[derive(Debug, Clone)]
pub struct Sector {
    /// Which sector is this, starting from 0.
    pub num: usize,
    /// The offset, in bytes, of the start of this sector.
    pub base: usize,
    /// The length, in bytes, of this sector.
    pub size: usize,
}

pub struct SectorIter<'a> {
    iter: Enumerate<slice::Iter<'a, usize>>,
    base: usize,
}

impl<'a> Iterator for SectorIter<'a> {
    type Item = Sector;

    fn next(&mut self) -> Option<Sector> {
        match self.iter.next() {
            None => None,
            Some((num, &size)) => {
                let base = self.base;
                self.base += size;
                Some(Sector {
                    num: num,
                    base: base,
                    size: size,
                })
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::{Flash, SimFlash, Error, ErrorKind, Result, Sector};

    #[test]
    fn test_flash() {
        // NXP-style, uniform sectors.
        let mut f1 = SimFlash::new(vec![4096usize; 256], 1);
        test_device(&mut f1);

        // STM style, non-uniform sectors
        let mut f2 = SimFlash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 64 * 1024,
                                128 * 1024, 128 * 1024, 128 * 1024], 1);
        test_device(&mut f2);
    }

    fn test_device(flash: &mut Flash) {
        let sectors: Vec<Sector> = flash.sector_iter().collect();

        flash.erase(0, sectors[0].size).unwrap();
        let flash_size = flash.device_size();
        flash.erase(0, flash_size).unwrap();
        assert!(flash.erase(0, sectors[0].size - 1).is_bounds());

        // Verify that write and erase do something.
        flash.write(0, &[0]).unwrap();
        let mut buf = [0; 4];
        flash.read(0, &mut buf).unwrap();
        assert_eq!(buf, [0, 0xff, 0xff, 0xff]);

        flash.erase(0, sectors[0].size).unwrap();
        flash.read(0, &mut buf).unwrap();
        assert_eq!(buf, [0xff; 4]);

        // Program the first and last byte of each sector, verify that has been done, and then
        // erase to verify the erase boundaries.
        for sector in &sectors {
            let byte = [(sector.num & 127) as u8];
            flash.write(sector.base, &byte).unwrap();
            flash.write(sector.base + sector.size - 1, &byte).unwrap();
        }

        // Verify the above
        let mut buf = Vec::new();
        for sector in &sectors {
            let byte = (sector.num & 127) as u8;
            buf.resize(sector.size, 0);
            flash.read(sector.base, &mut buf).unwrap();
            assert_eq!(buf.first(), Some(&byte));
            assert_eq!(buf.last(), Some(&byte));
            assert!(buf[1..buf.len()-1].iter().all(|&x| x == 0xff));
        }
    }

    // Helper checks for the result type.
    trait EChecker {
        fn is_bounds(&self) -> bool;
    }

    impl<T> EChecker for Result<T> {

        fn is_bounds(&self) -> bool {
            match *self {
                Err(Error(ErrorKind::OutOfBounds(_), _)) => true,
                _ => false,
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::i16;
use std::f64::consts::{PI};
use std::sync::{Arc, Mutex};
use std::thread;
use cpal;
use ::{noise, lerp};

const SAMPLE_RATE: u32 = 44100;

/// Play a 44100 Hz mono sound using the sample data from the input
/// iterator. The input sound samples should be in range [-1.0, 1.0].
pub fn play<T: Iterator<Item=f64> + Send + 'static>(sample: Arc<Mutex<T>>) {
    let mut voice = cpal::Voice::new();

    thread::spawn(move || loop {
        {
            let mut wave_data = sample.lock().unwrap();
            let mut buffer = voice.append_data(1, cpal::SamplesRate(SAMPLE_RATE), 32768);
            for sample in buffer.iter_mut() {
                match wave_data.next() {
                    // XXX: https://github.com/tomaka/cpal/issues/39
                    // CPAL samples operate in the i16 space but must be cast to u16.
                    Some(w) => *sample = (w * i16::MAX as f64) as u16,
                    None => return,
                }
            }
        }
        voice.play();
    });
}

pub struct Sample<W> {
    wave: W,
    max_t: Option<usize>,
    t: usize,
}

impl<W: Wave> Sample<W> {
    /// Return an iterator that stops after the given duration.
    pub fn duration(mut self, duration_s: f64) -> Sample<W> {
        self.max_t = Some((duration_s * SAMPLE_RATE as f64) as usize);
        self
    }
}

impl<W: Wave> Iterator for Sample<W> {
    type Item = f64;

    fn next(&mut self) -> Option<f64> {
        if let Some(max_t) = self.max_t {
            if self.t >= max_t { return None; }
        }

        let sample = self.wave.sample(self.t as f64 / SAMPLE_RATE as f64);
        self.t += 1;
        Some(sample)
    }
}

/// Sampleable waveform.
pub trait Wave: Sized {
    /// Get the value of the wave in [-1.0, 1.0] at the given time in seconds.
    fn sample(&self, t: f64) -> f64;

    /// Set the volume of the sound.
    fn volume(self, vol: f64) -> Enveloped<Self, f64> {
        Enveloped { wave: self, envelope: vol }
    }

    /// Set the pitch of the sound.
    fn pitch(self, hz: f64) -> Pitched<Self> {
        Pitched { inner: self, hz: hz }
    }

    /// Give the sound an attack-decay-sustain-release envelope of a given
    /// duration.
    fn adsr(self, duration: f64, atk: f64, dec: f64, sus: f64, rel: f64) -> Enveloped<Self, Adsr> {
        Enveloped {
            wave: self,
            envelope: Adsr {
                attack_s: atk,
                decay_s: dec,
                sustain_volume: sus,
                release_s: rel,
                duration_s: duration,
            }
        }
    }

    /// Turn the sound into a sampling iterator.
    fn into_iter(self) -> Sample<Self> {
        Sample {
            wave: self,
            max_t: None,
            t: 0,
        }
    }
}

pub trait Envelope: Sized {
    fn volume(&self, t: f64) -> f64;
}

/// Different waves at 1 Hz.
pub enum Waveform {
    Sine,
    Square,
    Saw,
    Triangle,
    Noise,
}

impl Wave for Waveform {
    fn sample(&self, t: f64) -> f64 {
        use self::Waveform::*;

        let frac = t % 1.0;

        match self {
            &Sine => (frac * PI).sin(),
            &Square => if frac < 0.5 { -1.0 } else { 1.0 },
            &Saw => -1.0 + frac * 2.0,
            &Triangle => if frac < 0.5 { -1.0 + frac * 4.0 } else { 3.0 - frac * 4.0 },
            &Noise => noise((t * 1024.0) as i32) as f64,
        }
    }
}

pub struct Pitched<W> {
    inner: W,
    hz: f64,
}

impl<W: Wave> Wave for Pitched<W> {
    fn sample(&self, t: f64) -> f64 { self.inner.sample(t * self.hz) }
}

pub struct Enveloped<W, E> {
    wave: W,
    envelope: E,
}

impl<W: Wave, E: Envelope> Wave for Enveloped<W, E> {
    fn sample(&self, t: f64) -> f64 { self.wave.sample(t) * self.envelope.volume(t) }
}

pub struct Adsr {
    attack_s: f64,
    decay_s: f64,
    sustain_volume: f64,
    release_s: f64,
    duration_s: f64,
}

impl Envelope for Adsr {
    fn volume(&self, mut t: f64) -> f64 {
        if t < 0.0 || t > self.duration_s { return 0.0; }

        let sustain_s = self.duration_s - self.attack_s - self.decay_s - self.release_s;

        if t < self.attack_s { return lerp(0.0, 1.0, t / self.attack_s); }
        t -= self.attack_s;

        if t < self.decay_s { return lerp(1.0, self.sustain_volume, t / self.decay_s); }
        t -= self.decay_s;

        if t < sustain_s { return self.sustain_volume; }
        t -= sustain_s;

        lerp(self.sustain_volume, 0.0, t / self.release_s)
    }
}

// Volume adjustment
impl Envelope for f64 {
    fn volume(&self, _: f64) -> f64 { *self }
}

#[derive(Clone)]
pub struct Mixer {
    inner: Arc<Mutex<InnerMixer>>,
}

impl Mixer {
    /// Spawns a new mixer thread and returns a handle to control it.
    pub fn new() -> Mixer {
        let inner = Arc::new(Mutex::new(InnerMixer::new()));
        play(inner.clone());
        Mixer { inner: inner }
    }

    /// Acquire a lock to the inner mixer mutex and add a wave to it.
    pub fn add<T: Iterator<Item=f64>+Send+'static>(&mut self, wave: T) {
        self.inner.lock().unwrap().add(Box::new(wave));
    }
}

struct InnerMixer {
    waves: Vec<Box<Iterator<Item=f64> + Send>>,
}

impl InnerMixer {
    fn new() -> InnerMixer {
        InnerMixer {
            waves: Vec::new(),
        }
    }

    fn add(&mut self, wave: Box<Iterator<Item=f64> + Send>) {
        self.waves.push(wave);
    }
}

impl Iterator for InnerMixer {
    type Item = f64;

    fn next(&mut self) -> Option<f64> {
        let mut ret = 0.0;
        // Indexes of ended waves.
        let mut deletes = Vec::new();

        // Reverse the range because we want indices going to deletes vector
        // in reverse order.
        for i in (0..(self.waves.len())).rev() {
            match self.waves[i].next() {
                None => { deletes.push(i); }
                Some(a) => {
                    // Do some hacky equalization to keep summed waves from
                    // going outside the wave envelope.
                    ret = a + ret - a.signum() * (a * ret).max(0.0);
                }
            }
        }

        // Because deletes is in reverse order, we can swap-remove everything
        // we come across and not invalidate the values further in the list.
        for &del_idx in deletes.iter() {
            self.waves.swap_remove(del_idx);
        }

        Some(ret)
    }
}
<commit_msg>Duty cycle for square waves<commit_after>use std::i16;
use std::f64::consts::{PI};
use std::sync::{Arc, Mutex};
use std::thread;
use cpal;
use ::{noise, lerp};

const SAMPLE_RATE: u32 = 44100;

/// Play a 44100 Hz mono sound using the sample data from the input
/// iterator. The input sound samples should be in range [-1.0, 1.0].
pub fn play<T: Iterator<Item=f64> + Send + 'static>(sample: Arc<Mutex<T>>) {
    let mut voice = cpal::Voice::new();

    thread::spawn(move || loop {
        {
            let mut wave_data = sample.lock().unwrap();
            let mut buffer = voice.append_data(1, cpal::SamplesRate(SAMPLE_RATE), 32768);
            for sample in buffer.iter_mut() {
                match wave_data.next() {
                    // XXX: https://github.com/tomaka/cpal/issues/39
                    // CPAL samples operate in the i16 space but must be cast to u16.
                    Some(w) => *sample = (w * i16::MAX as f64) as u16,
                    None => return,
                }
            }
        }
        voice.play();
    });
}

pub struct Sample<W> {
    wave: W,
    max_t: Option<usize>,
    t: usize,
}

impl<W: Wave> Sample<W> {
    /// Return an iterator that stops after the given duration.
    pub fn duration(mut self, duration_s: f64) -> Sample<W> {
        self.max_t = Some((duration_s * SAMPLE_RATE as f64) as usize);
        self
    }
}

impl<W: Wave> Iterator for Sample<W> {
    type Item = f64;

    fn next(&mut self) -> Option<f64> {
        if let Some(max_t) = self.max_t {
            if self.t >= max_t { return None; }
        }

        let sample = self.wave.sample(self.t as f64 / SAMPLE_RATE as f64);
        self.t += 1;
        Some(sample)
    }
}

/// Sampleable waveform.
pub trait Wave: Sized {
    /// Get the value of the wave in [-1.0, 1.0] at the given time in seconds.
    fn sample(&self, t: f64) -> f64;

    /// Set the volume of the sound.
    fn volume(self, vol: f64) -> Enveloped<Self, f64> {
        Enveloped { wave: self, envelope: vol }
    }

    /// Set the pitch of the sound.
    fn pitch(self, hz: f64) -> Pitched<Self> {
        Pitched { inner: self, hz: hz }
    }

    /// Give the sound an attack-decay-sustain-release envelope of a given
    /// duration.
    fn adsr(self, duration: f64, atk: f64, dec: f64, sus: f64, rel: f64) -> Enveloped<Self, Adsr> {
        Enveloped {
            wave: self,
            envelope: Adsr {
                attack_s: atk,
                decay_s: dec,
                sustain_volume: sus,
                release_s: rel,
                duration_s: duration,
            }
        }
    }

    /// Turn the sound into a sampling iterator.
    fn into_iter(self) -> Sample<Self> {
        Sample {
            wave: self,
            max_t: None,
            t: 0,
        }
    }
}

pub trait Envelope: Sized {
    fn volume(&self, t: f64) -> f64;
}

/// Different waves at 1 Hz.
pub enum Waveform {
    Sine,
    /// The parameter is the duty cycle of the square wave, in [0.0, 1.0]
    Square(f64),
    Saw,
    Triangle,
    Noise,
}

impl Wave for Waveform {
    fn sample(&self, t: f64) -> f64 {
        use self::Waveform::*;

        let frac = t % 1.0;

        match self {
            &Sine => (frac * PI).sin(),
            &Square(duty) => if frac < duty { 1.0 } else { -1.0 },
            &Saw => -1.0 + frac * 2.0,
            &Triangle => if frac < 0.5 { -1.0 + frac * 4.0 } else { 3.0 - frac * 4.0 },
            &Noise => noise((t * 1024.0) as i32) as f64,
        }
    }
}

pub struct Pitched<W> {
    inner: W,
    hz: f64,
}

impl<W: Wave> Wave for Pitched<W> {
    fn sample(&self, t: f64) -> f64 { self.inner.sample(t * self.hz) }
}

pub struct Enveloped<W, E> {
    wave: W,
    envelope: E,
}

impl<W: Wave, E: Envelope> Wave for Enveloped<W, E> {
    fn sample(&self, t: f64) -> f64 { self.wave.sample(t) * self.envelope.volume(t) }
}

pub struct Adsr {
    attack_s: f64,
    decay_s: f64,
    sustain_volume: f64,
    release_s: f64,
    duration_s: f64,
}

impl Envelope for Adsr {
    fn volume(&self, mut t: f64) -> f64 {
        if t < 0.0 || t > self.duration_s { return 0.0; }

        let sustain_s = self.duration_s - self.attack_s - self.decay_s - self.release_s;

        if t < self.attack_s { return lerp(0.0, 1.0, t / self.attack_s); }
        t -= self.attack_s;

        if t < self.decay_s { return lerp(1.0, self.sustain_volume, t / self.decay_s); }
        t -= self.decay_s;

        if t < sustain_s { return self.sustain_volume; }
        t -= sustain_s;

        lerp(self.sustain_volume, 0.0, t / self.release_s)
    }
}

// Volume adjustment
impl Envelope for f64 {
    fn volume(&self, _: f64) -> f64 { *self }
}

#[derive(Clone)]
pub struct Mixer {
    inner: Arc<Mutex<InnerMixer>>,
}

impl Mixer {
    /// Spawns a new mixer thread and returns a handle to control it.
    pub fn new() -> Mixer {
        let inner = Arc::new(Mutex::new(InnerMixer::new()));
        play(inner.clone());
        Mixer { inner: inner }
    }

    /// Acquire a lock to the inner mixer mutex and add a wave to it.
    pub fn add<T: Iterator<Item=f64>+Send+'static>(&mut self, wave: T) {
        self.inner.lock().unwrap().add(Box::new(wave));
    }
}

struct InnerMixer {
    waves: Vec<Box<Iterator<Item=f64> + Send>>,
}

impl InnerMixer {
    fn new() -> InnerMixer {
        InnerMixer {
            waves: Vec::new(),
        }
    }

    fn add(&mut self, wave: Box<Iterator<Item=f64> + Send>) {
        self.waves.push(wave);
    }
}

impl Iterator for InnerMixer {
    type Item = f64;

    fn next(&mut self) -> Option<f64> {
        let mut ret = 0.0;
        // Indexes of ended waves.
        let mut deletes = Vec::new();

        // Reverse the range because we want indices going to deletes vector
        // in reverse order.
        for i in (0..(self.waves.len())).rev() {
            match self.waves[i].next() {
                None => { deletes.push(i); }
                Some(a) => {
                    // Do some hacky equalization to keep summed waves from
                    // going outside the wave envelope.
                    ret = a + ret - a.signum() * (a * ret).max(0.0);
                }
            }
        }

        // Because deletes is in reverse order, we can swap-remove everything
        // we come across and not invalidate the values further in the list.
        for &del_idx in deletes.iter() {
            self.waves.swap_remove(del_idx);
        }

        Some(ret)
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::ptr;
use std::sync::atomic::{self, AtomicUsize};
use std::sync::atomic::Ordering::{self, Relaxed, Acquire, Release, SeqCst};
use std::ops::{Deref, DerefMut};

use bag::Bag;
use cache_padded::CachePadded;

trait AnyType {}
impl<T: ?Sized> AnyType for T {}

struct Participants {
    bag: Bag<CachePadded<Participant>>,
}

struct Participant {
    epoch: AtomicUsize,
    active: AtomicUsize,
    op_count: u32,
}

impl Participants {
    const fn new() -> Participants {
        Participants { bag: Bag::new() }
    }

    fn enroll(&self) -> *mut Participant {
        let participant = Participant {
            epoch: AtomicUsize::new(0),
            active: AtomicUsize::new(0),
            op_count: 0,
        };
        unsafe {
            self.bag.insert(CachePadded::new(participant)) as *mut _
        }
    }
}

struct EpochState {
    epoch: CachePadded<AtomicUsize>,
    garbage: [CachePadded<Bag<*mut AnyType>>; 3],
    participants: Participants,
}

unsafe impl Send for EpochState {}
unsafe impl Sync for EpochState {}

impl EpochState {
    const fn new() -> EpochState {
        EpochState {
            epoch: CachePadded::zeroed(),
            garbage: [CachePadded::zeroed(),
                      CachePadded::zeroed(),
                      CachePadded::zeroed()],
            participants: Participants::new(),
        }
    }
}

static EPOCH: EpochState = EpochState::new();

impl Participant {
    fn enter(&mut self) {
        self.active.store(self.active.load(Relaxed) + 1, Relaxed);
        atomic::fence(SeqCst);

        let epoch = EPOCH.epoch.load(Relaxed);
        if epoch == self.epoch.load(Relaxed) {
            self.op_count = self.op_count.saturating_add(1);
        } else {
            self.epoch.store(epoch, Relaxed);
            self.op_count = 0;
        }
    }

    fn exit(&mut self) {
        self.active.store(self.active.load(Relaxed) - 1, Release);
    }

    fn reclaim<T>(&mut self, data: *mut T) {
        let data: *mut AnyType = data;
        EPOCH.garbage[self.epoch.load(Relaxed)]
             .insert(unsafe {
                 // forget any borrows within `data`:
                 mem::transmute(data)
             });
    }
}

pub fn try_collect() -> bool {
    let cur_epoch = EPOCH.epoch.load(SeqCst);

    for p in EPOCH.participants.bag.iter() {
        if p.active.load(Relaxed) > 0 && p.epoch.load(Relaxed) != cur_epoch {
            return false
        }
    }

    let new_epoch = (cur_epoch + 1) % 3;
    atomic::fence(Acquire);
    if EPOCH.epoch.compare_and_swap(cur_epoch, new_epoch, SeqCst) != cur_epoch {
        return false
    }

    unsafe {
        for g in EPOCH.garbage[(new_epoch + 1) % 3].iter_clobber() {
            // the pointer g is now unique; drop it
            mem::drop(Box::from_raw(g))
        }
    }

    true
}

pub struct Owned<T> {
    data: Box<T>,
}

impl<T> Deref for Owned<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.data
    }
}

impl<T> DerefMut for Owned<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.data
    }
}

#[derive(PartialEq, Eq)]
pub struct Shared<'a, T: 'a> {
    data: &'a T,
}

impl<'a, T> Copy for Shared<'a, T> {}
impl<'a, T> Clone for Shared<'a, T> {
    fn clone(&self) -> Shared<'a, T> {
        Shared { data: self.data }
    }
}

impl<'a, T> Deref for Shared<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        self.data
    }
}

impl<'a, T> Shared<'a, T> {
    unsafe fn from_raw(raw: *mut T) -> Shared<'a, T> {
        Shared { data: mem::transmute(raw) }
    }

    unsafe fn from_ref(r: &T) -> Shared<'a, T> {
        Shared { data: mem::transmute(r) }
    }

    unsafe fn from_owned(owned: Owned<T>) -> Shared<'a, T> {
        Shared::from_ref(owned.deref())
    }

    fn as_raw(&self) -> *mut T {
        self.data as *const _ as *mut _
    }
}

impl<T> Owned<T> {
    fn as_raw(&self) -> *mut T {
        self.deref() as *const _ as *mut _
    }
}

pub struct AtomicPtr<T> {
    ptr: atomic::AtomicPtr<T>,
}

impl<T> Default for AtomicPtr<T> {
    fn default() -> AtomicPtr<T> {
        AtomicPtr { ptr: atomic::AtomicPtr::new(ptr::null_mut()) }
    }
}

impl<T> AtomicPtr<T> {
    pub fn load<'a>(&self, ord: Ordering, _: &'a Guard) -> Option<Shared<'a, T>> {
        let p = self.ptr.load(ord);
        if p == ptr::null_mut() {
            None
        } else {
            Some(unsafe { Shared::from_raw(p) })
        }
    }

    pub fn store<'a>(&self, val: Owned<T>, ord: Ordering, _: &'a Guard) -> Shared<'a, T> {
        unsafe {
            let shared = Shared::from_owned(val);
            self.store_shared(shared, ord);
            shared
        }
    }

    pub fn store_null(&self, ord: Ordering) {
        self.ptr.store(ptr::null_mut(), ord)
    }

    pub unsafe fn store_shared(&self, val: Shared<T>, ord: Ordering) {
        self.ptr.store(val.as_raw(), ord)
    }

    pub fn cas<'a>(&self, old: Shared<T>, new: Owned<T>, ord: Ordering, _: &'a Guard)
                   -> Result<Shared<'a, T>, Owned<T>>
    {
        if self.ptr.compare_and_swap(old.as_raw(), new.as_raw(), ord) == old.as_raw() {
            Ok(unsafe { Shared::from_owned(new) })
        } else {
            Err(new)
        }
    }

    pub fn cas_to_null(&self, old: Shared<T>, ord: Ordering) -> bool {
        self.ptr.compare_and_swap(old.as_raw(), ptr::null_mut(), ord) == old.as_raw()
    }

    pub unsafe fn cas_shared(&self, old: Shared<T>, new: Shared<T>, ord: Ordering) -> bool {
        self.ptr.compare_and_swap(old.as_raw(), new.as_raw(), ord) == old.as_raw()
    }

    pub fn swap<'a>(&self, new: Owned<T>, ord: Ordering, _: &'a Guard) -> Shared<'a, T> {
        unsafe { Shared::from_raw(self.ptr.swap(new.as_raw(), ord)) }
    }

    pub fn swap_null<'a>(&self, ord: Ordering, _: &'a Guard) -> Shared<'a, T> {
        unsafe { Shared::from_raw(self.ptr.swap(ptr::null_mut(), ord)) }
    }
}

thread_local!(static LOCAL_EPOCH: *mut Participant = EPOCH.participants.enroll());

pub fn pin() -> Guard {
    LOCAL_EPOCH.with(|p| unsafe { (**p).enter() });
    Guard {
        _dummy: ()
    }
}

pub struct Guard {
    _dummy: ()
}

impl Drop for Guard {
    fn drop(&mut self) {
        LOCAL_EPOCH.with(|p| unsafe { (**p).exit() });
    }
}
<commit_msg>Add unlinked method for reclaimation<commit_after>use std::mem;
use std::ptr;
use std::sync::atomic::{self, AtomicUsize};
use std::sync::atomic::Ordering::{self, Relaxed, Acquire, Release, SeqCst};
use std::ops::{Deref, DerefMut};

use bag::Bag;
use cache_padded::CachePadded;

trait AnyType {}
impl<T: ?Sized> AnyType for T {}

struct Participants {
    bag: Bag<CachePadded<Participant>>,
}

struct Participant {
    epoch: AtomicUsize,
    active: AtomicUsize,
    op_count: u32,
}

impl Participants {
    const fn new() -> Participants {
        Participants { bag: Bag::new() }
    }

    fn enroll(&self) -> *mut Participant {
        let participant = Participant {
            epoch: AtomicUsize::new(0),
            active: AtomicUsize::new(0),
            op_count: 0,
        };
        unsafe {
            self.bag.insert(CachePadded::new(participant)) as *mut _
        }
    }
}

struct EpochState {
    epoch: CachePadded<AtomicUsize>,
    garbage: [CachePadded<Bag<*mut AnyType>>; 3],
    participants: Participants,
}

unsafe impl Send for EpochState {}
unsafe impl Sync for EpochState {}

impl EpochState {
    const fn new() -> EpochState {
        EpochState {
            epoch: CachePadded::zeroed(),
            garbage: [CachePadded::zeroed(),
                      CachePadded::zeroed(),
                      CachePadded::zeroed()],
            participants: Participants::new(),
        }
    }
}

static EPOCH: EpochState = EpochState::new();

impl Participant {
    fn enter(&mut self) {
        self.active.store(self.active.load(Relaxed) + 1, Relaxed);
        atomic::fence(SeqCst);

        let epoch = EPOCH.epoch.load(Relaxed);
        if epoch == self.epoch.load(Relaxed) {
            self.op_count = self.op_count.saturating_add(1);
        } else {
            self.epoch.store(epoch, Relaxed);
            self.op_count = 0;
        }
    }

    fn exit(&mut self) {
        self.active.store(self.active.load(Relaxed) - 1, Release);
    }

    fn reclaim<T>(&mut self, data: *mut T) {
        let data: *mut AnyType = data;
        EPOCH.garbage[self.epoch.load(Relaxed)]
             .insert(unsafe {
                 // forget any borrows within `data`:
                 mem::transmute(data)
             });
    }
}

pub fn try_collect() -> bool {
    let cur_epoch = EPOCH.epoch.load(SeqCst);

    for p in EPOCH.participants.bag.iter() {
        if p.active.load(Relaxed) > 0 && p.epoch.load(Relaxed) != cur_epoch {
            return false
        }
    }

    let new_epoch = (cur_epoch + 1) % 3;
    atomic::fence(Acquire);
    if EPOCH.epoch.compare_and_swap(cur_epoch, new_epoch, SeqCst) != cur_epoch {
        return false
    }

    unsafe {
        for g in EPOCH.garbage[(new_epoch + 1) % 3].iter_clobber() {
            // the pointer g is now unique; drop it
            mem::drop(Box::from_raw(g))
        }
    }

    true
}

pub struct Owned<T> {
    data: Box<T>,
}

impl<T> Deref for Owned<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.data
    }
}

impl<T> DerefMut for Owned<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.data
    }
}

#[derive(PartialEq, Eq)]
pub struct Shared<'a, T: 'a> {
    data: &'a T,
}

impl<'a, T> Copy for Shared<'a, T> {}
impl<'a, T> Clone for Shared<'a, T> {
    fn clone(&self) -> Shared<'a, T> {
        Shared { data: self.data }
    }
}

impl<'a, T> Deref for Shared<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        self.data
    }
}

impl<'a, T> Shared<'a, T> {
    unsafe fn from_raw(raw: *mut T) -> Shared<'a, T> {
        Shared { data: mem::transmute(raw) }
    }

    unsafe fn from_ref(r: &T) -> Shared<'a, T> {
        Shared { data: mem::transmute(r) }
    }

    unsafe fn from_owned(owned: Owned<T>) -> Shared<'a, T> {
        Shared::from_ref(owned.deref())
    }

    fn as_raw(&self) -> *mut T {
        self.data as *const _ as *mut _
    }
}

impl<T> Owned<T> {
    fn as_raw(&self) -> *mut T {
        self.deref() as *const _ as *mut _
    }
}

pub struct AtomicPtr<T> {
    ptr: atomic::AtomicPtr<T>,
}

impl<T> Default for AtomicPtr<T> {
    fn default() -> AtomicPtr<T> {
        AtomicPtr { ptr: atomic::AtomicPtr::new(ptr::null_mut()) }
    }
}

impl<T> AtomicPtr<T> {
    pub fn load<'a>(&self, ord: Ordering, _: &'a Guard) -> Option<Shared<'a, T>> {
        let p = self.ptr.load(ord);
        if p == ptr::null_mut() {
            None
        } else {
            Some(unsafe { Shared::from_raw(p) })
        }
    }

    pub fn store<'a>(&self, val: Owned<T>, ord: Ordering, _: &'a Guard) -> Shared<'a, T> {
        unsafe {
            let shared = Shared::from_owned(val);
            self.store_shared(shared, ord);
            shared
        }
    }

    pub fn store_null(&self, ord: Ordering) {
        self.ptr.store(ptr::null_mut(), ord)
    }

    pub unsafe fn store_shared(&self, val: Shared<T>, ord: Ordering) {
        self.ptr.store(val.as_raw(), ord)
    }

    pub fn cas<'a>(&self, old: Shared<T>, new: Owned<T>, ord: Ordering, _: &'a Guard)
                   -> Result<Shared<'a, T>, Owned<T>>
    {
        if self.ptr.compare_and_swap(old.as_raw(), new.as_raw(), ord) == old.as_raw() {
            Ok(unsafe { Shared::from_owned(new) })
        } else {
            Err(new)
        }
    }

    pub fn cas_to_null(&self, old: Shared<T>, ord: Ordering) -> bool {
        self.ptr.compare_and_swap(old.as_raw(), ptr::null_mut(), ord) == old.as_raw()
    }

    pub unsafe fn cas_shared(&self, old: Shared<T>, new: Shared<T>, ord: Ordering) -> bool {
        self.ptr.compare_and_swap(old.as_raw(), new.as_raw(), ord) == old.as_raw()
    }

    pub fn swap<'a>(&self, new: Owned<T>, ord: Ordering, _: &'a Guard) -> Shared<'a, T> {
        unsafe { Shared::from_raw(self.ptr.swap(new.as_raw(), ord)) }
    }

    pub fn swap_null<'a>(&self, ord: Ordering, _: &'a Guard) -> Shared<'a, T> {
        unsafe { Shared::from_raw(self.ptr.swap(ptr::null_mut(), ord)) }
    }
}

thread_local!(static LOCAL_EPOCH: *mut Participant = EPOCH.participants.enroll());

pub fn pin() -> Guard {
    LOCAL_EPOCH.with(|p| unsafe { (**p).enter() });
    Guard {
        _dummy: ()
    }
}

pub struct Guard {
    _dummy: ()
}

impl Guard {
    pub fn unlinked<T>(&self, val: Shared<T>) {
        LOCAL_EPOCH.with(|p| unsafe { (**p).reclaim(val.as_raw()) })
    }
}

impl Drop for Guard {
    fn drop(&mut self) {
        LOCAL_EPOCH.with(|p| unsafe { (**p).exit() });
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use super::*;
use rand::{ChaChaRng, Rng, SeedableRng};
use std::{mem, ptr, slice};
use std::collections::VecDeque;
use std::sync::Arc;

use dav1d_sys::*;

fn fill_frame(ra: &mut ChaChaRng, frame: &mut Frame) {
  for plane in frame.planes.iter_mut() {
    let stride = plane.cfg.stride;
    for row in plane.data.chunks_mut(stride) {
      for mut pixel in row {
        let v: u8 = ra.gen();
        *pixel = v as u16;
      }
    }
  }
}

struct Decoder {
  dec: *mut Dav1dContext
}

fn setup_decoder() -> Decoder {
  unsafe {
    let mut settings = mem::uninitialized();
    let mut dec: Decoder = mem::uninitialized();

    dav1d_default_settings(&mut settings);

    let ret = dav1d_open(&mut dec.dec, &settings);

    if ret != 0 {
      panic!("Cannot instantiate the decoder {}", ret);
    }

    dec
  }
}

impl Drop for Decoder {
  fn drop(&mut self) {
    unsafe { dav1d_close(&mut self.dec) };
  }
}

fn setup_encoder(
  w: usize, h: usize, speed: usize, quantizer: usize, bit_depth: usize,
  chroma_sampling: ChromaSampling, min_keyint: u64, max_keyint: u64,
  low_latency: bool
) -> Context {

  let mut enc = EncoderConfig::with_speed_preset(speed);
  enc.quantizer = quantizer;
  enc.min_key_frame_interval = min_keyint;
  enc.max_key_frame_interval = max_keyint;
  enc.low_latency = low_latency;

  let cfg = Config {
    frame_info: FrameInfo {
      width: w,
      height: h,
      bit_depth,
      chroma_sampling,
      ..Default::default()
    },
    timebase: Rational::new(1, 1000),
    enc
  };

  cfg.new_context()
}

// TODO: support non-multiple-of-16 dimensions
static DIMENSION_OFFSETS: &[(usize, usize)] =
  &[(0, 0), (4, 4), (8, 8), (16, 16)];

fn speed(s: usize) {
  let quantizer = 100;
  let limit = 5;
  let w = 64;
  let h = 80;

  for b in DIMENSION_OFFSETS.iter() {
      encode_decode(w + b.0, h + b.1, s, quantizer, limit, 8, 15, 15, true);
  }
}

macro_rules! test_speeds {
  ($($S:expr),+) => {
    $(
        paste::item!{
            #[test]
            #[ignore]
            fn [<speed_ $S>]() {
                speed($S)
            }
        }
    )*
  }
}

test_speeds!{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }

macro_rules! test_dimensions {
  ($(($W:expr, $H:expr)),+) => {
    $(
        paste::item!{
            #[test]
            fn [<dimension_ $W x $H>]() {
                dimension($W, $H)
            }
        }
    )*
  }
}

test_dimensions!{
  (8, 8),
  (16, 16),
  (32, 32),
  (64, 64),
  (128, 128),
  (256, 256),
  (512, 512),
  (1024, 1024),
  (2048, 2048),
  (258, 258),
  (260, 260),
  (262, 262),
  (264, 264),
  (265, 265)
}

fn dimension(w: usize, h: usize) {
  let quantizer = 100;
  let limit = 1;
  let speed = 4;

  encode_decode(w, h, speed, quantizer, limit, 8, 15, 15, true);
}

#[test]
fn quantizer() {
  let limit = 5;
  let w = 64;
  let h = 80;
  let speed = 4;

  for b in DIMENSION_OFFSETS.iter() {
    for &q in [80, 100, 120].iter() {
      encode_decode(w + b.0, h + b.1, speed, q, limit, 8, 15, 15, true);
    }
  }
}

#[test]
fn keyframes() {
  let limit = 12;
  let w = 64;
  let h = 80;
  let speed = 10;
  let q = 100;

  encode_decode(w, h, speed, q, limit, 8, 6, 6, true);
}

#[test]
fn reordering() {
  let limit = 12;
  let w = 64;
  let h = 80;
  let speed = 10;
  let q = 100;

  for keyint in &[4, 5, 6] {
    encode_decode(w, h, speed, q, limit, 8, *keyint, *keyint, false);
  }
}

#[test]
#[ignore]
fn odd_size_frame_with_full_rdo() {
  let limit = 3;
  let w = 512 + 32 + 16 + 5;
  let h = 512 + 16 + 5;
  let speed = 0;
  let qindex = 100;

  encode_decode(w, h, speed, qindex, limit, 8, 15, 15, true);
}

fn high_bd(bits: usize) {
  let quantizer = 100;
  let limit = 3; // Include inter frames
  let speed = 0; // Test as many tools as possible
  let w = 64;
  let h = 80;

  encode_decode(w, h, speed, quantizer, limit, bits, 15, 15, true);
}

#[test]
fn high_bd_10() {
  high_bd(10);
}

#[test]
fn high_bd_12() {
  high_bd(12);
}

fn compare_plane<T: Ord + std::fmt::Debug>(
  rec: &[T], rec_stride: usize, dec: &[T], dec_stride: usize, width: usize,
  height: usize
) {
  for line in rec.chunks(rec_stride).zip(dec.chunks(dec_stride)).take(height) {
    assert_eq!(&line.0[..width], &line.1[..width]);
  }
}

fn compare_pic(pic: &Dav1dPicture, frame: &Frame, bit_depth: usize, width: usize, height: usize) {
  use plane::Plane;

  let cmp_plane = |data, stride, frame_plane: &Plane| {
    let w = width >> frame_plane.cfg.xdec;
    let h = height >> frame_plane.cfg.ydec;
    let rec_stride = frame_plane.cfg.stride;

    if bit_depth > 8 {
      let dec = unsafe {
        let data = data as *const u16;
        let size = stride * h;

        slice::from_raw_parts(data, size)
      };

      let rec: Vec<u16> =
        frame_plane.data_origin().iter().map(|&v| v).collect();

      compare_plane::<u16>(&rec[..], rec_stride, dec, stride, w, h);
    } else {
      let dec = unsafe {
        let data = data as *const u8;
        let size = stride * h;

        slice::from_raw_parts(data, size)
      };

      let rec: Vec<u8> =
        frame_plane.data_origin().iter().map(|&v| v as u8).collect();

      compare_plane::<u8>(&rec[..], rec_stride, dec, stride, w, h);
    }
  };

  let lstride = pic.stride[0] as usize;
  let cstride = pic.stride[1] as usize;

  cmp_plane(pic.data[0], lstride, &frame.planes[0]);
  cmp_plane(pic.data[1], cstride, &frame.planes[1]);
  cmp_plane(pic.data[2], cstride, &frame.planes[2]);
}

fn encode_decode(
  w: usize, h: usize, speed: usize, quantizer: usize, limit: usize,
  bit_depth: usize, min_keyint: u64, max_keyint: u64, low_latency: bool
) {
  let mut ra = ChaChaRng::from_seed([0; 32]);

  let dec = setup_decoder();
  let mut ctx =
    setup_encoder(w, h, speed, quantizer, bit_depth, ChromaSampling::Cs420,
                  min_keyint, max_keyint, low_latency);

  println!("Encoding {}x{} speed {} quantizer {}", w, h, speed, quantizer);

  let mut rec_fifo = VecDeque::new();

  for _ in 0..limit {
    let mut input = ctx.new_frame();
    fill_frame(&mut ra, Arc::get_mut(&mut input).unwrap());

    let _ = ctx.send_frame(input);

    let mut done = false;
    let mut corrupted_count = 0;
    while !done {
      let res = ctx.receive_packet();
      if let Ok(pkt) = res {
        println!("Encoded packet {}", pkt.number);

        if let Some(pkt_rec) = pkt.rec {
          rec_fifo.push_back(pkt_rec.clone());
        }

        let packet = pkt.data;

        unsafe {
          let mut data: Dav1dData = mem::zeroed();
          println!("Decoding frame {}", pkt.number);
          let mut ptr = dav1d_data_create(&mut data, packet.len());
          ptr::copy_nonoverlapping(packet.as_ptr(), ptr, packet.len());
          let ret = dav1d_send_data(
            dec.dec, &mut data
          );
          println!("Decoded. -> {}", ret);
          if ret != 0 { /*
            let error_msg = aom_codec_error(&mut dec.dec);
            println!(
              "  Decode codec_decode failed: {}",
              CStr::from_ptr(error_msg).to_string_lossy()
            );
            let detail = aom_codec_error_detail(&mut dec.dec);
            if !detail.is_null() {
              println!(
                "  Decode codec_decode failed {}",
                CStr::from_ptr(detail).to_string_lossy()
              );
            } */

            corrupted_count += 1;
          }

          if ret == 0 {
            loop {
              let mut pic: Dav1dPicture = mem::zeroed();
              println!("Retrieving frame");
              let ret = dav1d_get_picture(dec.dec, &mut pic);
              println!("Retrieved.");
              if ret == -(EAGAIN as i32) {
                break;
              }
              if ret != 0 {
                /* let detail = aom_codec_error_detail(&mut dec.dec);
                panic!(
                  "Decode codec_control failed {}",
                  CStr::from_ptr(detail).to_string_lossy()
                );
                */
                panic!("Decode fail");
              }

              let rec = rec_fifo.pop_front().unwrap();
              compare_pic(&pic, &rec, bit_depth, w, h);
            }
          }
        }
      } else {
        done = true;
      }
    }
    assert_eq!(corrupted_count, 0);
  }
}
<commit_msg>Fix the comparison function for high bd<commit_after>// Copyright (c) 2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use super::*;
use rand::{ChaChaRng, Rng, SeedableRng};
use std::{mem, ptr, slice};
use std::collections::VecDeque;
use std::sync::Arc;

use dav1d_sys::*;

fn fill_frame(ra: &mut ChaChaRng, frame: &mut Frame) {
  for plane in frame.planes.iter_mut() {
    let stride = plane.cfg.stride;
    for row in plane.data.chunks_mut(stride) {
      for mut pixel in row {
        let v: u8 = ra.gen();
        *pixel = v as u16;
      }
    }
  }
}

struct Decoder {
  dec: *mut Dav1dContext
}

fn setup_decoder() -> Decoder {
  unsafe {
    let mut settings = mem::uninitialized();
    let mut dec: Decoder = mem::uninitialized();

    dav1d_default_settings(&mut settings);

    let ret = dav1d_open(&mut dec.dec, &settings);

    if ret != 0 {
      panic!("Cannot instantiate the decoder {}", ret);
    }

    dec
  }
}

impl Drop for Decoder {
  fn drop(&mut self) {
    unsafe { dav1d_close(&mut self.dec) };
  }
}

fn setup_encoder(
  w: usize, h: usize, speed: usize, quantizer: usize, bit_depth: usize,
  chroma_sampling: ChromaSampling, min_keyint: u64, max_keyint: u64,
  low_latency: bool
) -> Context {

  let mut enc = EncoderConfig::with_speed_preset(speed);
  enc.quantizer = quantizer;
  enc.min_key_frame_interval = min_keyint;
  enc.max_key_frame_interval = max_keyint;
  enc.low_latency = low_latency;

  let cfg = Config {
    frame_info: FrameInfo {
      width: w,
      height: h,
      bit_depth,
      chroma_sampling,
      ..Default::default()
    },
    timebase: Rational::new(1, 1000),
    enc
  };

  cfg.new_context()
}

// TODO: support non-multiple-of-16 dimensions
static DIMENSION_OFFSETS: &[(usize, usize)] =
  &[(0, 0), (4, 4), (8, 8), (16, 16)];

fn speed(s: usize) {
  let quantizer = 100;
  let limit = 5;
  let w = 64;
  let h = 80;

  for b in DIMENSION_OFFSETS.iter() {
      encode_decode(w + b.0, h + b.1, s, quantizer, limit, 8, 15, 15, true);
  }
}

macro_rules! test_speeds {
  ($($S:expr),+) => {
    $(
        paste::item!{
            #[test]
            #[ignore]
            fn [<speed_ $S>]() {
                speed($S)
            }
        }
    )*
  }
}

test_speeds!{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }

macro_rules! test_dimensions {
  ($(($W:expr, $H:expr)),+) => {
    $(
        paste::item!{
            #[test]
            fn [<dimension_ $W x $H>]() {
                dimension($W, $H)
            }
        }
    )*
  }
}

test_dimensions!{
  (8, 8),
  (16, 16),
  (32, 32),
  (64, 64),
  (128, 128),
  (256, 256),
  (512, 512),
  (1024, 1024),
  (2048, 2048),
  (258, 258),
  (260, 260),
  (262, 262),
  (264, 264),
  (265, 265)
}

fn dimension(w: usize, h: usize) {
  let quantizer = 100;
  let limit = 1;
  let speed = 4;

  encode_decode(w, h, speed, quantizer, limit, 8, 15, 15, true);
}

#[test]
fn quantizer() {
  let limit = 5;
  let w = 64;
  let h = 80;
  let speed = 4;

  for b in DIMENSION_OFFSETS.iter() {
    for &q in [80, 100, 120].iter() {
      encode_decode(w + b.0, h + b.1, speed, q, limit, 8, 15, 15, true);
    }
  }
}

#[test]
fn keyframes() {
  let limit = 12;
  let w = 64;
  let h = 80;
  let speed = 10;
  let q = 100;

  encode_decode(w, h, speed, q, limit, 8, 6, 6, true);
}

#[test]
fn reordering() {
  let limit = 12;
  let w = 64;
  let h = 80;
  let speed = 10;
  let q = 100;

  for keyint in &[4, 5, 6] {
    encode_decode(w, h, speed, q, limit, 8, *keyint, *keyint, false);
  }
}

#[test]
#[ignore]
fn odd_size_frame_with_full_rdo() {
  let limit = 3;
  let w = 512 + 32 + 16 + 5;
  let h = 512 + 16 + 5;
  let speed = 0;
  let qindex = 100;

  encode_decode(w, h, speed, qindex, limit, 8, 15, 15, true);
}

fn high_bd(bits: usize) {
  let quantizer = 100;
  let limit = 3; // Include inter frames
  let speed = 0; // Test as many tools as possible
  let w = 64;
  let h = 80;

  encode_decode(w, h, speed, quantizer, limit, bits, 15, 15, true);
}

#[test]
fn high_bd_10() {
  high_bd(10);
}

#[test]
fn high_bd_12() {
  high_bd(12);
}

fn compare_plane<T: Ord + std::fmt::Debug>(
  rec: &[T], rec_stride: usize, dec: &[T], dec_stride: usize, width: usize,
  height: usize
) {
  for line in rec.chunks(rec_stride).zip(dec.chunks(dec_stride)).take(height) {
    assert_eq!(&line.0[..width], &line.1[..width]);
  }
}

fn compare_pic(pic: &Dav1dPicture, frame: &Frame, bit_depth: usize, width: usize, height: usize) {
  use plane::Plane;

  let cmp_plane = |data, stride, frame_plane: &Plane| {
    let w = width >> frame_plane.cfg.xdec;
    let h = height >> frame_plane.cfg.ydec;
    let rec_stride = frame_plane.cfg.stride;

    if bit_depth > 8 {
      let stride = stride / 2;
      let dec = unsafe {
        let data = data as *const u16;
        let size = stride * h;

        slice::from_raw_parts(data, size)
      };

      let rec: Vec<u16> =
        frame_plane.data_origin().iter().map(|&v| v).collect();

      compare_plane::<u16>(&rec[..], rec_stride, dec, stride, w, h);
    } else {
      let dec = unsafe {
        let data = data as *const u8;
        let size = stride * h;

        slice::from_raw_parts(data, size)
      };

      let rec: Vec<u8> =
        frame_plane.data_origin().iter().map(|&v| v as u8).collect();

      compare_plane::<u8>(&rec[..], rec_stride, dec, stride, w, h);
    }
  };

  let lstride = pic.stride[0] as usize;
  let cstride = pic.stride[1] as usize;

  cmp_plane(pic.data[0], lstride, &frame.planes[0]);
  cmp_plane(pic.data[1], cstride, &frame.planes[1]);
  cmp_plane(pic.data[2], cstride, &frame.planes[2]);
}

fn encode_decode(
  w: usize, h: usize, speed: usize, quantizer: usize, limit: usize,
  bit_depth: usize, min_keyint: u64, max_keyint: u64, low_latency: bool
) {
  let mut ra = ChaChaRng::from_seed([0; 32]);

  let dec = setup_decoder();
  let mut ctx =
    setup_encoder(w, h, speed, quantizer, bit_depth, ChromaSampling::Cs420,
                  min_keyint, max_keyint, low_latency);

  println!("Encoding {}x{} speed {} quantizer {}", w, h, speed, quantizer);

  let mut rec_fifo = VecDeque::new();

  for _ in 0..limit {
    let mut input = ctx.new_frame();
    fill_frame(&mut ra, Arc::get_mut(&mut input).unwrap());

    let _ = ctx.send_frame(input);

    let mut done = false;
    let mut corrupted_count = 0;
    while !done {
      let res = ctx.receive_packet();
      if let Ok(pkt) = res {
        println!("Encoded packet {}", pkt.number);

        if let Some(pkt_rec) = pkt.rec {
          rec_fifo.push_back(pkt_rec.clone());
        }

        let packet = pkt.data;

        unsafe {
          let mut data: Dav1dData = mem::zeroed();
          println!("Decoding frame {}", pkt.number);
          let mut ptr = dav1d_data_create(&mut data, packet.len());
          ptr::copy_nonoverlapping(packet.as_ptr(), ptr, packet.len());
          let ret = dav1d_send_data(
            dec.dec, &mut data
          );
          println!("Decoded. -> {}", ret);
          if ret != 0 { /*
            let error_msg = aom_codec_error(&mut dec.dec);
            println!(
              "  Decode codec_decode failed: {}",
              CStr::from_ptr(error_msg).to_string_lossy()
            );
            let detail = aom_codec_error_detail(&mut dec.dec);
            if !detail.is_null() {
              println!(
                "  Decode codec_decode failed {}",
                CStr::from_ptr(detail).to_string_lossy()
              );
            } */

            corrupted_count += 1;
          }

          if ret == 0 {
            loop {
              let mut pic: Dav1dPicture = mem::zeroed();
              println!("Retrieving frame");
              let ret = dav1d_get_picture(dec.dec, &mut pic);
              println!("Retrieved.");
              if ret == -(EAGAIN as i32) {
                break;
              }
              if ret != 0 {
                /* let detail = aom_codec_error_detail(&mut dec.dec);
                panic!(
                  "Decode codec_control failed {}",
                  CStr::from_ptr(detail).to_string_lossy()
                );
                */
                panic!("Decode fail");
              }

              let rec = rec_fifo.pop_front().unwrap();
              compare_pic(&pic, &rec, bit_depth, w, h);
            }
          }
        }
      } else {
        done = true;
      }
    }
    assert_eq!(corrupted_count, 0);
  }
}
<|endoftext|>


<commit_before>use syntax::ast;
use syntax::ptr::P;

pub enum Block {
    Describe {
        name: String,
        blocks: Vec<Block>
    },

    It {
        name: String,
        block: P<ast::Block>
    }
}
<commit_msg>Derive `Show` for `Block`.<commit_after>use syntax::ast;
use syntax::ptr::P;

#[deriving(Show)]
pub enum Block {
    Describe {
        name: String,
        blocks: Vec<Block>
    },

    It {
        name: String,
        block: P<ast::Block>
    }
}
<|endoftext|>


<commit_before>
use std::fmt;
use std::error;
use iron::status::Status;
use iron::IronError;

#[derive(Debug)]
struct Error {
    pub status: Status,
    pub payload: String,
}

impl Error {
    fn new(status: Status, payload: String) -> Self {
        Error {
            status: status,
            payload: payload,
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        &self.payload
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "Status: {}\nPayload:\n{}", self.status, self.payload)
    }
}

pub fn bad_request<T>(details: T) -> IronError where T: Into<String> {
    let details = format!("{{'details': '{}'}}", details.into());
    let error = Error::new(Status::BadRequest, details.clone());
    IronError::new(error, (Status::BadRequest, details))
}
<commit_msg>Rewrite error module.<commit_after>
use std::fmt;
use std::error;
use iron::status::Status;
use iron::IronError;

#[derive(Debug, PartialEq)]
pub enum Error {
    BadRequest(String),
}

impl Error {
    fn status(&self) -> Status {
        match *self {
            Error::BadRequest(_) => Status::BadRequest,
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::BadRequest(ref e) => e,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::BadRequest(ref e) => writeln!(f, "BadRequest: {}", e),
        }
    }
}

impl From<Error> for IronError {
    fn from(error: Error) -> Self {
        let details = format!("{{'details': '{}'}}", error::Error::description(&error));
        let response = (error.status(), details);
        IronError::new(error, response)
    }
}

pub fn bad_request<T>(details: T) -> IronError where T: Into<String> {
    Error::BadRequest(details.into()).into()
}
<|endoftext|>


<commit_before>/// Error types

error_chain! {
    types {
        Error, ErrorKind, ResultExt, Result;
    }

    errors {

        // Errors for tokenizer

        QueryParsingError(query: String) {
            description("parsing the query failed")
            display("Parsing the query '{}' failed", query)
        }

        EmptyQueryError {
            description("the query is empty")
            display("The query on the TOML is empty")
        }

        EmptyIdentifier {
            description("Query an empty identifier: ''")
            display("The passed query has an empty identifier")
        }

        ArrayAccessWithoutIndex {
            description("trying to access array without index")
            display("The passed query tries to access an array but does not specify the index")
        }

        ArrayAccessWithInvalidIndex {
            description("trying to pass an invalid index")
            display("The passed query tries to access an array but does not specify a valid index")
        }

        // Errors for Resolver

        IdentifierNotFoundInDocument(ident: String) {
            description("Identifier missing in document")
            display("The identfier '{}' is not present in the document", ident)
        }

        NoIndexInTable(i: usize) {
            description("Cannot deref index from table")
            display("Got an index query '[{}]' but have table", i)
        }

        NoIdentifierInArray(s: String) {
            description("Cannot query identifier in array")
            display("Got an identifier query '{}' but have array", s)
        }

        QueryingValueAsTable(s: String) {
            description("Querying a table where a value is")
            display("Got an identifier query '{}' but have value", s)
        }

        QueryingValueAsArray(i: usize) {
            description("Querying a table where a value is")
            display("Got an index query '{}' but have value", i)
        }

        CannotDeleteNonEmptyTable(tabname: String) {
            description("Cannot delete Table that is not empty")
            display("Cannot delete table '{}' which is not empty", tabname)
        }

        CannotDeleteNonEmptyArray(arrname: String) {
            description("Cannot delete Array that is not empty")
            display("Cannot delete array '{}' which is not empty", arrname)
        }

    }
}
<commit_msg>Add type mismatch error<commit_after>/// Error types

error_chain! {
    types {
        Error, ErrorKind, ResultExt, Result;
    }

    errors {

        // Errors for tokenizer

        QueryParsingError(query: String) {
            description("parsing the query failed")
            display("Parsing the query '{}' failed", query)
        }

        EmptyQueryError {
            description("the query is empty")
            display("The query on the TOML is empty")
        }

        EmptyIdentifier {
            description("Query an empty identifier: ''")
            display("The passed query has an empty identifier")
        }

        ArrayAccessWithoutIndex {
            description("trying to access array without index")
            display("The passed query tries to access an array but does not specify the index")
        }

        ArrayAccessWithInvalidIndex {
            description("trying to pass an invalid index")
            display("The passed query tries to access an array but does not specify a valid index")
        }

        // Errors for Resolver

        IdentifierNotFoundInDocument(ident: String) {
            description("Identifier missing in document")
            display("The identfier '{}' is not present in the document", ident)
        }

        NoIndexInTable(i: usize) {
            description("Cannot deref index from table")
            display("Got an index query '[{}]' but have table", i)
        }

        NoIdentifierInArray(s: String) {
            description("Cannot query identifier in array")
            display("Got an identifier query '{}' but have array", s)
        }

        QueryingValueAsTable(s: String) {
            description("Querying a table where a value is")
            display("Got an identifier query '{}' but have value", s)
        }

        QueryingValueAsArray(i: usize) {
            description("Querying a table where a value is")
            display("Got an index query '{}' but have value", i)
        }

        CannotDeleteNonEmptyTable(tabname: String) {
            description("Cannot delete Table that is not empty")
            display("Cannot delete table '{}' which is not empty", tabname)
        }

        CannotDeleteNonEmptyArray(arrname: String) {
            description("Cannot delete Array that is not empty")
            display("Cannot delete array '{}' which is not empty", arrname)
        }

        CannotAccessBecauseTypeMismatch(expected: &'static str, actual: &'static str) {
            description("Cannot access value because of type mismatch")
            display("Cannot access {} because expected {}", actual, expected)
        }
    }
}
<|endoftext|>