<commit_before>#![feature(test)]
#![allow(dead_code)]
extern crate test;
#[macro_use]
extern crate log;
extern crate env_logger;
use std::rc::Rc;
use std::cell::RefCell;
use std::fmt;
use std::ops::{Drop, Deref, DerefMut};
use std::convert::AsRef;

pub trait Recycleable {
  fn new() -> Self;
  fn reset(&mut self);
}

pub trait InitializeWith<T> {
  fn initialize_with(&mut self, source: T);
}

impl Recycleable for String {
  #[inline(always)]
  fn new() -> String {
    String::new()
  }
  #[inline(always)]
  fn reset(&mut self) {
    self.clear();
  }
}

impl <T> Recycleable for Vec<T> {
  #[inline(always)]
  fn new() -> Vec<T> {
    Vec::new()
  }
  #[inline(always)]
  fn reset(&mut self) {
    self.clear();
  }
}

impl <A> InitializeWith<A> for String where A : AsRef<str> {
  #[inline(always)]
  fn initialize_with(&mut self, source: A) {
    let s : &str = source.as_ref();
    self.push_str(s);
  }
}

pub struct Recycled<T> where T : Recycleable {
  pub value: Option<T>,
  pool: Rc<RefCell<Vec<T>>>
}

impl <T> Drop for Recycled<T> where T : Recycleable {
  #[inline(always)]
  fn drop(&mut self) {
    if let Some(mut value) = self.value.take() {
      value.reset();
      let _ = self.pool.borrow_mut().push(value);
    }
  }
}

impl <T> fmt::Display for Recycled<T> where T : fmt::Display + Recycleable {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    match self.value {
      Some(ref s) => s.fmt(f),
      None => write!(f, "Empty Recycled<T>")
    }
  }
}

impl <T> Deref for Recycled<T> where T : Recycleable {
  type Target = T;
  #[inline(always)]
  fn deref<'a>(&'a self) -> &'a T {
    match self.value.as_ref() {
      Some(v) => v,
      None => panic!("Recycleable wrapper missing its value.")
    }
  }
}

impl <T> DerefMut for Recycled<T> where T : Recycleable {
  #[inline(always)]
  fn deref_mut<'a>(&'a mut self) -> &'a mut T {
    match self.value.as_mut() {
      Some(v) => v,
      None => panic!("Recycleable wrapper missing its value.")
    }
  }
}

impl <T> Recycled<T> where T : Recycleable {
  #[inline(always)]
  pub fn new(pool: Rc<RefCell<Vec<T>>>, value: T) -> Recycled<T> {
    Recycled {
      value: Some(value),
      pool: pool
    }
  }

  #[inline(always)]
  pub fn new_from<A>(pool: Rc<RefCell<Vec<T>>>, mut value: T, source: A) -> Recycled<T> where T : InitializeWith<A> {
    value.initialize_with(source);
    Recycled {
      value: Some(value),
      pool: pool
    }
  }

  #[inline(always)]
  pub fn detach(mut self) -> T {
    let value = self.value.take().unwrap();
    drop(self);
    value
  }
}

pub struct Pool <T> where T : Recycleable {
  values: Rc<RefCell<Vec<T>>>,
}

impl <T> Pool <T> where T: Recycleable {
  pub fn with_size(size: u32) -> Pool <T> {
    let values: Vec<T> =
      (0..size)
      .map(|_| T::new() )
      .collect();
    Pool {
      values: Rc::new(RefCell::new(values)),
    }
  }

  #[inline(always)]
  pub fn attach(&mut self, mut value: T) {
    value.reset();
    self.values.borrow_mut().push(value);
  }

  #[inline(always)]
  pub fn detached(&mut self) -> T {
    match self.values.borrow_mut().pop() {
      Some(v) => v,
      None => T::new()
    }
  }

  #[inline(always)]
  pub fn new(&mut self) -> Recycled<T> {
    let t = self.detached();
    let pool_reference = self.values.clone();
    Recycled::new(pool_reference, t)
  }

  #[inline(always)]
  pub fn new_from<A>(&mut self, source: A) -> Recycled<T> where T: InitializeWith<A> {
    let t = self.detached();
    let pool_reference = self.values.clone();
    Recycled::new_from(pool_reference, t, source)
  }

  #[inline(always)]
  pub fn size(&self) -> usize {
    self.values.borrow().len()
  }
}

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

  const ITERATIONS : u32 = 10_000;

  // Calling String::new() is very close to a no-op; no actual allocation
  // is performed until bytes are pushed onto the end of the String. As such,
  // we need to explicitly ask for some space to be available to trigger allocation.
  const EMPTY_STRING_CAPACITY : usize = 4;

  #[bench]
  fn bench01_standard_allocation_speed(b: &mut Bencher) {
    b.iter(|| {
      for _ in 0..ITERATIONS {
        let _string = black_box(String::with_capacity(EMPTY_STRING_CAPACITY));
        let _string = black_box(String::with_capacity(EMPTY_STRING_CAPACITY));
        let _string = black_box(String::with_capacity(EMPTY_STRING_CAPACITY));
        let _string = black_box(String::with_capacity(EMPTY_STRING_CAPACITY));
        let _string = black_box(String::with_capacity(EMPTY_STRING_CAPACITY));
      }
    });
  }

  #[bench]
  fn bench02_pooled_allocation_speed(b: &mut Bencher) {
    let mut pool : Pool<String> = Pool::with_size(5);
    b.iter(|| {
      for _ in 0..ITERATIONS {
        let _string = pool.new();
        let _string = pool.new();
        let _string = pool.new();
        let _string = pool.new();
        let _string = pool.new();
      }
    });
  }

  #[bench]
  fn bench03_standard_initialized_allocation_speed(b: &mut Bencher) {
    b.iter(|| {
      for _ in 0..ITERATIONS {
        let _string = "man".to_owned();
        let _string = "dog".to_owned();
        let _string = "cat".to_owned();
        let _string = "mouse".to_owned();
        let _string = "cheese".to_owned();
      }
    });
  }

  #[bench]
  fn bench04_pooled_initialized_allocation_speed(b: &mut Bencher) {
    let _ = env_logger::init();
    let mut pool : Pool<String> = Pool::with_size(5);
    b.iter(|| {
      for _ in 0..ITERATIONS {
        let _string = pool.new_from("man");
        let _string = pool.new_from("dog");
        let _string = pool.new_from("cat");
        let _string = pool.new_from("mouse");
        let _string = pool.new_from("cheese");
      }
    });
  }
  #[bench]
  fn bench05_allocate_vec_vec_str(bencher: &mut Bencher) {
      bencher.iter(|| {
          let mut v1 = Vec::new();
          for _ in 0..100 {
              let mut v2 = Vec::new();
              for _ in 0..100 {
                  v2.push(("test!").to_owned());
              }
              v1.push(v2);
          }
          v1
      });
  }

  #[bench]
  fn bench06_pooled_vec_vec_str(bencher: &mut Bencher) {
      let mut vec_str_pool : Pool<Vec<Recycled<String>>> = Pool::with_size(100);
      let mut str_pool : Pool<String> = Pool::with_size(10000);
      bencher.iter(|| {
          let mut v1 = Vec::new();
          for _ in 0..100 {
              let mut v2 = vec_str_pool.new();
              for _ in 0..100 {
                  v2.push(str_pool.new_from("test!"));
              }
              v1.push(v2);
          }
          v1
      });
  }

  #[test]
  fn test_deref() {
      let mut str_pool : Pool<String> = Pool::with_size(1);
      let rstring = str_pool.new_from("cat");
      assert_eq!("cat", *rstring);
  }

  #[test]
  fn test_deref_mut() {
      let mut str_pool : Pool<String> = Pool::with_size(1);
      let mut rstring = str_pool.new_from("cat");
      (*rstring).push_str("s love eating mice");
      println!("{}", *rstring);
      assert_eq!("cats love eating mice", *rstring);
  }

  #[test]
  fn test_recycle() {
      let mut str_pool : Pool<String> = Pool::with_size(1);
      {
        assert_eq!(1, str_pool.size());
        let _rstring = str_pool.new_from("cat");
        assert_eq!(0, str_pool.size());
      }
      assert_eq!(1, str_pool.size());
  }

  #[test]
  fn test_detached() {
      let mut str_pool : Pool<String> = Pool::with_size(1);
      {
        assert_eq!(1, str_pool.size());
        let _rstring = str_pool.detached();
        assert_eq!(0, str_pool.size());
      }
      assert_eq!(0, str_pool.size());
  }

}
<commit_msg>Small tweak.<commit_after>#![feature(test)]
#![allow(dead_code)]
extern crate test;
#[macro_use]
extern crate log;
extern crate env_logger;
use std::rc::Rc;
use std::cell::RefCell;
use std::fmt;
use std::ops::{Drop, Deref, DerefMut};
use std::convert::AsRef;

pub trait Recycleable {
  fn new() -> Self;
  fn reset(&mut self);
}

pub trait InitializeWith<T> {
  fn initialize_with(&mut self, source: T);
}

impl Recycleable for String {
  #[inline(always)]
  fn new() -> String {
    String::new()
  }
  #[inline(always)]
  fn reset(&mut self) {
    self.clear();
  }
}

impl <T> Recycleable for Vec<T> {
  #[inline(always)]
  fn new() -> Vec<T> {
    Vec::new()
  }
  #[inline(always)]
  fn reset(&mut self) {
    self.clear();
  }
}

impl <A> InitializeWith<A> for String where A : AsRef<str> {
  #[inline(always)]
  fn initialize_with(&mut self, source: A) {
    let s : &str = source.as_ref();
    self.push_str(s);
  }
}

pub struct Recycled<T> where T : Recycleable {
  pub value: Option<T>,
  pool: Rc<RefCell<Vec<T>>>
}

impl <T> Drop for Recycled<T> where T : Recycleable {
  #[inline(always)]
  fn drop(&mut self) {
    if let Some(mut value) = self.value.take() {
      value.reset();
      self.pool.borrow_mut().push(value);
    }
  }
}

impl <T> fmt::Display for Recycled<T> where T : fmt::Display + Recycleable {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    match self.value {
      Some(ref s) => s.fmt(f),
      None => write!(f, "Empty Recycled<T>")
    }
  }
}

impl <T> Deref for Recycled<T> where T : Recycleable {
  type Target = T;
  #[inline(always)]
  fn deref<'a>(&'a self) -> &'a T {
    match self.value.as_ref() {
      Some(v) => v,
      None => panic!("Recycleable wrapper missing its value.")
    }
  }
}

impl <T> DerefMut for Recycled<T> where T : Recycleable {
  #[inline(always)]
  fn deref_mut<'a>(&'a mut self) -> &'a mut T {
    match self.value.as_mut() {
      Some(v) => v,
      None => panic!("Recycleable wrapper missing its value.")
    }
  }
}

impl <T> Recycled<T> where T : Recycleable {
  #[inline(always)]
  pub fn new(pool: Rc<RefCell<Vec<T>>>, value: T) -> Recycled<T> {
    Recycled {
      value: Some(value),
      pool: pool
    }
  }

  #[inline(always)]
  pub fn new_from<A>(pool: Rc<RefCell<Vec<T>>>, mut value: T, source: A) -> Recycled<T> where T : InitializeWith<A> {
    value.initialize_with(source);
    Recycled {
      value: Some(value),
      pool: pool
    }
  }

  #[inline(always)]
  pub fn detach(mut self) -> T {
    let value = self.value.take().unwrap();
    drop(self);
    value
  }
}

pub struct Pool <T> where T : Recycleable {
  values: Rc<RefCell<Vec<T>>>,
}

impl <T> Pool <T> where T: Recycleable {
  #[inline(always)]
  pub fn with_size(size: u32) -> Pool <T> {
    let values: Vec<T> =
      (0..size)
      .map(|_| T::new() )
      .collect();
    Pool {
      values: Rc::new(RefCell::new(values)),
    }
  }

  #[inline(always)]
  pub fn attach(&mut self, mut value: T) {
    value.reset();
    self.values.borrow_mut().push(value);
  }

  #[inline(always)]
  pub fn detached(&mut self) -> T {
    match self.values.borrow_mut().pop() {
      Some(v) => v,
      None => T::new()
    }
  }

  #[inline(always)]
  pub fn new(&mut self) -> Recycled<T> {
    let t = self.detached();
    let pool_reference = self.values.clone();
    Recycled::new(pool_reference, t)
  }

  #[inline(always)]
  pub fn new_from<A>(&mut self, source: A) -> Recycled<T> where T: InitializeWith<A> {
    let t = self.detached();
    let pool_reference = self.values.clone();
    Recycled::new_from(pool_reference, t, source)
  }

  #[inline(always)]
  pub fn size(&self) -> usize {
    self.values.borrow().len()
  }
}

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

  const ITERATIONS : u32 = 10_000;

  // Calling String::new() is very close to a no-op; no actual allocation
  // is performed until bytes are pushed onto the end of the String. As such,
  // we need to explicitly ask for some space to be available to trigger allocation.
  const EMPTY_STRING_CAPACITY : usize = 4;

  #[bench]
  fn bench01_standard_allocation_speed(b: &mut Bencher) {
    b.iter(|| {
      for _ in 0..ITERATIONS {
        let _string = black_box(String::with_capacity(EMPTY_STRING_CAPACITY));
        let _string = black_box(String::with_capacity(EMPTY_STRING_CAPACITY));
        let _string = black_box(String::with_capacity(EMPTY_STRING_CAPACITY));
        let _string = black_box(String::with_capacity(EMPTY_STRING_CAPACITY));
        let _string = black_box(String::with_capacity(EMPTY_STRING_CAPACITY));
      }
    });
  }

  #[bench]
  fn bench02_pooled_allocation_speed(b: &mut Bencher) {
    let mut pool : Pool<String> = Pool::with_size(5);
    b.iter(|| {
      for _ in 0..ITERATIONS {
        let _string = pool.new();
        let _string = pool.new();
        let _string = pool.new();
        let _string = pool.new();
        let _string = pool.new();
      }
    });
  }

  #[bench]
  fn bench03_standard_initialized_allocation_speed(b: &mut Bencher) {
    b.iter(|| {
      for _ in 0..ITERATIONS {
        let _string = "man".to_owned();
        let _string = "dog".to_owned();
        let _string = "cat".to_owned();
        let _string = "mouse".to_owned();
        let _string = "cheese".to_owned();
      }
    });
  }

  #[bench]
  fn bench04_pooled_initialized_allocation_speed(b: &mut Bencher) {
    let _ = env_logger::init();
    let mut pool : Pool<String> = Pool::with_size(5);
    b.iter(|| {
      for _ in 0..ITERATIONS {
        let _string = pool.new_from("man");
        let _string = pool.new_from("dog");
        let _string = pool.new_from("cat");
        let _string = pool.new_from("mouse");
        let _string = pool.new_from("cheese");
      }
    });
  }
  #[bench]
  fn bench05_allocate_vec_vec_str(bencher: &mut Bencher) {
      bencher.iter(|| {
          let mut v1 = Vec::new();
          for _ in 0..100 {
              let mut v2 = Vec::new();
              for _ in 0..100 {
                  v2.push(("test!").to_owned());
              }
              v1.push(v2);
          }
          v1
      });
  }

  #[bench]
  fn bench06_pooled_vec_vec_str(bencher: &mut Bencher) {
      let mut vec_str_pool : Pool<Vec<Recycled<String>>> = Pool::with_size(100);
      let mut str_pool : Pool<String> = Pool::with_size(10000);
      bencher.iter(|| {
          let mut v1 = Vec::new();
          for _ in 0..100 {
              let mut v2 = vec_str_pool.new();
              for _ in 0..100 {
                  v2.push(str_pool.new_from("test!"));
              }
              v1.push(v2);
          }
          v1
      });
  }

  #[test]
  fn test_deref() {
      let mut str_pool : Pool<String> = Pool::with_size(1);
      let rstring = str_pool.new_from("cat");
      assert_eq!("cat", *rstring);
  }

  #[test]
  fn test_deref_mut() {
      let mut str_pool : Pool<String> = Pool::with_size(1);
      let mut rstring = str_pool.new_from("cat");
      (*rstring).push_str("s love eating mice");
      println!("{}", *rstring);
      assert_eq!("cats love eating mice", *rstring);
  }

  #[test]
  fn test_recycle() {
      let mut str_pool : Pool<String> = Pool::with_size(1);
      {
        assert_eq!(1, str_pool.size());
        let _rstring = str_pool.new_from("cat");
        assert_eq!(0, str_pool.size());
      }
      assert_eq!(1, str_pool.size());
  }

  #[test]
  fn test_detached() {
      let mut str_pool : Pool<String> = Pool::with_size(1);
      {
        assert_eq!(1, str_pool.size());
        let _rstring = str_pool.detached();
        assert_eq!(0, str_pool.size());
      }
      assert_eq!(0, str_pool.size());
  }

}
<|endoftext|>


<commit_before>//! Library providing a parser combinator.
//!
//! ```
//! use chomp::{Input, ParseResult, Error};
//! use chomp::{take_while1, token};
//!
//! let i = Input::new("martin wernstål\n".as_bytes());
//!
//! #[derive(Debug, Eq, PartialEq)]
//! struct Name<'a> {
//!     first: &'a [u8],
//!     last:  &'a [u8],
//! }
//!
//! fn name(i: Input<u8>) -> ParseResult<u8, Name, Error<u8>> {
//!     take_while1(i, |c| c != b' ').bind(|i, first|
//!         token(i, b' ').bind(|i, _| // skipping this char
//!             take_while1(i, |c| c != b'\n').bind(|i, last|
//!                 i.ret(Name{
//!                     first: first,
//!                     last:  last,
//!                 }))))
//! }
//!
//! assert_eq!(name(i).unwrap(), Name{first: b"martin", last: "wernstål".as_bytes()});
//! ```
use ::std::fmt;

#[macro_use]
mod macros;
mod iter;

pub mod internal;
pub mod parsers;
pub mod combinators;

pub use combinators::{
    count,
    option,
    or,
    many,
    many1,
    skip_many,
};
pub use parsers::{
    any,
    not_token,
    peek,
    satisfy,
    string,
    take,
    take_remainder,
    take_till,
    take_while,
    take_while1,
    token,
};
pub use err::Error;
pub use iter::Iter;

use internal::State;

/// Linear type containing the parser state, this type is threaded though `bind`.
#[must_use]
#[derive(Debug, Eq, PartialEq)]
pub struct Input<'a, I: 'a>(&'a [I]);

impl<'a, I> Input<'a, I> {
    /// Creates a new input to be passed to parsers and/or combinators.
    #[inline]
    pub fn new(i: &'a [I]) -> Self {
        Input(i)
    }

    /// Returns the value `t` with the input context.
    #[inline]
    pub fn ret<T, E>(self, t: T) -> ParseResult<'a, I, T, E> {
        internal::data(self.0, t)
    }

    /// Returns the error value `e` with the input context.
    #[inline]
    pub fn err<T, E>(self, e: E) -> ParseResult<'a, I, T, E> {
        internal::error(self.0, e)
    }
}

/// The basic return type of a parser.
#[must_use]
#[derive(Debug, Eq, PartialEq)]
pub struct ParseResult<'a, I: 'a, T: 'a, E: 'a>(State<'a, I, T, E>);

impl<'a, I, T, E> ParseResult<'a, I, T, E> {
    pub fn bind<F, U, V = E>(self, f: F) -> ParseResult<'a, I, U, V>
      where F: FnOnce(Input<'a, I>, T) -> ParseResult<'a, I, U, V>,
            V: From<E> {
        match self.0 {
            State::Data(i, t)    => f(Input(i), t).map_err(From::from),
            State::Error(i, e)   => ParseResult(State::Error(i, From::from(e))),
            State::Incomplete(n) => ParseResult(State::Incomplete(n)),
        }
    }

    pub fn map<U, F>(self, f: F) -> ParseResult<'a, I, U, E>
      where F: FnOnce(T) -> U {
        match self.0 {
            State::Data(i, t)    => ParseResult(State::Data(i, f(t))),
            State::Error(i, e)   => ParseResult(State::Error(i, e)),
            State::Incomplete(n) => ParseResult(State::Incomplete(n)),
        }
    }

    #[inline]
    pub fn map_err<V, F>(self, f: F) -> ParseResult<'a, I, T, V>
      where F: FnOnce(E) -> V {
        match self.0 {
            State::Data(i, t)    => ParseResult(State::Data(i, t)),
            State::Error(i, e)   => ParseResult(State::Error(i, f(e))),
            State::Incomplete(n) => ParseResult(State::Incomplete(n)),
        }
    }
}

impl<'a, I, T, E: fmt::Debug> ParseResult<'a, I, T, E> {
    /// Extracts the contained type if the parser is in a success-state, panics otherwise.
    #[inline]
    pub fn unwrap(self) -> T {
        match self.0 {
            State::Data(_, t)    => t,
            State::Error(_, e)   => panic!("called `Parser::unwrap` on a parser in an error state: {:?}", e),
            State::Incomplete(_) => panic!("called `Parser::unwrap` on a parser in an incomplete state"),
        }
    }
}

impl<'a, I, T: fmt::Debug, E> ParseResult<'a, I, T, E> {
    pub fn unwrap_err(self) -> E {
        match self.0 {
            State::Data(_, t)    => panic!("called `Parser::unwrap_err` on a parser in a success state: {:?}", t),
            State::Error(_, e)   => e,
            State::Incomplete(_) => panic!("called `Parser::unwrap_err` on a parser in an incomplete state"),
        }
    }
}

/// Result for dealing with the basic parsers when parsing a stream of `u8`.
pub type U8Result<'a, T>        = ParseResult<'a, u8, T, Error<u8>>;
/// Result returned from the basic parsers.
pub type SimpleResult<'a, I, T> = ParseResult<'a, I, T, Error<I>>;

#[cfg(feature = "verbose_error")]
mod err {
    //! This is a private module to contain the more verbose error type as well as adapters for
    //! using it.
    //!
    //! All adapters are #[inline(always)] and will construct the appropriate error type.
    use std::any;
    use std::error;
    use std::fmt;

    use ::ParseResult;
    use ::internal;

    #[derive(Debug, Eq, PartialEq)]
    pub enum Error<I> {
        Expected(I),
        Unexpected,
        String(Vec<I>),
    }

    impl<I> fmt::Display for Error<I>
      where I: fmt::Debug {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            match *self {
                Error::Expected(ref c) => write!(f, "expected {:?}", *c),
                Error::Unexpected      => write!(f, "unexpected"),
                Error::String(ref s)   => write!(f, "expected {:?}", *s),
            }
        }
    }

    impl<I> error::Error for Error<I>
      where I: any::Any + fmt::Debug {
        fn description(&self) -> &str {
            match *self {
                Error::Expected(_) => "expected a certain token, received another",
                Error::Unexpected  => "received an unexpected token",
                Error::String(_)   => "expected a certain string of tokens, encountered an unexpected token",
            }
        }
    }

    #[inline(always)]
    pub fn unexpected<I>() -> Error<I> {
        Error::Unexpected
    }

    #[inline(always)]
    pub fn expected<'a, I>(i: I) -> Error<I> {
        Error::Expected(i)
    }

    #[inline(always)]
    pub fn string<'a, 'b, I, T>(buffer: &'a [I], _offset: usize, expected: &'b [I]) -> ParseResult<'a, I, T, Error<I>>
      where I: Copy {
        internal::error(buffer, Error::String(expected.to_vec()))
    }
}

#[cfg(not(feature = "verbose_error"))]
mod err {
    //! This is a private module to contain the smaller error type as well as adapters for using
    //! it.
    //!
    //! All adapters are #[inline(always)], and will just noop the data.
    use ::std::any;
    use ::std::error;
    use ::std::fmt;

    use ::std::marker::PhantomData;

    use ::ParseResult;
    use ::internal;

    #[derive(Debug, Eq, PartialEq)]
    pub struct Error<I>(PhantomData<I>);

    impl<I: fmt::Debug> fmt::Display for Error<I> {
        fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
            write!(f, "generic parse error (chomp was compiled without --feature verbose_error)")
        }
    }

    impl<I: any::Any + fmt::Debug> error::Error for Error<I> {
        fn description(&self) -> &str {
            "generic parse error (chomp was compiled without --feature verbose_error)"
        }
    }

    #[inline(always)]
    pub fn unexpected<I>() -> Error<I> {
        Error(PhantomData)
    }

    #[inline(always)]
    pub fn expected<'a, I>(_: I) -> Error<I> {
        Error(PhantomData)
    }

    #[inline(always)]
    pub fn string<'a, 'b, I, T>(buffer: &'a [I], offset: usize, _expected: &'b [I]) -> ParseResult<'a, I, T, Error<I>>
      where I: Copy {
        internal::error(&buffer[offset..], Error(PhantomData))
    }
}
<commit_msg>Added tests for monad laws<commit_after>//! Library providing a parser combinator.
//!
//! ```
//! use chomp::{Input, ParseResult, Error};
//! use chomp::{take_while1, token};
//!
//! let i = Input::new("martin wernstål\n".as_bytes());
//!
//! #[derive(Debug, Eq, PartialEq)]
//! struct Name<'a> {
//!     first: &'a [u8],
//!     last:  &'a [u8],
//! }
//!
//! fn name(i: Input<u8>) -> ParseResult<u8, Name, Error<u8>> {
//!     take_while1(i, |c| c != b' ').bind(|i, first|
//!         token(i, b' ').bind(|i, _| // skipping this char
//!             take_while1(i, |c| c != b'\n').bind(|i, last|
//!                 i.ret(Name{
//!                     first: first,
//!                     last:  last,
//!                 }))))
//! }
//!
//! assert_eq!(name(i).unwrap(), Name{first: b"martin", last: "wernstål".as_bytes()});
//! ```
use ::std::fmt;

#[macro_use]
mod macros;
mod iter;

pub mod internal;
pub mod parsers;
pub mod combinators;

pub use combinators::{
    count,
    option,
    or,
    many,
    many1,
    skip_many,
};
pub use parsers::{
    any,
    not_token,
    peek,
    satisfy,
    string,
    take,
    take_remainder,
    take_till,
    take_while,
    take_while1,
    token,
};
pub use err::Error;
pub use iter::Iter;

use internal::State;

/// Linear type containing the parser state, this type is threaded though `bind`.
#[must_use]
#[derive(Debug, Eq, PartialEq)]
pub struct Input<'a, I: 'a>(&'a [I]);

impl<'a, I> Input<'a, I> {
    /// Creates a new input to be passed to parsers and/or combinators.
    #[inline]
    pub fn new(i: &'a [I]) -> Self {
        Input(i)
    }

    /// Returns the value `t` with the input context.
    #[inline]
    pub fn ret<T, E>(self, t: T) -> ParseResult<'a, I, T, E> {
        internal::data(self.0, t)
    }

    /// Returns the error value `e` with the input context.
    #[inline]
    pub fn err<T, E>(self, e: E) -> ParseResult<'a, I, T, E> {
        internal::error(self.0, e)
    }
}

/// The basic return type of a parser.
#[must_use]
#[derive(Debug, Eq, PartialEq)]
pub struct ParseResult<'a, I: 'a, T: 'a, E: 'a>(State<'a, I, T, E>);

impl<'a, I, T, E> ParseResult<'a, I, T, E> {
    pub fn bind<F, U, V = E>(self, f: F) -> ParseResult<'a, I, U, V>
      where F: FnOnce(Input<'a, I>, T) -> ParseResult<'a, I, U, V>,
            V: From<E> {
        match self.0 {
            State::Data(i, t)    => f(Input(i), t).map_err(From::from),
            State::Error(i, e)   => ParseResult(State::Error(i, From::from(e))),
            State::Incomplete(n) => ParseResult(State::Incomplete(n)),
        }
    }

    pub fn map<U, F>(self, f: F) -> ParseResult<'a, I, U, E>
      where F: FnOnce(T) -> U {
        match self.0 {
            State::Data(i, t)    => ParseResult(State::Data(i, f(t))),
            State::Error(i, e)   => ParseResult(State::Error(i, e)),
            State::Incomplete(n) => ParseResult(State::Incomplete(n)),
        }
    }

    #[inline]
    pub fn map_err<V, F>(self, f: F) -> ParseResult<'a, I, T, V>
      where F: FnOnce(E) -> V {
        match self.0 {
            State::Data(i, t)    => ParseResult(State::Data(i, t)),
            State::Error(i, e)   => ParseResult(State::Error(i, f(e))),
            State::Incomplete(n) => ParseResult(State::Incomplete(n)),
        }
    }
}

impl<'a, I, T, E: fmt::Debug> ParseResult<'a, I, T, E> {
    /// Extracts the contained type if the parser is in a success-state, panics otherwise.
    #[inline]
    pub fn unwrap(self) -> T {
        match self.0 {
            State::Data(_, t)    => t,
            State::Error(_, e)   => panic!("called `Parser::unwrap` on a parser in an error state: {:?}", e),
            State::Incomplete(_) => panic!("called `Parser::unwrap` on a parser in an incomplete state"),
        }
    }
}

impl<'a, I, T: fmt::Debug, E> ParseResult<'a, I, T, E> {
    pub fn unwrap_err(self) -> E {
        match self.0 {
            State::Data(_, t)    => panic!("called `Parser::unwrap_err` on a parser in a success state: {:?}", t),
            State::Error(_, e)   => e,
            State::Incomplete(_) => panic!("called `Parser::unwrap_err` on a parser in an incomplete state"),
        }
    }
}

/// Result for dealing with the basic parsers when parsing a stream of `u8`.
pub type U8Result<'a, T>        = ParseResult<'a, u8, T, Error<u8>>;
/// Result returned from the basic parsers.
pub type SimpleResult<'a, I, T> = ParseResult<'a, I, T, Error<I>>;

#[cfg(feature = "verbose_error")]
mod err {
    //! This is a private module to contain the more verbose error type as well as adapters for
    //! using it.
    //!
    //! All adapters are #[inline(always)] and will construct the appropriate error type.
    use std::any;
    use std::error;
    use std::fmt;

    use ::ParseResult;
    use ::internal;

    #[derive(Debug, Eq, PartialEq)]
    pub enum Error<I> {
        Expected(I),
        Unexpected,
        String(Vec<I>),
    }

    impl<I> fmt::Display for Error<I>
      where I: fmt::Debug {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            match *self {
                Error::Expected(ref c) => write!(f, "expected {:?}", *c),
                Error::Unexpected      => write!(f, "unexpected"),
                Error::String(ref s)   => write!(f, "expected {:?}", *s),
            }
        }
    }

    impl<I> error::Error for Error<I>
      where I: any::Any + fmt::Debug {
        fn description(&self) -> &str {
            match *self {
                Error::Expected(_) => "expected a certain token, received another",
                Error::Unexpected  => "received an unexpected token",
                Error::String(_)   => "expected a certain string of tokens, encountered an unexpected token",
            }
        }
    }

    #[inline(always)]
    pub fn unexpected<I>() -> Error<I> {
        Error::Unexpected
    }

    #[inline(always)]
    pub fn expected<'a, I>(i: I) -> Error<I> {
        Error::Expected(i)
    }

    #[inline(always)]
    pub fn string<'a, 'b, I, T>(buffer: &'a [I], _offset: usize, expected: &'b [I]) -> ParseResult<'a, I, T, Error<I>>
      where I: Copy {
        internal::error(buffer, Error::String(expected.to_vec()))
    }
}

#[cfg(not(feature = "verbose_error"))]
mod err {
    //! This is a private module to contain the smaller error type as well as adapters for using
    //! it.
    //!
    //! All adapters are #[inline(always)], and will just noop the data.
    use ::std::any;
    use ::std::error;
    use ::std::fmt;

    use ::std::marker::PhantomData;

    use ::ParseResult;
    use ::internal;

    #[derive(Debug, Eq, PartialEq)]
    pub struct Error<I>(PhantomData<I>);

    impl<I: fmt::Debug> fmt::Display for Error<I> {
        fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
            write!(f, "generic parse error (chomp was compiled without --feature verbose_error)")
        }
    }

    impl<I: any::Any + fmt::Debug> error::Error for Error<I> {
        fn description(&self) -> &str {
            "generic parse error (chomp was compiled without --feature verbose_error)"
        }
    }

    #[inline(always)]
    pub fn unexpected<I>() -> Error<I> {
        Error(PhantomData)
    }

    #[inline(always)]
    pub fn expected<'a, I>(_: I) -> Error<I> {
        Error(PhantomData)
    }

    #[inline(always)]
    pub fn string<'a, 'b, I, T>(buffer: &'a [I], offset: usize, _expected: &'b [I]) -> ParseResult<'a, I, T, Error<I>>
      where I: Copy {
        internal::error(&buffer[offset..], Error(PhantomData))
    }
}

#[cfg(test)]
mod test {
    use ::{Input, ParseResult};
    use ::internal::State;

    #[test]
    fn monad_left_identity() {
        fn f<I: Copy>(i: Input<I>, n: u32) -> ParseResult<I, u32, ()> {
            i.ret(n + 1)
        }

        let m1 = Input(b"test");
        let m2 = Input(b"test");

        let a = 123;
        // return a >>= f
        let lhs = m1.ret(a).bind(f);
        // f a
        let rhs = f(m2, a);

        assert_eq!(lhs.0, State::Data(b"test", 124));
        assert_eq!(rhs.0, State::Data(b"test", 124));
    }

    #[test]
    fn monad_right_identity() {
        let m1 = Input(b"test").ret::<_, ()>(1);
        let m2 = Input(b"test").ret::<_, ()>(1);

        // m1 >>= ret === m2
        let lhs = m1.bind::<_, _, ()>(Input::ret);
        let rhs = m2;

        assert_eq!(lhs.0, State::Data(b"test", 1));
        assert_eq!(rhs.0, State::Data(b"test", 1));
    }

    #[test]
    fn monad_associativity() {
         fn f<I: Copy>(i: Input<I>, num: u32) -> ParseResult<I, u64, ()> {
            i.ret((num + 1) as u64)
        }

        fn g<I: Copy>(i: Input<I>, num: u64) -> ParseResult<I, u64, ()> {
            i.ret(num * 2)
        }

        let lhs_m = Input(b"test").ret::<_, ()>(2);
        let rhs_m = Input(b"test").ret::<_, ()>(2);

        // (m >>= f) >>= g
        let lhs = lhs_m.bind(f).bind(g);
        // m >>= (\x -> f x >>= g)
        let rhs = rhs_m.bind(|i, x| f(i, x).bind(g));

        assert_eq!(lhs.0, State::Data(b"test", 6));
        assert_eq!(rhs.0, State::Data(b"test", 6));
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(rustlex)]
#[allow(plugin_as_library)]
extern crate rustlex;
#[macro_use] extern crate log;
extern crate time;
extern crate term;

pub mod frontend;
pub mod backend;
pub use backend::zcode::zfile;
pub mod utils;

use frontend::codegen;

use std::io::{Read,Write};

pub fn compile<R: Read, W: Write>(input: &mut R, output: &mut W) {
    // compile

    //screen
    let mut clean_input = frontend::screener::screen(input);

    // tokenize
    let tokens = frontend::lexer::lex(&mut clean_input);

    debug!("");
    for token in tokens.iter() {
    	debug!("{:?}", token);
    }

    // parse tokens and create ast
    let ast = frontend::parser::parse_tokens(tokens);
    ast.print();

    // create code
    codegen::generate_zcode(ast, output);
}
<commit_msg>Fix use of the new function signatures<commit_after>#![feature(plugin)]
#![plugin(rustlex)]
#[allow(plugin_as_library)]
extern crate rustlex;
#[macro_use] extern crate log;
extern crate time;
extern crate term;

pub mod frontend;
pub mod backend;
pub use backend::zcode::zfile;
pub mod utils;

use frontend::codegen;

use std::io::{Read,Write};

pub fn compile<R: Read, W: Write>(input: &mut R, output: &mut W) {
    // compile

    //screen
    let mut clean_input = frontend::screener::screen(input);

    // tokenize
    let tokens = frontend::lexer::lex(&mut clean_input);

    debug!("");
    for token in tokens {
    	debug!("{:?}", token);
    }

    // parse tokens and create ast
    let ast = frontend::parser::parse_tokens(tokens.collect()); //use collect until we work on iterators directly
    ast.print();

    // create code
    codegen::generate_zcode(ast, output);
}
<|endoftext|>


<commit_before>//! Lettre is an email library that allows creating and sending messages. It provides:
//!
//! * An easy to use email builder
//! * Pluggable email transports
//! * Unicode support
//! * Secure defaults
//!
//! Lettre requires Rust 1.40 or newer.
//!
//! ## Optional features
//!
//! * **builder**: Message builder
//! * **file-transport**: Transport that write messages into a file
//! * **smtp-transport**: Transport over SMTP
//! * **sendmail-transport**: Transport over SMTP
//! * **rustls-tls**: TLS support with the `rustls` crate
//! * **native-tls**: TLS support with the `native-tls` crate
//! * **tokio02**: Allow to asyncronously send emails using tokio 0.2.x
//! * **tokio02-rustls-tls**: Async TLS support with the `rustls` crate using tokio 0.2
//! * **tokio02-native-tls**: Async TLS support with the `native-tls` crate using tokio 0.2
//! * **async-std1**: Allow to asyncronously send emails using async-std 1.x (SMTP isn't supported yet)
//! * **r2d2**: Connection pool for SMTP transport
//! * **tracing**: Logging using the `tracing` crate
//! * **serde**: Serialization/Deserialization of entities
//! * **hostname**: Ability to try to use actual hostname in SMTP transaction

#![doc(html_root_url = "https://docs.rs/crate/lettre/0.10.0-alpha.2")]
#![doc(html_favicon_url = "https://lettre.rs/favicon.ico")]
#![doc(html_logo_url = "https://avatars0.githubusercontent.com/u/15113230?v=4")]
#![deny(
    missing_copy_implementations,
    trivial_casts,
    trivial_numeric_casts,
    unstable_features,
    unused_import_braces,
    unsafe_code
)]

pub mod address;
pub mod error;
#[cfg(feature = "builder")]
pub mod message;
pub mod transport;

#[macro_use]
extern crate hyperx;

use crate::error::Error;
#[cfg(feature = "builder")]
pub use crate::message::{
    header::{self, Headers},
    EmailFormat, Mailbox, Mailboxes, Message,
};
#[cfg(feature = "file-transport")]
pub use crate::transport::file::FileTransport;
#[cfg(feature = "sendmail-transport")]
pub use crate::transport::sendmail::SendmailTransport;
#[cfg(all(feature = "smtp-transport", feature = "connection-pool"))]
pub use crate::transport::smtp::r2d2::SmtpConnectionManager;
#[cfg(feature = "smtp-transport")]
pub use crate::transport::smtp::SmtpTransport;
#[cfg(all(feature = "smtp-transport", feature = "tokio02"))]
pub use crate::transport::smtp::{AsyncSmtpTransport, Tokio02Connector};
pub use crate::{address::Address, transport::stub::StubTransport};
#[cfg(any(feature = "async-std1", feature = "tokio02"))]
use async_trait::async_trait;
#[cfg(feature = "builder")]
use std::convert::TryFrom;

/// Simple email envelope representation
///
/// We only accept mailboxes, and do not support source routes (as per RFC).
#[derive(PartialEq, Eq, Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Envelope {
    /// The envelope recipients' addresses
    ///
    /// This can not be empty.
    forward_path: Vec<Address>,
    /// The envelope sender address
    reverse_path: Option<Address>,
}

impl Envelope {
    /// Creates a new envelope, which may fail if `to` is empty.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::str::FromStr;
    /// # use lettre::{Address, Envelope};
    ///
    /// let sender = Address::from_str("from@email.com").unwrap();
    /// let recipients = vec![Address::from_str("to@email.com").unwrap()];
    ///
    /// let envelope = Envelope::new(Some(sender), recipients);
    /// ```
    ///
    /// # Errors
    ///
    /// If `to` has no elements in it.
    pub fn new(from: Option<Address>, to: Vec<Address>) -> Result<Envelope, Error> {
        if to.is_empty() {
            return Err(Error::MissingTo);
        }
        Ok(Envelope {
            forward_path: to,
            reverse_path: from,
        })
    }

    /// Gets the destination addresses of the envelope.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::str::FromStr;
    /// # use lettre::{Address, Envelope};
    ///
    /// let sender = Address::from_str("from@email.com").unwrap();
    /// let recipients = vec![Address::from_str("to@email.com").unwrap()];
    ///
    /// let envelope = Envelope::new(Some(sender), recipients.clone()).unwrap();
    /// assert_eq!(envelope.to(), recipients);
    /// ```
    pub fn to(&self) -> &[Address] {
        self.forward_path.as_slice()
    }

    /// Gets the sender of the envelope.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::str::FromStr;
    /// # use lettre::{Address, Envelope};
    ///
    /// let sender = Address::from_str("from@email.com").unwrap();
    /// let recipients = vec![Address::from_str("to@email.com").unwrap()];
    ///
    /// let envelope = Envelope::new(Some(sender), recipients.clone()).unwrap();
    /// assert!(envelope.from().is_some());
    ///
    /// let senderless = Envelope::new(None, recipients.clone()).unwrap();
    /// assert!(senderless.from().is_none());
    /// ```
    pub fn from(&self) -> Option<&Address> {
        self.reverse_path.as_ref()
    }
}

impl TryFrom<&Headers> for Envelope {
    type Error = Error;

    fn try_from(headers: &Headers) -> Result<Self, Self::Error> {
        let from = match headers.get::<header::Sender>() {
            // If there is a Sender, use it
            Some(header::Sender(a)) => Some(a.email.clone()),
            // ... else try From
            None => match headers.get::<header::From>() {
                Some(header::From(a)) => {
                    let from: Vec<Mailbox> = a.clone().into();
                    if from.len() > 1 {
                        return Err(Error::TooManyFrom);
                    }
                    Some(from[0].email.clone())
                }
                None => None,
            },
        };

        fn add_addresses_from_mailboxes(
            addresses: &mut Vec<Address>,
            mailboxes: Option<&Mailboxes>,
        ) {
            if let Some(mailboxes) = mailboxes {
                for mailbox in mailboxes.iter() {
                    addresses.push(mailbox.email.clone());
                }
            }
        }
        let mut to = vec![];
        add_addresses_from_mailboxes(&mut to, headers.get::<header::To>().map(|h| &h.0));
        add_addresses_from_mailboxes(&mut to, headers.get::<header::Cc>().map(|h| &h.0));
        add_addresses_from_mailboxes(&mut to, headers.get::<header::Bcc>().map(|h| &h.0));

        Self::new(from, to)
    }
}

/// Blocking Transport method for emails
pub trait Transport {
    /// Response produced by the Transport
    type Ok;
    /// Error produced by the Transport
    type Error;

    /// Sends the email
    #[cfg(feature = "builder")]
    fn send(&self, message: &Message) -> Result<Self::Ok, Self::Error> {
        let raw = message.formatted();
        self.send_raw(message.envelope(), &raw)
    }

    fn send_raw(&self, envelope: &Envelope, email: &[u8]) -> Result<Self::Ok, Self::Error>;
}

/// async-std 1.x based Transport method for emails
#[cfg(feature = "async-std1")]
#[async_trait]
pub trait AsyncStd1Transport {
    /// Response produced by the Transport
    type Ok;
    /// Error produced by the Transport
    type Error;

    /// Sends the email
    #[cfg(feature = "builder")]
    // TODO take &Message
    async fn send(&self, message: Message) -> Result<Self::Ok, Self::Error> {
        let raw = message.formatted();
        let envelope = message.envelope();
        self.send_raw(&envelope, &raw).await
    }

    async fn send_raw(&self, envelope: &Envelope, email: &[u8]) -> Result<Self::Ok, Self::Error>;
}

/// tokio 0.2.x based Transport method for emails
#[cfg(feature = "tokio02")]
#[async_trait]
pub trait Tokio02Transport {
    /// Response produced by the Transport
    type Ok;
    /// Error produced by the Transport
    type Error;

    /// Sends the email
    #[cfg(feature = "builder")]
    // TODO take &Message
    async fn send(&self, message: Message) -> Result<Self::Ok, Self::Error> {
        let raw = message.formatted();
        let envelope = message.envelope();
        self.send_raw(&envelope, &raw).await
    }

    async fn send_raw(&self, envelope: &Envelope, email: &[u8]) -> Result<Self::Ok, Self::Error>;
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::message::{header, Mailbox, Mailboxes};
    use hyperx::header::Headers;

    #[test]
    fn envelope_from_headers() {
        let from = Mailboxes::new().with("kayo@example.com".parse().unwrap());
        let to = Mailboxes::new().with("amousset@example.com".parse().unwrap());

        let mut headers = Headers::new();
        headers.set(header::From(from));
        headers.set(header::To(to));

        assert_eq!(
            Envelope::try_from(&headers).unwrap(),
            Envelope::new(
                Some(Address::new("kayo", "example.com").unwrap()),
                vec![Address::new("amousset", "example.com").unwrap()]
            )
            .unwrap()
        );
    }

    #[test]
    fn envelope_from_headers_sender() {
        let from = Mailboxes::new().with("kayo@example.com".parse().unwrap());
        let sender = Mailbox::new(None, "kayo2@example.com".parse().unwrap());
        let to = Mailboxes::new().with("amousset@example.com".parse().unwrap());

        let mut headers = Headers::new();
        headers.set(header::From(from));
        headers.set(header::Sender(sender));
        headers.set(header::To(to));

        assert_eq!(
            Envelope::try_from(&headers).unwrap(),
            Envelope::new(
                Some(Address::new("kayo2", "example.com").unwrap()),
                vec![Address::new("amousset", "example.com").unwrap()]
            )
            .unwrap()
        );
    }

    #[test]
    fn envelope_from_headers_no_to() {
        let from = Mailboxes::new().with("kayo@example.com".parse().unwrap());
        let sender = Mailbox::new(None, "kayo2@example.com".parse().unwrap());

        let mut headers = Headers::new();
        headers.set(header::From(from));
        headers.set(header::Sender(sender));

        assert!(Envelope::try_from(&headers).is_err(),);
    }
}
<commit_msg>fix(email): Make doctest rustc-1.40 compatible<commit_after>//! Lettre is an email library that allows creating and sending messages. It provides:
//!
//! * An easy to use email builder
//! * Pluggable email transports
//! * Unicode support
//! * Secure defaults
//!
//! Lettre requires Rust 1.40 or newer.
//!
//! ## Optional features
//!
//! * **builder**: Message builder
//! * **file-transport**: Transport that write messages into a file
//! * **smtp-transport**: Transport over SMTP
//! * **sendmail-transport**: Transport over SMTP
//! * **rustls-tls**: TLS support with the `rustls` crate
//! * **native-tls**: TLS support with the `native-tls` crate
//! * **tokio02**: Allow to asyncronously send emails using tokio 0.2.x
//! * **tokio02-rustls-tls**: Async TLS support with the `rustls` crate using tokio 0.2
//! * **tokio02-native-tls**: Async TLS support with the `native-tls` crate using tokio 0.2
//! * **async-std1**: Allow to asyncronously send emails using async-std 1.x (SMTP isn't supported yet)
//! * **r2d2**: Connection pool for SMTP transport
//! * **tracing**: Logging using the `tracing` crate
//! * **serde**: Serialization/Deserialization of entities
//! * **hostname**: Ability to try to use actual hostname in SMTP transaction

#![doc(html_root_url = "https://docs.rs/crate/lettre/0.10.0-alpha.2")]
#![doc(html_favicon_url = "https://lettre.rs/favicon.ico")]
#![doc(html_logo_url = "https://avatars0.githubusercontent.com/u/15113230?v=4")]
#![deny(
    missing_copy_implementations,
    trivial_casts,
    trivial_numeric_casts,
    unstable_features,
    unused_import_braces,
    unsafe_code
)]

pub mod address;
pub mod error;
#[cfg(feature = "builder")]
pub mod message;
pub mod transport;

#[macro_use]
extern crate hyperx;

use crate::error::Error;
#[cfg(feature = "builder")]
pub use crate::message::{
    header::{self, Headers},
    EmailFormat, Mailbox, Mailboxes, Message,
};
#[cfg(feature = "file-transport")]
pub use crate::transport::file::FileTransport;
#[cfg(feature = "sendmail-transport")]
pub use crate::transport::sendmail::SendmailTransport;
#[cfg(all(feature = "smtp-transport", feature = "connection-pool"))]
pub use crate::transport::smtp::r2d2::SmtpConnectionManager;
#[cfg(feature = "smtp-transport")]
pub use crate::transport::smtp::SmtpTransport;
#[cfg(all(feature = "smtp-transport", feature = "tokio02"))]
pub use crate::transport::smtp::{AsyncSmtpTransport, Tokio02Connector};
pub use crate::{address::Address, transport::stub::StubTransport};
#[cfg(any(feature = "async-std1", feature = "tokio02"))]
use async_trait::async_trait;
#[cfg(feature = "builder")]
use std::convert::TryFrom;

/// Simple email envelope representation
///
/// We only accept mailboxes, and do not support source routes (as per RFC).
#[derive(PartialEq, Eq, Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Envelope {
    /// The envelope recipients' addresses
    ///
    /// This can not be empty.
    forward_path: Vec<Address>,
    /// The envelope sender address
    reverse_path: Option<Address>,
}

impl Envelope {
    /// Creates a new envelope, which may fail if `to` is empty.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::str::FromStr;
    /// # use lettre::{Address, Envelope};
    ///
    /// let sender = Address::from_str("from@email.com").unwrap();
    /// let recipients = vec![Address::from_str("to@email.com").unwrap()];
    ///
    /// let envelope = Envelope::new(Some(sender), recipients);
    /// ```
    ///
    /// # Errors
    ///
    /// If `to` has no elements in it.
    pub fn new(from: Option<Address>, to: Vec<Address>) -> Result<Envelope, Error> {
        if to.is_empty() {
            return Err(Error::MissingTo);
        }
        Ok(Envelope {
            forward_path: to,
            reverse_path: from,
        })
    }

    /// Gets the destination addresses of the envelope.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::str::FromStr;
    /// # use lettre::{Address, Envelope};
    ///
    /// let sender = Address::from_str("from@email.com").unwrap();
    /// let recipients = vec![Address::from_str("to@email.com").unwrap()];
    ///
    /// let envelope = Envelope::new(Some(sender), recipients.clone()).unwrap();
    /// assert_eq!(envelope.to(), recipients.as_slice());
    /// ```
    pub fn to(&self) -> &[Address] {
        self.forward_path.as_slice()
    }

    /// Gets the sender of the envelope.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::str::FromStr;
    /// # use lettre::{Address, Envelope};
    ///
    /// let sender = Address::from_str("from@email.com").unwrap();
    /// let recipients = vec![Address::from_str("to@email.com").unwrap()];
    ///
    /// let envelope = Envelope::new(Some(sender), recipients.clone()).unwrap();
    /// assert!(envelope.from().is_some());
    ///
    /// let senderless = Envelope::new(None, recipients.clone()).unwrap();
    /// assert!(senderless.from().is_none());
    /// ```
    pub fn from(&self) -> Option<&Address> {
        self.reverse_path.as_ref()
    }
}

impl TryFrom<&Headers> for Envelope {
    type Error = Error;

    fn try_from(headers: &Headers) -> Result<Self, Self::Error> {
        let from = match headers.get::<header::Sender>() {
            // If there is a Sender, use it
            Some(header::Sender(a)) => Some(a.email.clone()),
            // ... else try From
            None => match headers.get::<header::From>() {
                Some(header::From(a)) => {
                    let from: Vec<Mailbox> = a.clone().into();
                    if from.len() > 1 {
                        return Err(Error::TooManyFrom);
                    }
                    Some(from[0].email.clone())
                }
                None => None,
            },
        };

        fn add_addresses_from_mailboxes(
            addresses: &mut Vec<Address>,
            mailboxes: Option<&Mailboxes>,
        ) {
            if let Some(mailboxes) = mailboxes {
                for mailbox in mailboxes.iter() {
                    addresses.push(mailbox.email.clone());
                }
            }
        }
        let mut to = vec![];
        add_addresses_from_mailboxes(&mut to, headers.get::<header::To>().map(|h| &h.0));
        add_addresses_from_mailboxes(&mut to, headers.get::<header::Cc>().map(|h| &h.0));
        add_addresses_from_mailboxes(&mut to, headers.get::<header::Bcc>().map(|h| &h.0));

        Self::new(from, to)
    }
}

/// Blocking Transport method for emails
pub trait Transport {
    /// Response produced by the Transport
    type Ok;
    /// Error produced by the Transport
    type Error;

    /// Sends the email
    #[cfg(feature = "builder")]
    fn send(&self, message: &Message) -> Result<Self::Ok, Self::Error> {
        let raw = message.formatted();
        self.send_raw(message.envelope(), &raw)
    }

    fn send_raw(&self, envelope: &Envelope, email: &[u8]) -> Result<Self::Ok, Self::Error>;
}

/// async-std 1.x based Transport method for emails
#[cfg(feature = "async-std1")]
#[async_trait]
pub trait AsyncStd1Transport {
    /// Response produced by the Transport
    type Ok;
    /// Error produced by the Transport
    type Error;

    /// Sends the email
    #[cfg(feature = "builder")]
    // TODO take &Message
    async fn send(&self, message: Message) -> Result<Self::Ok, Self::Error> {
        let raw = message.formatted();
        let envelope = message.envelope();
        self.send_raw(&envelope, &raw).await
    }

    async fn send_raw(&self, envelope: &Envelope, email: &[u8]) -> Result<Self::Ok, Self::Error>;
}

/// tokio 0.2.x based Transport method for emails
#[cfg(feature = "tokio02")]
#[async_trait]
pub trait Tokio02Transport {
    /// Response produced by the Transport
    type Ok;
    /// Error produced by the Transport
    type Error;

    /// Sends the email
    #[cfg(feature = "builder")]
    // TODO take &Message
    async fn send(&self, message: Message) -> Result<Self::Ok, Self::Error> {
        let raw = message.formatted();
        let envelope = message.envelope();
        self.send_raw(&envelope, &raw).await
    }

    async fn send_raw(&self, envelope: &Envelope, email: &[u8]) -> Result<Self::Ok, Self::Error>;
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::message::{header, Mailbox, Mailboxes};
    use hyperx::header::Headers;

    #[test]
    fn envelope_from_headers() {
        let from = Mailboxes::new().with("kayo@example.com".parse().unwrap());
        let to = Mailboxes::new().with("amousset@example.com".parse().unwrap());

        let mut headers = Headers::new();
        headers.set(header::From(from));
        headers.set(header::To(to));

        assert_eq!(
            Envelope::try_from(&headers).unwrap(),
            Envelope::new(
                Some(Address::new("kayo", "example.com").unwrap()),
                vec![Address::new("amousset", "example.com").unwrap()]
            )
            .unwrap()
        );
    }

    #[test]
    fn envelope_from_headers_sender() {
        let from = Mailboxes::new().with("kayo@example.com".parse().unwrap());
        let sender = Mailbox::new(None, "kayo2@example.com".parse().unwrap());
        let to = Mailboxes::new().with("amousset@example.com".parse().unwrap());

        let mut headers = Headers::new();
        headers.set(header::From(from));
        headers.set(header::Sender(sender));
        headers.set(header::To(to));

        assert_eq!(
            Envelope::try_from(&headers).unwrap(),
            Envelope::new(
                Some(Address::new("kayo2", "example.com").unwrap()),
                vec![Address::new("amousset", "example.com").unwrap()]
            )
            .unwrap()
        );
    }

    #[test]
    fn envelope_from_headers_no_to() {
        let from = Mailboxes::new().with("kayo@example.com".parse().unwrap());
        let sender = Mailbox::new(None, "kayo2@example.com".parse().unwrap());

        let mut headers = Headers::new();
        headers.set(header::From(from));
        headers.set(header::Sender(sender));

        assert!(Envelope::try_from(&headers).is_err(),);
    }
}
<|endoftext|>


<commit_before>#![feature(libc)]

extern crate libc;

use libc::{c_void, c_int, c_char};
use std::ffi::CString;
use std::slice;

pub type Voidptr = *mut c_void;

#[link(name = "sophia", kind="static")]
extern {
    fn sp_env() -> Voidptr;
    fn sp_object(a: Voidptr) -> Voidptr;
    fn sp_open(a: Voidptr) -> c_int;
    fn sp_drop(a: Voidptr) -> c_int;
    fn sp_destroy(a: Voidptr) -> c_int;
    fn sp_error(a: Voidptr) -> c_int;
    fn sp_asynchronous(a: Voidptr) -> Voidptr;
    fn sp_poll(a: Voidptr) -> Voidptr;
    fn sp_setobject(a: Voidptr, b: *const c_char, c: Voidptr) -> c_int;
    fn sp_setstring(a: Voidptr, b: *const c_char, c: *const c_void, d: c_int) -> c_int;
    fn sp_setint(a: Voidptr, b: *const c_char, c: i64) -> c_int;

    fn sp_getobject(a: Voidptr, b: *const u8) -> Voidptr;
    fn sp_getstring(a: Voidptr, b: *const u8, c: *mut c_int) -> Voidptr;
    fn sp_getint(a: Voidptr, b: *mut u8) -> i64;
    fn sp_set(a: Voidptr, b: Voidptr) -> c_int;
    fn sp_update(a: Voidptr, b: Voidptr) -> c_int;
    fn sp_delete(a: Voidptr, b: Voidptr) -> c_int;
    fn sp_get(a: Voidptr, b: Voidptr) -> Voidptr;
    fn sp_cursor(a: Voidptr, b: Voidptr) -> Voidptr;
    fn sp_begin(a: Voidptr) -> Voidptr;
    fn sp_prepare(a: Voidptr) -> c_int;
    fn sp_commit(a: Voidptr) -> c_int;
}

pub struct Env {
    env: Voidptr
}

pub struct Db {
    db: Voidptr
}

unsafe impl Sync for Db {}

impl Env {
    pub fn new() -> Env {
        Env {env: unsafe{sp_env()}}
    }

    pub fn destroy(self) {
        unsafe{sp_destroy(self.env)};
    }

    pub fn db(&mut self, dbname: &str) {
        let dbname = CString::new(dbname).unwrap();
        unsafe {sp_setstring(self.env, "db\0".as_ptr() as *const c_char, dbname.as_ptr() as *const c_void, 0) };
    }

    pub fn open(&mut self) {
        unsafe {sp_open(self.env)};
    }

    pub fn get_object(&mut self, attr: &str) -> Voidptr {
        let attr = CString::new(attr).unwrap();
        unsafe {sp_getobject(self.env, attr.as_ptr() as *const u8)}
    }

    pub fn get_db(&mut self, dbname: &str) -> Option<Db> {
        let dbstr = "db.".to_string() + dbname;
        let attr = CString::new(&dbstr[..]).unwrap();
        unsafe {
            let obj = sp_getobject(self.env, attr.as_ptr() as *const u8);
            if obj.is_null() {
                None
            }
            else {
                Some(Db {db: obj})
            }
        }
    }

    pub fn setattr(&mut self, key: &str, val: &str) {
        let key = CString::new(key).unwrap();
        let val = CString::new(val).unwrap();
        unsafe {sp_setstring(self.env, key.as_ptr(), val.as_ptr() as *const c_void, 0) };
    }

    pub fn setintattr(&mut self, key: &str, val: i64) {
        let key = CString::new(key).unwrap();
        unsafe {sp_setint(self.env, key.as_ptr(), val) };
    }

}

pub struct Object {
    obj: Voidptr
}

impl Object {
    pub fn get_value<'a>(&'a mut self) -> Option<&'a[u8]> {
        unsafe {
            if self.obj.is_null() {
                return None;
            }
            let mut sz = 0;
            let valptr = sp_getstring(self.obj, "value\0".as_ptr(), &mut sz);

            // XXX: what if we stored an empty value?
            if valptr.is_null() {
                return None;
            }

            let s = slice::from_raw_parts(valptr as *const u8, sz as usize);
            return Some(s);
        }
    }
}

impl Drop for Object {
    fn drop(&mut self) {
        unsafe {sp_destroy(self.obj);}
    }
}

impl Db {
    pub fn set(&mut self, key: &[u8], value: &[u8]) {
        unsafe {
            let o = sp_object(self.db);
            sp_setstring(o, "key\0".as_ptr() as *const c_char, key.as_ptr() as Voidptr, key.len() as i32);
            sp_setstring(o, "value\0".as_ptr() as *const c_char, value.as_ptr() as Voidptr, value.len() as i32);
            sp_set(self.db, o);
            sp_destroy(o);
        }
    }

    pub fn get(&mut self, key: &[u8]) -> Object {
        unsafe {
            let o = sp_object(self.db);
            sp_setstring(o, "key\0".as_ptr() as *const c_char, key.as_ptr() as Voidptr, key.len() as i32);
            let o2 = sp_get(self.db, o);
            return Object{obj: o2};
        }
    }
}
<commit_msg>Also implement Send for Db<commit_after>#![feature(libc)]

extern crate libc;

use libc::{c_void, c_int, c_char};
use std::ffi::CString;
use std::slice;

pub type Voidptr = *mut c_void;

#[link(name = "sophia", kind="static")]
extern {
    fn sp_env() -> Voidptr;
    fn sp_object(a: Voidptr) -> Voidptr;
    fn sp_open(a: Voidptr) -> c_int;
    fn sp_drop(a: Voidptr) -> c_int;
    fn sp_destroy(a: Voidptr) -> c_int;
    fn sp_error(a: Voidptr) -> c_int;
    fn sp_asynchronous(a: Voidptr) -> Voidptr;
    fn sp_poll(a: Voidptr) -> Voidptr;
    fn sp_setobject(a: Voidptr, b: *const c_char, c: Voidptr) -> c_int;
    fn sp_setstring(a: Voidptr, b: *const c_char, c: *const c_void, d: c_int) -> c_int;
    fn sp_setint(a: Voidptr, b: *const c_char, c: i64) -> c_int;

    fn sp_getobject(a: Voidptr, b: *const u8) -> Voidptr;
    fn sp_getstring(a: Voidptr, b: *const u8, c: *mut c_int) -> Voidptr;
    fn sp_getint(a: Voidptr, b: *mut u8) -> i64;
    fn sp_set(a: Voidptr, b: Voidptr) -> c_int;
    fn sp_update(a: Voidptr, b: Voidptr) -> c_int;
    fn sp_delete(a: Voidptr, b: Voidptr) -> c_int;
    fn sp_get(a: Voidptr, b: Voidptr) -> Voidptr;
    fn sp_cursor(a: Voidptr, b: Voidptr) -> Voidptr;
    fn sp_begin(a: Voidptr) -> Voidptr;
    fn sp_prepare(a: Voidptr) -> c_int;
    fn sp_commit(a: Voidptr) -> c_int;
}

pub struct Env {
    env: Voidptr
}

pub struct Db {
    db: Voidptr
}

unsafe impl Sync for Db {}
unsafe impl Send for Db {}

impl Env {
    pub fn new() -> Env {
        Env {env: unsafe{sp_env()}}
    }

    pub fn destroy(self) {
        unsafe{sp_destroy(self.env)};
    }

    pub fn db(&mut self, dbname: &str) {
        let dbname = CString::new(dbname).unwrap();
        unsafe {sp_setstring(self.env, "db\0".as_ptr() as *const c_char, dbname.as_ptr() as *const c_void, 0) };
    }

    pub fn open(&mut self) {
        unsafe {sp_open(self.env)};
    }

    pub fn get_object(&mut self, attr: &str) -> Voidptr {
        let attr = CString::new(attr).unwrap();
        unsafe {sp_getobject(self.env, attr.as_ptr() as *const u8)}
    }

    pub fn get_db(&mut self, dbname: &str) -> Option<Db> {
        let dbstr = "db.".to_string() + dbname;
        let attr = CString::new(&dbstr[..]).unwrap();
        unsafe {
            let obj = sp_getobject(self.env, attr.as_ptr() as *const u8);
            if obj.is_null() {
                None
            }
            else {
                Some(Db {db: obj})
            }
        }
    }

    pub fn setattr(&mut self, key: &str, val: &str) {
        let key = CString::new(key).unwrap();
        let val = CString::new(val).unwrap();
        unsafe {sp_setstring(self.env, key.as_ptr(), val.as_ptr() as *const c_void, 0) };
    }

    pub fn setintattr(&mut self, key: &str, val: i64) {
        let key = CString::new(key).unwrap();
        unsafe {sp_setint(self.env, key.as_ptr(), val) };
    }

}

pub struct Object {
    obj: Voidptr
}

impl Object {
    pub fn get_value<'a>(&'a mut self) -> Option<&'a[u8]> {
        unsafe {
            if self.obj.is_null() {
                return None;
            }
            let mut sz = 0;
            let valptr = sp_getstring(self.obj, "value\0".as_ptr(), &mut sz);

            // XXX: what if we stored an empty value?
            if valptr.is_null() {
                return None;
            }

            let s = slice::from_raw_parts(valptr as *const u8, sz as usize);
            return Some(s);
        }
    }
}

impl Drop for Object {
    fn drop(&mut self) {
        unsafe {sp_destroy(self.obj);}
    }
}

impl Db {
    pub fn set(&mut self, key: &[u8], value: &[u8]) {
        unsafe {
            let o = sp_object(self.db);
            sp_setstring(o, "key\0".as_ptr() as *const c_char, key.as_ptr() as Voidptr, key.len() as i32);
            sp_setstring(o, "value\0".as_ptr() as *const c_char, value.as_ptr() as Voidptr, value.len() as i32);
            sp_set(self.db, o);
            sp_destroy(o);
        }
    }

    pub fn get(&mut self, key: &[u8]) -> Object {
        unsafe {
            let o = sp_object(self.db);
            sp_setstring(o, "key\0".as_ptr() as *const c_char, key.as_ptr() as Voidptr, key.len() as i32);
            let o2 = sp_get(self.db, o);
            return Object{obj: o2};
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
extern crate walkdir;

pub type Asset = Box<Fn(String) -> Option<Vec<u8>> + std::marker::Sync + std::marker::Send>;

#[cfg(debug_assertions)]
pub fn generate_assets(parent_path: String) -> Asset {
    use std::fs::File;
    use std::path::Path;
    use std::io::Read;
    info!("loading folder -> {}", parent_path);
    Box::new(move |file_path| {
        let name = &format!("{}{}", parent_path, file_path);
        let path = &Path::new(name);
        let key = String::from(path.to_str().expect("Path does not have a string representation"));
        info!("asset from file -> {}", key);
        let mut file = match File::open(path) {
            Ok(mut file) => file,
            Err(e) => {
                error!("could not open file -> {} {}", key, e);
                return None
            }
        };
        let mut data: Vec<u8> = Vec::new();
        match file.read_to_end(&mut data) {
            Ok(_) => Some(data),
            Err(e) =>  {
                error!("could not open file -> {} {}", key, e);
                return None
            }
        }
    })
}

#[cfg(not(debug_assertions))]
pub fn generate_assets<'a>(parent_path: String) -> Asset {
    use std::fs::File;
    use std::io::Read;
    use std::path::Path;
    use walkdir::WalkDir;
    use std::collections::HashMap;

    info!("loading folder -> {}", parent_path);
    let mut map = HashMap::new();
    for entry in WalkDir::new(parent_path.clone()).into_iter().filter_map(|e| e.ok()).filter(|e| e.file_type().is_file()) {
        info!("asset from file -> {}", entry.path().display());
        let base = &parent_path.clone();
        let key = String::from(entry.path().to_str().expect("Path does not have a string representation")).replace(base, "");
        let mut file = File::open(&Path::new(&entry.path())).unwrap_or_else(|e| {
            panic!("could not open file -> {} {}", key, e);
        });
        let mut data: Vec<u8> = Vec::new();
        file.read_to_end(&mut data).unwrap_or_else(|e| {
            panic!("could not read file -> {} {}", key, e);
        });
        map.insert(key, data);
    }
    Box::new(move |file_path| {
        match map.get(&file_path) {
            Some(s) => Some(s.to_vec()),
            None => None,
        }
    })
}

#[macro_export]
macro_rules! embed {
    ($x:expr) => ( ::generate_assets($x) )
}

#[cfg(test)]
mod tests {
    #[test]
    #[cfg(debug_assertions)]
    fn dev() {
        let asset = embed!("examples/public/".to_owned());
        match asset("index.html".to_owned()) {
            None => assert!(false, "index.html should exist"),
            _ => assert!(true),
        }
        match asset("gg.html".to_owned()) {
            Some(_) => assert!(false, "gg.html should not exist"),
            _ => assert!(true),
        }
        match asset("images/llama.png".to_owned()) {
            None => assert!(false, "llama.png should exist"),
            _ => assert!(true),
        }
    }

    #[test]
    #[cfg(not(debug_assertions))]
    fn prod() {
        let asset = embed!("examples/public/".to_owned());
        match asset("index.html".to_owned()) {
            None => assert!(false, "index.html should exist"),
            _ => assert!(true),
        }
        match asset("gg.html".to_owned()) {
            Some(_) => assert!(false, "gg.html should not exist"),
            _ => assert!(true),
        }
        match asset("images/llama.png".to_owned()) {
            None => assert!(false, "llama.png should exist"),
            _ => assert!(true),
        }
    }
}
<commit_msg>Uses $crate variable so embed! works in external macros<commit_after>#[macro_use]
extern crate log;
extern crate walkdir;

pub type Asset = Box<Fn(String) -> Option<Vec<u8>> + std::marker::Sync + std::marker::Send>;

#[cfg(debug_assertions)]
pub fn generate_assets(parent_path: String) -> Asset {
    use std::fs::File;
    use std::path::Path;
    use std::io::Read;
    info!("loading folder -> {}", parent_path);
    Box::new(move |file_path| {
        let name = &format!("{}{}", parent_path, file_path);
        let path = &Path::new(name);
        let key = String::from(path.to_str().expect("Path does not have a string representation"));
        info!("asset from file -> {}", key);
        let mut file = match File::open(path) {
            Ok(mut file) => file,
            Err(e) => {
                error!("could not open file -> {} {}", key, e);
                return None
            }
        };
        let mut data: Vec<u8> = Vec::new();
        match file.read_to_end(&mut data) {
            Ok(_) => Some(data),
            Err(e) =>  {
                error!("could not open file -> {} {}", key, e);
                return None
            }
        }
    })
}

#[cfg(not(debug_assertions))]
pub fn generate_assets<'a>(parent_path: String) -> Asset {
    use std::fs::File;
    use std::io::Read;
    use std::path::Path;
    use walkdir::WalkDir;
    use std::collections::HashMap;

    info!("loading folder -> {}", parent_path);
    let mut map = HashMap::new();
    for entry in WalkDir::new(parent_path.clone()).into_iter().filter_map(|e| e.ok()).filter(|e| e.file_type().is_file()) {
        info!("asset from file -> {}", entry.path().display());
        let base = &parent_path.clone();
        let key = String::from(entry.path().to_str().expect("Path does not have a string representation")).replace(base, "");
        let mut file = File::open(&Path::new(&entry.path())).unwrap_or_else(|e| {
            panic!("could not open file -> {} {}", key, e);
        });
        let mut data: Vec<u8> = Vec::new();
        file.read_to_end(&mut data).unwrap_or_else(|e| {
            panic!("could not read file -> {} {}", key, e);
        });
        map.insert(key, data);
    }
    Box::new(move |file_path| {
        match map.get(&file_path) {
            Some(s) => Some(s.to_vec()),
            None => None,
        }
    })
}

#[macro_export]
macro_rules! embed {
    ($x:expr) => ( $crate::generate_assets($x) )
}

#[cfg(test)]
mod tests {
    #[test]
    #[cfg(debug_assertions)]
    fn dev() {
        let asset = embed!("examples/public/".to_owned());
        match asset("index.html".to_owned()) {
            None => assert!(false, "index.html should exist"),
            _ => assert!(true),
        }
        match asset("gg.html".to_owned()) {
            Some(_) => assert!(false, "gg.html should not exist"),
            _ => assert!(true),
        }
        match asset("images/llama.png".to_owned()) {
            None => assert!(false, "llama.png should exist"),
            _ => assert!(true),
        }
    }

    #[test]
    #[cfg(not(debug_assertions))]
    fn prod() {
        let asset = embed!("examples/public/".to_owned());
        match asset("index.html".to_owned()) {
            None => assert!(false, "index.html should exist"),
            _ => assert!(true),
        }
        match asset("gg.html".to_owned()) {
            Some(_) => assert!(false, "gg.html should not exist"),
            _ => assert!(true),
        }
        match asset("images/llama.png".to_owned()) {
            None => assert!(false, "llama.png should exist"),
            _ => assert!(true),
        }
    }
}
<|endoftext|>


<commit_before>
//! **petgraph** is a graph data structure library.
//!
//! The most prominent type is [`Graph`](./graph/struct.Graph.html) which is
//! a directed or undirected graph with arbitrary associated node and edge data.
//!
//! Petgraph also provides [`GraphMap`](./graphmap/struct.GraphMap.html) which
//! is an undirected hashmap-backed graph which only allows simple node identifiers
//! (such as integers or references).

extern crate fixedbitset;

pub use graph::Graph;
pub use graphmap::GraphMap;

pub use visit::{
    Bfs,
    BfsIter,
    Dfs,
    DfsIter,
};
pub use EdgeDirection::{Outgoing, Incoming};

mod scored;
pub mod algo;
#[doc(hidden)] // Not for public consumption -- only for testing
pub mod generate;
pub mod graphmap;
pub mod graph;
pub mod dot;
pub mod visit;
pub mod unionfind;
mod dijkstra;
mod isomorphism;
mod traits_graph;
#[cfg(feature = "quickcheck")]
pub mod quickcheck;

// Index into the NodeIndex and EdgeIndex arrays
/// Edge direction
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum EdgeDirection {
    /// An `Outgoing` edge is an outward edge *from* the current node.
    Outgoing = 0,
    /// An `Incoming` edge is an inbound edge *to* the current node.
    Incoming = 1
}

impl EdgeDirection {
    #[inline]
    fn opposite(&self) -> EdgeDirection {
        match *self {
            Outgoing => Incoming,
            Incoming => Outgoing,
        }
    }
}

/// Marker type for a directed graph.
#[derive(Copy, Clone, Debug)]
pub enum Directed { }

/// Marker type for an undirected graph.
#[derive(Copy, Clone, Debug)]
pub enum Undirected { }

/// A graph's edge type determines whether is has directed edges or not.
pub trait EdgeType {
    fn is_directed() -> bool;
}

impl EdgeType for Directed {
    #[inline]
    fn is_directed() -> bool { true }
}

impl EdgeType for Undirected {
    #[inline]
    fn is_directed() -> bool { false }
}

/// Convert an element like `(i, j)` or `(i, j, w)` into
/// a triple of source, target, edge weight.
///
/// For `Graph::from_edges` and `GraphMap::from_edges`.
pub trait IntoWeightedEdge<E> {
    type NodeId;
    fn into_weighted_edge(self) -> (Self::NodeId, Self::NodeId, E);
}

impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix)
    where E: Default
{
    type NodeId = Ix;

    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        let (s, t) = self;
        (s, t, E::default())
    }
}

impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix, E)
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        self
    }
}

impl<'a, Ix, E> IntoWeightedEdge<E> for (Ix, Ix, &'a E)
    where E: Clone
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        let (a, b, c) = self;
        (a, b, c.clone())
    }
}

impl<'a, Ix, E> IntoWeightedEdge<E> for &'a (Ix, Ix)
    where Ix: Copy, E: Default
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        let (s, t) = *self;
        (s, t, E::default())
    }
}

impl<'a, Ix, E> IntoWeightedEdge<E> for &'a (Ix, Ix, E)
    where Ix: Copy, E: Clone
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        self.clone()
    }
}
<commit_msg>Add method EdgeDirection::opposite and impl Eq, Ord, Hash<commit_after>
//! **petgraph** is a graph data structure library.
//!
//! The most prominent type is [`Graph`](./graph/struct.Graph.html) which is
//! a directed or undirected graph with arbitrary associated node and edge data.
//!
//! Petgraph also provides [`GraphMap`](./graphmap/struct.GraphMap.html) which
//! is an undirected hashmap-backed graph which only allows simple node identifiers
//! (such as integers or references).

extern crate fixedbitset;

pub use graph::Graph;
pub use graphmap::GraphMap;

pub use visit::{
    Bfs,
    BfsIter,
    Dfs,
    DfsIter,
};
pub use EdgeDirection::{Outgoing, Incoming};

mod scored;
pub mod algo;
#[doc(hidden)] // Not for public consumption -- only for testing
pub mod generate;
pub mod graphmap;
pub mod graph;
pub mod dot;
pub mod visit;
pub mod unionfind;
mod dijkstra;
mod isomorphism;
mod traits_graph;
#[cfg(feature = "quickcheck")]
pub mod quickcheck;

// Index into the NodeIndex and EdgeIndex arrays
/// Edge direction
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
pub enum EdgeDirection {
    /// An `Outgoing` edge is an outward edge *from* the current node.
    Outgoing = 0,
    /// An `Incoming` edge is an inbound edge *to* the current node.
    Incoming = 1
}

impl EdgeDirection {
    /// Return the opposite `EdgeDirection`.
    #[inline]
    pub fn opposite(&self) -> EdgeDirection {
        match *self {
            Outgoing => Incoming,
            Incoming => Outgoing,
        }
    }
}

/// Marker type for a directed graph.
#[derive(Copy, Clone, Debug)]
pub enum Directed { }

/// Marker type for an undirected graph.
#[derive(Copy, Clone, Debug)]
pub enum Undirected { }

/// A graph's edge type determines whether is has directed edges or not.
pub trait EdgeType {
    fn is_directed() -> bool;
}

impl EdgeType for Directed {
    #[inline]
    fn is_directed() -> bool { true }
}

impl EdgeType for Undirected {
    #[inline]
    fn is_directed() -> bool { false }
}

/// Convert an element like `(i, j)` or `(i, j, w)` into
/// a triple of source, target, edge weight.
///
/// For `Graph::from_edges` and `GraphMap::from_edges`.
pub trait IntoWeightedEdge<E> {
    type NodeId;
    fn into_weighted_edge(self) -> (Self::NodeId, Self::NodeId, E);
}

impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix)
    where E: Default
{
    type NodeId = Ix;

    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        let (s, t) = self;
        (s, t, E::default())
    }
}

impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix, E)
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        self
    }
}

impl<'a, Ix, E> IntoWeightedEdge<E> for (Ix, Ix, &'a E)
    where E: Clone
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        let (a, b, c) = self;
        (a, b, c.clone())
    }
}

impl<'a, Ix, E> IntoWeightedEdge<E> for &'a (Ix, Ix)
    where Ix: Copy, E: Default
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        let (s, t) = *self;
        (s, t, E::default())
    }
}

impl<'a, Ix, E> IntoWeightedEdge<E> for &'a (Ix, Ix, E)
    where Ix: Copy, E: Clone
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        self.clone()
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Adrien Champion. See the COPYRIGHT file at the top-level
// directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(non_upper_case_globals)]
#![deny(missing_docs)]

//! API for the kinō model-checker.

extern crate term ;
extern crate system ;
extern crate unroll ;
#[macro_use]
extern crate common ;
extern crate bmc ;
extern crate kind ;
extern crate twind ;
extern crate tig ;
extern crate pruner ;

mod master ;

// pub use term::* ;
pub use system::* ;
// pub use unroll::* ;
// pub use common::* ;

/// The techniques provided by kino.
pub mod teks {
  pub use bmc::Bmc ;
  pub use kind::KInd ;
  pub use tig::* ;
}

pub use master::Master ;
pub use system::ctxt::Context ;
use system::ctxt::Res as CtxtRes ;

/// Loads a file, creates a context.
pub fn load(path: & str) -> Result< (Context, CtxtRes), String> {
  use std::fs::File ;
  use term::Factory ;
  match File::open(path) {
    Ok(mut file) => {
      let factory = Factory::mk() ;
      let mut context = Context::mk(factory, 1000) ;
      match context.read(& mut file) {
        Ok(res) => Ok( (context, res) ),
        Err(e) => Err(
          format!("error reading file `{}`\n{}", path, e)
        ),
      }
    },
    Err(e) => Err(
      format!("could not open file `{}`\n{}", path, e)
    ),
  }
}

/// Loads a file, creates a context, runs the master.
pub fn analyze(path: & str) -> Result< (Context, Vec<Prop>), String> {
  let (mut context, res) = try!( load(path) ) ;
  match res {
    CtxtRes::Exit => Ok( (context, vec![]) ),
    CtxtRes::Check(sys, props) => {
      let log = ::common::log::MasterLog::default() ;
      let conf = ::common::conf::Master::default() ;
      match Master::launch(
        & log, & mut context, sys, props.clone(), None, conf
      ) {
        Ok(()) => Ok( (context, props) ),
        Err(()) => Err(
          format!("master did not return successfully")
        ),
      }
    },
    CtxtRes::CheckAss(_, _, _) => Err(
      format!("verify assuming is not supported")
    ),
  }
}<commit_msg>Updated top-level lib for tests<commit_after>// Copyright 2015 Adrien Champion. See the COPYRIGHT file at the top-level
// directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(non_upper_case_globals)]
#![deny(missing_docs)]

//! API for the kinō model-checker.

extern crate term ;
extern crate system ;
extern crate unroll ;
#[macro_use]
extern crate common ;
extern crate bmc ;
extern crate kind ;
extern crate twind ;
extern crate tig ;
extern crate pruner ;

mod master ;

pub use term::{ Sym, SymMaker } ;
pub use system::* ;
// pub use unroll::* ;
// pub use common::* ;

/// The techniques provided by kino.
pub mod teks {
  pub use bmc::Bmc ;
  pub use kind::KInd ;
  pub use tig::* ;
}

pub use master::Master ;
pub use system::ctxt::Context ;
use system::ctxt::Res as CtxtRes ;

/// Loads a file, creates a context.
pub fn load(path: & str) -> Result< (Context, CtxtRes), String> {
  use std::fs::File ;
  use term::Factory ;
  match File::open(path) {
    Ok(mut file) => {
      let factory = Factory::mk() ;
      let mut context = Context::mk(factory, 1000) ;
      match context.read(& mut file) {
        Ok(res) => Ok( (context, res) ),
        Err(e) => Err(
          format!("error reading file `{}`\n{}", path, e)
        ),
      }
    },
    Err(e) => Err(
      format!("could not open file `{}`\n{}", path, e)
    ),
  }
}

/// Loads a file, creates a context, runs the master.
pub fn analyze(path: & str) -> Result< (Context, Vec<Prop>), String> {
  let (mut context, res) = try!( load(path) ) ;
  match res {
    CtxtRes::Exit => Ok( (context, vec![]) ),
    CtxtRes::Check(sys, props) => {
      let log = ::common::log::MasterLog::default() ;
      let conf = ::common::conf::Master::default() ;
      match Master::launch(
        & log, & mut context, sys, props.clone(), None, conf
      ) {
        Ok(()) => Ok( (context, props) ),
        Err(()) => Err(
          format!("master did not return successfully")
        ),
      }
    },
    CtxtRes::CheckAss(_, _, _) => Err(
      format!("verify assuming is not supported")
    ),
  }
}<|endoftext|>


<commit_before>//! An SVG composer and parser.
//!
//! ## Example: Composing
//!
//! ```
//! # extern crate svg;
//! use svg::Document;
//! use svg::node::element::Path;
//! use svg::node::element::path::Data;
//!
//! # fn main() {
//! let data = Data::new()
//!                 .move_to((10, 10))
//!                 .line_by((0, 50))
//!                 .line_by((50, 0))
//!                 .line_by((0, -50))
//!                 .close();
//!
//! let path = Path::new()
//!                 .set("fill", "none")
//!                 .set("stroke", "black")
//!                 .set("stroke-width", 3)
//!                 .set("d", data);
//!
//! let document = Document::new()
//!                         .set("viewBox", (0, 0, 70, 70))
//!                         .add(path);
//!
//! svg::save("image.svg", &document).unwrap();
//! # ::std::fs::remove_file("image.svg");
//! # }
//! ```
//!
//! ## Example: Parsing
//!
//! ```
//! # extern crate svg;
//! use svg::node::element::path::{Command, Data};
//! use svg::node::element::tag::Path;
//! use svg::parser::Event;
//!
//! # fn main() {
//! let path = "image.svg";
//! # let path = "tests/fixtures/benton.svg";
//! for event in svg::open(path).unwrap() {
//!     match event {
//!         Event::Tag(Path, _, attributes) => {
//!             let data = attributes.get("d").unwrap();
//!             let data = Data::parse(data).unwrap();
//!             for command in data.iter() {
//!                 match command {
//!                     &Command::Move(..) => println!("Move!"),
//!                     &Command::Line(..) => println!("Line!"),
//!                     _ => {},
//!                 }
//!             }
//!         },
//!         _ => {},
//!     }
//! }
//! # }
//! ```

use std::io;
use std::path::Path;

pub mod node;
pub mod parser;

pub use node::Node;
pub use parser::Parser;

/// A document.
pub type Document = node::element::SVG;

/// Open a document.
pub fn open<'l, T>(path: T) -> io::Result<Parser<'l>> where T: AsRef<Path> {
    use std::fs::File;
    use std::io::Read;

    let mut content = String::new();
    let mut file = try!(File::open(path));
    try!(file.read_to_string(&mut content));
    Ok(Parser::new(content))
}

/// Save a document.
pub fn save<T, U>(path: T, document: &U) -> io::Result<()> where T: AsRef<Path>, U: Node {
    use std::fs::File;
    use std::io::Write;

    let mut file = try!(File::create(path));
    file.write_all(&document.to_string().into_bytes())
}

#[cfg(test)]
mod tests {
    #[test]
    fn open() {
        use parser::Event;

        let mut parser = ::open("tests/fixtures/benton.svg").unwrap();

        macro_rules! test(
            ($matcher:pat) => (match parser.next().unwrap() {
                $matcher => {},
                _ => unreachable!(),
            });
        );

        test!(Event::Instruction);
        test!(Event::Comment);
        test!(Event::Declaration);
        test!(Event::Tag("svg", _, _));
        test!(Event::Tag("path", _, _));
        test!(Event::Tag("path", _, _));
        test!(Event::Tag("path", _, _));
        test!(Event::Tag("path", _, _));
        test!(Event::Tag("svg", _, _));

        assert!(parser.next().is_none());
    }
}
<commit_msg>Added method to load / save from arbitrary target, not only files (#5)<commit_after>//! An SVG composer and parser.
//!
//! ## Example: Composing
//!
//! ```
//! # extern crate svg;
//! use svg::Document;
//! use svg::node::element::Path;
//! use svg::node::element::path::Data;
//!
//! # fn main() {
//! let data = Data::new()
//!                 .move_to((10, 10))
//!                 .line_by((0, 50))
//!                 .line_by((50, 0))
//!                 .line_by((0, -50))
//!                 .close();
//!
//! let path = Path::new()
//!                 .set("fill", "none")
//!                 .set("stroke", "black")
//!                 .set("stroke-width", 3)
//!                 .set("d", data);
//!
//! let document = Document::new()
//!                         .set("viewBox", (0, 0, 70, 70))
//!                         .add(path);
//!
//! svg::save("image.svg", &document).unwrap();
//! # ::std::fs::remove_file("image.svg");
//! # }
//! ```
//!
//! ## Example: Parsing
//!
//! ```
//! # extern crate svg;
//! use std::fs::File;
//! use svg::node::element::path::{Command, Data};
//! use svg::node::element::tag::Path;
//! use svg::parser::Event;
//!
//! # fn main() {
//! let path = "image.svg";
//! # let path = "tests/fixtures/benton.svg";
//! for event in svg::open(path).unwrap() {
//!     match event {
//!         Event::Tag(Path, _, attributes) => {
//!             let data = attributes.get("d").unwrap();
//!             let data = Data::parse(data).unwrap();
//!             for command in data.iter() {
//!                 match command {
//!                     &Command::Move(..) => println!("Move!"),
//!                     &Command::Line(..) => println!("Line!"),
//!                     _ => {},
//!                 }
//!             }
//!         },
//!         _ => {},
//!     }
//! }
//! # }
//! ```

use std::io::{self, Read, Write};
use std::path::Path;

pub mod node;
pub mod parser;

pub use node::Node;
pub use parser::Parser;

/// A document.
pub type Document = node::element::SVG;

/// Open a document.
pub fn open<'l, T>(path: T) -> io::Result<Parser<'l>> where T: AsRef<Path> {
    use std::fs::File;
    let mut file = File::open(path)?;
    read_internal(&mut file)
}

/// Read a document.
pub fn read<'l, T>(source: T) -> io::Result<Parser<'l>> where T: Read {
    read_internal(source)
}

/// Save a document.
pub fn save<T, U>(path: T, document: &U) -> io::Result<()> where T: AsRef<Path>, U: Node {
    use std::fs::File;
    let mut file = File::create(path)?;
    write_internal(&mut file, document)
}

/// Write a document.
pub fn write<T, U>(target: T, document: &U) -> io::Result<()> where T: Write, U: Node {
    write_internal(target, document)
}

#[inline(always)]
fn read_internal<'l, R>(mut source: R) -> io::Result<Parser<'l>> where R: Read {
    let mut content = String::new();
    source.read_to_string(&mut content)?;
    Ok(Parser::new(content))
}

#[inline(always)]
fn write_internal<T, U>(mut target: T, document: &U) -> io::Result<()> where T: Write, U: Node {
    target.write_all(&document.to_string().into_bytes())
}

#[cfg(test)]
mod tests {

    const TEST_PATH: &'static str = "tests/fixtures/benton.svg";

    #[test]
    fn open() {
        use parser::Event;

        let mut parser = ::open(self::TEST_PATH).unwrap();

        macro_rules! test(
            ($matcher:pat) => (match parser.next().unwrap() {
                $matcher => {},
                _ => unreachable!(),
            });
        );

        test!(Event::Instruction);
        test!(Event::Comment);
        test!(Event::Declaration);
        test!(Event::Tag("svg", _, _));
        test!(Event::Tag("path", _, _));
        test!(Event::Tag("path", _, _));
        test!(Event::Tag("path", _, _));
        test!(Event::Tag("path", _, _));
        test!(Event::Tag("svg", _, _));

        assert!(parser.next().is_none());
    }

    #[test]
    fn read() {
        use std::fs::File;
        let _ = ::read(&mut File::open(self::TEST_PATH).unwrap());
    }
}
<|endoftext|>


<commit_before>//! A macro for defining `#[cfg]` if-else statements.
//!
//! The macro provided by this crate, `cfg_if`, is similar to the `if/elif` C
//! preprocessor macro by allowing definition of a cascade of `#[cfg]` cases,
//! emitting the implementation which matches first.
//!
//! This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
//! without having to rewrite each clause multiple times.
//!
//! # Example
//!
//! ```
//! #[macro_use]
//! extern crate cfg_if;
//!
//! cfg_if! {
//!     if #[cfg(unix)] {
//!         fn foo() { /* unix specific functionality */ }
//!     } else if #[cfg(target_pointer_width = "32")] {
//!         fn foo() { /* non-unix, 32-bit functionality */ }
//!     } else {
//!         fn foo() { /* fallback implementation */ }
//!     }
//! }
//!
//! # fn main() {}
//! ```

#![no_std]

#![doc(html_root_url = "https://docs.rs/cfg-if")]
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]

#[macro_export]
macro_rules! cfg_if {
    // match if/else chains with a final `else`
    ($(
        if #[cfg($($meta:meta),*)] { $($it:item)* }
    ) else * else {
        $($it2:item)*
    }) => {
        cfg_if! {
            @__items
            () ;
            $( ( ($($meta),*) ($($it)*) ), )*
            ( () ($($it2)*) ),
        }
    };

    // match if/else chains lacking a final `else`
    (
        if #[cfg($($i_met:meta),*)] { $($i_it:item)* }
        $(
            else if #[cfg($($e_met:meta),*)] { $($e_it:item)* }
        )*
    ) => {
        cfg_if! {
            @__items
            () ;
            ( ($($i_met),*) ($($i_it)*) ),
            $( ( ($($e_met),*) ($($e_it)*) ), )*
            ( () () ),
        }
    };

    // Internal and recursive macro to emit all the items
    //
    // Collects all the negated cfgs in a list at the beginning and after the
    // semicolon is all the remaining items
    (@__items ($($not:meta,)*) ; ) => {};
    (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
        // Emit all items within one block, applying an approprate #[cfg]. The
        // #[cfg] will require all `$m` matchers specified and must also negate
        // all previous matchers.
        cfg_if! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* }

        // Recurse to emit all other items in `$rest`, and when we do so add all
        // our `$m` matchers to the list of `$not` matchers as future emissions
        // will have to negate everything we just matched as well.
        cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* }
    };

    // Internal macro to Apply a cfg attribute to a list of items
    (@__apply $m:meta, $($it:item)*) => {
        $(#[$m] $it)*
    };
}

#[cfg(test)]
mod tests {
    cfg_if! {
        if #[cfg(test)] {
            use core::option::Option as Option2;
            fn works1() -> Option2<u32> { Some(1) }
        } else {
            fn works1() -> Option<u32> { None }
        }
    }

    cfg_if! {
        if #[cfg(foo)] {
            fn works2() -> bool { false }
        } else if #[cfg(test)] {
            fn works2() -> bool { true }
        } else {
            fn works2() -> bool { false }
        }
    }

    cfg_if! {
        if #[cfg(foo)] {
            fn works3() -> bool { false }
        } else {
            fn works3() -> bool { true }
        }
    }

    cfg_if! {
        if #[cfg(test)] {
            use core::option::Option as Option3;
            fn works4() -> Option3<u32> { Some(1) }
        }
    }

    cfg_if! {
        if #[cfg(foo)] {
            fn works5() -> bool { false }
        } else if #[cfg(test)] {
            fn works5() -> bool { true }
        }
    }

    #[test]
    fn it_works() {
        assert!(works1().is_some());
        assert!(works2());
        assert!(works3());
        assert!(works4().is_some());
        assert!(works5());
    }
}
<commit_msg>Add local_inner_macros attribute<commit_after>//! A macro for defining `#[cfg]` if-else statements.
//!
//! The macro provided by this crate, `cfg_if`, is similar to the `if/elif` C
//! preprocessor macro by allowing definition of a cascade of `#[cfg]` cases,
//! emitting the implementation which matches first.
//!
//! This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
//! without having to rewrite each clause multiple times.
//!
//! # Example
//!
//! ```
//! #[macro_use]
//! extern crate cfg_if;
//!
//! cfg_if! {
//!     if #[cfg(unix)] {
//!         fn foo() { /* unix specific functionality */ }
//!     } else if #[cfg(target_pointer_width = "32")] {
//!         fn foo() { /* non-unix, 32-bit functionality */ }
//!     } else {
//!         fn foo() { /* fallback implementation */ }
//!     }
//! }
//!
//! # fn main() {}
//! ```

#![no_std]

#![doc(html_root_url = "https://docs.rs/cfg-if")]
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]

#[macro_export(local_inner_macros)]
macro_rules! cfg_if {
    // match if/else chains with a final `else`
    ($(
        if #[cfg($($meta:meta),*)] { $($it:item)* }
    ) else * else {
        $($it2:item)*
    }) => {
        cfg_if! {
            @__items
            () ;
            $( ( ($($meta),*) ($($it)*) ), )*
            ( () ($($it2)*) ),
        }
    };

    // match if/else chains lacking a final `else`
    (
        if #[cfg($($i_met:meta),*)] { $($i_it:item)* }
        $(
            else if #[cfg($($e_met:meta),*)] { $($e_it:item)* }
        )*
    ) => {
        cfg_if! {
            @__items
            () ;
            ( ($($i_met),*) ($($i_it)*) ),
            $( ( ($($e_met),*) ($($e_it)*) ), )*
            ( () () ),
        }
    };

    // Internal and recursive macro to emit all the items
    //
    // Collects all the negated cfgs in a list at the beginning and after the
    // semicolon is all the remaining items
    (@__items ($($not:meta,)*) ; ) => {};
    (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
        // Emit all items within one block, applying an approprate #[cfg]. The
        // #[cfg] will require all `$m` matchers specified and must also negate
        // all previous matchers.
        cfg_if! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* }

        // Recurse to emit all other items in `$rest`, and when we do so add all
        // our `$m` matchers to the list of `$not` matchers as future emissions
        // will have to negate everything we just matched as well.
        cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* }
    };

    // Internal macro to Apply a cfg attribute to a list of items
    (@__apply $m:meta, $($it:item)*) => {
        $(#[$m] $it)*
    };
}

#[cfg(test)]
mod tests {
    cfg_if! {
        if #[cfg(test)] {
            use core::option::Option as Option2;
            fn works1() -> Option2<u32> { Some(1) }
        } else {
            fn works1() -> Option<u32> { None }
        }
    }

    cfg_if! {
        if #[cfg(foo)] {
            fn works2() -> bool { false }
        } else if #[cfg(test)] {
            fn works2() -> bool { true }
        } else {
            fn works2() -> bool { false }
        }
    }

    cfg_if! {
        if #[cfg(foo)] {
            fn works3() -> bool { false }
        } else {
            fn works3() -> bool { true }
        }
    }

    cfg_if! {
        if #[cfg(test)] {
            use core::option::Option as Option3;
            fn works4() -> Option3<u32> { Some(1) }
        }
    }

    cfg_if! {
        if #[cfg(foo)] {
            fn works5() -> bool { false }
        } else if #[cfg(test)] {
            fn works5() -> bool { true }
        }
    }

    #[test]
    fn it_works() {
        assert!(works1().is_some());
        assert!(works2());
        assert!(works3());
        assert!(works4().is_some());
        assert!(works5());
    }
}
<|endoftext|>


<commit_before>#![feature(std_misc)]
use std::sync::Semaphore;
use std::thread;

pub struct ThreadPool {
    sem: std::sync::Semaphore,
}

impl ThreadPool {
    pub fn new(size: isize) -> ThreadPool {
       ThreadPool { sem: std::sync::Semaphore::new(size) }
    }

    pub fn spawn<'a, T, F>(&'a self, func: F) -> std::thread::JoinGuard<'a, T>
        where T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
    {
       let guard = self.sem.access();
       thread::scoped(move || {
           let _guard = guard;
           func()
       })
    }
}

#[test]
fn it_works() {
    let pool = ThreadPool::new(2);
    pool.spawn(move || {
        std::thread::sleep_ms(1000);
        println!("Done!");
    });

    pool.spawn(move || {
        std::thread::sleep_ms(1000);
        println!("Done!");
    });

    pool.spawn(move || {
        std::thread::sleep_ms(1000);
        println!("Done!");
    })
}
<commit_msg>fix(spawn->scoped) rename pool method to reflect thread type used<commit_after>#![feature(std_misc)]
use std::sync::Semaphore;
use std::thread;

pub struct ThreadPool {
    sem: std::sync::Semaphore,
}

impl ThreadPool {
    pub fn new(size: isize) -> ThreadPool {
       ThreadPool { sem: std::sync::Semaphore::new(size) }
    }

    pub fn scoped<'a, T, F>(&'a self, func: F) -> std::thread::JoinGuard<'a, T>
        where T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
    {
       let guard = self.sem.access();
       thread::scoped(move || {
           let _guard = guard;
           func()
       })
    }
}

#[test]
fn it_works() {
    let pool = ThreadPool::new(2);
    pool.spawn(move || {
        std::thread::sleep_ms(1000);
        println!("Done!");
    });

    pool.spawn(move || {
        std::thread::sleep_ms(1000);
        println!("Done!");
    });

    pool.spawn(move || {
        std::thread::sleep_ms(1000);
        println!("Done!");
    })
}
<|endoftext|>