<commit_before>//!
//! [Under construction](https://github.com/nikomatsakis/rayon/issues/231)
//!
//! ## Restricting multiple versions
//!
//! In order to ensure proper coordination between threadpools, and especially
//! to make sure there's only one global threadpool, `rayon-core` is actively
//! restricted from building multiple versions of itself into a single target.
//! You may see a build error like this in violation:
//!
//! ```text
//! error: native library `rayon-core` is being linked to by more
//! than one package, and can only be linked to by one package
//! ```
//!
//! While we strive to keep `rayon-core` semver-compatible, it's still
//! possible to arrive at this situation if different crates have overly
//! restrictive tilde or inequality requirements for `rayon-core`.  The
//! conflicting requirements will need to be resolved before the build will
//! succeed.

#![allow(non_camel_case_types)] // I prefer to use ALL_CAPS for type parameters
#![cfg_attr(test, feature(conservative_impl_trait))]

// If you're not compiling the unstable code, it often happens that
// there is stuff that is considered "dead code" and so forth. So
// disable warnings in that scenario.
#![cfg_attr(not(rayon_unstable), allow(warnings))]

#[allow(unused_imports)]
use log::Event::*;
use std::any::Any;
use std::env;
use std::error::Error;
use std::str::FromStr;
use std::fmt;

extern crate coco;
#[macro_use]
extern crate lazy_static;
extern crate libc;
extern crate num_cpus;
extern crate rand;

#[macro_use]
mod log;

mod latch;
mod join;
mod job;
mod registry;
mod scope;
mod sleep;
mod spawn;
mod test;
mod thread_pool;
mod unwind;
mod util;

#[cfg(rayon_unstable)]
pub mod internal;
pub use thread_pool::ThreadPool;
pub use thread_pool::current_thread_index;
pub use thread_pool::current_thread_has_pending_tasks;
pub use join::join;
pub use scope::{scope, Scope};
pub use spawn::spawn;

/// Returns the number of threads in the current registry. If this
/// code is executing within a Rayon thread-pool, then this will be
/// the number of threads for the thread-pool of the current
/// thread. Otherwise, it will be the number of threads for the global
/// thread-pool.
///
/// This can be useful when trying to judge how many times to split
/// parallel work (the parallel iterator traits use this value
/// internally for this purpose).
///
/// ### Future compatibility note
///
/// Note that unless this thread-pool was created with a
/// configuration that specifies the number of threads, then this
/// number may vary over time in future versions (see [the
/// `num_threads()` method for details][snt]).
///
/// [snt]: struct.Configuration.html#method.num_threads
pub fn current_num_threads() -> usize {
    ::registry::Registry::current_num_threads()
}

/// Contains the rayon thread pool configuration.
#[derive(Default)]
pub struct Configuration {
    /// The number of threads in the rayon thread pool.
    /// If zero will use the RAYON_NUM_THREADS environment variable.
    /// If RAYON_NUM_THREADS is invalid or zero will use the default.
    num_threads: usize,

    /// Custom closure, if any, to handle a panic that we cannot propagate
    /// anywhere else.
    panic_handler: Option<Box<PanicHandler>>,

    /// Closure to compute the name of a thread.
    get_thread_name: Option<Box<FnMut(usize) -> String>>,

    /// The stack size for the created worker threads
    stack_size: Option<usize>,

    /// Closure invoked on worker thread start.
    start_handler: Option<Box<StartHandler>>,

    /// Closure invoked on worker thread exit.
    exit_handler: Option<Box<ExitHandler>>,

    /// If false, worker threads will execute spawned jobs in a
    /// "depth-first" fashion. If true, they will do a "breadth-first"
    /// fashion. Depth-first is the default.
    breadth_first: bool,
}

/// The type for a panic handling closure. Note that this same closure
/// may be invoked multiple times in parallel.
type PanicHandler = Fn(Box<Any + Send>) + Send + Sync;

/// The type for a closure that gets invoked when a thread starts. The
/// closure is passed the index of the thread on which it is invoked.
/// Note that this same closure may be invoked multiple times in parallel.
type StartHandler = Fn(usize) + Send + Sync;

/// The type for a closure that gets invoked when a thread exits. The
/// closure is passed the index of the thread on which is is invoked.
/// Note that this same closure may be invoked multiple times in parallel.
type ExitHandler = Fn(usize) + Send + Sync;

impl Configuration {
    /// Creates and return a valid rayon thread pool configuration, but does not initialize it.
    pub fn new() -> Configuration {
        Configuration::default()
    }

    /// Get the number of threads that will be used for the thread
    /// pool. See `num_threads()` for more information.
    fn get_num_threads(&self) -> usize {
        if self.num_threads > 0 {
            self.num_threads
        } else {
            match env::var("RAYON_NUM_THREADS").ok().and_then(|s| usize::from_str(&s).ok()) {
                Some(x) if x > 0 => return x,
                Some(x) if x == 0 => return num_cpus::get(),
                _ => {},
            }

            // Support for deprecated `RAYON_RS_NUM_CPUS`.
            match env::var("RAYON_RS_NUM_CPUS").ok().and_then(|s| usize::from_str(&s).ok()) {
                Some(x) if x > 0 => x,
                _ => num_cpus::get(),
            }
        }
    }

    /// Get the thread name for the thread with the given index.
    fn get_thread_name(&mut self, index: usize) -> Option<String> {
        self.get_thread_name.as_mut().map(|c| c(index))
    }

    /// Set a closure which takes a thread index and returns
    /// the thread's name.
    pub fn thread_name<F>(mut self, closure: F) -> Self
    where F: FnMut(usize) -> String + 'static {
        self.get_thread_name = Some(Box::new(closure));
        self
    }

    /// Set the number of threads to be used in the rayon threadpool.
    ///
    /// If you specify a non-zero number of threads using this
    /// function, then the resulting thread-pools are guaranteed to
    /// start at most this number of threads.
    ///
    /// If `num_threads` is 0, or you do not call this function, then
    /// the Rayon runtime will select the number of threads
    /// automatically. At present, this is based on the
    /// `RAYON_NUM_THREADS` environment variable (if set),
    /// or the number of logical CPUs (otherwise).
    /// In the future, however, the default behavior may
    /// change to dynamically add or remove threads as needed.
    ///
    /// **Future compatibility warning:** Given the default behavior
    /// may change in the future, if you wish to rely on a fixed
    /// number of threads, you should use this function to specify
    /// that number. To reproduce the current default behavior, you
    /// may wish to use the [`num_cpus`
    /// crate](https://crates.io/crates/num_cpus) to query the number
    /// of CPUs dynamically.
    ///
    /// **Old environment variable:** `RAYON_NUM_THREADS` is a one-to-one
    /// replacement of the now deprecated `RAYON_RS_NUM_CPUS` environment
    /// variable. If both variables are specified, `RAYON_NUM_THREADS` will
    /// be prefered.
    pub fn num_threads(mut self, num_threads: usize) -> Configuration {
        self.num_threads = num_threads;
        self
    }

    /// Returns a copy of the current panic handler.
    fn take_panic_handler(&mut self) -> Option<Box<PanicHandler>> {
        self.panic_handler.take()
    }

    /// Normally, whenever Rayon catches a panic, it tries to
    /// propagate it to someplace sensible, to try and reflect the
    /// semantics of sequential execution. But in some cases,
    /// particularly with the `spawn()` APIs, there is no
    /// obvious place where we should propagate the panic to.
    /// In that case, this panic handler is invoked.
    ///
    /// If no panic handler is set, the default is to abort the
    /// process, under the principle that panics should not go
    /// unobserved.
    ///
    /// If the panic handler itself panics, this will abort the
    /// process. To prevent this, wrap the body of your panic handler
    /// in a call to `std::panic::catch_unwind()`.
    pub fn panic_handler<H>(mut self, panic_handler: H) -> Configuration
        where H: Fn(Box<Any + Send>) + Send + Sync + 'static
    {
        self.panic_handler = Some(Box::new(panic_handler));
        self
    }

    /// Get the stack size of the worker threads
    fn get_stack_size(&self) -> Option<usize>{
        self.stack_size
    }

    /// Set the stack size of the worker threads
    pub fn stack_size(mut self, stack_size: usize) -> Self {
        self.stack_size = Some(stack_size);
        self
    }

    /// Suggest to worker threads that they execute spawned jobs in a
    /// "breadth-first" fashion. Typically, when a worker thread is
    /// idle or blocked, it will attempt to execute the job from the
    /// *top* of its local deque of work (i.e., the job most recently
    /// spawned). If this flag is set to true, however, workers will
    /// prefer to execute in a *breadth-first* fashion -- that is,
    /// they will search for jobs at the *bottom* of their local
    /// deque. (At present, workers *always* steal from the bottom of
    /// other worker's deques, regardless of the setting of this
    /// flag.)
    ///
    /// If you think of the tasks as a tree, where a parent task
    /// spawns its children in the tree, then this flag loosely
    /// corresponds to doing a breadth-first traversal of the tree,
    /// whereas the default would be to do a depth-first traversal.
    ///
    /// **Note that this is an "execution hint".** Rayon's task
    /// execution is highly dynamic and the precise order in which
    /// independent tasks are executed is not intended to be
    /// guaranteed.
    pub fn breadth_first(mut self) -> Self {
        self.breadth_first = true;
        self
    }

    fn get_breadth_first(&self) -> bool {
        self.breadth_first
    }

    /// Takes the current thread start callback, leaving `None`.
    fn take_start_handler(&mut self) -> Option<Box<StartHandler>> {
        self.start_handler.take()
    }

    /// Set a callback to be invoked on thread start.
    ///
    /// The closure is passed the index of the thread on which it is invoked.
    /// Note that this same closure may be invoked multiple times in parallel.
    /// If this closure panics, the panic will be passed to the panic handler.
    /// If that handler returns, then startup will continue normally.
    pub fn start_handler<H>(mut self, start_handler: H) -> Configuration
        where H: Fn(usize) + Send + Sync + 'static
    {
        self.start_handler = Some(Box::new(start_handler));
        self
    }

    /// Returns a current thread exit callback, leaving `None`.
    fn take_exit_handler(&mut self) -> Option<Box<ExitHandler>> {
        self.exit_handler.take()
    }

    /// Set a callback to be invoked on thread exit.
    ///
    /// The closure is passed the index of the thread on which it is invoked.
    /// Note that this same closure may be invoked multiple times in parallel.
    /// If this closure panics, the panic will be passed to the panic handler.
    /// If that handler returns, then the thread will exit normally.
    pub fn exit_handler<H>(mut self, exit_handler: H) -> Configuration
        where H: Fn(usize) + Send + Sync + 'static
    {
        self.exit_handler = Some(Box::new(exit_handler));
        self
    }
}

/// Initializes the global thread pool. This initialization is
/// **optional**.  If you do not call this function, the thread pool
/// will be automatically initialized with the default
/// configuration. In fact, calling `initialize` is not recommended,
/// except for in two scenarios:
///
/// - You wish to change the default configuration.
/// - You are running a benchmark, in which case initializing may
///   yield slightly more consistent results, since the worker threads
///   will already be ready to go even in the first iteration.  But
///   this cost is minimal.
///
/// Initialization of the global thread pool happens exactly
/// once. Once started, the configuration cannot be
/// changed. Therefore, if you call `initialize` a second time, it
/// will return an error. An `Ok` result indicates that this
/// is the first initialization of the thread pool.
pub fn initialize(config: Configuration) -> Result<(), Box<Error>> {
    let registry = try!(registry::init_global_registry(config));
    registry.wait_until_primed();
    Ok(())
}

impl fmt::Debug for Configuration {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let Configuration { ref num_threads, ref get_thread_name,
                            ref panic_handler, ref stack_size,
                            ref start_handler, ref exit_handler,
                            ref breadth_first } = *self;

        // Just print `Some(<closure>)` or `None` to the debug
        // output.
        struct ClosurePlaceholder;
        impl fmt::Debug for ClosurePlaceholder {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                f.write_str("<closure>")
            }
        }
        let get_thread_name = get_thread_name.as_ref().map(|_| ClosurePlaceholder);
        let panic_handler = panic_handler.as_ref().map(|_| ClosurePlaceholder);
        let start_handler = start_handler.as_ref().map(|_| ClosurePlaceholder);
        let exit_handler = exit_handler.as_ref().map(|_| ClosurePlaceholder);

        f.debug_struct("Configuration")
         .field("num_threads", num_threads)
         .field("get_thread_name", &get_thread_name)
         .field("panic_handler", &panic_handler)
         .field("stack_size", &stack_size)
         .field("start_handler", &start_handler)
         .field("exit_handler", &exit_handler)
         .field("breadth_first", &breadth_first)
         .finish()
    }
}
<commit_msg>Add `build` method to `Configuration`.<commit_after>//!
//! [Under construction](https://github.com/nikomatsakis/rayon/issues/231)
//!
//! ## Restricting multiple versions
//!
//! In order to ensure proper coordination between threadpools, and especially
//! to make sure there's only one global threadpool, `rayon-core` is actively
//! restricted from building multiple versions of itself into a single target.
//! You may see a build error like this in violation:
//!
//! ```text
//! error: native library `rayon-core` is being linked to by more
//! than one package, and can only be linked to by one package
//! ```
//!
//! While we strive to keep `rayon-core` semver-compatible, it's still
//! possible to arrive at this situation if different crates have overly
//! restrictive tilde or inequality requirements for `rayon-core`.  The
//! conflicting requirements will need to be resolved before the build will
//! succeed.

#![allow(non_camel_case_types)] // I prefer to use ALL_CAPS for type parameters
#![cfg_attr(test, feature(conservative_impl_trait))]

// If you're not compiling the unstable code, it often happens that
// there is stuff that is considered "dead code" and so forth. So
// disable warnings in that scenario.
#![cfg_attr(not(rayon_unstable), allow(warnings))]

#[allow(unused_imports)]
use log::Event::*;
use std::any::Any;
use std::env;
use std::error::Error;
use std::str::FromStr;
use std::fmt;

extern crate coco;
#[macro_use]
extern crate lazy_static;
extern crate libc;
extern crate num_cpus;
extern crate rand;

#[macro_use]
mod log;

mod latch;
mod join;
mod job;
mod registry;
mod scope;
mod sleep;
mod spawn;
mod test;
mod thread_pool;
mod unwind;
mod util;

#[cfg(rayon_unstable)]
pub mod internal;
pub use thread_pool::ThreadPool;
pub use thread_pool::current_thread_index;
pub use thread_pool::current_thread_has_pending_tasks;
pub use join::join;
pub use scope::{scope, Scope};
pub use spawn::spawn;

/// Returns the number of threads in the current registry. If this
/// code is executing within a Rayon thread-pool, then this will be
/// the number of threads for the thread-pool of the current
/// thread. Otherwise, it will be the number of threads for the global
/// thread-pool.
///
/// This can be useful when trying to judge how many times to split
/// parallel work (the parallel iterator traits use this value
/// internally for this purpose).
///
/// ### Future compatibility note
///
/// Note that unless this thread-pool was created with a
/// configuration that specifies the number of threads, then this
/// number may vary over time in future versions (see [the
/// `num_threads()` method for details][snt]).
///
/// [snt]: struct.Configuration.html#method.num_threads
pub fn current_num_threads() -> usize {
    ::registry::Registry::current_num_threads()
}

/// Contains the rayon thread pool configuration.
#[derive(Default)]
pub struct Configuration {
    /// The number of threads in the rayon thread pool.
    /// If zero will use the RAYON_NUM_THREADS environment variable.
    /// If RAYON_NUM_THREADS is invalid or zero will use the default.
    num_threads: usize,

    /// Custom closure, if any, to handle a panic that we cannot propagate
    /// anywhere else.
    panic_handler: Option<Box<PanicHandler>>,

    /// Closure to compute the name of a thread.
    get_thread_name: Option<Box<FnMut(usize) -> String>>,

    /// The stack size for the created worker threads
    stack_size: Option<usize>,

    /// Closure invoked on worker thread start.
    start_handler: Option<Box<StartHandler>>,

    /// Closure invoked on worker thread exit.
    exit_handler: Option<Box<ExitHandler>>,

    /// If false, worker threads will execute spawned jobs in a
    /// "depth-first" fashion. If true, they will do a "breadth-first"
    /// fashion. Depth-first is the default.
    breadth_first: bool,
}

/// The type for a panic handling closure. Note that this same closure
/// may be invoked multiple times in parallel.
type PanicHandler = Fn(Box<Any + Send>) + Send + Sync;

/// The type for a closure that gets invoked when a thread starts. The
/// closure is passed the index of the thread on which it is invoked.
/// Note that this same closure may be invoked multiple times in parallel.
type StartHandler = Fn(usize) + Send + Sync;

/// The type for a closure that gets invoked when a thread exits. The
/// closure is passed the index of the thread on which is is invoked.
/// Note that this same closure may be invoked multiple times in parallel.
type ExitHandler = Fn(usize) + Send + Sync;

impl Configuration {
    /// Creates and return a valid rayon thread pool configuration, but does not initialize it.
    pub fn new() -> Configuration {
        Configuration::default()
    }

    /// Create a new `ThreadPool` initialized using this configuration.
    pub fn build(self) -> Result<ThreadPool, Box<Error + 'static>> {
        ThreadPool::new(self)
    }

    /// Get the number of threads that will be used for the thread
    /// pool. See `num_threads()` for more information.
    fn get_num_threads(&self) -> usize {
        if self.num_threads > 0 {
            self.num_threads
        } else {
            match env::var("RAYON_NUM_THREADS").ok().and_then(|s| usize::from_str(&s).ok()) {
                Some(x) if x > 0 => return x,
                Some(x) if x == 0 => return num_cpus::get(),
                _ => {},
            }

            // Support for deprecated `RAYON_RS_NUM_CPUS`.
            match env::var("RAYON_RS_NUM_CPUS").ok().and_then(|s| usize::from_str(&s).ok()) {
                Some(x) if x > 0 => x,
                _ => num_cpus::get(),
            }
        }
    }

    /// Get the thread name for the thread with the given index.
    fn get_thread_name(&mut self, index: usize) -> Option<String> {
        self.get_thread_name.as_mut().map(|c| c(index))
    }

    /// Set a closure which takes a thread index and returns
    /// the thread's name.
    pub fn thread_name<F>(mut self, closure: F) -> Self
    where F: FnMut(usize) -> String + 'static {
        self.get_thread_name = Some(Box::new(closure));
        self
    }

    /// Set the number of threads to be used in the rayon threadpool.
    ///
    /// If you specify a non-zero number of threads using this
    /// function, then the resulting thread-pools are guaranteed to
    /// start at most this number of threads.
    ///
    /// If `num_threads` is 0, or you do not call this function, then
    /// the Rayon runtime will select the number of threads
    /// automatically. At present, this is based on the
    /// `RAYON_NUM_THREADS` environment variable (if set),
    /// or the number of logical CPUs (otherwise).
    /// In the future, however, the default behavior may
    /// change to dynamically add or remove threads as needed.
    ///
    /// **Future compatibility warning:** Given the default behavior
    /// may change in the future, if you wish to rely on a fixed
    /// number of threads, you should use this function to specify
    /// that number. To reproduce the current default behavior, you
    /// may wish to use the [`num_cpus`
    /// crate](https://crates.io/crates/num_cpus) to query the number
    /// of CPUs dynamically.
    ///
    /// **Old environment variable:** `RAYON_NUM_THREADS` is a one-to-one
    /// replacement of the now deprecated `RAYON_RS_NUM_CPUS` environment
    /// variable. If both variables are specified, `RAYON_NUM_THREADS` will
    /// be prefered.
    pub fn num_threads(mut self, num_threads: usize) -> Configuration {
        self.num_threads = num_threads;
        self
    }

    /// Returns a copy of the current panic handler.
    fn take_panic_handler(&mut self) -> Option<Box<PanicHandler>> {
        self.panic_handler.take()
    }

    /// Normally, whenever Rayon catches a panic, it tries to
    /// propagate it to someplace sensible, to try and reflect the
    /// semantics of sequential execution. But in some cases,
    /// particularly with the `spawn()` APIs, there is no
    /// obvious place where we should propagate the panic to.
    /// In that case, this panic handler is invoked.
    ///
    /// If no panic handler is set, the default is to abort the
    /// process, under the principle that panics should not go
    /// unobserved.
    ///
    /// If the panic handler itself panics, this will abort the
    /// process. To prevent this, wrap the body of your panic handler
    /// in a call to `std::panic::catch_unwind()`.
    pub fn panic_handler<H>(mut self, panic_handler: H) -> Configuration
        where H: Fn(Box<Any + Send>) + Send + Sync + 'static
    {
        self.panic_handler = Some(Box::new(panic_handler));
        self
    }

    /// Get the stack size of the worker threads
    fn get_stack_size(&self) -> Option<usize>{
        self.stack_size
    }

    /// Set the stack size of the worker threads
    pub fn stack_size(mut self, stack_size: usize) -> Self {
        self.stack_size = Some(stack_size);
        self
    }

    /// Suggest to worker threads that they execute spawned jobs in a
    /// "breadth-first" fashion. Typically, when a worker thread is
    /// idle or blocked, it will attempt to execute the job from the
    /// *top* of its local deque of work (i.e., the job most recently
    /// spawned). If this flag is set to true, however, workers will
    /// prefer to execute in a *breadth-first* fashion -- that is,
    /// they will search for jobs at the *bottom* of their local
    /// deque. (At present, workers *always* steal from the bottom of
    /// other worker's deques, regardless of the setting of this
    /// flag.)
    ///
    /// If you think of the tasks as a tree, where a parent task
    /// spawns its children in the tree, then this flag loosely
    /// corresponds to doing a breadth-first traversal of the tree,
    /// whereas the default would be to do a depth-first traversal.
    ///
    /// **Note that this is an "execution hint".** Rayon's task
    /// execution is highly dynamic and the precise order in which
    /// independent tasks are executed is not intended to be
    /// guaranteed.
    pub fn breadth_first(mut self) -> Self {
        self.breadth_first = true;
        self
    }

    fn get_breadth_first(&self) -> bool {
        self.breadth_first
    }

    /// Takes the current thread start callback, leaving `None`.
    fn take_start_handler(&mut self) -> Option<Box<StartHandler>> {
        self.start_handler.take()
    }

    /// Set a callback to be invoked on thread start.
    ///
    /// The closure is passed the index of the thread on which it is invoked.
    /// Note that this same closure may be invoked multiple times in parallel.
    /// If this closure panics, the panic will be passed to the panic handler.
    /// If that handler returns, then startup will continue normally.
    pub fn start_handler<H>(mut self, start_handler: H) -> Configuration
        where H: Fn(usize) + Send + Sync + 'static
    {
        self.start_handler = Some(Box::new(start_handler));
        self
    }

    /// Returns a current thread exit callback, leaving `None`.
    fn take_exit_handler(&mut self) -> Option<Box<ExitHandler>> {
        self.exit_handler.take()
    }

    /// Set a callback to be invoked on thread exit.
    ///
    /// The closure is passed the index of the thread on which it is invoked.
    /// Note that this same closure may be invoked multiple times in parallel.
    /// If this closure panics, the panic will be passed to the panic handler.
    /// If that handler returns, then the thread will exit normally.
    pub fn exit_handler<H>(mut self, exit_handler: H) -> Configuration
        where H: Fn(usize) + Send + Sync + 'static
    {
        self.exit_handler = Some(Box::new(exit_handler));
        self
    }
}

/// Initializes the global thread pool. This initialization is
/// **optional**.  If you do not call this function, the thread pool
/// will be automatically initialized with the default
/// configuration. In fact, calling `initialize` is not recommended,
/// except for in two scenarios:
///
/// - You wish to change the default configuration.
/// - You are running a benchmark, in which case initializing may
///   yield slightly more consistent results, since the worker threads
///   will already be ready to go even in the first iteration.  But
///   this cost is minimal.
///
/// Initialization of the global thread pool happens exactly
/// once. Once started, the configuration cannot be
/// changed. Therefore, if you call `initialize` a second time, it
/// will return an error. An `Ok` result indicates that this
/// is the first initialization of the thread pool.
pub fn initialize(config: Configuration) -> Result<(), Box<Error>> {
    let registry = try!(registry::init_global_registry(config));
    registry.wait_until_primed();
    Ok(())
}

impl fmt::Debug for Configuration {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let Configuration { ref num_threads, ref get_thread_name,
                            ref panic_handler, ref stack_size,
                            ref start_handler, ref exit_handler,
                            ref breadth_first } = *self;

        // Just print `Some(<closure>)` or `None` to the debug
        // output.
        struct ClosurePlaceholder;
        impl fmt::Debug for ClosurePlaceholder {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                f.write_str("<closure>")
            }
        }
        let get_thread_name = get_thread_name.as_ref().map(|_| ClosurePlaceholder);
        let panic_handler = panic_handler.as_ref().map(|_| ClosurePlaceholder);
        let start_handler = start_handler.as_ref().map(|_| ClosurePlaceholder);
        let exit_handler = exit_handler.as_ref().map(|_| ClosurePlaceholder);

        f.debug_struct("Configuration")
         .field("num_threads", num_threads)
         .field("get_thread_name", &get_thread_name)
         .field("panic_handler", &panic_handler)
         .field("stack_size", &stack_size)
         .field("start_handler", &start_handler)
         .field("exit_handler", &exit_handler)
         .field("breadth_first", &breadth_first)
         .finish()
    }
}
<|endoftext|>


<commit_before>/// A cache block number.
///
/// Every cache block is assigned a number which is associated with the block in memory.
type BlockNumber = usize;

/// A cache block.
///
/// This stores a single sector in memory, for more performant reads and writes.
///
/// The terminology "cache block" is similar to "cache lines" in CPUs. They represent a single
/// fixed-size block which is cached in memory.
struct Block {
    /// The sector the block stores.
    sector: disk::Sector,
    /// The data of the sector.
    ///
    /// This shall reflect what is on the disk unless the block is marked dirty.
    data: Box<[u8]>,
    /// Does the data in memory reflect the data on the disk?
    ///
    /// This is called _the dirty flag_ and defines if a flush is needed or if the in-memory data
    /// already matches the on-disk data. Whenever it is written in memory, the flag should be set
    /// so that we're sure that it gets flushed properly to the disk.
    dirty: bool,
    /// Disk sectors that shall be flushed _before_ this block.
    ///
    /// This defines the flush dependencies and is crucial to the consistency of the cache. In
    /// particular, ordering matters, since unexpected crashes should never leave the system in an
    /// inconsistent state.
    ///
    /// To consider flush ordering, we define a poset on the cache blocks. If `A < B`, `A` should
    /// be written prior to `B`. This is represented as an ADG. The algorithm for flushing is:
    /// write the orphan nodes to the disk, until no nodes are dirty.
    ///
    /// In other words, the sectors in this vector are _guaranteed_ to be written before the block
    /// itself.
    flush_dependencies: Vec<disk::Sector>,
}

impl Block {
    /// Reset the cache block.
    ///
    /// This resets the dirty flag and clears the flush dependencies.
    ///
    /// Note that it does not change the data or the sector.
    fn reset(&mut self) {
        // The cache block starts out as clean...
        self.dirty = false;
        // ...and hence has no dependencies.
        self.flush_dependencies.clear();
    }

    /// Add a sector to flush before the block.
    fn add_dependency(&mut self, sector: disk::Sector) {
        // To avoid meta-cycles, we make sure that the dependent sector isn't the sector of the
        // block itself.
        if self.sector != sector {
            self.flush_dependencies.push(sector);
        }
    }
}

/// A cached disk.
///
/// This wrapper manages caching and the consistency issues originating from it.
///
/// It organizes the cache into _cache blocks_ each representing some _disk sector_. The cache
/// blocks are put in a _dependency graph_ which enforces the ordering of flushes (writes to
/// disks).
struct Cache<D> {
    /// The raw disk.
    disk: D,
    /// The cache replacement tracker.
    ///
    /// This tracks the state of the replacement algorithm, which chooses which cache block shall
    /// be replaced in favor of a new cache. It serves to estimate/guess which block is likely not
    /// used in the near future. This guessed block is then replaced by a fresh new cache block.
    cache_tracker: plru::DynamicCache,
    /// The sector-to-cache-block map.
    ///
    /// This associates the disk sector with its respective cache block.
    block_map: RwLock<HashMap<disk::Sector, BlockNumber>>,
    /// The cache blocks.
    blocks: RwLock<Vec<[RwLock<Block>]>>,
}

impl<D: Disk> Cached<D> {
    /// Execute a transaction on the cache.
    pub fn run<T: Transaction>(&mut self, transaction: T) -> Result<(), disk::Error> {
        transaction.execute(self, None)?;
    }

    /// Flush a cache block to the disk.
    ///
    /// This can potentially trigger outer flushes if the cache block has flush dependencies.
    pub fn flush(&mut self, block: BlockNumber) -> Result<(), disk::Error> {
        // Read the block.
        let block = &mut self.blocks[block];

        // Flush all the dependencies. This is important for correct ordering!
        for sector_dep in block.flush_dependencies {
            if let Some(block_dep) = self.block_map.get(sector_dep) {
                self.flush(block_dep)?;
            }
            // It could happen naturally that the dependent sector was not found in the block
            // map. Namely, if the sector was replaced by another cache block. In such case, the
            // sector is naturally already flushed (during replacement) and thus there is no
            // consistency issues.
        }

        // Check if the block is (still) dirty.
        if block.dirty {
            // Write the block to the disk.
            self.disk.write(block.sector, &block.data)?;
            // Unset the dirty flag.
            block.dirty = false;
        }
    }

    /// Allocate (or find replacement) for a new cache block.
    ///
    /// This finds a cache block which can be used for new objects.
    ///
    /// It will reset and flush the block and update the block map.
    fn alloc_block(&mut self) -> BlockNumber {
        // Test if the cache is filled.
        if self.blocks.len() < self.cache_tracker.len() {
            // The cache is not filled, so we don't need to replace any cache block, we can simply
            // push.
            self.blocks.push(Block {
                sector: sector,
                data: vec![0; disk::SECTOR_SIZE],
                dirty: false,
                flush_dependencies: Vec::new(),
            });

            self.blocks.len() - 1
        } else {
            // Find a candidate for replacement.
            let block_number = self.cache_tracker.replace();

            // Flush it to the disk before throwing the data away.
            self.flush(block_number);

            // Remove the old sector from the cache block map.
            let block = &mut self.blocks[block_number];
            self.block_map.remove(block.sector);

            // Reset the cache block.
            block.reset();

            block_number
        }
    }

    /// Fetch an uncached disk sector to the cache.
    ///
    /// This will fetch `sector` from the disk to store it in the in-memory cache structure.
    fn fetch_fresh(&mut self, sector: disk::Sector) -> Result<&mut Block, disk::Error> {
        // Allocate a new cache block.
        let block_number = self.alloc_block();
        let block = &mut self.blocks[block_number];

        // Read the sector from the disk.
        self.disk.read(sector, &mut block.data)?;

        // Update the sector number.
        block.sector = sector;

        // Update the cache block map with the new block.
        self.block_map.insert(sector, block_number);
    }

    /// Get the cache block for a sector.
    ///
    /// This grabs the sector from the cache or from the disk, if necessary.
    fn get(&mut self, sector: disk::Sector) -> Result<&mut Block, disk::Error> {
        // Check if the sector already exists in the cache.
        if let Some(block) = self.block_map.get_mut(sector) {
            // It did!

            // Touch the cache block.
            self.cache_tracker.touch(block);

            // Read the block.
            Ok(&mut self.blocks[block])
        } else {
            // It didn't, so we read it from the disk:
            self.fetch_fresh(sector)
        }
    }
}

/// A cache transaction.
///
/// This refer an atomic instruction for modifying the cache.
///
/// Transactions are said to _depend_ on another transaction if the other transaction ought to be
/// commited to the disk prior to the transaction itself.
trait Transaction {
    /// Execute a transaction on a cache.
    ///
    /// This executes a transaction into a cache `cache`. The transaction depends on the cache
    /// block specified in `dependency`, if any. `dependency` shall be flushed before the
    /// transaction is committed to the disk.
    ///
    /// The returned value (if it suceeds) is a cache block number specifying the cache block that
    /// was modified in the transaction. If multiple blocks were modified, they shall depend on
    /// each other and the returned value should be the last block in the dependency chain.
    fn execute<D: Disk>(self, cache: &mut Cache<D>, dependency: Option<BlockNumber>)
        -> Result<BlockNumber, disk::Error>;

    /// Append another transaction to be executed sequentially.
    ///
    /// This adapter takes some transaction `next` and produces a new transaction, which will run
    /// the two transactions sequentially such that `next` depends on `self`.
    fn then<T: Transaction>(self, next: T) -> impl Transaction {
        Sequential(self, next)
    }
}

/// An adapter than runs two transactions sequentially.
///
/// This will make sure `T` is committed to the disk before `U`.
struct Sequential<T: Tranaction, U: Transaction>(T, U);

impl<T: Transaction, U: Tranaction> Transaction for Sequential<T, U> {
    fn execute<D: Disk>(self, cache: &mut Cache<D>, dependency: Option<BlockNumber>)
        -> Result<&mut Block, disk::Error> {
        // Execute the first transaction.
        let block_number = self.0.execute(dependency, cache)?;
        // Execute the second transaction to depend on the first transaction.
        self.1.execute(cache, Some(block_number))
    }
}

/// A sector write transaction.
///
/// This is a transaction to commit some new data to a sector, either in memory or on disk.
struct WriteSector<'a> {
    /// The sector to write.
    sector: disk::Sector,
    /// The data to write.
    ///
    /// This buffer must be of the sector size.
    data: &'a [u8],
}

impl<T: Transaction, U: Tranaction> Transaction for WriteSector<T, U> {
    fn execute<D: Disk>(self, cache: &mut Cache<D>, dependency: Option<BlockNumber>)
        -> Result<&mut Block, disk::Error> {
        // Allocate a new cache block.
        let block_number = cache.alloc_block();
        let block = &mut cache.blocks[block_number];

        // Copy the data into the freshly allocated cache block.
        block.data.copy_from_slice(data);

        // Update the sector number.
        block.sector = sector;
        // Add the potential dependency to the cache block.
        if let Some(dependency) = dependency {
            block.add_dependency(dependency)
        }
        // Mark dirty.
        block.dirty = true;

        // Update the cache block map with the new block.
        cache.block_map.insert(sector, block_number);

        block
    }
}

/// A transaction to write a 64-bit little-endian integer.
struct WriteU64 {
    /// The cluster to write the integer in.
    cluster: cluster::Pointer,
    /// The offset byte in which the integer will be written.
    offset: usize,
    /// The integer to be written.
    x: u64,
}

impl<T: Transaction, U: Tranaction> Transaction for Write<T, U> {
    fn execute<D: Disk>(self, cache: &mut Cache<D>, dependency: Option<BlockNumber>) -> Result<&mut Block, disk::Error> {
        // Calculate the sector for the cluster.
        let sector = self.cluster * cluster::SIZE / disk::SECTOR_SIZE + self.offset / disk::SECTOR_SIZE;

        // Read the cache block of the sector.
        let block = cache.get(sector)?;
        // Add the potential dependency to the cache block.
        if let Some(dependency) = dependency {
            block.add_dependency(dependency)
        }
        // Mark dirty.
        block.dirty = true;

        // Write the integer into the data buffer.
        LittleEndian::write(block.data[self.offset % disk::SECTOR_SIZE..], x);
    }
}
<commit_msg>Add the concept of the cache pipeline.<commit_after>/// A cache block number.
///
/// Every cache block is assigned a number which is associated with the block in memory.
type BlockNumber = usize;

/// A cache block.
///
/// This stores a single sector in memory, for more performant reads and writes.
///
/// The terminology "cache block" is similar to "cache lines" in CPUs. They represent a single
/// fixed-size block which is cached in memory.
struct Block {
    /// The sector the block stores.
    sector: disk::Sector,
    /// The data of the sector.
    ///
    /// This shall reflect what is on the disk unless the block is marked dirty.
    data: Box<[u8]>,
    /// Does the data in memory reflect the data on the disk?
    ///
    /// This is called _the dirty flag_ and defines if a flush is needed or if the in-memory data
    /// already matches the on-disk data. Whenever it is written in memory, the flag should be set
    /// so that we're sure that it gets flushed properly to the disk.
    dirty: bool,
    /// Disk sectors that shall be flushed _before_ this block.
    ///
    /// This defines the flush dependencies and is crucial to the consistency of the cache. In
    /// particular, ordering matters, since unexpected crashes should never leave the system in an
    /// inconsistent state.
    ///
    /// To consider flush ordering, we define a poset on the cache blocks. If `A < B`, `A` should
    /// be written prior to `B`. This is represented as an ADG. The algorithm for flushing is:
    /// write the orphan nodes to the disk, until no nodes are dirty.
    ///
    /// In other words, the sectors in this vector are _guaranteed_ to be written before the block
    /// itself.
    flush_dependencies: Vec<disk::Sector>,
}

impl Block {
    /// Reset the cache block.
    ///
    /// This resets the dirty flag and clears the flush dependencies.
    ///
    /// Note that it does not change the data or the sector.
    fn reset(&mut self) {
        // The cache block starts out as clean...
        self.dirty = false;
        // ...and hence has no dependencies.
        self.flush_dependencies.clear();
    }

    /// Add a sector to flush before the block.
    fn add_dependency(&mut self, sector: disk::Sector) {
        // To avoid meta-cycles, we make sure that the dependent sector isn't the sector of the
        // block itself.
        if self.sector != sector {
            self.flush_dependencies.push(sector);
        }
    }
}

/// A cached disk.
///
/// This wrapper manages caching and the consistency issues originating from it.
///
/// It organizes the cache into _cache blocks_ each representing some _disk sector_. The cache
/// blocks are put in a _dependency graph_ which enforces the ordering of flushes (writes to
/// disks).
struct Cache<D> {
    /// The raw disk.
    disk: D,
    /// The cache replacement tracker.
    ///
    /// This tracks the state of the replacement algorithm, which chooses which cache block shall
    /// be replaced in favor of a new cache. It serves to estimate/guess which block is likely not
    /// used in the near future. This guessed block is then replaced by a fresh new cache block.
    cache_tracker: plru::DynamicCache,
    /// The sector-to-cache-block map.
    ///
    /// This associates the disk sector with its respective cache block.
    block_map: RwLock<HashMap<disk::Sector, BlockNumber>>,
    /// The cache blocks.
    blocks: RwLock<Vec<[RwLock<Block>]>>,
    /// The pipeline of writes to-be-committed.
    ///
    /// These are not commited to the block map yet and will not be until `.commit()` is called.
    /// They are ensured to be written to the disk in the order of the pipeline.
    pipeline: Vec<(disk::Sector, Box<[u8]>)>,
}

impl<D: Disk> Cached<D> {
    /// Flush a cache block to the disk.
    ///
    /// This can potentially trigger outer flushes if the cache block has flush dependencies.
    ///
    /// Note that this doesn't commit the pipeline.
    pub fn flush(&mut self, block: BlockNumber) -> Result<(), disk::Error> {
        // Read the block.
        let block = &mut self.blocks[block];

        // Flush all the dependencies. This is important for correct ordering!
        for sector_dep in block.flush_dependencies {
            if let Some(block_dep) = self.block_map.get(sector_dep) {
                self.flush(block_dep)?;
            }
            // It could happen naturally that the dependent sector was not found in the block
            // map. Namely, if the sector was replaced by another cache block. In such case, the
            // sector is naturally already flushed (during replacement) and thus there is no
            // consistency issues.
        }

        // Check if the block is (still) dirty.
        if block.dirty {
            // Write the block to the disk.
            self.disk.write(block.sector, &block.data)?;
            // Unset the dirty flag.
            block.dirty = false;
        }
    }

    /// Read a sector from the disk.
    ///
    /// Note that this does not respond to writes in the pipeline, only committed transactions.
    pub fn read(&self, sector: disk::Sector) -> Result<&[u8], disk::Error> {
        Ok(self.get(sector)?.data)
    }

    /// Queue a write to the pipeline.
    ///
    /// This pushes a transaction to the pipeline, which can be committed through `.commit()`.
    pub fn queue(&mut self, sector: disk::Sector, buf: Box<[u8]>) {
        self.pipeline.push((sector, buf));
    }

    /// Commit the transactions in the pipeline to the cache.
    ///
    /// This commits the sectors and data given in the pipeline in the specified order enforcing
    /// consistency with respect to the flush order.
    pub fn commit(&mut self) {
        if Some((first_sector, first_buf)) = writes.next() {
            // Write the first block which has no dependencies.
            let mut block = self.commit_write(first_sector, first_buf, None);

            // Write the rest with the previous write as dependency.
            for (sector, buf) in self.pipeline.drain() {
                block = self.commit_write(sector, buf, Some(block.sector));
            }
        }
    }

    /// Commits a sector write with some dependency.
    ///
    /// This writes `buf` into sector `sector` in the cache, ensuring that the sector (if any)
    /// `dependency` is flushed to the disk prior to `sector`.
    fn commit_write(&mut self, sector: cluster::Pointer, buf: Box<[u8]>, dependency: Option<disk::Sector>) -> &mut Block {
        // Allocate a new cache block.
        let block_number = cache.alloc_block();
        let block = &mut cache.blocks[block_number];

        // Put the data into the freshly allocated cache block.
        block.data = buf;

        // Update the sector number.
        block.sector = sector;
        // Add the potential dependency to the cache block.
        if let Some(dependency) = dependency {
            block.add_dependency(dependency)
        }
        // Mark dirty.
        block.dirty = true;

        // Update the cache block map with the new block.
        cache.block_map.insert(sector, block_number);

        block
    }

    /// Allocate (or find replacement) for a new cache block.
    ///
    /// This finds a cache block which can be used for new objects.
    ///
    /// It will reset and flush the block and update the block map.
    fn alloc_block(&mut self) -> BlockNumber {
        // Test if the cache is filled.
        if self.blocks.len() < self.cache_tracker.len() {
            // The cache is not filled, so we don't need to replace any cache block, we can simply
            // push.
            self.blocks.push(Block {
                sector: sector,
                data: vec![0; disk::SECTOR_SIZE],
                dirty: false,
                flush_dependencies: Vec::new(),
            });

            self.blocks.len() - 1
        } else {
            // Find a candidate for replacement.
            let block_number = self.cache_tracker.replace();

            // Flush it to the disk before throwing the data away.
            self.flush(block_number);

            // Remove the old sector from the cache block map.
            let block = &mut self.blocks[block_number];
            self.block_map.remove(block.sector);

            // Reset the cache block.
            block.reset();

            block_number
        }
    }

    /// Fetch an uncached disk sector to the cache.
    ///
    /// This will fetch `sector` from the disk to store it in the in-memory cache structure.
    fn fetch_fresh(&mut self, sector: disk::Sector) -> Result<&mut Block, disk::Error> {
        // Allocate a new cache block.
        let block_number = self.alloc_block();
        let block = &mut self.blocks[block_number];

        // Read the sector from the disk.
        self.disk.read(sector, &mut block.data)?;

        // Update the sector number.
        block.sector = sector;

        // Update the cache block map with the new block.
        self.block_map.insert(sector, block_number);
    }

    /// Get the cache block for a sector.
    ///
    /// This grabs the sector from the cache or from the disk, if necessary.
    fn get(&mut self, sector: disk::Sector) -> Result<&mut Block, disk::Error> {
        // Check if the sector already exists in the cache.
        if let Some(block) = self.block_map.get_mut(sector) {
            // It did!

            // Touch the cache block.
            self.cache_tracker.touch(block);

            // Read the block.
            Ok(&mut self.blocks[block])
        } else {
            // It didn't, so we read it from the disk:
            self.fetch_fresh(sector)
        }
    }
}
<|endoftext|>


<commit_before>// (c) 2017 Productize SPRL <joost@productize.be>

use std::iter::Peekable;
use std::slice::Iter;

use Sexp;
pub use Result as SResult;

/// convert an `&Sexp` to something
pub trait FromSexp
    where Self: Sized
{
    /// convert from a symbolic-expression to something
    fn from_sexp(&Sexp) -> SResult<Self>;
}

/// convert from a symbolic-expression to something (dispatcher)
pub fn from_sexp<T: FromSexp>(s: &Sexp) -> SResult<T> {
    T::from_sexp(s)
}

/// Atom iterator wrapper
pub struct IterAtom<'a> {
    name: String,
    /// containing iterable (pub for now)
    pub iter: Peekable<Iter<'a, Sexp>>,
}

impl<'a> IterAtom<'a> {
    /// deconstruct a `Sexp` that is a list and starts with 'name'
    pub fn new(s: &'a Sexp, name: &str) -> SResult<IterAtom<'a>> {
        let v = s.list()?;
        let mut i = v.iter();
        let st = match i.next() {
            None => return Err(format!("missing first element {} in list {}", name, s).into()),
            Some(e) => e.string()?,
        };
        if st != name {
            return Err(format!("list {} doesn't start with {}, but with {}", s, name, st).into());
        }
        let i = i.peekable();
        Ok(IterAtom {
            name: name.into(),
            iter: i,
        })
    }

    /// deconstruct a `Sexp` that is a list and doesn't start with a name
    pub fn new_nameless(s: &'a Sexp, name:&str) -> SResult<IterAtom<'a>> {
        Ok(IterAtom {
            name: name.into(),
            iter: s.list()?.iter().peekable(),
        })
    }

    fn expect<T, F>(&mut self, name: &str, get: F) -> SResult<T>
        where F: Fn(&Sexp) -> SResult<T>
    {
        match self.iter.next() {
            Some(x) => get(x),
            None => return Err(format!("missing {} field in {}", name, self.name).into()),
        }
    }

    /// expect an integer while iterating a `Sexp` list
    pub fn i(&mut self, name: &str) -> SResult<i64> {
        self.expect(name, |x| x.i().map_err(From::from))
    }

    /// expect a float while iterating a `Sexp` list
    pub fn f(&mut self, name: &str) -> SResult<f64> {
        self.expect(name, |x| x.f().map_err(From::from))
    }

    /// expect a String while iterating a `Sexp` list
    pub fn s(&mut self, name: &str) -> SResult<String> {
        self.expect(name, |x| x.s().map_err(From::from))
    }

    /// expect a list contained String while iterating a `Sexp` list
    pub fn s_in_list(&mut self, name: &str) -> SResult<String> {
        self.expect(name,
                    |x| x.named_value_s(name).map_err(From::from))
    }

    /// expect a list contained i64 while iterating a `Sexp` list
    pub fn i_in_list(&mut self, name: &str) -> SResult<i64> {
        self.expect(name, |x| x.named_value_i(name).map_err(From::from))
    }

    /// expect a list contained f64 while iterating a `Sexp` list
    pub fn f_in_list(&mut self, name: &str) -> SResult<f64> {
        self.expect(name, |x| x.named_value_f(name).map_err(From::from))
    }

    /// expect a `Sexp` while iterating a `Sexp` list
    pub fn t<T: FromSexp>(&mut self, name: &str) -> SResult<T> {
        self.expect(name, |x| T::from_sexp(x))
    }

        /// expect a list containing a `Sexp` while iterating a `Sexp` list
    pub fn t_in_list<T: FromSexp>(&mut self, name: &str) -> SResult<T> {
        self.expect(name, |x| T::from_sexp(x.named_value(name)?))
    }

    /// expect remainder of iterator to be a `Vec<T>`
    pub fn vec<T: FromSexp>(&mut self) -> SResult<Vec<T>> {
        let mut res = Vec::new();
        loop {
            match self.iter.next() {
                None => break,
                Some(e) => {
                    let p = from_sexp(e)?;
                    res.push(p);
                }
            }
        }
        Ok(res)
    }

    /// maybe something while iterating a `Sexp` list
    fn maybe<X, F>(&mut self, convert: F) -> Option<X>
        where F: Fn(&Sexp) -> SResult<X>
    {
        let res = match self.iter.peek() {
            None => None,
            Some(s) => {
                match convert(s) {
                    Ok(t) => Some(t),
                    Err(_) => None,
                }
            }
        };
        match res {
            Some(x) => {
                let _ = self.iter.next();
                Some(x)
            }
            x => x,
        }
    }

    /// maybe a `FromSexp` while iterating a `Sexp` list
    pub fn maybe_t<T: FromSexp>(&mut self) -> Option<T> {
        self.maybe(|x| T::from_sexp(x))
    }

    /// maybe a `String` while iterating a `Sexp` list
    pub fn maybe_s(&mut self) -> Option<String> {
        self.maybe(|x| x.s())
    }

    /// maybe a `String` while iterating a `Sexp` list
    pub fn maybe_literal_s(&mut self, l:&str) -> Option<String> {
        self.maybe(|x| {
            let z = x.s()?;
            if &z == l {
                Ok(z)
            } else {
                Err("unexpected".into())
            }
        })
    }

    /// maybe an `i64` while iterating a `Sexp` list
    pub fn maybe_i(&mut self) -> Option<i64> {
        self.maybe(|x| x.i())
    }

    /// maybe an `f64` while iterating a `Sexp` list
    pub fn maybe_f(&mut self) -> Option<f64> {
        self.maybe(|x| x.f())
    }

    /// maybe a list containing a `String` while iterating a `Sexp` list
    pub fn maybe_s_in_list(&mut self, name:&str) -> Option<String> {
        self.maybe(|x| x.named_value_s(name))
    }

    /// maybe a list containing an `i64` while iterating a `Sexp` list
    pub fn maybe_i_in_list(&mut self, name:&str) -> Option<i64> {
        self.maybe(|x| x.named_value_i(name))
    }

    /// maybe a list containing an `f64` while iterating a `Sexp` list
    pub fn maybe_f_in_list(&mut self, name:&str) -> Option<f64> {
        self.maybe(|x| x.named_value_f(name))
    }

    /// make sure we consumed all of the iterator
    pub fn close<T>(&mut self, x:T) -> SResult<T> {
        match self.iter.next() {
            Some(x) => Err(format!("Unexpected {} in {}", x, self.name).into()),
            None => Ok(x)
        }
    }
}
<commit_msg>cargo fmt<commit_after>// (c) 2017 Productize SPRL <joost@productize.be>

use std::iter::Peekable;
use std::slice::Iter;

use Sexp;
pub use Result as SResult;

/// convert an `&Sexp` to something
pub trait FromSexp
    where Self: Sized
{
    /// convert from a symbolic-expression to something
    fn from_sexp(&Sexp) -> SResult<Self>;
}

/// convert from a symbolic-expression to something (dispatcher)
pub fn from_sexp<T: FromSexp>(s: &Sexp) -> SResult<T> {
    T::from_sexp(s)
}

/// Atom iterator wrapper
pub struct IterAtom<'a> {
    name: String,
    /// containing iterable (pub for now)
    pub iter: Peekable<Iter<'a, Sexp>>,
}

impl<'a> IterAtom<'a> {
    /// deconstruct a `Sexp` that is a list and starts with 'name'
    pub fn new(s: &'a Sexp, name: &str) -> SResult<IterAtom<'a>> {
        let v = s.list()?;
        let mut i = v.iter();
        let st = match i.next() {
            None => return Err(format!("missing first element {} in list {}", name, s).into()),
            Some(e) => e.string()?,
        };
        if st != name {
            return Err(format!("list {} doesn't start with {}, but with {}", s, name, st).into());
        }
        let i = i.peekable();
        Ok(IterAtom {
            name: name.into(),
            iter: i,
        })
    }

    /// deconstruct a `Sexp` that is a list and doesn't start with a name
    pub fn new_nameless(s: &'a Sexp, name: &str) -> SResult<IterAtom<'a>> {
        Ok(IterAtom {
            name: name.into(),
            iter: s.list()?.iter().peekable(),
        })
    }

    fn expect<T, F>(&mut self, name: &str, get: F) -> SResult<T>
        where F: Fn(&Sexp) -> SResult<T>
    {
        match self.iter.next() {
            Some(x) => get(x),
            None => return Err(format!("missing {} field in {}", name, self.name).into()),
        }
    }

    /// expect an integer while iterating a `Sexp` list
    pub fn i(&mut self, name: &str) -> SResult<i64> {
        self.expect(name, |x| x.i().map_err(From::from))
    }

    /// expect a float while iterating a `Sexp` list
    pub fn f(&mut self, name: &str) -> SResult<f64> {
        self.expect(name, |x| x.f().map_err(From::from))
    }

    /// expect a String while iterating a `Sexp` list
    pub fn s(&mut self, name: &str) -> SResult<String> {
        self.expect(name, |x| x.s().map_err(From::from))
    }

    /// expect a list contained String while iterating a `Sexp` list
    pub fn s_in_list(&mut self, name: &str) -> SResult<String> {
        self.expect(name, |x| x.named_value_s(name).map_err(From::from))
    }

    /// expect a list contained i64 while iterating a `Sexp` list
    pub fn i_in_list(&mut self, name: &str) -> SResult<i64> {
        self.expect(name, |x| x.named_value_i(name).map_err(From::from))
    }

    /// expect a list contained f64 while iterating a `Sexp` list
    pub fn f_in_list(&mut self, name: &str) -> SResult<f64> {
        self.expect(name, |x| x.named_value_f(name).map_err(From::from))
    }

    /// expect a `Sexp` while iterating a `Sexp` list
    pub fn t<T: FromSexp>(&mut self, name: &str) -> SResult<T> {
        self.expect(name, |x| T::from_sexp(x))
    }

    /// expect a list containing a `Sexp` while iterating a `Sexp` list
    pub fn t_in_list<T: FromSexp>(&mut self, name: &str) -> SResult<T> {
        self.expect(name, |x| T::from_sexp(x.named_value(name)?))
    }

    /// expect remainder of iterator to be a `Vec<T>`
    pub fn vec<T: FromSexp>(&mut self) -> SResult<Vec<T>> {
        let mut res = Vec::new();
        loop {
            match self.iter.next() {
                None => break,
                Some(e) => {
                    let p = from_sexp(e)?;
                    res.push(p);
                }
            }
        }
        Ok(res)
    }

    /// maybe something while iterating a `Sexp` list
    fn maybe<X, F>(&mut self, convert: F) -> Option<X>
        where F: Fn(&Sexp) -> SResult<X>
    {
        let res = match self.iter.peek() {
            None => None,
            Some(s) => {
                match convert(s) {
                    Ok(t) => Some(t),
                    Err(_) => None,
                }
            }
        };
        match res {
            Some(x) => {
                let _ = self.iter.next();
                Some(x)
            }
            x => x,
        }
    }

    /// maybe a `FromSexp` while iterating a `Sexp` list
    pub fn maybe_t<T: FromSexp>(&mut self) -> Option<T> {
        self.maybe(|x| T::from_sexp(x))
    }

    /// maybe a `String` while iterating a `Sexp` list
    pub fn maybe_s(&mut self) -> Option<String> {
        self.maybe(|x| x.s())
    }

    /// maybe a `String` while iterating a `Sexp` list
    pub fn maybe_literal_s(&mut self, l: &str) -> Option<String> {
        self.maybe(|x| {
            let z = x.s()?;
            if &z == l {
                Ok(z)
            } else {
                Err("unexpected".into())
            }
        })
    }

    /// maybe an `i64` while iterating a `Sexp` list
    pub fn maybe_i(&mut self) -> Option<i64> {
        self.maybe(|x| x.i())
    }

    /// maybe an `f64` while iterating a `Sexp` list
    pub fn maybe_f(&mut self) -> Option<f64> {
        self.maybe(|x| x.f())
    }

    /// maybe a list containing a `String` while iterating a `Sexp` list
    pub fn maybe_s_in_list(&mut self, name: &str) -> Option<String> {
        self.maybe(|x| x.named_value_s(name))
    }

    /// maybe a list containing an `i64` while iterating a `Sexp` list
    pub fn maybe_i_in_list(&mut self, name: &str) -> Option<i64> {
        self.maybe(|x| x.named_value_i(name))
    }

    /// maybe a list containing an `f64` while iterating a `Sexp` list
    pub fn maybe_f_in_list(&mut self, name: &str) -> Option<f64> {
        self.maybe(|x| x.named_value_f(name))
    }

    /// make sure we consumed all of the iterator
    pub fn close<T>(&mut self, x: T) -> SResult<T> {
        match self.iter.next() {
            Some(x) => Err(format!("Unexpected {} in {}", x, self.name).into()),
            None => Ok(x),
        }
    }
}
<|endoftext|>


<commit_before>#![crate_name = "ansi_term"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![desc = "A rust library for ANSI terminal colours and styles (bold, underline)"]

//! This is a library for controlling colours and formatting, such as
//! red bold text or blue underlined text, on ANSI terminals.
//!
//! ```rust
//! extern crate ansi_term;
//! use ansi_term::Colour::{Black, Red, Green, Yellow, Blue, Purple, Cyan, Fixed};
//! use ansi_term::Style::Plain;
//! use ansi_term::Paint;
//! ```
//!
//! Simple Colours
//! --------------
//!
//! You can format strings by calling the `paint` method on a Colour
//! or a Style object, passing in the string you want to format. For
//! example, to get some red text, call the `paint` method on `Red`:
//!
//! ```rust
//! Red.paint("Red!")
//! ```
//!
//! You can also call the `paint` method on a Style. To turn a Colour
//! into a Style, use the `normal` method, though this does the exact
//! some thing as above:
//!
//! ```rust
//! Red.normal().paint("Still red!")
//! ```
//!
//! Bold, Underline, and Background
//! -------------------------------
//!
//! To do anything more complex than just foreground colours, you need
//! to use Style objects. Calling the `bold` or `underline` method on
//! a Colour returns a Style that has the appropriate property set on
//! it:
//!
//! ```rust
//! Blue.bold().paint("Blue bold!")
//! Yellow.underline().paint("Yellow underline!")
//! ```
//!
//! Again, you can call these methods on Styles as well as just Colours:
//!
//! ```rust
//! Blue.normal().bold().paint("Still blue bold!")
//! ```
//!
//! Finally, you can set the background colour of a Style by using the
//! `on` method:
//!
//! ```rust
//! Blue.on(Yellow).paint("Blue on yellow!")
//! ```
//!
//! Extended Colours
//! ----------------
//!
//! You can access the extended range of 256 colours by using the
//! Fixed constructor, which takes an argument of the colour number to
//! use. This can be used wherever you would use a Colour:
//!
//! ```rust
//! Fixed(134).paint("A sort of light purple.")
//! ```
//!
//! This even works for background colours:
//!
//! ```rust
//! Fixed(221).on(Fixed(124)).paint("Mustard in the ketchup.")
//! ```
//!
//! No Formatting
//! -------------
//!
//! Finally, for the sake of completeness, the Plain style provides
//! neither colours nor formatting.
//!
//! ```rust
//! Plain.paint("No colours here.")
//! ```

#![feature(phase)] extern crate regex;
#[phase(plugin)] extern crate regex_macros;
use Colour::{Black, Red, Green, Yellow, Blue, Purple, Cyan, White, Fixed};
use Style::{Plain, Foreground, Styled};

pub trait Paint {
    /// Paints the given text with this colour.
    fn paint(&self, input: &str) -> String;

    /// Returns a Style with the underline property set.
    fn underline(&self) -> Style;

    /// Return a Style with the bold property set.
    fn bold(&self) -> Style;

    /// Return a Style with the background colour set.
    fn on(&self, background: Colour) -> Style;
}

/// A colour is one specific type of ANSI escape code, and can refer
/// to either the foreground or background colour.
pub enum Colour {
    Black, Red, Green, Yellow, Blue, Purple, Cyan, White, Fixed(u8),
}

// These are the standard numeric sequences.
// See http://invisible-island.net/xterm/ctlseqs/ctlseqs.html

impl Colour {
    fn foreground_code(&self) -> String {
        match *self {
            Black => "30".to_string(),
            Red => "31".to_string(),
            Green => "32".to_string(),
            Yellow => "33".to_string(),
            Blue => "34".to_string(),
            Purple => "35".to_string(),
            Cyan => "36".to_string(),
            White => "37".to_string(),
            Fixed(num) => format!("38;5;{}", num),
        }
    }

    fn background_code(&self) -> String {
        match *self {
            Black => "40".to_string(),
            Red => "41".to_string(),
            Green => "42".to_string(),
            Yellow => "43".to_string(),
            Blue => "44".to_string(),
            Purple => "45".to_string(),
            Cyan => "46".to_string(),
            White => "47".to_string(),
            Fixed(num) => format!("48;5;{}", num),
        }
    }

    /// Return a Style with the foreground colour set to this colour.
    pub fn normal(&self) -> Style {
        Styled { foreground: *self, background: None, bold: false, underline: false }
    }
}

/// The Paint trait represents a style or colour that can be applied
/// to a piece of text.
impl Paint for Colour {
    /// This is a short-cut so you don't have to use Blue.normal() just
    /// to get blue text.
    fn paint(&self, input: &str) -> String {
        let re = format!("\x1B[{}m{}\x1B[0m", self.foreground_code(), input);
        return re.to_string();
    }

    fn underline(&self) -> Style {
        Styled { foreground: *self, background: None, bold: false, underline: true }
    }

    fn bold(&self) -> Style {
        Styled { foreground: *self, background: None, bold: true, underline: false }
    }

    fn on(&self, background: Colour) -> Style {
        Styled { foreground: *self, background: Some(background), bold: false, underline: false }
    }
}

/// A style is a collection of properties that can format a string
/// using ANSI escape codes.
pub enum Style {

    /// The Plain style provides no formatting.
    Plain,

    /// The Foreground style provides just a foreground colour.
    Foreground(Colour),

    ///
    /// The Styled style is a catch-all for anything more complicated
    /// than that. It's technically possible for there to be other
    /// cases, such as "bold foreground", but probably isn't worth it.
    Styled { foreground: Colour, background: Option<Colour>, bold: bool, underline: bool, },
}

impl Paint for Style {
    fn paint(&self, input: &str) -> String {
        match *self {
            Plain => input.to_string(),
            Foreground(c) => c.paint(input),
            Styled { foreground, background, bold, underline } => {
                let bg = match background {
                    Some(c) => format!("{};", c.background_code()),
                    None => "".to_string()
                };
                let bo = if bold { "1;" } else { "" };
                let un = if underline { "4;" } else { "" };
                let painted = format!("\x1B[{}{}{}{}m{}\x1B[0m", bo, un, bg, foreground.foreground_code(), input.to_string());
                return painted.to_string();
            }
        }
    }

    fn bold(&self) -> Style {
        match *self {
            Plain => Styled { foreground: White, background: None, bold: true, underline: false },
            Foreground(c) => Styled { foreground: c, background: None, bold: true, underline: false },
            Styled { foreground, background, bold: _, underline } => Styled { foreground: foreground, background: background, bold: true, underline: underline },
        }
    }

    fn underline(&self) -> Style {
        match *self {
            Plain => Styled { foreground: White, background: None, bold: false, underline: true },
            Foreground(c) => Styled { foreground: c, background: None, bold: false, underline: true },
            Styled { foreground, background, bold, underline: _ } => Styled { foreground: foreground, background: background, bold: bold, underline: true },
        }
    }

    fn on(&self, background: Colour) -> Style {
        match *self {
            Plain => Styled { foreground: White,background: Some(background), bold: false, underline: false },
            Foreground(c) => Styled { foreground: c, background: Some(background), bold: false, underline: false },
            Styled { foreground, background: _, bold, underline } => Styled { foreground: foreground, background: Some(background), bold: bold, underline: underline },
        }
    }
}

/// Return a String with all ANSI escape codes removed. For example:
///
/// ```rust
/// strip_formatting(Blue.paint("hello!")) == "hello!"
/// ```
pub fn strip_formatting(input: String) -> String {
    // What's blue and smells like red paint? Blue paint.
    let re = regex!("\x1B\\[.+?m");
    re.replace_all(input.as_slice(), "").to_string()
}

#[cfg(test)]
mod tests {
    use super::strip_formatting;
    use super::Style::Plain;
    use super::Colour::{Black, Red, Green, Yellow, Blue, Purple, Cyan, White, Fixed};
    use super::Paint;

    #[test]
    fn test_plain() {
        let hi = Plain.paint("text/plain");
        assert!(hi == "text/plain".to_string());
    }

    #[test]
    fn test_red() {
        let hi = Red.paint("hi");
        assert!(hi == "\x1B[31mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_black() {
        let hi = Black.normal().paint("hi");
        assert!(hi == "\x1B[30mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_yellow_bold() {
        let hi = Yellow.bold().paint("hi");
        assert!(hi == "\x1B[1;33mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_yellow_bold_2() {
        let hi = Yellow.normal().bold().paint("hi");
        assert!(hi == "\x1B[1;33mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_blue_underline() {
        let hi = Blue.underline().paint("hi");
        assert!(hi == "\x1B[4;34mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_green_bold_underline() {
        let hi = Green.bold().underline().paint("hi");
        assert!(hi == "\x1B[1;4;32mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_green_bold_underline_2() {
        let hi = Green.underline().bold().paint("hi");
        assert!(hi == "\x1B[1;4;32mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_purple_on_white() {
        let hi = Purple.on(White).paint("hi");
        assert!(hi == "\x1B[47;35mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_purple_on_white_2() {
        let hi = Purple.normal().on(White).paint("hi");
        assert!(hi == "\x1B[47;35mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_cyan_bold_on_white() {
        let hi = Cyan.bold().on(White).paint("hi");
        assert!(hi == "\x1B[1;47;36mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_cyan_underline_on_white() {
        let hi = Cyan.underline().on(White).paint("hi");
        assert!(hi == "\x1B[4;47;36mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_cyan_bold_underline_on_white() {
        let hi = Cyan.bold().underline().on(White).paint("hi");
        assert!(hi == "\x1B[1;4;47;36mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_cyan_underline_bold_on_white() {
        let hi = Cyan.underline().bold().on(White).paint("hi");
        assert!(hi == "\x1B[1;4;47;36mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_fixed() {
        let hi = Fixed(100).paint("hi");
        assert!(hi == "\x1B[38;5;100mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_fixed_on_purple() {
        let hi = Fixed(100).on(Purple).paint("hi");
        assert!(hi == "\x1B[45;38;5;100mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_fixed_on_fixed() {
        let hi = Fixed(100).on(Fixed(200)).paint("hi");
        assert!(hi == "\x1B[48;5;200;38;5;100mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_strip_formatting() {
        let hi = strip_formatting(Blue.paint("hi"));
        assert!(hi == "hi".to_string());
    }

    #[test]
    fn test_strip_formatting_2() {
        let hi = strip_formatting(Blue.on(Fixed(230)).bold().paint("hi"));
        assert!(hi == "hi".to_string());
    }
}
<commit_msg>Use SendStr to reduce allocations<commit_after>#![crate_name = "ansi_term"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![desc = "A rust library for ANSI terminal colours and styles (bold, underline)"]

//! This is a library for controlling colours and formatting, such as
//! red bold text or blue underlined text, on ANSI terminals.
//!
//! ```rust
//! extern crate ansi_term;
//! use ansi_term::Colour::{Black, Red, Green, Yellow, Blue, Purple, Cyan, Fixed};
//! use ansi_term::Style::Plain;
//! use ansi_term::Paint;
//! ```
//!
//! Simple Colours
//! --------------
//!
//! You can format strings by calling the `paint` method on a Colour
//! or a Style object, passing in the string you want to format. For
//! example, to get some red text, call the `paint` method on `Red`:
//!
//! ```rust
//! Red.paint("Red!")
//! ```
//!
//! You can also call the `paint` method on a Style. To turn a Colour
//! into a Style, use the `normal` method, though this does the exact
//! some thing as above:
//!
//! ```rust
//! Red.normal().paint("Still red!")
//! ```
//!
//! Bold, Underline, and Background
//! -------------------------------
//!
//! To do anything more complex than just foreground colours, you need
//! to use Style objects. Calling the `bold` or `underline` method on
//! a Colour returns a Style that has the appropriate property set on
//! it:
//!
//! ```rust
//! Blue.bold().paint("Blue bold!")
//! Yellow.underline().paint("Yellow underline!")
//! ```
//!
//! Again, you can call these methods on Styles as well as just Colours:
//!
//! ```rust
//! Blue.normal().bold().paint("Still blue bold!")
//! ```
//!
//! Finally, you can set the background colour of a Style by using the
//! `on` method:
//!
//! ```rust
//! Blue.on(Yellow).paint("Blue on yellow!")
//! ```
//!
//! Extended Colours
//! ----------------
//!
//! You can access the extended range of 256 colours by using the
//! Fixed constructor, which takes an argument of the colour number to
//! use. This can be used wherever you would use a Colour:
//!
//! ```rust
//! Fixed(134).paint("A sort of light purple.")
//! ```
//!
//! This even works for background colours:
//!
//! ```rust
//! Fixed(221).on(Fixed(124)).paint("Mustard in the ketchup.")
//! ```
//!
//! No Formatting
//! -------------
//!
//! Finally, for the sake of completeness, the Plain style provides
//! neither colours nor formatting.
//!
//! ```rust
//! Plain.paint("No colours here.")
//! ```

#![feature(phase)] extern crate regex;
#[phase(plugin)] extern crate regex_macros;
use Colour::{Black, Red, Green, Yellow, Blue, Purple, Cyan, White, Fixed};
use Style::{Plain, Foreground, Styled};
use std::str::SendStr;

pub trait Paint {
    /// Paints the given text with this colour.
    fn paint(&self, input: &str) -> String;

    /// Returns a Style with the underline property set.
    fn underline(&self) -> Style;

    /// Return a Style with the bold property set.
    fn bold(&self) -> Style;

    /// Return a Style with the background colour set.
    fn on(&self, background: Colour) -> Style;
}

/// A colour is one specific type of ANSI escape code, and can refer
/// to either the foreground or background colour.
pub enum Colour {
    Black, Red, Green, Yellow, Blue, Purple, Cyan, White, Fixed(u8),
}

// These are the standard numeric sequences.
// See http://invisible-island.net/xterm/ctlseqs/ctlseqs.html

impl Colour {
    fn foreground_code(&self) -> SendStr {
        match *self {
            Black  => "30".into_maybe_owned(),
            Red    => "31".into_maybe_owned(),
            Green  => "32".into_maybe_owned(),
            Yellow => "33".into_maybe_owned(),
            Blue   => "34".into_maybe_owned(),
            Purple => "35".into_maybe_owned(),
            Cyan   => "36".into_maybe_owned(),
            White  => "37".into_maybe_owned(),
            Fixed(num) => format!("38;5;{}", num).into_maybe_owned(),
        }
    }

    fn background_code(&self) -> SendStr {
        match *self {
            Black  => "40".into_maybe_owned(),
            Red    => "41".into_maybe_owned(),
            Green  => "42".into_maybe_owned(),
            Yellow => "43".into_maybe_owned(),
            Blue   => "44".into_maybe_owned(),
            Purple => "45".into_maybe_owned(),
            Cyan   => "46".into_maybe_owned(),
            White  => "47".into_maybe_owned(),
            Fixed(num) => format!("48;5;{}", num).into_maybe_owned(),
        }
    }

    /// Return a Style with the foreground colour set to this colour.
    pub fn normal(&self) -> Style {
        Styled { foreground: *self, background: None, bold: false, underline: false }
    }
}

/// The Paint trait represents a style or colour that can be applied
/// to a piece of text.
impl Paint for Colour {
    /// This is a short-cut so you don't have to use Blue.normal() just
    /// to get blue text.
    fn paint(&self, input: &str) -> String {
        let re = format!("\x1B[{}m{}\x1B[0m", self.foreground_code(), input);
        return re.to_string();
    }

    fn underline(&self) -> Style {
        Styled { foreground: *self, background: None, bold: false, underline: true }
    }

    fn bold(&self) -> Style {
        Styled { foreground: *self, background: None, bold: true, underline: false }
    }

    fn on(&self, background: Colour) -> Style {
        Styled { foreground: *self, background: Some(background), bold: false, underline: false }
    }
}

/// A style is a collection of properties that can format a string
/// using ANSI escape codes.
pub enum Style {

    /// The Plain style provides no formatting.
    Plain,

    /// The Foreground style provides just a foreground colour.
    Foreground(Colour),

    ///
    /// The Styled style is a catch-all for anything more complicated
    /// than that. It's technically possible for there to be other
    /// cases, such as "bold foreground", but probably isn't worth it.
    Styled { foreground: Colour, background: Option<Colour>, bold: bool, underline: bool, },
}

impl Paint for Style {
    fn paint(&self, input: &str) -> String {
        match *self {
            Plain => input.to_string(),
            Foreground(c) => c.paint(input),
            Styled { foreground, background, bold, underline } => {
                let bg = match background {
                    Some(c) => format!("{};", c.background_code()).into_maybe_owned(),
                    None => "".into_maybe_owned(),
                };
                let bo = if bold { "1;" } else { "" };
                let un = if underline { "4;" } else { "" };
                let painted = format!("\x1B[{}{}{}{}m{}\x1B[0m", bo, un, bg, foreground.foreground_code(), input.to_string());
                return painted.to_string();
            }
        }
    }

    fn bold(&self) -> Style {
        match *self {
            Plain => Styled { foreground: White, background: None, bold: true, underline: false },
            Foreground(c) => Styled { foreground: c, background: None, bold: true, underline: false },
            Styled { foreground, background, bold: _, underline } => Styled { foreground: foreground, background: background, bold: true, underline: underline },
        }
    }

    fn underline(&self) -> Style {
        match *self {
            Plain => Styled { foreground: White, background: None, bold: false, underline: true },
            Foreground(c) => Styled { foreground: c, background: None, bold: false, underline: true },
            Styled { foreground, background, bold, underline: _ } => Styled { foreground: foreground, background: background, bold: bold, underline: true },
        }
    }

    fn on(&self, background: Colour) -> Style {
        match *self {
            Plain => Styled { foreground: White,background: Some(background), bold: false, underline: false },
            Foreground(c) => Styled { foreground: c, background: Some(background), bold: false, underline: false },
            Styled { foreground, background: _, bold, underline } => Styled { foreground: foreground, background: Some(background), bold: bold, underline: underline },
        }
    }
}

/// Return a String with all ANSI escape codes removed. For example:
///
/// ```rust
/// strip_formatting(Blue.paint("hello!")) == "hello!"
/// ```
pub fn strip_formatting(input: String) -> String {
    // What's blue and smells like red paint? Blue paint.
    let re = regex!("\x1B\\[.+?m");
    re.replace_all(input.as_slice(), "").to_string()
}

#[cfg(test)]
mod tests {
    use super::strip_formatting;
    use super::Style::Plain;
    use super::Colour::{Black, Red, Green, Yellow, Blue, Purple, Cyan, White, Fixed};
    use super::Paint;

    #[test]
    fn test_plain() {
        let hi = Plain.paint("text/plain");
        assert!(hi == "text/plain".to_string());
    }

    #[test]
    fn test_red() {
        let hi = Red.paint("hi");
        assert!(hi == "\x1B[31mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_black() {
        let hi = Black.normal().paint("hi");
        assert!(hi == "\x1B[30mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_yellow_bold() {
        let hi = Yellow.bold().paint("hi");
        assert!(hi == "\x1B[1;33mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_yellow_bold_2() {
        let hi = Yellow.normal().bold().paint("hi");
        assert!(hi == "\x1B[1;33mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_blue_underline() {
        let hi = Blue.underline().paint("hi");
        assert!(hi == "\x1B[4;34mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_green_bold_underline() {
        let hi = Green.bold().underline().paint("hi");
        assert!(hi == "\x1B[1;4;32mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_green_bold_underline_2() {
        let hi = Green.underline().bold().paint("hi");
        assert!(hi == "\x1B[1;4;32mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_purple_on_white() {
        let hi = Purple.on(White).paint("hi");
        assert!(hi == "\x1B[47;35mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_purple_on_white_2() {
        let hi = Purple.normal().on(White).paint("hi");
        assert!(hi == "\x1B[47;35mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_cyan_bold_on_white() {
        let hi = Cyan.bold().on(White).paint("hi");
        assert!(hi == "\x1B[1;47;36mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_cyan_underline_on_white() {
        let hi = Cyan.underline().on(White).paint("hi");
        assert!(hi == "\x1B[4;47;36mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_cyan_bold_underline_on_white() {
        let hi = Cyan.bold().underline().on(White).paint("hi");
        assert!(hi == "\x1B[1;4;47;36mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_cyan_underline_bold_on_white() {
        let hi = Cyan.underline().bold().on(White).paint("hi");
        assert!(hi == "\x1B[1;4;47;36mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_fixed() {
        let hi = Fixed(100).paint("hi");
        assert!(hi == "\x1B[38;5;100mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_fixed_on_purple() {
        let hi = Fixed(100).on(Purple).paint("hi");
        assert!(hi == "\x1B[45;38;5;100mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_fixed_on_fixed() {
        let hi = Fixed(100).on(Fixed(200)).paint("hi");
        assert!(hi == "\x1B[48;5;200;38;5;100mhi\x1B[0m".to_string());
    }

    #[test]
    fn test_strip_formatting() {
        let hi = strip_formatting(Blue.paint("hi"));
        assert!(hi == "hi".to_string());
    }

    #[test]
    fn test_strip_formatting_2() {
        let hi = strip_formatting(Blue.on(Fixed(230)).bold().paint("hi"));
        assert!(hi == "hi".to_string());
    }
}
<|endoftext|>


<commit_before>//! Mergesort algorithm.
//!
//! The `efficient` module contains the efficient sorting algorithm "Mergesort".
//!
//! Source: https://en.wikipedia.org/wiki/Merge_sort

extern crate libc;

use std::slice;
use std::ptr;

/// Mergesort
///
/// # Details
///
///
///
/// # Scaling
///
///
///
/// # Optimizations
///
///
///
/// # Notes
///
/// The type T of the vector elements to sort _must_ implement the `PartialOrd` trait so the
/// compiler knows how to compare the elements and sort them.
///
/// # Examples
///
/// ```
/// let mut data: Vec<i32> = vec![4, 2, 3, 1, 5];
/// sorting::efficientsorts::merge::sort(&mut data);
/// assert_eq!(vec![1, 2, 3, 4, 5], data);
/// ```
///
pub fn sort<T: PartialOrd+Clone>(input: &mut [T]) {
    let n = input.len();

    if n <= 1 {
        // return;
    } else if n == 2 {
        if input.first() > input.last() {
            input.swap(0, 1);
        }
    } else {
        assert!(n > 2);

        // The subvectors of input are now sorted. Merge them into temporary buffer.
        let mut tmp: Vec<T> = Vec::with_capacity(n);

        // New code block as to enforce "split_left" and "split_right"'s lifetime, ending the
        // mutable borrow on input. This is required to copy the elements of "tmp" back
        // into "input".
        {
            let n2 = n / 2;
            let (mut split_left, mut split_right) = input.split_at_mut(n2);

            // Recursively call the function on slices of the vector.
            sort(&mut split_left);
            sort(&mut split_right);

            let mut iter_left  = split_left.iter().peekable();
            let mut iter_right = split_right.iter().peekable();

            for _ in 0..n {
                if !iter_left.peek().is_none() && !iter_right.peek().is_none() {
                    let take_left: bool = iter_left.peek() < iter_right.peek();
                    if take_left {
                        tmp.push(iter_left.next().cloned().unwrap());
                    } else {
                        tmp.push(iter_right.next().cloned().unwrap());
                    }
                } else if iter_left.peek().is_none() {
                    // Left is now empty: take right
                    debug_assert!(iter_left.peek().is_none());
                    debug_assert!(!iter_right.peek().is_none());
                    tmp.push(iter_right.next().cloned().unwrap());
                } else {
                    // Right is now empty: take left
                    debug_assert!(!iter_left.peek().is_none());
                    debug_assert!(iter_right.peek().is_none());
                    tmp.push(iter_left.next().cloned().unwrap());
                }
            }
        }

        // Copy content of "tmp" back into "input" vector.
        assert_eq!(tmp.len(), n);
        unsafe {
            ptr::copy_nonoverlapping(tmp.as_ptr(), input.as_mut_ptr(), n);
        }
    }
}

#[no_mangle]
pub extern "C" fn ffi_mergesort_i8(array_pointer: *const libc::int8_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i8, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_mergesort_i16(array_pointer: *const libc::int16_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i16, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_mergesort_i32(array_pointer: *const libc::int32_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_mergesort_i64(array_pointer: *const libc::int64_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i64, n as usize)
    };
    sort(&mut to_sort);
}

#[no_mangle]
pub extern "C" fn ffi_mergesort_u8(array_pointer: *const libc::uint8_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u8, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_mergesort_u16(array_pointer: *const libc::uint16_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u16, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_mergesort_u32(array_pointer: *const libc::uint32_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_mergesort_u64(array_pointer: *const libc::uint64_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u64, n as usize)
    };
    sort(&mut to_sort);
}

#[no_mangle]
pub extern "C" fn ffi_mergesort_f32(array_pointer: *const libc::c_void, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut f32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_mergesort_f64(array_pointer: *const libc::c_void, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut f64, n as usize)
    };
    sort(&mut to_sort);
}
<commit_msg>Comments<commit_after>//! Mergesort algorithm.
//!
//! The `efficient` module contains the efficient sorting algorithm "Mergesort".
//!
//! Source: https://en.wikipedia.org/wiki/Merge_sort

extern crate libc;

use std::slice;
use std::ptr;

/// Mergesort
///
/// # Details
///
///
///
/// # Scaling
///
///
///
/// # Optimizations
///
///
///
/// # Notes
///
/// The type T of the vector elements to sort _must_ implement the `PartialOrd` trait so the
/// compiler knows how to compare the elements and sort them.
///
/// # Examples
///
/// ```
/// let mut data: Vec<i32> = vec![4, 2, 3, 1, 5];
/// sorting::efficientsorts::merge::sort(&mut data);
/// assert_eq!(vec![1, 2, 3, 4, 5], data);
/// ```
///
pub fn sort<T: PartialOrd+Clone>(input: &mut [T]) {
    let n = input.len();

    if n <= 1 {
        // Nothing to do
    } else if n == 2 {
        // Manually sort the two elements
        if input.first() > input.last() {
            input.swap(0, 1);
        }
    } else {
        // Perform a merge sort
        assert!(n > 2);

        // Allocate a vector that will hold the sorted "input" values temporarily.
        // This prevents having to move elements inside the "input" vector directly.
        // This makes the implementation O(N) for space complexity.
        let mut tmp: Vec<T> = Vec::with_capacity(n);

        // New code block as to enforce "split_left" and "split_right"'s lifetime, ending the
        // mutable borrow on input. This is required to copy the elements of "tmp" back
        // into "input".
        {
            let n2 = n / 2;
            let (mut split_left, mut split_right) = input.split_at_mut(n2);

            // Recursively call the function on slices of the vector.
            sort(&mut split_left);
            sort(&mut split_right);

            // Keep peekable iterators into left and right slices.
            // NOTE: We need a peekable iterator as we must not iterate over each slice at every
            //       loop iteration.
            let mut iter_left  = split_left.iter().peekable();
            let mut iter_right = split_right.iter().peekable();

            // Loop over the size of the "input" vector. We'll copy the smallest element of
            // either the left or right slice into "tmp".
            for _ in 0..n {
                // If there is still elements in both the left and right slice, take the
                // smallest of the two jump to the next element of the peekable iterator
                // of that particular slice.
                if !iter_left.peek().is_none() && !iter_right.peek().is_none() {
                    // Should we take an element from the left slice?
                    let take_left: bool = iter_left.peek() < iter_right.peek();
                    if take_left {
                        // If so, get the element and push() it at the end of the "tmp" vector.
                        // Use next() to advance that slice's iterator.
                        tmp.push(iter_left.next().cloned().unwrap());
                    } else {
                        // If not, insert the element from the right slice instead.
                        tmp.push(iter_right.next().cloned().unwrap());
                    }
                } else if iter_left.peek().is_none() {
                    // Left slice is now purged: insert into "tmp" elements from the right slice,
                    // advancing the iterator.
                    debug_assert!(iter_left.peek().is_none());
                    debug_assert!(!iter_right.peek().is_none());
                    tmp.push(iter_right.next().cloned().unwrap());
                } else {
                    // Right slice is now purged: insert into "tmp" elements from the left slice,
                    // advancing the iterator.
                    debug_assert!(!iter_left.peek().is_none());
                    debug_assert!(iter_right.peek().is_none());
                    tmp.push(iter_left.next().cloned().unwrap());
                }
            }
        }

        // Copy content of "tmp" back into "input" vector.
        assert_eq!(tmp.len(), n);
        unsafe {
            ptr::copy_nonoverlapping(tmp.as_ptr(), input.as_mut_ptr(), n);
        }
    }
}

#[no_mangle]
pub extern "C" fn ffi_mergesort_i8(array_pointer: *const libc::int8_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i8, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_mergesort_i16(array_pointer: *const libc::int16_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i16, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_mergesort_i32(array_pointer: *const libc::int32_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_mergesort_i64(array_pointer: *const libc::int64_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i64, n as usize)
    };
    sort(&mut to_sort);
}

#[no_mangle]
pub extern "C" fn ffi_mergesort_u8(array_pointer: *const libc::uint8_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u8, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_mergesort_u16(array_pointer: *const libc::uint16_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u16, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_mergesort_u32(array_pointer: *const libc::uint32_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_mergesort_u64(array_pointer: *const libc::uint64_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u64, n as usize)
    };
    sort(&mut to_sort);
}

#[no_mangle]
pub extern "C" fn ffi_mergesort_f32(array_pointer: *const libc::c_void, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut f32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_mergesort_f64(array_pointer: *const libc::c_void, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut f64, n as usize)
    };
    sort(&mut to_sort);
}
<|endoftext|>