<commit_before>// Copyright 2015 Drew Short <drew@sothr.com>.
//
// 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.

#![feature(core)] //Required to compile 3/31/2015. Test again later when libs have stablized.
#![feature(step_by)] //Required to compile 5/11/2015. Test again later. This is used to step over a range.

extern crate num;

pub mod str_util;
pub mod prime_util;
pub mod number_util;

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

    #[test]
    fn test_string_for_vector() {
        let vec = vec![1, 2];
        assert_eq!("1,2", str_util::string_for_vector(vec));
    }

    #[test]
    fn test_example() {
        assert_eq!("test", "test");
    }

    #[test]
    fn test_list_of_primes() {
        let limit = 2_000_000u64;
        let mut primes = Vec::new();
        for i in 2..limit {
            if prime_util::is_prime(i) {
                primes.push(i);
            }
        }

        //now check that the function returns the same list as the brute force algorithm
        let supposed_primes = prime_util::list_of_primes(limit).expect("Not enough primes?!?!");

        // make sure all values are indeed prime
        for prime in supposed_primes.iter() {
            assert_eq!((true,prime), (prime_util::is_prime(*prime),prime));
        }

        // if the sets aren't the same size, check what are missing from the sieve
        // The order should be identical
        if primes.len() > supposed_primes.len() {
            for i in 0..primes.len() {
                assert_eq!(primes[i], supposed_primes[i]);
            }
        }

        assert_eq!(primes.len(), supposed_primes.len());
    }
}
<commit_msg>Fixing for nightly build<commit_after>// Copyright 2015 Drew Short <drew@sothr.com>.
//
// 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.

#![feature(step_by)] //Required to compile 5/11/2015. Test again later. This is used to step over a range.
#![feature(iter_order)] //Required to compile 7/8/2015

extern crate num;

pub mod str_util;
pub mod prime_util;
pub mod number_util;

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

    #[test]
    fn test_string_for_vector() {
        let vec = vec![1, 2];
        assert_eq!("1,2", str_util::string_for_vector(vec));
    }

    #[test]
    fn test_example() {
        assert_eq!("test", "test");
    }

    #[test]
    fn test_list_of_primes() {
        let limit = 2_000_000u64;
        let mut primes = Vec::new();
        for i in 2..limit {
            if prime_util::is_prime(i) {
                primes.push(i);
            }
        }

        //now check that the function returns the same list as the brute force algorithm
        let supposed_primes = prime_util::list_of_primes(limit).expect("Not enough primes?!?!");

        // make sure all values are indeed prime
        for prime in supposed_primes.iter() {
            assert_eq!((true,prime), (prime_util::is_prime(*prime),prime));
        }

        // if the sets aren't the same size, check what are missing from the sieve
        // The order should be identical
        if primes.len() > supposed_primes.len() {
            for i in 0..primes.len() {
                assert_eq!(primes[i], supposed_primes[i]);
            }
        }

        assert_eq!(primes.len(), supposed_primes.len());
    }
}
<|endoftext|>


<commit_before>//! A library providing a generic connection pool.
#![feature(unsafe_destructor, phase)]
#![warn(missing_doc)]
#![doc(html_root_url="http://www.rust-ci.org/sfackler/r2d2/doc")]

#[phase(plugin, link)]
extern crate log;
extern crate serialize;

use std::comm;
use std::collections::{Deque, RingBuf};
use std::sync::{Arc, Mutex};
use std::fmt;

pub use config::Config;

mod config;

/// A trait which provides database-specific functionality.
pub trait PoolManager<C, E>: Send+Sync {
    /// Attempts to create a new connection.
    fn connect(&self) -> Result<C, E>;

    /// Determines if the connection is still connected to the database.
    ///
    /// A standard implementation would check if a simple query like `SELECT 1`
    /// succeeds.
    fn is_valid(&self, conn: &C) -> bool;
}

/// A trait which handles errors reported by the `PoolManager`.
pub trait ErrorHandler<E>: Send+Sync {
    /// Handles a connection error.
    fn handle_error(&self, error: E);
}

/// An `ErrorHandler` which does nothing.
pub struct NoopErrorHandler;

impl<E> ErrorHandler<E> for NoopErrorHandler {
    fn handle_error(&self, _: E) {}
}

/// An `ErrorHandler` which logs at the error level.
pub struct LoggingErrorHandler;

impl<E> ErrorHandler<E> for LoggingErrorHandler where E: fmt::Show {
    fn handle_error(&self, error: E) {
        error!("Error opening connection: {}", error);
    }
}

/// An error type returned if pool creation fails.
#[deriving(PartialEq, Eq)]
pub enum NewPoolError<E> {
    /// The provided pool configuration was invalid.
    InvalidConfig(&'static str),
    /// The manager returned an error when creating a connection.
    ConnectionError(E),
}

impl<E> fmt::Show for NewPoolError<E> where E: fmt::Show {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InvalidConfig(ref error) => write!(f, "Invalid config: {}", error),
            ConnectionError(ref error) => write!(f, "Unable to create connections: {}", error),
        }
    }
}

enum Command<C> {
    AddConnection,
    TestConnection(C),
}

struct PoolInternals<C, E> {
    conns: RingBuf<C>,
    num_conns: uint,
}

struct InnerPool<C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    config: Config,
    manager: M,
    error_handler: H,
    internals: Mutex<PoolInternals<C, E>>,
}

/// A generic connection pool.
pub struct Pool<C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    helper_chan: Mutex<Sender<Command<C>>>,
    inner: Arc<InnerPool<C, E, M, H>>
}

impl<C, E, M, H> Pool<C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    /// Creates a new connection pool.
    pub fn new(config: Config, manager: M, error_handler: H)
               -> Result<Pool<C, E, M, H>, NewPoolError<E>> {
        match config.validate() {
            Ok(()) => {}
            Err(err) => return Err(InvalidConfig(err))
        }

        let mut internals = PoolInternals {
            conns: RingBuf::new(),
            num_conns: config.pool_size,
        };

        for _ in range(0, config.pool_size) {
            match manager.connect() {
                Ok(conn) => internals.conns.push(conn),
                Err(err) => return Err(ConnectionError(err)),
            }
        }

        let inner = Arc::new(InnerPool {
            config: config,
            manager: manager,
            error_handler: error_handler,
            internals: Mutex::new(internals),
        });

        let (sender, receiver) = comm::channel();
        // FIXME :(
        let receiver = Arc::new(Mutex::new(receiver));

        for _ in range(0, config.helper_tasks) {
            let inner = inner.clone();
            let receiver = receiver.clone();
            spawn(proc() helper_task(receiver, inner));
        }

        Ok(Pool {
            helper_chan: Mutex::new(sender),
            inner: inner,
        })
    }

    /// Retrieves a connection from the pool.
    pub fn get<'a>(&'a self) -> Result<PooledConnection<'a, C, E, M, H>, E> {
        let mut internals = self.inner.internals.lock();

        loop {
            match internals.conns.pop_front() {
                Some(conn) => {
                    if self.inner.config.test_on_check_out {
                        drop(internals);
                        let valid = self.inner.manager.is_valid(&conn);

                        if !valid {
                            internals = self.inner.internals.lock();
                            internals.num_conns -= 1;
                            continue;
                        }
                    }

                    return Ok(PooledConnection {
                        pool: self,
                        conn: Some(conn),
                    })
                }
                None => internals.cond.wait(),
            }
        }
    }

    fn put_back(&self, conn: C) {
        let mut internals = self.inner.internals.lock();
        internals.conns.push(conn);
        internals.cond.signal();
    }
}

fn helper_task<C, E, M, H>(receiver: Arc<Mutex<Receiver<Command<C>>>>,
                           inner: Arc<InnerPool<C, E, M, H>>)
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    loop {
        let mut receiver = receiver.lock();
        let res = receiver.recv_opt();
        drop(receiver);

        match res {
            Ok(AddConnection) => add_connection(&*inner),
            Ok(TestConnection(conn)) => test_connection(&*inner, conn),
            Err(()) => break,
        }
    }
}

fn add_connection<C, E, M, H>(inner: &InnerPool<C, E, M, H>)
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    match inner.manager.connect() {
        Ok(conn) => {
            let mut internals = inner.internals.lock();
            internals.conns.push(conn);
            internals.num_conns += 1;
            internals.cond.signal();
        }
        Err(err) => inner.error_handler.handle_error(err),
    }
}

fn test_connection<C, E, M, H>(inner: &InnerPool<C, E, M, H>, conn: C)
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    let is_valid = inner.manager.is_valid(&conn);
    let mut internals = inner.internals.lock();
    if is_valid {
        internals.conns.push(conn);
    } else {
        internals.num_conns -= 1;
    }
}

/// A smart pointer wrapping an underlying connection.
pub struct PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    pool: &'a Pool<C, E, M, H>,
    conn: Option<C>,
}

#[unsafe_destructor]
impl<'a, C, E, M, H> Drop for PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    fn drop(&mut self) {
        self.pool.put_back(self.conn.take().unwrap());
    }
}

impl<'a, C, E, M, H> Deref<C> for PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    fn deref(&self) -> &C {
        self.conn.as_ref().unwrap()
    }
}
<commit_msg>Tiny cleanup<commit_after>//! A library providing a generic connection pool.
#![feature(unsafe_destructor, phase)]
#![warn(missing_doc)]
#![doc(html_root_url="http://www.rust-ci.org/sfackler/r2d2/doc")]

#[phase(plugin, link)]
extern crate log;
extern crate serialize;

use std::comm;
use std::collections::{Deque, RingBuf};
use std::sync::{Arc, Mutex};
use std::fmt;

pub use config::Config;

mod config;

/// A trait which provides database-specific functionality.
pub trait PoolManager<C, E>: Send+Sync {
    /// Attempts to create a new connection.
    fn connect(&self) -> Result<C, E>;

    /// Determines if the connection is still connected to the database.
    ///
    /// A standard implementation would check if a simple query like `SELECT 1`
    /// succeeds.
    fn is_valid(&self, conn: &C) -> bool;
}

/// A trait which handles errors reported by the `PoolManager`.
pub trait ErrorHandler<E>: Send+Sync {
    /// Handles a connection error.
    fn handle_error(&self, error: E);
}

/// An `ErrorHandler` which does nothing.
pub struct NoopErrorHandler;

impl<E> ErrorHandler<E> for NoopErrorHandler {
    fn handle_error(&self, _: E) {}
}

/// An `ErrorHandler` which logs at the error level.
pub struct LoggingErrorHandler;

impl<E> ErrorHandler<E> for LoggingErrorHandler where E: fmt::Show {
    fn handle_error(&self, error: E) {
        error!("Error opening connection: {}", error);
    }
}

/// An error type returned if pool creation fails.
#[deriving(PartialEq, Eq)]
pub enum NewPoolError<E> {
    /// The provided pool configuration was invalid.
    InvalidConfig(&'static str),
    /// The manager returned an error when creating a connection.
    ConnectionError(E),
}

impl<E> fmt::Show for NewPoolError<E> where E: fmt::Show {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InvalidConfig(ref error) => write!(f, "Invalid config: {}", error),
            ConnectionError(ref error) => write!(f, "Unable to create connections: {}", error),
        }
    }
}

enum Command<C> {
    AddConnection,
    TestConnection(C),
}

struct PoolInternals<C, E> {
    conns: RingBuf<C>,
    num_conns: uint,
}

struct InnerPool<C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    config: Config,
    manager: M,
    error_handler: H,
    internals: Mutex<PoolInternals<C, E>>,
}

/// A generic connection pool.
pub struct Pool<C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    helper_chan: Mutex<Sender<Command<C>>>,
    inner: Arc<InnerPool<C, E, M, H>>
}

impl<C, E, M, H> Pool<C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    /// Creates a new connection pool.
    pub fn new(config: Config, manager: M, error_handler: H)
               -> Result<Pool<C, E, M, H>, NewPoolError<E>> {
        try!(config.validate().map_err(InvalidConfig));

        let mut internals = PoolInternals {
            conns: RingBuf::new(),
            num_conns: config.pool_size,
        };

        for _ in range(0, config.pool_size) {
            match manager.connect() {
                Ok(conn) => internals.conns.push(conn),
                Err(err) => return Err(ConnectionError(err)),
            }
        }

        let inner = Arc::new(InnerPool {
            config: config,
            manager: manager,
            error_handler: error_handler,
            internals: Mutex::new(internals),
        });

        let (sender, receiver) = comm::channel();
        // FIXME :(
        let receiver = Arc::new(Mutex::new(receiver));

        for _ in range(0, config.helper_tasks) {
            let inner = inner.clone();
            let receiver = receiver.clone();
            spawn(proc() helper_task(receiver, inner));
        }

        Ok(Pool {
            helper_chan: Mutex::new(sender),
            inner: inner,
        })
    }

    /// Retrieves a connection from the pool.
    pub fn get<'a>(&'a self) -> Result<PooledConnection<'a, C, E, M, H>, E> {
        let mut internals = self.inner.internals.lock();

        loop {
            match internals.conns.pop_front() {
                Some(conn) => {
                    if self.inner.config.test_on_check_out {
                        drop(internals);
                        let valid = self.inner.manager.is_valid(&conn);

                        if !valid {
                            internals = self.inner.internals.lock();
                            internals.num_conns -= 1;
                            continue;
                        }
                    }

                    return Ok(PooledConnection {
                        pool: self,
                        conn: Some(conn),
                    })
                }
                None => internals.cond.wait(),
            }
        }
    }

    fn put_back(&self, conn: C) {
        let mut internals = self.inner.internals.lock();
        internals.conns.push(conn);
        internals.cond.signal();
    }
}

fn helper_task<C, E, M, H>(receiver: Arc<Mutex<Receiver<Command<C>>>>,
                           inner: Arc<InnerPool<C, E, M, H>>)
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    loop {
        let mut receiver = receiver.lock();
        let res = receiver.recv_opt();
        drop(receiver);

        match res {
            Ok(AddConnection) => add_connection(&*inner),
            Ok(TestConnection(conn)) => test_connection(&*inner, conn),
            Err(()) => break,
        }
    }
}

fn add_connection<C, E, M, H>(inner: &InnerPool<C, E, M, H>)
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    match inner.manager.connect() {
        Ok(conn) => {
            let mut internals = inner.internals.lock();
            internals.conns.push(conn);
            internals.num_conns += 1;
            internals.cond.signal();
        }
        Err(err) => inner.error_handler.handle_error(err),
    }
}

fn test_connection<C, E, M, H>(inner: &InnerPool<C, E, M, H>, conn: C)
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    let is_valid = inner.manager.is_valid(&conn);
    let mut internals = inner.internals.lock();
    if is_valid {
        internals.conns.push(conn);
    } else {
        internals.num_conns -= 1;
    }
}

/// A smart pointer wrapping an underlying connection.
pub struct PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    pool: &'a Pool<C, E, M, H>,
    conn: Option<C>,
}

#[unsafe_destructor]
impl<'a, C, E, M, H> Drop for PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    fn drop(&mut self) {
        self.pool.put_back(self.conn.take().unwrap());
    }
}

impl<'a, C, E, M, H> Deref<C> for PooledConnection<'a, C, E, M, H>
        where C: Send, E: Send, M: PoolManager<C, E>, H: ErrorHandler<E> {
    fn deref(&self) -> &C {
        self.conn.as_ref().unwrap()
    }
}
<|endoftext|>


<commit_before>#![doc(html_logo_url = "https://avatars0.githubusercontent.com/u/7853871?s=128", html_favicon_url = "https://avatars0.githubusercontent.com/u/7853871?s=256", html_root_url = "http://ironframework.io/core/iron")]
#![crate_name = "iron"]
#![comment = "Rapid Web Development in Rust"]
#![license = "MIT"]

#![deny(missing_doc)]
#![deny(warnings)]

#![feature(macro_rules, phase, globs, unboxed_closures, slicing_syntax)]
//! The main crate for the Iron library.
//!
//! Iron is a high level web framework built in and for Rust.
//!
//! Iron provides a robust and efficient framework
//! for creating and plugging in middleware.
//!
//! Obligatory Hello World:
//!
//! ```ignore
//! fn hello_world(req: &mut Request) -> IronResult<Response> {
//!   Response::with(status::Ok, "Hello World!")
//! }
//!
//! Iron::new(hello_world).listen(Ipv4Addr(127, 0, 0, 1), 3000);
//! ```

// Stdlib dependencies
#[phase(plugin, link)] extern crate log;
#[cfg(test)] extern crate test;
extern crate serialize;

// Third party packages
extern crate content_type;
extern crate http;
extern crate "typemap" as tmap;
extern crate plugin;
extern crate error;
extern crate "url" as rust_url;
extern crate "replace-map" as rmap;

// Request + Response
pub use request::{Request, Url};
pub use response::Response;

// Middleware system
pub use middleware::{BeforeMiddleware, AfterMiddleware, AroundMiddleware,
                     Handler, Chain, ChainBuilder};

// Server
pub use iron::Iron;

// Extensions
pub use typemap::TypeMap;

// Status codes and Methods.
pub use http::status;
pub use http::method;

// Headers
pub use http::headers;

// Expose `GetCached` as `Plugin` so users can do `use iron::Plugin`.
pub use plugin::GetCached as Plugin;

// Errors
pub use error::{Error, ErrorRefExt};

// Return type of many methods
pub type IronError = Box<Error>;
pub type IronResult<T> = Result<T, IronError>;

/// Re-exports from the TypeMap crate.
pub mod typemap {
    pub use tmap::{TypeMap, Assoc};
}

// Publicized to show the documentation
pub mod middleware;

// Common Errors
pub mod errors;

// Internal modules
mod request;
mod response;
mod iron;

<commit_msg>(fix) Remove deprecated missing_doc.<commit_after>#![doc(html_logo_url = "https://avatars0.githubusercontent.com/u/7853871?s=128", html_favicon_url = "https://avatars0.githubusercontent.com/u/7853871?s=256", html_root_url = "http://ironframework.io/core/iron")]
#![crate_name = "iron"]
#![comment = "Rapid Web Development in Rust"]
#![license = "MIT"]

#![deny(missing_docs)]
#![deny(warnings)]

#![feature(macro_rules, phase, globs, unboxed_closures, slicing_syntax)]
//! The main crate for the Iron library.
//!
//! Iron is a high level web framework built in and for Rust.
//!
//! Iron provides a robust and efficient framework
//! for creating and plugging in middleware.
//!
//! Obligatory Hello World:
//!
//! ```ignore
//! fn hello_world(req: &mut Request) -> IronResult<Response> {
//!   Response::with(status::Ok, "Hello World!")
//! }
//!
//! Iron::new(hello_world).listen(Ipv4Addr(127, 0, 0, 1), 3000);
//! ```

// Stdlib dependencies
#[phase(plugin, link)] extern crate log;
#[cfg(test)] extern crate test;
extern crate serialize;

// Third party packages
extern crate content_type;
extern crate http;
extern crate "typemap" as tmap;
extern crate plugin;
extern crate error;
extern crate "url" as rust_url;
extern crate "replace-map" as rmap;

// Request + Response
pub use request::{Request, Url};
pub use response::Response;

// Middleware system
pub use middleware::{BeforeMiddleware, AfterMiddleware, AroundMiddleware,
                     Handler, Chain, ChainBuilder};

// Server
pub use iron::Iron;

// Extensions
pub use typemap::TypeMap;

// Status codes and Methods.
pub use http::status;
pub use http::method;

// Headers
pub use http::headers;

// Expose `GetCached` as `Plugin` so users can do `use iron::Plugin`.
pub use plugin::GetCached as Plugin;

// Errors
pub use error::{Error, ErrorRefExt};

// Return type of many methods
pub type IronError = Box<Error>;
pub type IronResult<T> = Result<T, IronError>;

/// Re-exports from the TypeMap crate.
pub mod typemap {
    pub use tmap::{TypeMap, Assoc};
}

// Publicized to show the documentation
pub mod middleware;

// Common Errors
pub mod errors;

// Internal modules
mod request;
mod response;
mod iron;

<|endoftext|>


<commit_before>#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]

//! A set of middleware for sharing data between requests in the Iron
//! framework.

extern crate iron;
extern crate plugin;

use iron::{Request, Response, BeforeMiddleware, AfterMiddleware, IronResult};
use iron::typemap::Key;
use std::sync::{Arc, RwLock, Mutex};
use std::fmt;
use std::error::Error;
use plugin::Plugin;

/// The type that can be returned by `eval` to indicate error.
#[derive(Clone, Debug)]
pub enum PersistentError {
    /// The value was not found.
    NotFound
}

impl Error for PersistentError {
    fn description(&self) -> &str {
        match *self {
            PersistentError::NotFound => "Value not found in extensions."
        }
    }
}

impl fmt::Display for PersistentError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.description().fmt(f)
    }
}

/// Middleware for data that persists between requests with read and write capabilities.
///
/// The data is stored behind a `RwLock`, so multiple read locks
/// can be taken out concurrently.
///
/// If most threads need to take out a write lock, you may want to
/// consider `Write`, which stores the data behind a `Mutex`, which
/// has a faster locking speed.
///
/// `State` can be linked as `BeforeMiddleware` to add data to the `Request`
/// extensions and it can be linked as an `AfterMiddleware` to add data to
/// the `Response` extensions.
///
/// `State` also implements `Plugin`, so the data stored within can be
/// accessed through `request.get::<State<P>>()` as an `Arc<RwLock<P::Value>>`.
pub struct State<P: Key> {
    data: Arc<RwLock<P::Value>>
}

/// Middleware for data that persists between Requests with read-only capabilities.
///
/// The data is stored behind an Arc, so multiple threads can have
/// concurrent, non-blocking access.
///
/// `Read` can be linked as `BeforeMiddleware` to add data to the `Request`
/// extensions and it can be linked as an `AfterMiddleware` to add data to
/// the `Response` extensions.
///
/// `Read` also implements `Plugin`, so the data stored within can be
/// accessed through `request.get::<Read<P>>()` as an `Arc<P::Value>`.
pub struct Read<P: Key> {
    data: Arc<P::Value>
}

/// Middleware for data that persists between Requests for data which mostly
/// needs to be written instead of read.
///
/// The data is stored behind a `Mutex`, so only one request at a time can
/// access the data. This is more performant than `State` in the case where
/// most uses of the data require a write lock.
///
/// `Write` can be linked as `BeforeMiddleware` to add data to the `Request`
/// extensions and it can be linked as an `AfterMiddleware` to add data to
/// the `Response` extensions.
///
/// `Write` also implements `Plugin`, so the data stored within can be
/// accessed through `request.get::<Write<P>>()` as an `Arc<Mutex<P::Value>>`.
pub struct Write<P: Key> {
    data: Arc<Mutex<P::Value>>
}

macro_rules! impl_persistent {
    ($name:ty, $out:ty, $param:ident) => {
    }
}

impl<P: Key> Clone for Read<P> where P::Value: Send + Sync {
    fn clone(&self) -> Read<P> {
        Read { data: self.data.clone() }
    }
}

impl<P: Key> Clone for State<P> where P::Value: Send + Sync {
    fn clone(&self) -> State<P> {
        State { data: self.data.clone() }
    }
}

impl<P: Key> Clone for Write<P> where P::Value: Send {
    fn clone(&self) -> Write<P> {
        Write { data: self.data.clone() }
    }
}

impl<P: Key> From<Arc<P::Value>> for Read<P> {
    fn from(data: Arc<P::Value>) -> Read<P> {
        Read { data: data }
    }
}

impl<P: Key> From<Arc<RwLock<P::Value>>> for State<P> {
    fn from(data: Arc<RwLock<P::Value>>) -> State<P> {
        State { data: data }
    }
}

impl<P: Key> From<Arc<Mutex<P::Value>>> for Write<P> {
    fn from(data: Arc<Mutex<P::Value>>) -> Write<P> {
        Write { data: data }
    }
}

impl<P: Key> Key for State<P> where P::Value: 'static {
    type Value = Arc<RwLock<P::Value>>;
}

impl<P: Key> Key for Read<P> where P::Value: 'static {
    type Value = Arc<P::Value>;
}

impl<P: Key> Key for Write<P> where P::Value: 'static {
    type Value = Arc<Mutex<P::Value>>;
}

impl<'a, 'b, P: Key> Plugin<Request<'a, 'b>> for State<P> where P::Value: Send + Sync {
    type Error = PersistentError;
    fn eval(req: &mut Request<'a, 'b>) -> Result<Arc<RwLock<P::Value>>, PersistentError> {
        req.extensions.get::<State<P>>().cloned().ok_or(PersistentError::NotFound)
    }
}

impl<'a, 'b, P: Key> Plugin<Request<'a, 'b>> for Read<P> where P::Value: Send + Sync {
    type Error = PersistentError;
    fn eval(req: &mut Request<'a, 'b>) -> Result<Arc<P::Value>, PersistentError> {
        req.extensions.get::<Read<P>>().cloned().ok_or(PersistentError::NotFound)
    }
}

impl<'a, 'b, P: Key> Plugin<Request<'a, 'b>> for Write<P> where P::Value: Send {
    type Error = PersistentError;
    fn eval(req: &mut Request<'a, 'b>) -> Result<Arc<Mutex<P::Value>>, PersistentError> {
        req.extensions.get::<Write<P>>().cloned().ok_or(PersistentError::NotFound)
    }
}

impl<P: Key> BeforeMiddleware for State<P> where P::Value: Send + Sync {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions.insert::<State<P>>(self.data.clone());
        Ok(())
    }
}

impl<P: Key> BeforeMiddleware for Read<P> where P::Value: Send + Sync {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions.insert::<Read<P>>(self.data.clone());
        Ok(())
    }
}

impl<P: Key> BeforeMiddleware for Write<P> where P::Value: Send {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions.insert::<Write<P>>(self.data.clone());
        Ok(())
    }
}

impl<P: Key> AfterMiddleware for State<P> where P::Value: Send + Sync {
    fn after(&self, _: &mut Request, mut res: Response) -> IronResult<Response> {
        res.extensions.insert::<State<P>>(self.data.clone());
        Ok(res)
    }
}

impl<P: Key> AfterMiddleware for Read<P> where P::Value: Send + Sync {
    fn after(&self, _: &mut Request, mut res: Response) -> IronResult<Response> {
        res.extensions.insert::<Read<P>>(self.data.clone());
        Ok(res)
    }
}

impl<P: Key> AfterMiddleware for Write<P> where P::Value: Send {
    fn after(&self, _: &mut Request, mut res: Response) -> IronResult<Response> {
        res.extensions.insert::<Write<P>>(self.data.clone());
        Ok(res)
    }
}

impl<P: Key> State<P> where P::Value: Send + Sync {
    /// Construct a new pair of `State` that can be passed directly to `Chain::link`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn both(start: P::Value) -> (State<P>, State<P>) {
        let x = State { data: Arc::new(RwLock::new(start)) };
        (x.clone(), x)
    }

    /// Construct a new `State` that can be passed directly to
    /// `Chain::link_before` or `Chain::link_after`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn one(start: P::Value) -> State<P> {
        State { data: Arc::new(RwLock::new(start)) }
    }
}

impl<P: Key> Read<P> where P::Value: Send + Sync {
    /// Construct a new pair of `Read` that can be passed directly to `Chain::link`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn both(start: P::Value) -> (Read<P>, Read<P>) {
        let x = Read { data: Arc::new(start) };
        (x.clone(), x)
    }

    /// Construct a new `Read` that can be passed directly to
    /// `Chain::link_before` or `Chain::link_after`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn one(start: P::Value) -> Read<P> {
        Read { data: Arc::new(start) }
    }
}

impl<P: Key> Write<P> where P::Value: Send {
    /// Construct a new pair of `Write` that can be passed directly to `Chain::link`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn both(start: P::Value) -> (Write<P>, Write<P>) {
        let x = Write { data: Arc::new(Mutex::new(start)) };
        (x.clone(), x)
    }

    /// Construct a new `Write` that can be passed directly to
    /// `Chain::link_before` or `Chain::link_after`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn one(start: P::Value) -> Write<P> {
        Write { data: Arc::new(Mutex::new(start)) }
    }
}
<commit_msg>Removed unused macro<commit_after>#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]

//! A set of middleware for sharing data between requests in the Iron
//! framework.

extern crate iron;
extern crate plugin;

use iron::{Request, Response, BeforeMiddleware, AfterMiddleware, IronResult};
use iron::typemap::Key;
use std::sync::{Arc, RwLock, Mutex};
use std::fmt;
use std::error::Error;
use plugin::Plugin;

/// The type that can be returned by `eval` to indicate error.
#[derive(Clone, Debug)]
pub enum PersistentError {
    /// The value was not found.
    NotFound
}

impl Error for PersistentError {
    fn description(&self) -> &str {
        match *self {
            PersistentError::NotFound => "Value not found in extensions."
        }
    }
}

impl fmt::Display for PersistentError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.description().fmt(f)
    }
}

/// Middleware for data that persists between requests with read and write capabilities.
///
/// The data is stored behind a `RwLock`, so multiple read locks
/// can be taken out concurrently.
///
/// If most threads need to take out a write lock, you may want to
/// consider `Write`, which stores the data behind a `Mutex`, which
/// has a faster locking speed.
///
/// `State` can be linked as `BeforeMiddleware` to add data to the `Request`
/// extensions and it can be linked as an `AfterMiddleware` to add data to
/// the `Response` extensions.
///
/// `State` also implements `Plugin`, so the data stored within can be
/// accessed through `request.get::<State<P>>()` as an `Arc<RwLock<P::Value>>`.
pub struct State<P: Key> {
    data: Arc<RwLock<P::Value>>
}

/// Middleware for data that persists between Requests with read-only capabilities.
///
/// The data is stored behind an Arc, so multiple threads can have
/// concurrent, non-blocking access.
///
/// `Read` can be linked as `BeforeMiddleware` to add data to the `Request`
/// extensions and it can be linked as an `AfterMiddleware` to add data to
/// the `Response` extensions.
///
/// `Read` also implements `Plugin`, so the data stored within can be
/// accessed through `request.get::<Read<P>>()` as an `Arc<P::Value>`.
pub struct Read<P: Key> {
    data: Arc<P::Value>
}

/// Middleware for data that persists between Requests for data which mostly
/// needs to be written instead of read.
///
/// The data is stored behind a `Mutex`, so only one request at a time can
/// access the data. This is more performant than `State` in the case where
/// most uses of the data require a write lock.
///
/// `Write` can be linked as `BeforeMiddleware` to add data to the `Request`
/// extensions and it can be linked as an `AfterMiddleware` to add data to
/// the `Response` extensions.
///
/// `Write` also implements `Plugin`, so the data stored within can be
/// accessed through `request.get::<Write<P>>()` as an `Arc<Mutex<P::Value>>`.
pub struct Write<P: Key> {
    data: Arc<Mutex<P::Value>>
}

impl<P: Key> Clone for Read<P> where P::Value: Send + Sync {
    fn clone(&self) -> Read<P> {
        Read { data: self.data.clone() }
    }
}

impl<P: Key> Clone for State<P> where P::Value: Send + Sync {
    fn clone(&self) -> State<P> {
        State { data: self.data.clone() }
    }
}

impl<P: Key> Clone for Write<P> where P::Value: Send {
    fn clone(&self) -> Write<P> {
        Write { data: self.data.clone() }
    }
}

impl<P: Key> From<Arc<P::Value>> for Read<P> {
    fn from(data: Arc<P::Value>) -> Read<P> {
        Read { data: data }
    }
}

impl<P: Key> From<Arc<RwLock<P::Value>>> for State<P> {
    fn from(data: Arc<RwLock<P::Value>>) -> State<P> {
        State { data: data }
    }
}

impl<P: Key> From<Arc<Mutex<P::Value>>> for Write<P> {
    fn from(data: Arc<Mutex<P::Value>>) -> Write<P> {
        Write { data: data }
    }
}

impl<P: Key> Key for State<P> where P::Value: 'static {
    type Value = Arc<RwLock<P::Value>>;
}

impl<P: Key> Key for Read<P> where P::Value: 'static {
    type Value = Arc<P::Value>;
}

impl<P: Key> Key for Write<P> where P::Value: 'static {
    type Value = Arc<Mutex<P::Value>>;
}

impl<'a, 'b, P: Key> Plugin<Request<'a, 'b>> for State<P> where P::Value: Send + Sync {
    type Error = PersistentError;
    fn eval(req: &mut Request<'a, 'b>) -> Result<Arc<RwLock<P::Value>>, PersistentError> {
        req.extensions.get::<State<P>>().cloned().ok_or(PersistentError::NotFound)
    }
}

impl<'a, 'b, P: Key> Plugin<Request<'a, 'b>> for Read<P> where P::Value: Send + Sync {
    type Error = PersistentError;
    fn eval(req: &mut Request<'a, 'b>) -> Result<Arc<P::Value>, PersistentError> {
        req.extensions.get::<Read<P>>().cloned().ok_or(PersistentError::NotFound)
    }
}

impl<'a, 'b, P: Key> Plugin<Request<'a, 'b>> for Write<P> where P::Value: Send {
    type Error = PersistentError;
    fn eval(req: &mut Request<'a, 'b>) -> Result<Arc<Mutex<P::Value>>, PersistentError> {
        req.extensions.get::<Write<P>>().cloned().ok_or(PersistentError::NotFound)
    }
}

impl<P: Key> BeforeMiddleware for State<P> where P::Value: Send + Sync {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions.insert::<State<P>>(self.data.clone());
        Ok(())
    }
}

impl<P: Key> BeforeMiddleware for Read<P> where P::Value: Send + Sync {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions.insert::<Read<P>>(self.data.clone());
        Ok(())
    }
}

impl<P: Key> BeforeMiddleware for Write<P> where P::Value: Send {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions.insert::<Write<P>>(self.data.clone());
        Ok(())
    }
}

impl<P: Key> AfterMiddleware for State<P> where P::Value: Send + Sync {
    fn after(&self, _: &mut Request, mut res: Response) -> IronResult<Response> {
        res.extensions.insert::<State<P>>(self.data.clone());
        Ok(res)
    }
}

impl<P: Key> AfterMiddleware for Read<P> where P::Value: Send + Sync {
    fn after(&self, _: &mut Request, mut res: Response) -> IronResult<Response> {
        res.extensions.insert::<Read<P>>(self.data.clone());
        Ok(res)
    }
}

impl<P: Key> AfterMiddleware for Write<P> where P::Value: Send {
    fn after(&self, _: &mut Request, mut res: Response) -> IronResult<Response> {
        res.extensions.insert::<Write<P>>(self.data.clone());
        Ok(res)
    }
}

impl<P: Key> State<P> where P::Value: Send + Sync {
    /// Construct a new pair of `State` that can be passed directly to `Chain::link`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn both(start: P::Value) -> (State<P>, State<P>) {
        let x = State { data: Arc::new(RwLock::new(start)) };
        (x.clone(), x)
    }

    /// Construct a new `State` that can be passed directly to
    /// `Chain::link_before` or `Chain::link_after`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn one(start: P::Value) -> State<P> {
        State { data: Arc::new(RwLock::new(start)) }
    }
}

impl<P: Key> Read<P> where P::Value: Send + Sync {
    /// Construct a new pair of `Read` that can be passed directly to `Chain::link`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn both(start: P::Value) -> (Read<P>, Read<P>) {
        let x = Read { data: Arc::new(start) };
        (x.clone(), x)
    }

    /// Construct a new `Read` that can be passed directly to
    /// `Chain::link_before` or `Chain::link_after`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn one(start: P::Value) -> Read<P> {
        Read { data: Arc::new(start) }
    }
}

impl<P: Key> Write<P> where P::Value: Send {
    /// Construct a new pair of `Write` that can be passed directly to `Chain::link`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn both(start: P::Value) -> (Write<P>, Write<P>) {
        let x = Write { data: Arc::new(Mutex::new(start)) };
        (x.clone(), x)
    }

    /// Construct a new `Write` that can be passed directly to
    /// `Chain::link_before` or `Chain::link_after`.
    ///
    /// The data is initialized with the passed-in value.
    pub fn one(start: P::Value) -> Write<P> {
        Write { data: Arc::new(Mutex::new(start)) }
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate dent;
extern crate term;
extern crate term_size;

use clap::{App, Arg};
use dent::plot;
use dent::summary::Summary;
use dent::t_test::{SigLevel, TTest, welch_t_test};

use std::fs::File;
use std::path::Path;
use std::io::{self, BufRead, BufReader};

mod fmt;
mod log;

fn fail<E>(err: E) -> ! where E: std::error::Error {
    log::error(&format!("{}", err));
    std::process::exit(1);
}

fn print_summary(s: &Summary) {
    let width = 10;
    let size_width = 6;

    println!(
        "{n:>nw$}  {min:>w$}  {max:>w$}  {med:>w$}  {mean:>w$}  {sd:>w$}  {se:>w$}",
        w = width,
        nw = size_width,
        n = "N",
        min = "Min",
        max = "Max",
        med = "Median",
        mean = "Mean",
        sd= "StdDev",
        se = "StdErr",
    );
    println!(
        "{n:>nw$}  {min:>w$}  {max:>w$}  {med:>w$}  {mean:>w$}  {sd:>w$}  {se:>w$}",
        w = width,
        nw = size_width,
        n = fmt::f(s.size(), width),
        min = fmt::f(s.min(), width),
        max = fmt::f(s.max(), width),
        med = fmt::f(s.median(), width),
        mean = fmt::f(s.mean(), width),
        sd = fmt::f(s.standard_deviation(), width),
        se = fmt::f(s.standard_error(), width),
    );
}

fn print_t_test(t_test: &TTest) {
    let width = 12;
    let reject = if t_test.reject { "yes" } else { "no" };

    println!("{l:>w$} = {v}", w = width, l = "Reject H₀?", v = reject);
    println!("{l:>w$} = {v}", w = width, l = "α", v = t_test.alpha);
    println!("{l:>w$} = {v}", w = width, l = "t", v = t_test.t);
    println!("{l:>w$} = {v}", w = width, l = "Crit. v", v = t_test.crit);
    println!("{l:>w$} = {v}", w = width, l = "DF", v = t_test.df);
}

fn summarize_file(path: &str, lax_parsing: bool) -> Summary {
    let p = Path::new(path);
    let f = match File::open(p) {
        Ok(f) => f,
        Err(e) => fail(e),
    };
    let reader = BufReader::new(f);

    let data = read_data(reader, lax_parsing);

    Summary::new(&data).unwrap()
}

fn read_data<R>(reader: R, lax_parsing: bool) -> Vec<f64> where R: BufRead {
    let mut data: Vec<f64> = vec![];

    for l in reader.lines() {
        let s = l.unwrap().trim().to_string();

        if s.is_empty() {
            continue;
        }

        match s.parse() {
            Ok(d) => data.push(d),
            err => if !lax_parsing { err.unwrap(); }
        }
    }

    data
}

fn parse_alpha(arg: &str) -> SigLevel {
    match arg {
        ".001" => SigLevel::Alpha001,
        ".005" => SigLevel::Alpha005,
        ".01"  => SigLevel::Alpha010,
        ".025" => SigLevel::Alpha025,
        ".05"  => SigLevel::Alpha050,
        ".1"   => SigLevel::Alpha100,
        _ => panic!(),
    }
}

fn summarize_stdin(lax_parsing: bool) -> Summary {
    let stdin = io::stdin();
    let data = read_data(stdin.lock(), lax_parsing);

    Summary::new(&data).unwrap()
}

fn display_t_test(
    summary1: &Summary,
    summary2: &Summary,
    alpha: SigLevel,
    draw_plot: bool,
    width: usize,
    ascii: bool,
) {
    let t_test = welch_t_test(&summary1, &summary2, alpha);

    if draw_plot {
        let p = plot::comparison_plot(&[&summary1, &summary2], width, ascii, true);
        println!("{}\n", p);
    }

    print_summary(&summary1);
    println!();
    print_summary(&summary2);
    println!();
    print_t_test(&t_test);
}

fn main() {
    let matches = App::new("dent")
        .version("0.3.0")
        .author("Joe Ranweiler <joe@lemma.co>")
        .about("A tiny tool for t-tests &c.")
        .arg(Arg::with_name("stdin")
             .short("s")
             .long("stdin")
             .help("Read and summarize data from stdin"))
        .arg(Arg::with_name("files")
             .multiple(true)
             .value_name("FILES")
             .takes_value(true)
             .required_unless("stdin")
             .help("Path to one or more files of sample data"))
        .arg(Arg::with_name("alpha")
             .short("a")
             .long("alpha")
             .value_name("ALPHA")
             .help("Significance level α")
             .takes_value(true)
             .default_value(".05"))
        .arg(Arg::with_name("lax")
             .long("lax")
             .help("Ignore non-numeric input lines"))
        .arg(Arg::with_name("plot")
             .short("p")
             .long("plot")
             .help("Print standard boxplots"))
        .arg(Arg::with_name("ascii")
             .long("ascii")
             .help("Use only ASCII characters in boxplots"))
        .arg(Arg::with_name("width")
             .short("w")
             .long("width")
             .value_name("WIDTH")
             .takes_value(true)
             .help("Width of boxplot"))
        .get_matches();

    let ascii = matches.is_present("ascii");
    let lax_parsing = matches.is_present("lax");
    let draw_plot = matches.is_present("plot");
    let use_stdin = matches.is_present("stdin");

    let width = matches
        .value_of("width")
        .and_then(|w| w.parse::<usize>().ok())
        .or(term_size::dimensions().map(|(w, _)| w))
        .unwrap_or(80);

    let summaries = if use_stdin {
        vec![summarize_stdin(lax_parsing)]
    } else {
        matches.values_of("files").unwrap()
            .map(|f| summarize_file(f, lax_parsing))
            .collect()
    };

    match summaries.len() {
        0 => unreachable!(),
        2 => {
            let alpha = parse_alpha(matches.value_of("alpha").unwrap());

            display_t_test(
                &summaries[0],
                &summaries[1],
                alpha,
                draw_plot,
                width,
                ascii,
            );
        }
        _ => {
            if draw_plot {
                let summary_refs: Vec<&Summary> = summaries
                    .iter()
                    .collect();

                let plot = plot::comparison_plot(&summary_refs, width, ascii, true);
                println!("{}\n", plot);
            }

            for i in 0..summaries.len() {
                if i > 0 {
                    println!();
                }
                print_summary(&summaries[i]);
            }
        },
    };
}
<commit_msg>Don't unwrap exe results, fail later with `ok!` macro<commit_after>extern crate clap;
extern crate dent;
extern crate term;
extern crate term_size;

use clap::{App, Arg};
use dent::plot;
use dent::summary::Summary;
use dent::t_test::{SigLevel, TTest, welch_t_test};

use std::error;
use std::fs::File;
use std::path::Path;
use std::io::{self, BufRead, BufReader};

mod fmt;
mod log;

macro_rules! ok {
    ($r: expr) => {
        match $r {
            Ok(t) => t,
            Err(e) => {
                log::error(&format!("{}", e));
                std::process::exit(1);
            }
        }
    }
}

fn print_summary(s: &Summary) {
    let width = 10;
    let size_width = 6;

    println!(
        "{n:>nw$}  {min:>w$}  {max:>w$}  {med:>w$}  {mean:>w$}  {sd:>w$}  {se:>w$}",
        w = width,
        nw = size_width,
        n = "N",
        min = "Min",
        max = "Max",
        med = "Median",
        mean = "Mean",
        sd= "StdDev",
        se = "StdErr",
    );
    println!(
        "{n:>nw$}  {min:>w$}  {max:>w$}  {med:>w$}  {mean:>w$}  {sd:>w$}  {se:>w$}",
        w = width,
        nw = size_width,
        n = fmt::f(s.size(), width),
        min = fmt::f(s.min(), width),
        max = fmt::f(s.max(), width),
        med = fmt::f(s.median(), width),
        mean = fmt::f(s.mean(), width),
        sd = fmt::f(s.standard_deviation(), width),
        se = fmt::f(s.standard_error(), width),
    );
}

fn print_t_test(t_test: &TTest) {
    let width = 12;
    let reject = if t_test.reject { "yes" } else { "no" };

    println!("{l:>w$} = {v}", w = width, l = "Reject H₀?", v = reject);
    println!("{l:>w$} = {v}", w = width, l = "α", v = t_test.alpha);
    println!("{l:>w$} = {v}", w = width, l = "t", v = t_test.t);
    println!("{l:>w$} = {v}", w = width, l = "Crit. v", v = t_test.crit);
    println!("{l:>w$} = {v}", w = width, l = "DF", v = t_test.df);
}

fn summarize_file(path: &str, lax_parsing: bool) -> Result<Summary, Box<error::Error>> {
    let p = Path::new(path);
    let f = File::open(p)?;
    let reader = BufReader::new(f);

    let data = read_data(reader, lax_parsing)?;

    Ok(Summary::new(&data).unwrap())
}

fn read_data<R>(reader: R, lax_parsing: bool) -> Result<Vec<f64>, Box<error::Error>>
    where R: BufRead {
    let mut data: Vec<f64> = vec![];

    for l in reader.lines() {
        let s = l.unwrap().trim().to_string();

        if s.is_empty() {
            continue;
        }

        match s.parse() {
            Ok(d) => data.push(d),
            err => if !lax_parsing { err?; }
        }
    }

    Ok(data)
}

fn parse_alpha(arg: &str) -> SigLevel {
    match arg {
        ".001" => SigLevel::Alpha001,
        ".005" => SigLevel::Alpha005,
        ".01"  => SigLevel::Alpha010,
        ".025" => SigLevel::Alpha025,
        ".05"  => SigLevel::Alpha050,
        ".1"   => SigLevel::Alpha100,
        _ => panic!(),
    }
}

fn summarize_stdin(lax_parsing: bool) -> Result<Summary, Box<error::Error>> {
    let stdin = io::stdin();
    let data = read_data(stdin.lock(), lax_parsing)?;

    Ok(Summary::new(&data).unwrap())
}

fn display_t_test(
    summary1: &Summary,
    summary2: &Summary,
    alpha: SigLevel,
    draw_plot: bool,
    width: usize,
    ascii: bool,
) {
    let t_test = welch_t_test(&summary1, &summary2, alpha);

    if draw_plot {
        let p = plot::comparison_plot(&[summary1, summary2], width, ascii, true);
        println!("{}\n", p);
    }

    print_summary(&summary1);
    println!();
    print_summary(&summary2);
    println!();
    print_t_test(&t_test);
}

fn display_summaries(
    summaries: &[Summary],
    draw_plot: bool,
    width: usize,
    ascii: bool,
) {
    if draw_plot {
        let summary_refs: Vec<&Summary> = summaries
            .iter()
            .collect();

        let plot = plot::comparison_plot(&summary_refs, width, ascii, true);
        println!("{}\n", plot);
    }

    for i in 0..summaries.len() {
        if i > 0 {
            println!();
        }
        print_summary(&summaries[i]);
    }
}

fn main() {
    let matches = App::new("dent")
        .version("0.3.0")
        .author("Joe Ranweiler <joe@lemma.co>")
        .about("A tiny tool for t-tests &c.")
        .arg(Arg::with_name("stdin")
             .short("s")
             .long("stdin")
             .help("Read and summarize data from stdin"))
        .arg(Arg::with_name("files")
             .multiple(true)
             .value_name("FILES")
             .takes_value(true)
             .required_unless("stdin")
             .help("Path to one or more files of sample data"))
        .arg(Arg::with_name("alpha")
             .short("a")
             .long("alpha")
             .value_name("ALPHA")
             .help("Significance level α")
             .takes_value(true)
             .default_value(".05"))
        .arg(Arg::with_name("lax")
             .long("lax")
             .help("Ignore non-numeric input lines"))
        .arg(Arg::with_name("plot")
             .short("p")
             .long("plot")
             .help("Print standard boxplots"))
        .arg(Arg::with_name("ascii")
             .long("ascii")
             .help("Use only ASCII characters in boxplots"))
        .arg(Arg::with_name("width")
             .short("w")
             .long("width")
             .value_name("WIDTH")
             .takes_value(true)
             .help("Width of boxplot"))
        .get_matches();

    let ascii = matches.is_present("ascii");
    let lax_parsing = matches.is_present("lax");
    let draw_plot = matches.is_present("plot");
    let use_stdin = matches.is_present("stdin");

    let width = matches
        .value_of("width")
        .and_then(|w| w.parse::<usize>().ok())
        .or(term_size::dimensions().map(|(w, _)| w))
        .unwrap_or(80);

    let summaries = if use_stdin {
        vec![ok!(summarize_stdin(lax_parsing))]
    } else {
        matches.values_of("files")
            .unwrap()
            .map(|f| ok!(summarize_file(f, lax_parsing)))
            .collect()
    };

    match summaries.len() {
        0 => unreachable!(),
        2 => {
            let alpha = parse_alpha(matches.value_of("alpha").unwrap());

            display_t_test(
                &summaries[0],
                &summaries[1],
                alpha,
                draw_plot,
                width,
                ascii,
            );
        }
        _ => {
            display_summaries(&summaries, draw_plot, width, ascii);
        },
    };
}
<|endoftext|>


<commit_before>#![feature(plugin, collections)]

#![plugin(regex_macros)]

//! # Handlebars
//! Handlebars is a modern and extensible templating solution originally created in the JavaScript world. It's used by many popular frameworks like [Ember.js](http://emberjs.com) and Chaplin. It's also ported to some other platforms such as [Java](https://github.com/jknack/handlebars.java).
//!
//! And this is handlebars Rust implementation, designed for server-side page generation. It's a general-purpose library so you use it for any kind of text generation.
//!
//! ## Handlebars spec
//!
//! ### Base
//!
//! You can go to [Handlebars.js](http://handlebarsjs.com/) website for its syntax. This implementation should be compatible with most parts of the spec, except:
//!
//! * raw helper syntax `{{{raw-helper}}}...{{{/raw-helper}}}` is implemented as block helper raw.
//! * configurable logging (hard-coded to rust native logging, with fixed level `INFO`)
//!
//! ### Extensions
//!
//! We have template reuse facilities supported via built-in helpers `>`, `partial` and `block`.
//!
//! There are two ways to reuse a template:
//!
//! * include (using `>`)
//! * inheritance (using `>` together with `block` and `partial`)
//!
//! Consult [Handlebar.java document about template inheritance](http://jknack.github.io/handlebars.java/reuse.html).
//!
//! ## Usage
//!
//! ### Template Creation and Registration
//!
//! Templates are created from String and registered to `Handlebars` with a name.
//!
//! ```
//!
//! extern crate handlebars;
//!
//! use handlebars::Handlebars;
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   let source = "hello {{world}}";
//!
//!   //compile returns an Option, we use unwrap() to deref it directly here
//!   handlebars.register_template_string("helloworld", source.to_string())
//!           .ok().expect("template created");
//! }
//! ```
//!
//! ### Rendering Something
//!
//! I should say that rendering is a little tricky. Since handlebars is originally a JavaScript templating framework. It supports dynamic features like duck-typing, truthy/falsy values. But for a static language like Rust, this is a little difficult. As a solution, I'm using the `serialize::json::Json` internally for data rendering, which seems good by far.
//!
//! That means, if you want to render something, you have to ensure that it implements the `serialize::json::ToJson` trait. Luckily, most built-in types already have trait. However, if you want to render your custom struct, you need to implement this trait manually. (Rust has a deriving facility, but it's just for selected types. Maybe I will add some syntax extensions or macros to simplify this process.)
//!
//! ```
//! #![feature(custom_derive, plugin)]
//! #![plugin(tojson_macros)]
//!
//! extern crate rustc_serialize;
//! extern crate handlebars;
//!
//! use rustc_serialize::json::{Json, ToJson};
//! use std::collections::BTreeMap;
//!
//! use handlebars::Handlebars;
//!
//! #[derive(ToJson)]
//! struct Person {
//!   name: String,
//!   age: i16,
//! }
//!
//! fn main() {
//!   let source = "hello {{world}}";
//!
//!   let mut handlebars = Handlebars::new();
//!   handlebars.register_template_string("helloworld", source.to_string())
//!           .ok().expect("template creation failed");
//!
//!   let mut data = Person {
//!       name: "Ning Sun".to_string(),
//!       age: 27
//!   };
//!   let result = handlebars.render("helloworld", &data);
//! }
//! ```
//!
//! ### Custom Helper
//!
//! Handlebars is nothing without helpers. You can also create your own helpers with rust. Helpers in handlebars-rust are custom struct implements the `HelperDef` trait, concretely, the `call` function. For your convenience, most of stateless helpers can be implemented as bare functions.
//!
//! ```
//!
//! extern crate handlebars;
//!
//! use handlebars::{Handlebars, HelperDef, RenderError, RenderContext, Helper, Context};
//!
//! // implement by a structure impls HelperDef
//! #[derive(Clone, Copy)]
//! struct SimpleHelper;
//!
//! impl HelperDef for SimpleHelper {
//!   fn call(&self, c: &Context, h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<String, RenderError> {
//!     let param = h.params().get(0).unwrap();
//!
//!     // get value from context data
//!     // rc.get_path() is current json parent path, you should always use it like this
//!     // param is the key of value you want to display
//!     let value = c.navigate(rc.get_path(), param);
//!     Ok(format!("My helper dumps: {} ", value))
//!   }
//! }
//!
//! // implement via bare function
//! fn another_simple_helper (c: &Context, h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<String, RenderError> {
//!     let param = h.params().get(0).unwrap();
//!
//!     // get value from context data
//!     // rc.get_path() is current json parent path, you should always use it like this
//!     // param is the key of value you want to display
//!     let value = c.navigate(rc.get_path(), param);
//!     Ok(format!("My second helper dumps: {} ", value))
//! }
//!
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   handlebars.register_helper("simple-helper", Box::new(SimpleHelper));
//!   handlebars.register_helper("another-simple-helper", Box::new(another_simple_helper));
//!
//!   //...
//! }
//! ```
//!
//! #### Arguments of HelpDef
//!
//! You can get data from the `Helper` argument about the template information:
//!
//! * `name()` for the helper name. This is known to you for most situation but if you are defining `helperMissing` or `blockHelperMissing`, this is important.
//! * `params()` is a vector of String as params in helper, like `{{#somehelper param1 param2 param3}}`.
//! * `hash()` is a map of String key and Json value, defined in helper as `{{@somehelper a=1 b="2" c=true}}`.
//! * `template()` gives you the nested template of block helper.
//! * `inverse()` gives you the inversed template of it, inversed template is the template behind `{{else}}`.
//!
//! You can learn more about helpers by looking into source code of built-in helpers.
//!
//! #### Built-in Helpers
//!
//! * `{{#raw}} ... {{/raw}}` escape handlebars expression within the block
//! * `{{#if ...}} ... {{else}} ... {{/if}}` if-else block
//! * `{{#unless ...}} ... {{else}} .. {{/unless}}` if-not-else block
//! * `{{#each ...}} ... {{/each}}` iterates over an array or object. Handlebar-rust doesn't support mustach iteration syntax so use this instead.
//! * `{{#with ...}} ... {{/with}}` change current context. Similar to {{#each}}, used for replace corresponding mustach syntax.
//! * `{{lookup ... ...}}` get value from array by `@index` or `@key`
//! * `{{#partial ...}} ... {{/partial}}` template reuse, used to replace block with same name
//! * `{{#block ...}} ... {{/block}}` template reuse, used to be replaced by partial with same name, with default content if partial not found.
//! * `{{> ...}}` include template with name
//! * `{{log ...}}` log value with rust logger, default level: INFO. Currently you cannot change the level.
//!

#[macro_use]
extern crate log;

extern crate rustc_serialize as serialize;
extern crate regex;
extern crate num;

pub use self::template::{Template, TemplateError, Helper};
pub use self::registry::Registry as Handlebars;
pub use self::render::{Renderable, RenderError, RenderContext};
pub use self::helpers::{HelperDef};
pub use self::context::{Context, JsonRender, JsonTruthy};

mod template;
mod registry;
mod render;
mod helpers;
mod context;
<commit_msg>(doc) update doc for helper defined from closure<commit_after>#![feature(plugin, collections)]

#![plugin(regex_macros)]

//! # Handlebars
//! Handlebars is a modern and extensible templating solution originally created in the JavaScript world. It's used by many popular frameworks like [Ember.js](http://emberjs.com) and Chaplin. It's also ported to some other platforms such as [Java](https://github.com/jknack/handlebars.java).
//!
//! And this is handlebars Rust implementation, designed for server-side page generation. It's a general-purpose library so you use it for any kind of text generation.
//!
//! ## Handlebars spec
//!
//! ### Base
//!
//! You can go to [Handlebars.js](http://handlebarsjs.com/) website for its syntax. This implementation should be compatible with most parts of the spec, except:
//!
//! * raw helper syntax `{{{raw-helper}}}...{{{/raw-helper}}}` is implemented as block helper raw.
//! * configurable logging (hard-coded to rust native logging, with fixed level `INFO`)
//!
//! ### Extensions
//!
//! We have template reuse facilities supported via built-in helpers `>`, `partial` and `block`.
//!
//! There are two ways to reuse a template:
//!
//! * include (using `>`)
//! * inheritance (using `>` together with `block` and `partial`)
//!
//! Consult [Handlebar.java document about template inheritance](http://jknack.github.io/handlebars.java/reuse.html).
//!
//! ## Usage
//!
//! ### Template Creation and Registration
//!
//! Templates are created from String and registered to `Handlebars` with a name.
//!
//! ```
//!
//! extern crate handlebars;
//!
//! use handlebars::Handlebars;
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   let source = "hello {{world}}";
//!
//!   //compile returns an Option, we use unwrap() to deref it directly here
//!   handlebars.register_template_string("helloworld", source.to_string())
//!           .ok().expect("template created");
//! }
//! ```
//!
//! ### Rendering Something
//!
//! I should say that rendering is a little tricky. Since handlebars is originally a JavaScript templating framework. It supports dynamic features like duck-typing, truthy/falsy values. But for a static language like Rust, this is a little difficult. As a solution, I'm using the `serialize::json::Json` internally for data rendering, which seems good by far.
//!
//! That means, if you want to render something, you have to ensure that it implements the `serialize::json::ToJson` trait. Luckily, most built-in types already have trait. However, if you want to render your custom struct, you need to implement this trait manually. (Rust has a deriving facility, but it's just for selected types. Maybe I will add some syntax extensions or macros to simplify this process.)
//!
//! ```
//! #![feature(custom_derive, plugin)]
//! #![plugin(tojson_macros)]
//!
//! extern crate rustc_serialize;
//! extern crate handlebars;
//!
//! use rustc_serialize::json::{Json, ToJson};
//! use std::collections::BTreeMap;
//!
//! use handlebars::Handlebars;
//!
//! #[derive(ToJson)]
//! struct Person {
//!   name: String,
//!   age: i16,
//! }
//!
//! fn main() {
//!   let source = "hello {{world}}";
//!
//!   let mut handlebars = Handlebars::new();
//!   handlebars.register_template_string("helloworld", source.to_string())
//!           .ok().expect("template creation failed");
//!
//!   let mut data = Person {
//!       name: "Ning Sun".to_string(),
//!       age: 27
//!   };
//!   let result = handlebars.render("helloworld", &data);
//! }
//! ```
//!
//! ### Custom Helper
//!
//! Handlebars is nothing without helpers. You can also create your own helpers with rust. Helpers in handlebars-rust are custom struct implements the `HelperDef` trait, concretely, the `call` function. For your convenience, most of stateless helpers can be implemented as bare functions.
//!
//! ```
//!
//! extern crate handlebars;
//!
//! use handlebars::{Handlebars, HelperDef, RenderError, RenderContext, Helper, Context};
//!
//! // implement by a structure impls HelperDef
//! #[derive(Clone, Copy)]
//! struct SimpleHelper;
//!
//! impl HelperDef for SimpleHelper {
//!   fn call(&self, c: &Context, h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<String, RenderError> {
//!     let param = h.params().get(0).unwrap();
//!
//!     // get value from context data
//!     // rc.get_path() is current json parent path, you should always use it like this
//!     // param is the key of value you want to display
//!     let value = c.navigate(rc.get_path(), param);
//!     Ok(format!("My helper dumps: {} ", value))
//!   }
//! }
//!
//! // implement via bare function
//! fn another_simple_helper (c: &Context, h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<String, RenderError> {
//!     let param = h.params().get(0).unwrap();
//!
//!     // get value from context data
//!     // rc.get_path() is current json parent path, you should always use it like this
//!     // param is the key of value you want to display
//!     let value = c.navigate(rc.get_path(), param);
//!     Ok(format!("My second helper dumps: {} ", value))
//! }
//!
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   handlebars.register_helper("simple-helper", Box::new(SimpleHelper));
//!   handlebars.register_helper("another-simple-helper", Box::new(another_simple_helper));
//!   // via closure
//!   handlebars.register_helper("closure-helper",
//!       Box::new(|c: &Context, h: &Helper, r: &Handlebars, rc: &mut RenderContext| -> Result<String, RenderError>{
//!         Ok(format!("..."))
//!       }));
//!
//!   //...
//! }
//! ```
//!
//! #### Arguments of HelpDef
//!
//! You can get data from the `Helper` argument about the template information:
//!
//! * `name()` for the helper name. This is known to you for most situation but if you are defining `helperMissing` or `blockHelperMissing`, this is important.
//! * `params()` is a vector of String as params in helper, like `{{#somehelper param1 param2 param3}}`.
//! * `hash()` is a map of String key and Json value, defined in helper as `{{@somehelper a=1 b="2" c=true}}`.
//! * `template()` gives you the nested template of block helper.
//! * `inverse()` gives you the inversed template of it, inversed template is the template behind `{{else}}`.
//!
//! You can learn more about helpers by looking into source code of built-in helpers.
//!
//! #### Built-in Helpers
//!
//! * `{{#raw}} ... {{/raw}}` escape handlebars expression within the block
//! * `{{#if ...}} ... {{else}} ... {{/if}}` if-else block
//! * `{{#unless ...}} ... {{else}} .. {{/unless}}` if-not-else block
//! * `{{#each ...}} ... {{/each}}` iterates over an array or object. Handlebar-rust doesn't support mustach iteration syntax so use this instead.
//! * `{{#with ...}} ... {{/with}}` change current context. Similar to {{#each}}, used for replace corresponding mustach syntax.
//! * `{{lookup ... ...}}` get value from array by `@index` or `@key`
//! * `{{#partial ...}} ... {{/partial}}` template reuse, used to replace block with same name
//! * `{{#block ...}} ... {{/block}}` template reuse, used to be replaced by partial with same name, with default content if partial not found.
//! * `{{> ...}}` include template with name
//! * `{{log ...}}` log value with rust logger, default level: INFO. Currently you cannot change the level.
//!

#[macro_use]
extern crate log;

extern crate rustc_serialize as serialize;
extern crate regex;
extern crate num;

pub use self::template::{Template, TemplateError, Helper};
pub use self::registry::Registry as Handlebars;
pub use self::render::{Renderable, RenderError, RenderContext};
pub use self::helpers::{HelperDef};
pub use self::context::{Context, JsonRender, JsonTruthy};

mod template;
mod registry;
mod render;
mod helpers;
mod context;
<|endoftext|>


<commit_before>#![feature(collections,io)]

/// Implements the XTEA block cipher, whose reference source is public
/// domain.  This code is also public domain.
///
/// Also implements a CBC-mode block cipher with padding.  I'm not
/// good at crypto so don't use this.

/// A key is 128 bits.  We don't seem to need SIMD anywhere so it's
/// just an array.
pub type Key = [u32; 4];

/// XTEA uses 64-bit blocks; for simplicity and to match the reference
/// source, we use an array here too.
pub type Block = [u32; 2];

static NUM_ROUNDS: u32 = 32;

/// Encrypts 64 bits of input using the key.
pub fn encipher(key: &Key, input: &Block) -> Block {
    // Reference source:
    // unsigned int i;
    // uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9;
    // for (i=0; i < num_rounds; i++) {
    //     v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
    //     sum += delta;
    //     v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
    // }
    // v[0]=v0; v[1]=v1;
    let [mut v0, mut v1] = *input;
    let delta = 0x9E3779B9;
    let mut sum: u32 = 0;
    for _ in 0..NUM_ROUNDS {
        v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[(sum & 3) as usize]);
        sum += delta;
        v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[((sum>>11) & 3) as usize])
    }
    [v0, v1]
}

/// Decrypts 64 bits of input using the key.
pub fn decipher(key: &Key, input: &Block) -> Block {
    // Reference source:
    // unsigned int i;
    // uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*num_rounds;
    // for (i=0; i < num_rounds; i++) {
    //     v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
    //     sum -= delta;
    //     v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
    // }
    // v[0]=v0; v[1]=v1;
    let [mut v0, mut v1] = *input;
    let delta = 0x9E3779B9;
    let mut sum = delta * NUM_ROUNDS;
    for _ in 0..NUM_ROUNDS {
        v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[((sum>>11) & 3) as usize]);
        sum -= delta;
        v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[(sum & 3) as usize]);
    }
    [v0, v1]
}

use std::io;
use std::mem;
use std::ptr;

fn read_block(chunk: &[u8]) -> Block {
    assert_eq!(chunk.len(), 8);
    unsafe {
        let mut block: Block = mem::uninitialized();
        let b0 = block.get_unchecked_mut(0) as *mut u32;
        let input = chunk.get_unchecked(0) as *const u8;
        ptr::copy_nonoverlapping(b0 as *mut u8, input, 8);
        block
    }
}

fn write_block(block: &Block) -> [u8; 8] {
    unsafe { mem::transmute(*block) }
}

/// Adapts encipher and decipher into a block cipher using CBC.
pub struct BlockCipher {
    key: Key,
    prev: Block,
}

impl BlockCipher {

    /// Creates an XTEA BlockCipher with a key and an initialization
    /// vector.
    pub fn new(key: Key, iv: Block) -> BlockCipher {
        BlockCipher{key: key, prev: iv}
    }

    fn encrypt_chunk(&mut self, chunk: &[u8], output: &mut io::Write) {
        let mut input_block: Block = read_block(chunk);
        input_block[0] ^= self.prev[0];
        input_block[1] ^= self.prev[1];
        self.prev = encipher(&self.key, &input_block);
        output.write_all(&write_block(&self.prev)).ok().unwrap();
    }

    /// Reads bytes from `input` until it's consumed, and writes the
    /// encrypted bytes to `output`.  Will pad to an 8-byte boundary.
    pub fn encrypt(&mut self, input: &mut io::BufRead, output: &mut io::Write) {
        loop {
            let consumed = {
                let bytes = input.fill_buf().ok().unwrap();
                if bytes.len() == 0 {
                    break;
                }
                for chunk in bytes.chunks(8) {
                    if chunk.len() < 8 {
                        let mut vec = chunk.to_vec();
                        vec.resize(8, 0u8);
                        self.encrypt_chunk(&vec, output);
                    } else {
                        self.encrypt_chunk(&chunk, output);
                    }
                }
                bytes.len()
            };
            input.consume(consumed);
        }
    }

    fn decrypt_chunk(&mut self, chunk: &[u8], output: &mut io::Write) {
        let input_block: Block = read_block(chunk);
        let mut decrypted_block = decipher(&self.key, &input_block);
        decrypted_block[0] ^= self.prev[0];
        decrypted_block[1] ^= self.prev[1];
        self.prev = input_block;
        output.write_all(&write_block(&decrypted_block)).ok().unwrap();
    }

    /// Reads encrypted bytes from `input` until it's consumed, and
    /// writes the decrypted bytes to `output`.  If the input needed
    /// to be padded, the result will have trailing zeroes.
    pub fn decrypt(&mut self, input: &mut io::BufRead, output: &mut io::Write) {
        loop {
            let consumed = {
                let bytes = input.fill_buf().ok().unwrap();
                if bytes.len() == 0 {
                    break;
                }
                for chunk in bytes.chunks(8) {
                    if chunk.len() < 8 {
                        let mut vec = chunk.to_vec();
                        vec.resize(8, 0u8);
                        self.decrypt_chunk(&vec, output);
                    } else {
                        self.decrypt_chunk(&chunk, output);
                    }
                }
                bytes.len()
            };
            input.consume(consumed);
        }
    }

}

#[test]
fn tea_works() {
    let key: Key = [10, 20, 30, 42];
    let plaintext: Block = [300, 400];
    let ciphertext = encipher(&key, &plaintext);
    assert!(plaintext != ciphertext);
    assert_eq!(plaintext, decipher(&key, &ciphertext));
}

#[test]
fn cipher_works() {
    let mut cipher = BlockCipher::new([123, 456, 789, 1011], [867, 5309]);
    let input: Vec<u8> = (0u8..128).collect();

    let mut crypted_cursor: io::Cursor<Vec<u8>> = io::Cursor::new(Vec::new());
    cipher.encrypt(&mut io::Cursor::new(input.clone()), &mut crypted_cursor);
    let crypted = crypted_cursor.into_inner();

    assert_eq!(input.len(), crypted.len());
    assert!(input != crypted);

    // reset cipher iv
    cipher = BlockCipher::new([123, 456, 789, 1011], [867, 5309]);

    let mut decrypted_cursor: io::Cursor<Vec<u8>> = io::Cursor::new(Vec::new());
    cipher.decrypt(&mut io::Cursor::new(crypted.clone()), &mut decrypted_cursor);
    let decrypted = decrypted_cursor.into_inner();
    assert_eq!(input, decrypted);
}

#[test]
fn cipher_padding() {
    let mut cipher = BlockCipher::new([123, 456, 789, 1011], [867, 5309]);
    let input: Vec<u8> = (0u8..123).collect();

    let mut crypted_cursor: io::Cursor<Vec<u8>> = io::Cursor::new(Vec::new());
    cipher.encrypt(&mut io::Cursor::new(input.clone()), &mut crypted_cursor);
    let crypted = crypted_cursor.into_inner();

    assert!(input.len() != crypted.len());
    assert!(input != crypted);

    // reset cipher iv
    cipher = BlockCipher::new([123, 456, 789, 1011], [867, 5309]);

    let mut decrypted_cursor: io::Cursor<Vec<u8>> = io::Cursor::new(Vec::new());
    cipher.decrypt(&mut io::Cursor::new(crypted.clone()), &mut decrypted_cursor);
    let decrypted = decrypted_cursor.into_inner();
    let mut padded_input = input.clone();
    padded_input.resize(128, 0u8);
    assert_eq!(padded_input, decrypted);
}
<commit_msg>changed padding to use PKCS#7<commit_after>#![feature(collections,io)]

/// Implements the XTEA block cipher, whose reference source is public
/// domain.  This code is also public domain.
///
/// Also implements a CBC-mode block cipher with padding.  I'm not
/// good at crypto so don't use this.

/// A key is 128 bits.  We don't seem to need SIMD anywhere so it's
/// just an array.
pub type Key = [u32; 4];

/// XTEA uses 64-bit blocks; for simplicity and to match the reference
/// source, we use an array here too.
pub type Block = [u32; 2];

static NUM_ROUNDS: u32 = 32;

/// Encrypts 64 bits of input using the key.
pub fn encipher(key: &Key, input: &Block) -> Block {
    // Reference source:
    // unsigned int i;
    // uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9;
    // for (i=0; i < num_rounds; i++) {
    //     v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
    //     sum += delta;
    //     v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
    // }
    // v[0]=v0; v[1]=v1;
    let [mut v0, mut v1] = *input;
    let delta = 0x9E3779B9;
    let mut sum: u32 = 0;
    for _ in 0..NUM_ROUNDS {
        v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[(sum & 3) as usize]);
        sum += delta;
        v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[((sum>>11) & 3) as usize])
    }
    [v0, v1]
}

/// Decrypts 64 bits of input using the key.
pub fn decipher(key: &Key, input: &Block) -> Block {
    // Reference source:
    // unsigned int i;
    // uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*num_rounds;
    // for (i=0; i < num_rounds; i++) {
    //     v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
    //     sum -= delta;
    //     v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
    // }
    // v[0]=v0; v[1]=v1;
    let [mut v0, mut v1] = *input;
    let delta = 0x9E3779B9;
    let mut sum = delta * NUM_ROUNDS;
    for _ in 0..NUM_ROUNDS {
        v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[((sum>>11) & 3) as usize]);
        sum -= delta;
        v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[(sum & 3) as usize]);
    }
    [v0, v1]
}

use std::io;
use std::mem;
use std::ptr;

fn read_block(chunk: &[u8]) -> Block {
    assert_eq!(chunk.len(), 8);
    unsafe {
        let mut block: Block = mem::uninitialized();
        let b0 = block.get_unchecked_mut(0) as *mut u32;
        let input = chunk.get_unchecked(0) as *const u8;
        ptr::copy_nonoverlapping(b0 as *mut u8, input, 8);
        block
    }
}

fn write_block(block: &Block) -> [u8; 8] {
    unsafe { mem::transmute(*block) }
}

/// Adapts encipher and decipher into a block cipher using CBC.
pub struct BlockCipher {
    key: Key,
    prev: Block,
}

impl BlockCipher {

    /// Creates an XTEA BlockCipher with a key and an initialization
    /// vector.
    pub fn new(key: Key, iv: Block) -> BlockCipher {
        BlockCipher{key: key, prev: iv}
    }

    fn encrypt_chunk(&mut self, chunk: &[u8], output: &mut io::Write) {
        let mut input_block: Block = read_block(chunk);
        input_block[0] ^= self.prev[0];
        input_block[1] ^= self.prev[1];
        self.prev = encipher(&self.key, &input_block);
        output.write_all(&write_block(&self.prev)).ok().unwrap();
    }

    /// Reads bytes from `input` until it's consumed, and writes the
    /// encrypted bytes to `output`.  Will pad to an 8-byte boundary.
    pub fn encrypt(&mut self, input: &mut io::BufRead, output: &mut io::Write) {
        let mut consumed;
        loop {
            consumed = 0;
            {
                let bytes = input.fill_buf().ok().unwrap();
                if bytes.len() < 8 {
                    let mut vec = bytes.to_vec();
                    vec.resize(8, 8 - bytes.len() as u8);
                    self.encrypt_chunk(&vec, output);
                    consumed = bytes.len();
                    break;
                }
                for chunk in bytes.chunks(8) {
                    if chunk.len() < 8 {
                        break;
                    }
                    self.encrypt_chunk(&chunk, output);
                    consumed += 8;
                }
            }
            input.consume(consumed);
        }
        input.consume(consumed);
    }

    fn decrypt_chunk(&mut self, chunk: &[u8]) -> [u8; 8] {
        let input_block: Block = read_block(chunk);
        let mut decrypted_block = decipher(&self.key, &input_block);
        decrypted_block[0] ^= self.prev[0];
        decrypted_block[1] ^= self.prev[1];
        self.prev = input_block;
        write_block(&decrypted_block)
    }

    /// Reads encrypted bytes from `input` until it's consumed, and
    /// writes the decrypted bytes to `output`.  If the input needed
    /// to be padded, the result will have trailing zeroes.
    pub fn decrypt(&mut self, input: &mut io::BufRead, output: &mut io::Write) {
        let mut last_chunk: [u8; 8] = [0u8; 8];
        let mut last_chunk_initialized = false;
        loop {
            let mut consumed = 0;
            {
                let bytes = input.fill_buf().ok().unwrap();
                if bytes.len() == 0 {
                    break;
                }
                assert!(bytes.len() >= 8);
                for chunk in bytes.chunks(8) {
                    if chunk.len() < 8 {
                        break;
                    }
                    if last_chunk_initialized {
                        output.write_all(&last_chunk).ok().unwrap();
                    }
                    last_chunk = self.decrypt_chunk(&chunk);
                    last_chunk_initialized = true;
                    consumed += 8;
                }
            };
            input.consume(consumed);
        }
        if last_chunk_initialized {
            let padded = last_chunk[7];
            if padded < 8 {
                output.write_all(&last_chunk[..(8 - padded) as usize]).ok().unwrap();
            }
        }
    }

}

#[test]
fn tea_works() {
    let key: Key = [10, 20, 30, 42];
    let plaintext: Block = [300, 400];
    let ciphertext = encipher(&key, &plaintext);
    assert!(plaintext != ciphertext);
    assert_eq!(plaintext, decipher(&key, &ciphertext));
}

#[test]
fn cipher_works() {
    let mut cipher = BlockCipher::new([123, 456, 789, 1011], [867, 5309]);
    let input: Vec<u8> = (0u8..128).collect();

    let mut crypted_cursor: io::Cursor<Vec<u8>> = io::Cursor::new(Vec::new());
    cipher.encrypt(&mut io::Cursor::new(input.clone()), &mut crypted_cursor);
    let crypted = crypted_cursor.into_inner();

    assert_eq!(input.len() + 8, crypted.len());
    assert!(input != crypted);

    // reset cipher iv
    cipher = BlockCipher::new([123, 456, 789, 1011], [867, 5309]);

    let mut decrypted_cursor: io::Cursor<Vec<u8>> = io::Cursor::new(Vec::new());
    cipher.decrypt(&mut io::Cursor::new(crypted.clone()), &mut decrypted_cursor);
    let decrypted = decrypted_cursor.into_inner();
    assert_eq!(input, decrypted);
}

#[test]
fn cipher_padding() {
    let mut cipher = BlockCipher::new([123, 456, 789, 1011], [867, 5309]);
    let input: Vec<u8> = (0u8..123).collect();

    let mut crypted_cursor: io::Cursor<Vec<u8>> = io::Cursor::new(Vec::new());
    cipher.encrypt(&mut io::Cursor::new(input.clone()), &mut crypted_cursor);
    let crypted = crypted_cursor.into_inner();

    assert_eq!(input.len() + 5, crypted.len());
    assert!(input != crypted);

    // reset cipher iv
    cipher = BlockCipher::new([123, 456, 789, 1011], [867, 5309]);

    let mut decrypted_cursor: io::Cursor<Vec<u8>> = io::Cursor::new(Vec::new());
    cipher.decrypt(&mut io::Cursor::new(crypted.clone()), &mut decrypted_cursor);
    let decrypted = decrypted_cursor.into_inner();
    assert_eq!(input, decrypted);
}
<|endoftext|>