<commit_before>/// Scoped thread.
///
/// # Examples
///
/// A basic scoped thread:
///
/// ```
/// crossbeam_utils::thread::scope(|scope| {
///     scope.spawn(|| {
///         println!("Hello from a scoped thread!");
///     });
/// }).unwrap();
/// ```
///
/// When writing concurrent Rust programs, you'll sometimes see a pattern like this, using
/// [`std::thread::spawn`][spawn]:
///
/// ```ignore
/// let array = [1, 2, 3];
/// let mut guards = vec![];
///
/// for i in &array {
///     let guard = std::thread::spawn(move || {
///         println!("element: {}", i);
///     });
///
///     guards.push(guard);
/// }
///
/// for guard in guards {
///     guard.join().unwrap();
/// }
/// ```
///
/// The basic pattern is:
///
/// 1. Iterate over some collection.
/// 2. Spin up a thread to operate on each part of the collection.
/// 3. Join all the threads.
///
/// However, this code actually gives an error:
///
/// ```text
/// error: `array` does not live long enough
/// for i in &array {
///           ^~~~~
/// in expansion of for loop expansion
/// note: expansion site
/// note: reference must be valid for the static lifetime...
/// note: ...but borrowed value is only valid for the block suffix following statement 0 at ...
///     let array = [1, 2, 3];
///     let mut guards = vec![];
///
///     for i in &array {
///         let guard = std::thread::spawn(move || {
///             println!("element: {}", i);
/// ...
/// error: aborting due to previous error
/// ```
///
/// Because [`std::thread::spawn`][spawn] doesn't know about this scope, it requires a
/// `'static` lifetime. One way of giving it a proper lifetime is to use an [`Arc`][arc]:
///
/// [arc]: http://doc.rust-lang.org/stable/std/sync/struct.Arc.html
/// [spawn]: https://doc.rust-lang.org/stable/std/thread/fn.spawn.html
///
/// ```
/// use std::sync::Arc;
///
/// let array = Arc::new([1, 2, 3]);
/// let mut guards = vec![];
///
/// for i in 0..array.len() {
///     let a = array.clone();
///
///     let guard = std::thread::spawn(move || {
///         println!("element: {}", a[i]);
///     });
///
///     guards.push(guard);
/// }
///
/// for guard in guards {
///     guard.join().unwrap();
/// }
/// ```
///
/// But this introduces unnecessary allocation, as `Arc<T>` puts its data on the heap, and we
/// also end up dealing with reference counts. We know that we're joining the threads before
/// our function returns, so just taking a reference _should_ be safe. Rust can't know that,
/// though.
///
/// Enter scoped threads. Here's our original example, using `spawn` from crossbeam rather
/// than from `std::thread`:
///
/// ```
/// let array = [1, 2, 3];
///
/// crossbeam_utils::thread::scope(|scope| {
///     for i in &array {
///         scope.spawn(move || {
///             println!("element: {}", i);
///         });
///     }
/// }).unwrap();
/// ```
///
/// Much more straightforward.

use std::cell::RefCell;
use std::fmt;
use std::marker::PhantomData;
use std::mem;
use std::ops::DerefMut;
use std::panic::{self, AssertUnwindSafe};
use std::rc::Rc;
use std::thread;
use std::io;
use std::sync::{Arc, Mutex};

#[doc(hidden)]
trait FnBox<T> {
    fn call_box(self: Box<Self>) -> T;
}

impl<T, F: FnOnce() -> T> FnBox<T> for F {
    fn call_box(self: Box<Self>) -> T {
        (*self)()
    }
}

/// Like `std::thread::spawn`, but without lifetime bounds on the closure.
pub unsafe fn spawn_unchecked<'a, F, T>(f: F) -> thread::JoinHandle<T>
where
    F: FnOnce() -> T,
    F: Send + 'a,
    T: Send + 'static,
{
    let builder = thread::Builder::new();
    builder_spawn_unchecked(builder, f).unwrap()
}

/// Like `std::thread::Builder::spawn`, but without lifetime bounds on the closure.
pub unsafe fn builder_spawn_unchecked<'a, F, T>(
    builder: thread::Builder,
    f: F,
) -> io::Result<thread::JoinHandle<T>>
where
    F: FnOnce() -> T,
    F: Send + 'a,
    T: Send + 'static,
{
    let closure: Box<FnBox<T> + 'a> = Box::new(f);
    let closure: Box<FnBox<T> + Send> = mem::transmute(closure);
    builder.spawn(move || {
        closure.call_box()
    })
}

pub struct Scope<'env> {
    /// The list of the deferred functions and thread join jobs.
    dtors: RefCell<Option<DtorChain<'env, thread::Result<()>>>>,
    // !Send + !Sync
    _marker: PhantomData<*const ()>,
}

struct DtorChain<'env, T> {
    dtor: Box<FnBox<T> + 'env>,
    next: Option<Box<DtorChain<'env, T>>>,
}

impl<'env, T> DtorChain<'env, T> {
    pub fn pop(chain: &mut Option<DtorChain<'env, T>>) -> Option<Box<FnBox<T> + 'env>> {
        chain.take().map(|mut node| {
            *chain = node.next.take().map(|b| *b);
            node.dtor
        })
    }
}

struct JoinState<T> {
    join_handle: thread::JoinHandle<()>,
    result: ScopedThreadResult<T>
}

impl<T> JoinState<T> {
    fn new(join_handle: thread::JoinHandle<()>, result: ScopedThreadResult<T>) -> JoinState<T> {
        JoinState {
            join_handle,
            result
        }
    }

    fn join(self) -> thread::Result<T> {
        let result = self.result;
        self.join_handle.join().map(|_| {
            result.lock().unwrap().take().unwrap()
        })
    }
}

/// A handle to a scoped thread
pub struct ScopedJoinHandle<'scope, T: 'scope> {
    // !Send + !Sync
    inner: Rc<RefCell<Option<JoinState<T>>>>,
    thread: thread::Thread,
    _marker: PhantomData<&'scope T>,
}

unsafe impl<'scope, T> Send for ScopedJoinHandle<'scope, T> {}
unsafe impl<'scope, T> Sync for ScopedJoinHandle<'scope, T> {}

/// Create a new `Scope` for [*scoped thread spawning*](struct.Scope.html#method.spawn).
///
/// In addition, you can [register ad-hoc functions](struct.Scope.html#method.defer) that are
/// deferred to be run. No matter what happens, before the `Scope` is dropped, it is guaranteed that
/// all the unjoined spawned scoped threads are joined and the deferred functions are run.
///
/// `thread::scope()` returns `Ok(())` if all the unjoined spawned threads and the deferred
/// functions did not panic. It returns `Err(e)` if one of them panics with `e`. If many of them
/// panics, it is still guaranteed that all the threads are joined and all the functions are run,
/// and `thread::scope()` returns `Err(e)` with `e` from a panicking thread or function.
///
/// # Examples
///
/// Creating and using a scope:
///
/// ```
/// crossbeam_utils::thread::scope(|scope| {
///     scope.defer(|| println!("Exiting scope"));
///     scope.spawn(|| println!("Running child thread in scope"));
/// }).unwrap();
/// // Prints messages
/// ```
pub fn scope<'env, F, R>(f: F) -> thread::Result<R>
where
    F: FnOnce(&Scope<'env>) -> R,
{
    let mut scope = Scope {
        dtors: RefCell::new(None),
        _marker: PhantomData,
    };
    let ret = f(&scope);
    scope.drop_all()?;
    Ok(ret)
}

impl<'env> fmt::Debug for Scope<'env> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Scope {{ ... }}")
    }
}

impl<'scope, T> fmt::Debug for ScopedJoinHandle<'scope, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ScopedJoinHandle {{ ... }}")
    }
}

impl<'env> Scope<'env> {
    // This method is carefully written in a transactional style, so that it can be called directly
    // and, if any dtor panics, can be resumed in the unwinding this causes. By initially running
    // the method outside of any destructor, we avoid any leakage problems due to
    // @rust-lang/rust#14875.
    fn drop_all(&mut self) -> thread::Result<()> {
        let mut ret = Ok(());
        while let Some(dtor) = DtorChain::pop(&mut self.dtors.borrow_mut()) {
            ret = ret.and(dtor.call_box());
        }
        ret
    }

    fn defer_inner<F>(&self, f: F)
    where
        F: (FnOnce() -> thread::Result<()>) + 'env,
    {
        let mut dtors = self.dtors.borrow_mut();
        *dtors = Some(DtorChain {
            dtor: Box::new(f),
            next: dtors.take().map(Box::new),
        });
    }

    /// Schedule code to be executed when exiting the scope.
    ///
    /// This is akin to having a destructor on the stack, except that it is *guaranteed* to be
    /// run. It is guaranteed that the function is called after all the spawned threads are joined.
    pub fn defer<F>(&self, f: F)
    where
        F: FnOnce() + 'env,
    {
        self.defer_inner(move || panic::catch_unwind(AssertUnwindSafe(f)));
    }

    /// Create a scoped thread.
    ///
    /// `spawn` is similar to the [`spawn`][spawn] function in Rust's standard library. The
    /// difference is that this thread is scoped, meaning that it's guaranteed to terminate before
    /// the current stack frame goes away, allowing you to reference the parent stack frame
    /// directly. This is ensured by having the parent thread join on the child thread before the
    /// scope exits.
    ///
    /// [spawn]: http://doc.rust-lang.org/std/thread/fn.spawn.html
    pub fn spawn<'scope, F, T>(&'scope self, f: F) -> ScopedJoinHandle<'scope, T>
    where
        F: FnOnce() -> T,
        F: Send + 'env,
        T: Send + 'env,
    {
        self.builder().spawn(f).unwrap()
    }

    /// Generates the base configuration for spawning a scoped thread, from which configuration
    /// methods can be chained.
    pub fn builder<'scope>(&'scope self) -> ScopedThreadBuilder<'scope, 'env> {
        ScopedThreadBuilder {
            scope: self,
            builder: thread::Builder::new(),
        }
    }
}

/// Scoped thread configuration. Provides detailed control over the properties and behavior of new
/// scoped threads.
pub struct ScopedThreadBuilder<'scope, 'env: 'scope> {
    scope: &'scope Scope<'env>,
    builder: thread::Builder,
}

impl<'scope, 'env: 'scope> ScopedThreadBuilder<'scope, 'env> {
    /// Names the thread-to-be. Currently the name is used for identification only in panic
    /// messages.
    pub fn name(mut self, name: String) -> ScopedThreadBuilder<'scope, 'env> {
        self.builder = self.builder.name(name);
        self
    }

    /// Sets the size of the stack for the new thread.
    pub fn stack_size(mut self, size: usize) -> ScopedThreadBuilder<'scope, 'env> {
        self.builder = self.builder.stack_size(size);
        self
    }

    /// Spawns a new thread, and returns a join handle for it.
    pub fn spawn<F, T>(self, f: F) -> io::Result<ScopedJoinHandle<'scope, T>>
    where
        F: FnOnce() -> T,
        F: Send + 'env,
        T: Send + 'env,
    {
        let result = Arc::new(Mutex::new(None));

        let join_handle = unsafe {
            let mut thread_result = Arc::clone(&result);
            builder_spawn_unchecked(self.builder, move || {
                *thread_result.lock().unwrap() = Some(f());
            })
        }?;

        let thread = join_handle.thread().clone();

        let join_state = JoinState::<T>::new(join_handle, result);
        let deferred_handle = Rc::new(RefCell::new(Some(join_state)));
        let my_handle = deferred_handle.clone();

        self.scope.defer_inner(move || {
            let state = deferred_handle.borrow_mut().deref_mut().take();
            if let Some(state) = state {
                state.join().map(|_| ())
            } else {
                Ok(())
            }
        });

        Ok(ScopedJoinHandle {
            inner: my_handle,
            thread: thread,
            _marker: PhantomData,
        })
    }
}

impl<'scope, T> ScopedJoinHandle<'scope, T> {
    /// Waits for the associated thread to finish.
    ///
    /// If the child thread panics, [`Err`] is returned with the parameter given to [`panic`].
    ///
    /// [`Err`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err
    /// [`panic`]: https://doc.rust-lang.org/std/macro.panic.html
    ///
    /// # Panics
    ///
    /// This function may panic on some platforms if a thread attempts to join itself or otherwise
    /// may create a deadlock with joining threads.
    pub fn join(self) -> thread::Result<T> {
        let state = self.inner.borrow_mut().deref_mut().take();
        state.unwrap().join()
    }

    /// Gets the underlying [`std::thread::Thread`] handle.
    ///
    /// [`std::thread::Thread`]: https://doc.rust-lang.org/std/thread/struct.Thread.html
    pub fn thread(&self) -> &thread::Thread {
        &self.thread
    }
}

impl<'env> Drop for Scope<'env> {
    fn drop(&mut self) {
        // Actually, there should be no deferred functions left to be run.
        self.drop_all().unwrap();
    }
}

type ScopedThreadResult<T> = Arc<Mutex<Option<T>>>;
<commit_msg>Use vector for dtors in thread and remove defer() (#32)<commit_after>/// Scoped thread.
///
/// # Examples
///
/// A basic scoped thread:
///
/// ```
/// crossbeam_utils::thread::scope(|scope| {
///     scope.spawn(|| {
///         println!("Hello from a scoped thread!");
///     });
/// }).unwrap();
/// ```
///
/// When writing concurrent Rust programs, you'll sometimes see a pattern like this, using
/// [`std::thread::spawn`][spawn]:
///
/// ```ignore
/// let array = [1, 2, 3];
/// let mut guards = vec![];
///
/// for i in &array {
///     let guard = std::thread::spawn(move || {
///         println!("element: {}", i);
///     });
///
///     guards.push(guard);
/// }
///
/// for guard in guards {
///     guard.join().unwrap();
/// }
/// ```
///
/// The basic pattern is:
///
/// 1. Iterate over some collection.
/// 2. Spin up a thread to operate on each part of the collection.
/// 3. Join all the threads.
///
/// However, this code actually gives an error:
///
/// ```text
/// error: `array` does not live long enough
/// for i in &array {
///           ^~~~~
/// in expansion of for loop expansion
/// note: expansion site
/// note: reference must be valid for the static lifetime...
/// note: ...but borrowed value is only valid for the block suffix following statement 0 at ...
///     let array = [1, 2, 3];
///     let mut guards = vec![];
///
///     for i in &array {
///         let guard = std::thread::spawn(move || {
///             println!("element: {}", i);
/// ...
/// error: aborting due to previous error
/// ```
///
/// Because [`std::thread::spawn`][spawn] doesn't know about this scope, it requires a
/// `'static` lifetime. One way of giving it a proper lifetime is to use an [`Arc`][arc]:
///
/// [arc]: http://doc.rust-lang.org/stable/std/sync/struct.Arc.html
/// [spawn]: https://doc.rust-lang.org/stable/std/thread/fn.spawn.html
///
/// ```
/// use std::sync::Arc;
///
/// let array = Arc::new([1, 2, 3]);
/// let mut guards = vec![];
///
/// for i in 0..array.len() {
///     let a = array.clone();
///
///     let guard = std::thread::spawn(move || {
///         println!("element: {}", a[i]);
///     });
///
///     guards.push(guard);
/// }
///
/// for guard in guards {
///     guard.join().unwrap();
/// }
/// ```
///
/// But this introduces unnecessary allocation, as `Arc<T>` puts its data on the heap, and we
/// also end up dealing with reference counts. We know that we're joining the threads before
/// our function returns, so just taking a reference _should_ be safe. Rust can't know that,
/// though.
///
/// Enter scoped threads. Here's our original example, using `spawn` from crossbeam rather
/// than from `std::thread`:
///
/// ```
/// let array = [1, 2, 3];
///
/// crossbeam_utils::thread::scope(|scope| {
///     for i in &array {
///         scope.spawn(move || {
///             println!("element: {}", i);
///         });
///     }
/// }).unwrap();
/// ```
///
/// Much more straightforward.
use std::any::Any;
use std::cell::RefCell;
use std::fmt;
use std::io;
use std::marker::PhantomData;
use std::mem;
use std::ops::DerefMut;
use std::panic;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::thread;

#[doc(hidden)]
trait FnBox<T> {
    fn call_box(self: Box<Self>) -> T;
}

impl<T, F: FnOnce() -> T> FnBox<T> for F {
    fn call_box(self: Box<Self>) -> T {
        (*self)()
    }
}

/// Like `std::thread::spawn`, but without lifetime bounds on the closure.
pub unsafe fn spawn_unchecked<'a, F, T>(f: F) -> thread::JoinHandle<T>
where
    F: FnOnce() -> T,
    F: Send + 'a,
    T: Send + 'static,
{
    let builder = thread::Builder::new();
    builder_spawn_unchecked(builder, f).unwrap()
}

/// Like `std::thread::Builder::spawn`, but without lifetime bounds on the closure.
pub unsafe fn builder_spawn_unchecked<'a, F, T>(
    builder: thread::Builder,
    f: F,
) -> io::Result<thread::JoinHandle<T>>
where
    F: FnOnce() -> T,
    F: Send + 'a,
    T: Send + 'static,
{
    let closure: Box<FnBox<T> + 'a> = Box::new(f);
    let closure: Box<FnBox<T> + Send> = mem::transmute(closure);
    builder.spawn(move || closure.call_box())
}

pub struct Scope<'env> {
    /// The list of the thread join jobs.
    joins: RefCell<Vec<Box<FnBox<thread::Result<()>> + 'env>>>,
    /// Thread panics invoked so far.
    panics: RefCell<Vec<Box<Any + Send + 'static>>>,
    // !Send + !Sync
    _marker: PhantomData<*const ()>,
}

struct JoinState<T> {
    join_handle: thread::JoinHandle<()>,
    result: ScopedThreadResult<T>,
}

impl<T> JoinState<T> {
    fn new(join_handle: thread::JoinHandle<()>, result: ScopedThreadResult<T>) -> JoinState<T> {
        JoinState {
            join_handle,
            result,
        }
    }

    fn join(self) -> thread::Result<T> {
        let result = self.result;
        self.join_handle
            .join()
            .map(|_| result.lock().unwrap().take().unwrap())
    }
}

/// A handle to a scoped thread
pub struct ScopedJoinHandle<'scope, T: 'scope> {
    // !Send + !Sync
    inner: Rc<RefCell<Option<JoinState<T>>>>,
    thread: thread::Thread,
    _marker: PhantomData<&'scope T>,
}

unsafe impl<'scope, T> Send for ScopedJoinHandle<'scope, T> {}
unsafe impl<'scope, T> Sync for ScopedJoinHandle<'scope, T> {}

/// Creates a new `Scope` for [*scoped thread spawning*](struct.Scope.html#method.spawn).
///
/// No matter what happens, before the `Scope` is dropped, it is guaranteed that all the unjoined
/// spawned scoped threads are joined.
///
/// `thread::scope()` returns `Ok(())` if all the unjoined spawned threads did not panic. It returns
/// `Err(e)` if one of them panics with `e`. If many of them panic, it is still guaranteed that all
/// the threads are joined, and `thread::scope()` returns `Err(e)` with `e` from a panicking thread.
///
/// # Examples
///
/// Creating and using a scope:
///
/// ```
/// crossbeam_utils::thread::scope(|scope| {
///     scope.spawn(|| println!("Exiting scope"));
///     scope.spawn(|| println!("Running child thread in scope"));
/// }).unwrap();
/// ```
pub fn scope<'env, F, R>(f: F) -> thread::Result<R>
where
    F: FnOnce(&Scope<'env>) -> R,
{
    let mut scope = Scope {
        joins: RefCell::new(Vec::new()),
        panics: RefCell::new(Vec::new()),
        _marker: PhantomData,
    };

    // Executes the scoped function. Panic will be catched as `Err`.
    let result = panic::catch_unwind(panic::AssertUnwindSafe(|| f(&scope)));

    // Joins all the threads.
    scope.join_all();
    let panic = scope.panics.borrow_mut().pop();

    // If any of the threads panicked, returns the panic's payload.
    if let Some(payload) = panic {
        return Err(payload);
    }

    // Returns the result of the scoped function.
    result
}

impl<'env> fmt::Debug for Scope<'env> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Scope {{ ... }}")
    }
}

impl<'scope, T> fmt::Debug for ScopedJoinHandle<'scope, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ScopedJoinHandle {{ ... }}")
    }
}

impl<'env> Scope<'env> {
    // This method is carefully written in a transactional style, so that it can be called directly
    // and, if any thread join panics, can be resumed in the unwinding this causes. By initially
    // running the method outside of any destructor, we avoid any leakage problems due to
    // @rust-lang/rust#14875.
    //
    // FIXME(jeehoonkang): @rust-lang/rust#14875 is fixed, so maybe we can remove the above comment.
    // But I'd like to write tests to check it before removing the comment.
    fn join_all(&mut self) {
        let mut joins = self.joins.borrow_mut();
        for join in joins.drain(..) {
            let result = join.call_box();
            if let Err(payload) = result {
                self.panics.borrow_mut().push(payload);
            }
        }
    }

    /// Create a scoped thread.
    ///
    /// `spawn` is similar to the [`spawn`][spawn] function in Rust's standard library. The
    /// difference is that this thread is scoped, meaning that it's guaranteed to terminate before
    /// the current stack frame goes away, allowing you to reference the parent stack frame
    /// directly. This is ensured by having the parent thread join on the child thread before the
    /// scope exits.
    ///
    /// [spawn]: http://doc.rust-lang.org/std/thread/fn.spawn.html
    pub fn spawn<'scope, F, T>(&'scope self, f: F) -> ScopedJoinHandle<'scope, T>
    where
        F: FnOnce() -> T,
        F: Send + 'env,
        T: Send + 'env,
    {
        self.builder().spawn(f).unwrap()
    }

    /// Generates the base configuration for spawning a scoped thread, from which configuration
    /// methods can be chained.
    pub fn builder<'scope>(&'scope self) -> ScopedThreadBuilder<'scope, 'env> {
        ScopedThreadBuilder {
            scope: self,
            builder: thread::Builder::new(),
        }
    }
}

/// Scoped thread configuration. Provides detailed control over the properties and behavior of new
/// scoped threads.
pub struct ScopedThreadBuilder<'scope, 'env: 'scope> {
    scope: &'scope Scope<'env>,
    builder: thread::Builder,
}

impl<'scope, 'env: 'scope> ScopedThreadBuilder<'scope, 'env> {
    /// Names the thread-to-be. Currently the name is used for identification only in panic
    /// messages.
    pub fn name(mut self, name: String) -> ScopedThreadBuilder<'scope, 'env> {
        self.builder = self.builder.name(name);
        self
    }

    /// Sets the size of the stack for the new thread.
    pub fn stack_size(mut self, size: usize) -> ScopedThreadBuilder<'scope, 'env> {
        self.builder = self.builder.stack_size(size);
        self
    }

    /// Spawns a new thread, and returns a join handle for it.
    pub fn spawn<F, T>(self, f: F) -> io::Result<ScopedJoinHandle<'scope, T>>
    where
        F: FnOnce() -> T,
        F: Send + 'env,
        T: Send + 'env,
    {
        let result = Arc::new(Mutex::new(None));

        let join_handle = unsafe {
            let mut thread_result = Arc::clone(&result);
            builder_spawn_unchecked(self.builder, move || {
                *thread_result.lock().unwrap() = Some(f());
            })
        }?;

        let thread = join_handle.thread().clone();

        let join_state = JoinState::<T>::new(join_handle, result);
        let deferred_handle = Rc::new(RefCell::new(Some(join_state)));
        let my_handle = deferred_handle.clone();

        self.scope.joins.borrow_mut().push(Box::new(move || {
            let state = deferred_handle.borrow_mut().deref_mut().take();
            if let Some(state) = state {
                state.join().map(|_| ())
            } else {
                Ok(())
            }
        }));

        Ok(ScopedJoinHandle {
            inner: my_handle,
            thread: thread,
            _marker: PhantomData,
        })
    }
}

impl<'scope, T> ScopedJoinHandle<'scope, T> {
    /// Waits for the associated thread to finish.
    ///
    /// If the child thread panics, [`Err`] is returned with the parameter given to [`panic`].
    ///
    /// [`Err`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err
    /// [`panic`]: https://doc.rust-lang.org/std/macro.panic.html
    ///
    /// # Panics
    ///
    /// This function may panic on some platforms if a thread attempts to join itself or otherwise
    /// may create a deadlock with joining threads.
    pub fn join(self) -> thread::Result<T> {
        let state = self.inner.borrow_mut().deref_mut().take();
        state.unwrap().join()
    }

    /// Gets the underlying [`std::thread::Thread`] handle.
    ///
    /// [`std::thread::Thread`]: https://doc.rust-lang.org/std/thread/struct.Thread.html
    pub fn thread(&self) -> &thread::Thread {
        &self.thread
    }
}

impl<'env> Drop for Scope<'env> {
    fn drop(&mut self) {
        // Note that `self.joins` can be non-empty when the code inside a `scope()` panics and
        // `drop()` is called in unwinding. Even if it's the case, we will join the unjoined
        // threads.
        //
        // We ignore panics from any threads because we're in course of unwinding anyway.
        self.join_all();
    }
}

type ScopedThreadResult<T> = Arc<Mutex<Option<T>>>;

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::atomic::AtomicUsize;
    use std::sync::atomic::Ordering;
    use std::{thread, time};

    const TIMES: usize = 10;
    const SMALL_STACK_SIZE: usize = 20;

    #[test]
    fn join() {
        let counter = AtomicUsize::new(0);
        scope(|scope| {
            let handle = scope.spawn(|| {
                counter.store(1, Ordering::Relaxed);
            });
            assert!(handle.join().is_ok());

            let panic_handle = scope.spawn(|| {
                panic!("\"My honey is running out!\", said Pooh.");
            });
            assert!(panic_handle.join().is_err());
        }).unwrap();

        // There should be sufficient synchronization.
        assert_eq!(1, counter.load(Ordering::Relaxed));
    }

    #[test]
    fn counter() {
        let counter = AtomicUsize::new(0);
        scope(|scope| {
            for _ in 0..TIMES {
                scope.spawn(|| {
                    counter.fetch_add(1, Ordering::Relaxed);
                });
            }
        }).unwrap();

        assert_eq!(TIMES, counter.load(Ordering::Relaxed));
    }

    #[test]
    fn counter_builder() {
        let counter = AtomicUsize::new(0);
        scope(|scope| {
            for i in 0..TIMES {
                scope
                    .builder()
                    .name(format!("child-{}", i))
                    .stack_size(SMALL_STACK_SIZE)
                    .spawn(|| {
                        counter.fetch_add(1, Ordering::Relaxed);
                    })
                    .unwrap();
            }
        }).unwrap();

        assert_eq!(TIMES, counter.load(Ordering::Relaxed));
    }

    #[test]
    fn counter_panic() {
        let counter = AtomicUsize::new(0);
        let result = scope(|scope| {
            scope.spawn(|| {
                panic!("\"My honey is running out!\", said Pooh.");
            });
            thread::sleep(time::Duration::from_millis(100));

            for _ in 0..TIMES {
                scope.spawn(|| {
                    counter.fetch_add(1, Ordering::Relaxed);
                });
            }
        });

        assert_eq!(TIMES, counter.load(Ordering::Relaxed));
        assert!(result.is_err());
    }

    #[test]
    fn panic_twice() {
        let result = scope(|scope| {
            scope.spawn(|| {
                panic!();
            });
            panic!();
        });
        assert!(result.is_err());
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{fs::File,
          io::prelude::*,
          path::Path,
          str::FromStr};

use crate::{common::ui::UI,
            hcore::{package::{PackageArchive,
                              PackageIdent},
                    service::ServiceBind}};
use base64;
use clap::ArgMatches;

use crate::export_docker::{DockerImage,
                           Result};

use crate::{env::EnvironmentVariable,
            manifestjson::ManifestJson,
            storage::PersistentStorage,
            topology::Topology};

/// Represents a Kubernetes manifest.
#[derive(Debug, Clone)]
pub struct Manifest {
    /// The identifier of the Habitat package
    pub pkg_ident: PackageIdent,
    /// Name of the Kubernetes resource.
    pub metadata_name: String,
    /// The docker image.
    pub image: String,
    /// The number of desired instances in the service group.
    pub count: u64,
    /// The relationship of a service with peers in the same service group.
    pub service_topology: Topology,
    /// The logical group of services in the service group.
    pub service_group: Option<String>,
    /// The config file content (in base64 encoded format).
    pub config: Option<String>,
    /// The name of the Kubernetes secret that contains the ring key, which encrypts the
    /// communication between Habitat supervisors.
    pub ring_secret_name: Option<String>,

    /// Any binds, as `ServiceBind` instances.
    pub binds: Vec<ServiceBind>,
    /// Persistent storage specification.
    pub persistent_storage: Option<PersistentStorage>,
    /// Environment.
    pub environment: Vec<EnvironmentVariable>,
}

impl Manifest {
    /// Create a Manifest instance from command-line arguments passed as [`clap::ArgMatches`].
    ///
    /// [`clap::ArgMatches`]: https://kbknapp.github.io/clap-rs/clap/struct.ArgMatches.html
    pub fn new_from_cli_matches(_ui: &mut UI,
                                matches: &ArgMatches<'_>,
                                image: Option<DockerImage>)
                                -> Result<Self> {
        let count = matches.value_of("COUNT").unwrap_or("1").parse()?;
        let topology: Topology = matches.value_of("TOPOLOGY")
                                        .unwrap_or("standalone")
                                        .parse()
                                        .unwrap_or_default();
        let group = matches.value_of("GROUP").map(str::to_string);
        let config_file = matches.value_of("CONFIG");
        let ring_secret_name = matches.value_of("RING_SECRET_NAME").map(str::to_string);
        // clap ensures that we do have the mandatory args so unwrap() is fine here
        let pkg_ident_str = matches.value_of("PKG_IDENT_OR_ARTIFACT")
                                   .expect("No package specified");
        let pkg_ident = if Path::new(pkg_ident_str).is_file() {
            // We're going to use the `$pkg_origin/$pkg_name`, fuzzy form of a package
            // identifier to ensure that update strategies will work if desired
            PackageArchive::new(pkg_ident_str).ident()?
        } else {
            PackageIdent::from_str(pkg_ident_str)?
        };

        let version_suffix = match pkg_ident.version {
            Some(ref v) => {
                pkg_ident.release
                         .as_ref()
                         .map(|r| format!("{}-{}", v, r))
                         .unwrap_or_else(|| v.to_string())
            }
            None => "latest".to_owned(),
        };
        let name = matches.value_of("K8S_NAME")
                          .map(str::to_string)
                          .unwrap_or_else(|| format!("{}-{}", pkg_ident.name, version_suffix));

        let formatted_resource_name = Manifest::formatted_resource_name(&name);

        let image_name = match matches.value_of("IMAGE_NAME") {
            Some(i) => i.to_string(),
            None => {
                let (image_name, tag) = match image {
                    Some(i) => {
                        (i.name().to_owned(),
                         i.tags()
                          .get(0)
                          .cloned()
                          .unwrap_or_else(|| "latest".to_owned()))
                    }
                    None => (format!("{}/{}", pkg_ident.origin, pkg_ident.name), version_suffix),
                };

                format!("{}:{}", image_name, tag)
            }
        };

        let binds = matches
            .values_of("BIND")
            .unwrap_or_default()
            .map(|b| ServiceBind::from_str(b).unwrap()) // unwrap ok as we've validated input
            .collect();

        let persistent_storage = PersistentStorage::from_args(&matches)?;
        let environment = EnvironmentVariable::from_args(&matches)?;

        let config = match config_file {
            None => None,
            Some(name) => {
                let mut contents = String::new();
                File::open(name)?.read_to_string(&mut contents)?;

                Some(base64::encode(&contents))
            }
        };

        Ok(Manifest { pkg_ident,
                      metadata_name: formatted_resource_name,
                      image: image_name,
                      count,
                      service_topology: topology,
                      service_group: group,
                      config,
                      ring_secret_name,
                      binds,
                      persistent_storage,
                      environment })
    }

    /// Generates manifest as a string and writes it to `write`.
    pub fn generate(&mut self, write: &mut dyn Write) -> Result<()> {
        let out: String = ManifestJson::new(&self).into();

        write.write_all(out.as_bytes())?;
        Ok(())
    }

    // Replaces any periods in the `name with hyphens
    // To make it a valid Kubernetes resource name
    fn formatted_resource_name(resource_name: &str) -> String {
        resource_name.replace(".", "-")
    }
}

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

    #[test]
    fn test_manifest_generation() {
        let mut m = Manifest { pkg_ident:          PackageIdent::from_str("core/nginx").unwrap(),
                               metadata_name:      "nginx-latest".to_owned(),
                               image:              "core/nginx:latest".to_owned(),
                               count:              3,
                               service_topology:   Default::default(),
                               service_group:      Some("group1".to_owned()),
                               config:             Some(base64::encode(&"port = 4444")),
                               ring_secret_name:   Some("deltaechofoxtrot".to_owned()),
                               binds:              vec![],
                               persistent_storage: None,
                               environment:        vec![], };

        let expected = include_str!("../tests/KubernetesManifestTest.yaml");

        let mut o = vec![];
        m.generate(&mut o).unwrap();

        let out = String::from_utf8(o).unwrap();

        assert_eq!(out, expected);
    }

    #[test]
    fn test_manifest_generation_binds() {
        let mut m = Manifest { pkg_ident:          PackageIdent::from_str("core/nginx").unwrap(),
                               metadata_name:      "nginx-latest".to_owned(),
                               image:              "core/nginx:latest".to_owned(),
                               count:              3,
                               service_topology:   Default::default(),
                               service_group:      Some("group1".to_owned()),
                               config:             None,
                               ring_secret_name:   Some("deltaechofoxtrot".to_owned()),
                               binds:              vec!["name1:service1.group1".parse().unwrap()],
                               persistent_storage: None,
                               environment:        vec![], };

        let expected = include_str!("../tests/KubernetesManifestTestBinds.yaml");

        let mut o = vec![];
        m.generate(&mut o).unwrap();

        let out = String::from_utf8(o).unwrap();

        assert_eq!(out, expected);
    }

    #[test]
    fn test_manifest_generation_persistent_storage() {
        let mut m = Manifest { pkg_ident:          PackageIdent::from_str("core/nginx").unwrap(),
                               metadata_name:      "nginx-latest".to_owned(),
                               image:              "core/nginx:latest".to_owned(),
                               count:              3,
                               service_topology:   Default::default(),
                               service_group:      Some("group1".to_owned()),
                               config:             None,
                               ring_secret_name:   Some("deltaechofoxtrot".to_owned()),
                               binds:              vec![],
                               persistent_storage: Some("10Gi:/foo/bar:standard".parse().unwrap()),
                               environment:        vec![], };

        let expected = include_str!("../tests/KubernetesManifestTestPersistentStorage.yaml");

        let mut o = vec![];
        m.generate(&mut o).unwrap();

        let out = String::from_utf8(o).unwrap();

        assert_eq!(out, expected);
    }

    #[test]
    fn test_manifest_generation_environment() {
        let mut m = Manifest { pkg_ident:          PackageIdent::from_str("core/nginx").unwrap(),
                               metadata_name:      "nginx-latest".to_owned(),
                               image:              "core/nginx:latest".to_owned(),
                               count:              3,
                               service_topology:   Default::default(),
                               service_group:      Some("group1".to_owned()),
                               config:             None,
                               ring_secret_name:   Some("deltaechofoxtrot".to_owned()),
                               binds:              vec![],
                               persistent_storage: None,
                               environment:        vec!["FOO=bar".parse().unwrap(),
                                                        "QUOTES=quo\"te".parse().unwrap(),], };

        let expected = include_str!("../tests/KubernetesManifestTestEnvironment.yaml");

        let mut o = vec![];
        m.generate(&mut o).unwrap();

        let out = String::from_utf8(o).unwrap();

        assert_eq!(out, expected);
    }

    #[test]
    fn test_resource_name() {
        let expected = String::from("sample-node-app-1-1-0-2019050321383");
        let formatted_resource_name = Manifest::formatted_resource_name("sample-node-app-1.1.0-2019050321383");

        assert_eq!(formatted_resource_name, expected);
    }
}
<commit_msg>Reformat something that somehow wasn't formatted right lolwtf<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{fs::File,
          io::prelude::*,
          path::Path,
          str::FromStr};

use crate::{common::ui::UI,
            hcore::{package::{PackageArchive,
                              PackageIdent},
                    service::ServiceBind}};
use base64;
use clap::ArgMatches;

use crate::export_docker::{DockerImage,
                           Result};

use crate::{env::EnvironmentVariable,
            manifestjson::ManifestJson,
            storage::PersistentStorage,
            topology::Topology};

/// Represents a Kubernetes manifest.
#[derive(Debug, Clone)]
pub struct Manifest {
    /// The identifier of the Habitat package
    pub pkg_ident: PackageIdent,
    /// Name of the Kubernetes resource.
    pub metadata_name: String,
    /// The docker image.
    pub image: String,
    /// The number of desired instances in the service group.
    pub count: u64,
    /// The relationship of a service with peers in the same service group.
    pub service_topology: Topology,
    /// The logical group of services in the service group.
    pub service_group: Option<String>,
    /// The config file content (in base64 encoded format).
    pub config: Option<String>,
    /// The name of the Kubernetes secret that contains the ring key, which encrypts the
    /// communication between Habitat supervisors.
    pub ring_secret_name: Option<String>,

    /// Any binds, as `ServiceBind` instances.
    pub binds: Vec<ServiceBind>,
    /// Persistent storage specification.
    pub persistent_storage: Option<PersistentStorage>,
    /// Environment.
    pub environment: Vec<EnvironmentVariable>,
}

impl Manifest {
    /// Create a Manifest instance from command-line arguments passed as [`clap::ArgMatches`].
    ///
    /// [`clap::ArgMatches`]: https://kbknapp.github.io/clap-rs/clap/struct.ArgMatches.html
    pub fn new_from_cli_matches(_ui: &mut UI,
                                matches: &ArgMatches<'_>,
                                image: Option<DockerImage>)
                                -> Result<Self> {
        let count = matches.value_of("COUNT").unwrap_or("1").parse()?;
        let topology: Topology = matches.value_of("TOPOLOGY")
                                        .unwrap_or("standalone")
                                        .parse()
                                        .unwrap_or_default();
        let group = matches.value_of("GROUP").map(str::to_string);
        let config_file = matches.value_of("CONFIG");
        let ring_secret_name = matches.value_of("RING_SECRET_NAME").map(str::to_string);
        // clap ensures that we do have the mandatory args so unwrap() is fine here
        let pkg_ident_str = matches.value_of("PKG_IDENT_OR_ARTIFACT")
                                   .expect("No package specified");
        let pkg_ident = if Path::new(pkg_ident_str).is_file() {
            // We're going to use the `$pkg_origin/$pkg_name`, fuzzy form of a package
            // identifier to ensure that update strategies will work if desired
            PackageArchive::new(pkg_ident_str).ident()?
        } else {
            PackageIdent::from_str(pkg_ident_str)?
        };

        let version_suffix = match pkg_ident.version {
            Some(ref v) => {
                pkg_ident.release
                         .as_ref()
                         .map(|r| format!("{}-{}", v, r))
                         .unwrap_or_else(|| v.to_string())
            }
            None => "latest".to_owned(),
        };
        let name = matches.value_of("K8S_NAME")
                          .map(str::to_string)
                          .unwrap_or_else(|| format!("{}-{}", pkg_ident.name, version_suffix));

        let formatted_resource_name = Manifest::formatted_resource_name(&name);

        let image_name = match matches.value_of("IMAGE_NAME") {
            Some(i) => i.to_string(),
            None => {
                let (image_name, tag) = match image {
                    Some(i) => {
                        (i.name().to_owned(),
                         i.tags()
                          .get(0)
                          .cloned()
                          .unwrap_or_else(|| "latest".to_owned()))
                    }
                    None => (format!("{}/{}", pkg_ident.origin, pkg_ident.name), version_suffix),
                };

                format!("{}:{}", image_name, tag)
            }
        };

        let binds = matches
            .values_of("BIND")
            .unwrap_or_default()
            .map(|b| ServiceBind::from_str(b).unwrap()) // unwrap ok as we've validated input
            .collect();

        let persistent_storage = PersistentStorage::from_args(&matches)?;
        let environment = EnvironmentVariable::from_args(&matches)?;

        let config = match config_file {
            None => None,
            Some(name) => {
                let mut contents = String::new();
                File::open(name)?.read_to_string(&mut contents)?;

                Some(base64::encode(&contents))
            }
        };

        Ok(Manifest { pkg_ident,
                      metadata_name: formatted_resource_name,
                      image: image_name,
                      count,
                      service_topology: topology,
                      service_group: group,
                      config,
                      ring_secret_name,
                      binds,
                      persistent_storage,
                      environment })
    }

    /// Generates manifest as a string and writes it to `write`.
    pub fn generate(&mut self, write: &mut dyn Write) -> Result<()> {
        let out: String = ManifestJson::new(&self).into();

        write.write_all(out.as_bytes())?;
        Ok(())
    }

    // Replaces any periods in the `name with hyphens
    // To make it a valid Kubernetes resource name
    fn formatted_resource_name(resource_name: &str) -> String { resource_name.replace(".", "-") }
}

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

    #[test]
    fn test_manifest_generation() {
        let mut m = Manifest { pkg_ident:          PackageIdent::from_str("core/nginx").unwrap(),
                               metadata_name:      "nginx-latest".to_owned(),
                               image:              "core/nginx:latest".to_owned(),
                               count:              3,
                               service_topology:   Default::default(),
                               service_group:      Some("group1".to_owned()),
                               config:             Some(base64::encode(&"port = 4444")),
                               ring_secret_name:   Some("deltaechofoxtrot".to_owned()),
                               binds:              vec![],
                               persistent_storage: None,
                               environment:        vec![], };

        let expected = include_str!("../tests/KubernetesManifestTest.yaml");

        let mut o = vec![];
        m.generate(&mut o).unwrap();

        let out = String::from_utf8(o).unwrap();

        assert_eq!(out, expected);
    }

    #[test]
    fn test_manifest_generation_binds() {
        let mut m = Manifest { pkg_ident:          PackageIdent::from_str("core/nginx").unwrap(),
                               metadata_name:      "nginx-latest".to_owned(),
                               image:              "core/nginx:latest".to_owned(),
                               count:              3,
                               service_topology:   Default::default(),
                               service_group:      Some("group1".to_owned()),
                               config:             None,
                               ring_secret_name:   Some("deltaechofoxtrot".to_owned()),
                               binds:              vec!["name1:service1.group1".parse().unwrap()],
                               persistent_storage: None,
                               environment:        vec![], };

        let expected = include_str!("../tests/KubernetesManifestTestBinds.yaml");

        let mut o = vec![];
        m.generate(&mut o).unwrap();

        let out = String::from_utf8(o).unwrap();

        assert_eq!(out, expected);
    }

    #[test]
    fn test_manifest_generation_persistent_storage() {
        let mut m = Manifest { pkg_ident:          PackageIdent::from_str("core/nginx").unwrap(),
                               metadata_name:      "nginx-latest".to_owned(),
                               image:              "core/nginx:latest".to_owned(),
                               count:              3,
                               service_topology:   Default::default(),
                               service_group:      Some("group1".to_owned()),
                               config:             None,
                               ring_secret_name:   Some("deltaechofoxtrot".to_owned()),
                               binds:              vec![],
                               persistent_storage: Some("10Gi:/foo/bar:standard".parse().unwrap()),
                               environment:        vec![], };

        let expected = include_str!("../tests/KubernetesManifestTestPersistentStorage.yaml");

        let mut o = vec![];
        m.generate(&mut o).unwrap();

        let out = String::from_utf8(o).unwrap();

        assert_eq!(out, expected);
    }

    #[test]
    fn test_manifest_generation_environment() {
        let mut m = Manifest { pkg_ident:          PackageIdent::from_str("core/nginx").unwrap(),
                               metadata_name:      "nginx-latest".to_owned(),
                               image:              "core/nginx:latest".to_owned(),
                               count:              3,
                               service_topology:   Default::default(),
                               service_group:      Some("group1".to_owned()),
                               config:             None,
                               ring_secret_name:   Some("deltaechofoxtrot".to_owned()),
                               binds:              vec![],
                               persistent_storage: None,
                               environment:        vec!["FOO=bar".parse().unwrap(),
                                                        "QUOTES=quo\"te".parse().unwrap(),], };

        let expected = include_str!("../tests/KubernetesManifestTestEnvironment.yaml");

        let mut o = vec![];
        m.generate(&mut o).unwrap();

        let out = String::from_utf8(o).unwrap();

        assert_eq!(out, expected);
    }

    #[test]
    fn test_resource_name() {
        let expected = String::from("sample-node-app-1-1-0-2019050321383");
        let formatted_resource_name =
            Manifest::formatted_resource_name("sample-node-app-1.1.0-2019050321383");

        assert_eq!(formatted_resource_name, expected);
    }
}
<|endoftext|>


<commit_before>use json;

use message;

struct Update {
    update_id: i32,
    message: Option<Message>,  // TODO: Change this into a Message struct
    edited_message: Option<Message>,  // TODO: Change this into a Message struct
    inline_query: Option<String>,  // TODO: Change this into an InlineQuery struct
    chosen_inline_result: Option<String>,  // TODO: Change this into a ChosenInlineResult struct
    callback_query: Option<String>,  // TODO: Change into a CallbackQuery struct
}

impl Update {
    pub fn new(rjson: json::JsonValue) {
        let update_id = rjson["update_id"];
    }
}
<commit_msg>Fixing some fields and adding a constructor.<commit_after>use json;

use message::Message;

struct Update {
    update_id: i32,
    message: Option<Message>,  // TODO: Change this into a Message struct
    edited_message: Option<Message>,  // TODO: Change this into a Message struct
    inline_query: Option<String>,  // TODO: Change this into an InlineQuery struct
    chosen_inline_result: Option<String>,  // TODO: Change this into a ChosenInlineResult struct
    callback_query: Option<String>,  // TODO: Change into a CallbackQuery struct
}

impl Update {
    pub fn new(rjson: json::JsonValue) -> Update {
        let update_id = rjson["update_id"].as_i32().unwrap();

        Update {
            update_id: update_id,
            message: None,
            edited_message: None,
            inline_query: None,
            chosen_inline_result: None,
            callback_query: None,
        }
    }
}
<|endoftext|>


<commit_before>//Implements http://rosettacode.org/wiki/9_billion_names_of_God_the_integer

extern crate num;

use num::bigint::BigUint;
use std::string::String;
use std::cmp::min;

fn cumu(num: uint, cache: &mut Vec<Vec<BigUint>>) -> &Vec<BigUint> {
    let len = cache.len();
    for l in range(len, num+1) {
        let initial_value:BigUint = from_str("0").unwrap();
        let mut r: Vec<BigUint> = vec!(initial_value);
        for x in range(1, l+1) {
            let y = r[x -1].clone();
            let z = (*cache)[l-x][min(x, l-x)].clone();
            let w = y+z;
            r.push(w)
        }
        cache.push(r);
    }
    &(*cache)[num]
}

// Returns a line
fn row(num: uint,  cache: &mut Vec<Vec<BigUint>>) -> String {
    let r = cumu(num,cache);
    let mut returned_string = String::new();
    for i in range(0,num) {
        let i = r[i+1] - r[i];
        returned_string.push_str(i.to_string().as_slice());
        returned_string.push_str(", ");
    }
    returned_string
}

#[cfg(not(test))]
fn main() {
    let mut cache: Vec<Vec<BigUint>> = Vec::new();
    let initial_value:BigUint = from_str("1").unwrap();
    let initial_vector : Vec<BigUint> = vec!(initial_value);
    cache.push(initial_vector);

    println!("rows");
    for n in range(1u, 11) {
        let x = n;
        println!("{}: {}", n, row(x,&mut cache));
    }

    println!("sums");

    let x: Vec<uint> = vec!(23, 123, 1234, 12345);
    for y in x.iter() {
  let z = cumu(*y,&mut cache);
  let w = z.last();
  println!("{}: {}", y, w.unwrap());
    }
}

#[test]
fn test_cumu() {
    let mut cache: Vec<Vec<BigUint>> = Vec::new();

    let initial_value:BigUint = from_str("1").unwrap();

    let initial_vector : Vec<BigUint> = vec!(initial_value);
    cache.push(initial_vector);

    let a: Vec<uint> = vec!(23, 123, 1234);
    let b: Vec<BigUint> = vec!(
        from_str("1255").unwrap(),
        from_str("2552338241").unwrap(),
        from_str("156978797223733228787865722354959930").unwrap());

    let mut n=0;
    for y in a.iter() {
        let z = cumu(*y,&mut cache);
        let w = z.last().unwrap();
        assert!(w == &b[n]);
        n= n+1;
    }
}

#[test]
fn test_row() {

    let mut cache: Vec<Vec<BigUint>> = Vec::new();

    let initial_value:BigUint = from_str("1").unwrap();

    let initial_vector : Vec<BigUint> = vec!(initial_value);
    cache.push(initial_vector);

    let a: String = from_str("1, 2, 1, 1, ").unwrap();

    let x = 4;
    assert!(a == row(x,&mut cache));

}
<commit_msg>9 billion names: refactor<commit_after>//Implements http://rosettacode.org/wiki/9_billion_names_of_God_the_integer

extern crate num;

use num::bigint::BigUint;
use std::cmp::min;
use std::iter::range_inclusive;
use std::num::{Zero, One};

pub struct Solver {
    // The `cache` is a private implementation detail,
    // it would be an improvement to throw away unused values
    // from the cache (to reduce memory for larger inputs)
    cache: Vec<Vec<BigUint>>
}

impl Solver {
    pub fn new() -> Solver {
        // Setup the cache with the initial row
        Solver { cache: vec![vec![One::one()]] }
    }

    // Returns a string representing a line
    pub fn row_string(&mut self, idx: uint) -> String {
        let r = self.cumulative(idx);

        range(0, idx).map(|i| r[i+1] - r[i])
                     .map(|n| n.to_string())
                     .collect::<Vec<String>>()
                     .connect(", ")
    }

    // Convenience method to access the last column in a culmulated calculation
    pub fn row_sum(&mut self, idx: uint) -> &BigUint {
        // This can never fail as we always add zero or one, so it's never empty.
        self.cumulative(idx).last().unwrap()
    }

    fn cumulative(&mut self, idx: uint) -> &[BigUint] {
        for l in range_inclusive(self.cache.len(), idx) {
            let mut r : Vec<BigUint> = vec![Zero::zero()];

            for x in range_inclusive(1, l) {
                let w = {
                    let y = &r[x-1];
                    let z = &self.cache[l-x][min(x, l-x)];
                    y + *z
                };
                r.push(w)
            }
            self.cache.push(r);
        }

        self.cache[idx].as_slice()
    }
}

#[cfg(not(test))]
fn main() {
    let mut solver = Solver::new();

    println!("rows");
    for n in range(1u, 11) {
        println!("{}: {}", n, solver.row_string(n));
    }

    println!("sums");
    for &y in [23u, 123, 1234, 12345].iter() {
        println!("{}: {}", y, solver.row_sum(y));
    }
}

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

    #[test]
    fn test_cumulative() {
        let mut solver = Solver::new();
        let t = |n: uint, expected: &str| {
            assert_eq!(solver.row_sum(n), &from_str(expected).unwrap())
        };

        t(23, "1255");
        t(123, "2552338241");
        t(1234, "156978797223733228787865722354959930");
    }

    #[test]
    fn test_row() {
        let mut solver = Solver::new();
        let t = |n: uint, expected: &str| {
            assert_eq!(solver.row_string(n).as_slice(), expected);
        };

        t(1, "1");
        t(2, "1, 1");
        t(3, "1, 1, 1");
        t(4, "1, 2, 1, 1");
        t(5, "1, 2, 2, 1, 1");
        t(6, "1, 3, 3, 2, 1, 1");
    }
}
<|endoftext|>


<commit_before>use keyboard::Key;
use keymap::{KeyMap, KeyMapState};
use command::{Builder, BuilderEvent, Command};

use super::Mode;

/// NormalMode mimics Vi's Normal mode.
pub struct NormalMode {
    keymap: KeyMap<Command>,
    builder: Builder,
}

impl NormalMode {

    /// Create a new instance of NormalMode
    pub fn new() -> NormalMode {
        NormalMode {
            keymap: NormalMode::key_defaults(),
            builder: Builder::new(),
        }
    }

    /// Creates a KeyMap with default NormalMode key bindings
    fn key_defaults() -> KeyMap<Command> {
        let mut keymap = KeyMap::new();

        keymap.bind_key(Key::Char('u'), Command::undo());
        keymap.bind_key(Key::Ctrl('r'), Command::redo());

        keymap
    }

}

impl Mode for NormalMode {
    fn handle_key_event(&mut self, key: Key) -> BuilderEvent {
        match self.builder.check_key(key) {
            // builder gives us a full command, return that
            BuilderEvent::Complete(cmd) => BuilderEvent::Complete(cmd),

            // no command from the builder, check the internal keymap
            BuilderEvent::Incomplete => {
                if let KeyMapState::Match(c) = self.keymap.check_key(key) {
                    BuilderEvent::Complete(c)
                } else {
                    BuilderEvent::Incomplete
                }
            }

            // invalid result from builder, return invalid
            BuilderEvent::Invalid => { BuilderEvent::Invalid }
        }
    }
}
<commit_msg>Fixed undo/redo in normal mode<commit_after>use keyboard::Key;
use keymap::{KeyMap, KeyMapState};
use command::{Builder, BuilderEvent, Command};

use super::Mode;

/// NormalMode mimics Vi's Normal mode.
pub struct NormalMode {
    keymap: KeyMap<Command>,
    builder: Builder,
}

impl NormalMode {

    /// Create a new instance of NormalMode
    pub fn new() -> NormalMode {
        NormalMode {
            keymap: NormalMode::key_defaults(),
            builder: Builder::new(),
        }
    }

    /// Creates a KeyMap with default NormalMode key bindings
    fn key_defaults() -> KeyMap<Command> {
        let mut keymap = KeyMap::new();

        keymap.bind_key(Key::Char('u'), Command::undo());
        keymap.bind_key(Key::Ctrl('r'), Command::redo());

        keymap
    }

    fn check_keymap(&mut self, key: Key) -> BuilderEvent {
        if let KeyMapState::Match(c) = self.keymap.check_key(key) {
            BuilderEvent::Complete(c)
        } else {
            BuilderEvent::Incomplete
        }
    }

}

impl Mode for NormalMode {
    fn handle_key_event(&mut self, key: Key) -> BuilderEvent {
        match self.builder.check_key(key) {
            // builder gives us a full command, return that
            BuilderEvent::Complete(cmd) => BuilderEvent::Complete(cmd),

            // no command from the builder, check the internal keymap
            BuilderEvent::Incomplete => { self.check_keymap(key) }

            // invalid result from builder, return invalid if the internal
            // keymap doesn't give a match
            BuilderEvent::Invalid => {
                let val = self.check_keymap(key);

                if let BuilderEvent::Incomplete = val {
                    BuilderEvent::Invalid
                } else {
                    val
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>//!
//! Values manipulated by services
//!
use std::cmp::{PartialOrd, Ordering};
use std::time::Duration;
use std::str::FromStr;
use std::sync::Arc;

use serde_json;
use chrono;
use serde::ser::{Serialize, Serializer};
use serde::de::{Deserialize, Deserializer, Error};

///
/// The type of values manipulated by endpoints.
///
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
pub enum Type {
    ///
    /// # Trivial values
    ///

    /// An empty value. Used for instance to inform that a countdown
    /// has reached 0 or that a device is ready.
    Unit,

    /// A boolean. Used for instance for on-off switches, presence
    /// detectors, etc.
    Bool,

    ///
    /// # Time
    ///

    /// A duration. Used for instance in countdowns.
    Duration,

    /// A precise timestamp. Used for instance to determine when an
    /// event has taken place.
    TimeStamp,

    Temperature,
    String,
    ///
    /// ...
    ///
    Color,
    Json,
    Binary,
    ExtNumeric,
}

/// A temperature. Internal representation may be either Fahrenheit or
/// Celcius. The FoxBox adapters are expected to perform conversions
/// to the format requested by their devices.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Temperature {
    /// Fahrenheit
    F(f64),
    /// Celcius
    C(f64),
}

impl Temperature {
    /// Get a temperature in Fahrenheit.
    pub fn as_f(&self) -> f64 {
        unimplemented!();
    }

    /// Get a temperature in Celcius.
    pub fn as_c(&self) -> f64 {
        unimplemented!();
    }
}

impl PartialOrd for Temperature {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.as_c().partial_cmp(&other.as_c())
    }
}

/// A color. Internal representation may vary. The FoxBox adapters are
/// expected to perform conversions to the format requested by their
/// device.
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
pub enum Color {
    RGBA(f64, f64, f64, f64, f64)
}

/// Representation of an object in JSON. It is often (albeit not
/// always) possible to choose a more precise data structure for
/// representing values send/accepted by a service. If possible,
/// adapters should rather pick such more precise data structure.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Json(pub serde_json::value::Value);

impl PartialOrd for Json {
    /// Two Json objects are never comparable to each other.
    fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
        None
    }
}

/// A data structure holding a numeric value of a type that has not
/// been standardized yet.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ExtNumeric {
    pub value: f64,

    /// The vendor. Used for namespacing purposes, to avoid
    /// confusing two incompatible extensions with similar
    /// names. For instance, "foxlink@mozilla.com".
    pub vendor: String,

    /// Identification of the adapter introducing this value.
    /// Designed to aid with tracing and debugging.
    pub adapter: String,

    /// A string describing the nature of the value, designed to
    /// aid with type-checking.
    ///
    /// Examples: `"GroundHumidity"`.
    pub kind: String,
}

impl PartialOrd for ExtNumeric {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        if self.vendor != other.vendor {
            return None;
        } else if self.kind != other.kind {
            return None;
        } else {
            self.value.partial_cmp(&other.value)
        }
    }
}

/// Representation of an actual value that can be sent to/received
/// from a service.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Value {
    Unit,
    Bool(bool),
    Duration(ValDuration),
    TimeStamp(TimeStamp),
    Temperature(Temperature),
    Color(Color),
    String(Arc<String>),

    // FIXME: Add more as we identify needs

    /// A numeric value representing a unit that has not been
    /// standardized yet into the API.
    ExtNumeric(ExtNumeric),

    /// A Json value. We put it behind an `Arc` to make sure that
    /// cloning remains unexpensive.
    Json(Arc<Json>),

    /// Binary data.
    Binary {
        /// The actual data. We put it behind an `Arc` to make sure
        /// that cloning remains unexpensive.
        data: Arc<Vec<u8>>,
        mimetype: String
    }
}

impl Value {
    pub fn get_type(&self) -> Type {
        match *self {
            Value::Unit => Type::Unit,
            Value::Bool(_) => Type::Bool,
            Value::String(_) => Type::String,
            Value::Duration(_) => Type::Duration,
            Value::TimeStamp(_) => Type::TimeStamp,
            Value::Temperature(_) => Type::Temperature,
            Value::Color(_) => Type::Color,
            Value::Json(_) => Type::Json,
            Value::Binary{..} => Type::Binary,
            Value::ExtNumeric(_) => Type::ExtNumeric,
        }
    }
}

impl PartialOrd for Value {
    /// Two values of the same type can be compared using the usual
    /// comparison for values of this type. Two values of distinct
    /// types cannot be compared.
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        use self::Value::*;
        use std::cmp::Ordering::*;
        match (self, other) {
            (&Unit, &Unit) => Some(Equal),
            (&Unit, _) => None,

            (&Bool(a), &Bool(b)) => a.partial_cmp(&b),
            (&Bool(_), _) => None,

            (&Duration(ref a), &Duration(ref b)) => a.partial_cmp(b),
            (&Duration(_), _) => None,

            (&TimeStamp(ref a), &TimeStamp(ref b)) => a.partial_cmp(b),
            (&TimeStamp(_), _) => None,

            (&Temperature(ref a), &Temperature(ref b)) => a.partial_cmp(b),
            (&Temperature(_), _) => None,

            (&Color(ref a), &Color(ref b)) => a.partial_cmp(b),
            (&Color(_), _) => None,

            (&ExtNumeric(ref a), &ExtNumeric(ref b)) => a.partial_cmp(b),
            (&ExtNumeric(_), _) => None,

            (&String(ref a), &String(ref b)) => a.partial_cmp(b),
            (&String(_), _) => None,

            (&Json(ref a), &Json(ref b)) => a.partial_cmp(b),
            (&Json(_), _) => None,

            (&Binary{mimetype: ref a_mimetype, data: ref a_data},
             &Binary{mimetype: ref b_mimetype, data: ref b_data}) if a_mimetype == b_mimetype => a_data.partial_cmp(b_data),
            (&Binary{..}, _) => None,
        }
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct ValDuration(Duration);
impl ValDuration {
    pub fn new(duration: Duration) -> Self {
        ValDuration(duration)
    }
}
impl Serialize for ValDuration {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        let as_ms : u64 = self.0.as_secs() * 1000
            + (self.0.subsec_nanos() as u64) / 1_000_000;
        as_ms.serialize(serializer)
    }
}
impl Deserialize for ValDuration {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer {
        let as_sec : f64 = try!(f64::deserialize(deserializer));
        Ok(ValDuration(Duration::new(as_sec as u64, as_sec.fract() as u32)))
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct TimeStamp(chrono::DateTime<chrono::Local>);
impl TimeStamp {
    pub fn from_s(s: i64) -> Self {
        use chrono::*;
        let naive = chrono::naive::datetime::NaiveDateTime::from_timestamp(s, 0);
        let offset = chrono::offset::fixed::FixedOffset::east(0);
        let date = DateTime::<Local>::from_utc(naive, offset);
        TimeStamp(date)
    }
}
impl Serialize for TimeStamp {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        let str = self.0.to_rfc3339();
        str.serialize(serializer)
    }
}
impl Deserialize for TimeStamp {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer {
        let str = try!(String::deserialize(deserializer));
        match chrono::DateTime::<chrono::Local>::from_str(&str) {
            Ok(dt) => Ok(TimeStamp(dt)),
            Err(_) => Err(D::Error::syntax("Invalid date"))
        }
    }
}
<commit_msg>Added values::Range<commit_after>//!
//! Values manipulated by services
//!
use std::cmp::{PartialOrd, Ordering};
use std::time::Duration;
use std::str::FromStr;
use std::sync::Arc;

use serde_json;
use chrono;
use serde::ser::{Serialize, Serializer};
use serde::de::{Deserialize, Deserializer, Error};

///
/// The type of values manipulated by endpoints.
///
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
pub enum Type {
    ///
    /// # Trivial values
    ///

    /// An empty value. Used for instance to inform that a countdown
    /// has reached 0 or that a device is ready.
    Unit,

    /// A boolean. Used for instance for on-off switches, presence
    /// detectors, etc.
    Bool,

    ///
    /// # Time
    ///

    /// A duration. Used for instance in countdowns.
    Duration,

    /// A precise timestamp. Used for instance to determine when an
    /// event has taken place.
    TimeStamp,

    Temperature,
    String,
    ///
    /// ...
    ///
    Color,
    Json,
    Binary,
    ExtNumeric,
}

/// A temperature. Internal representation may be either Fahrenheit or
/// Celcius. The FoxBox adapters are expected to perform conversions
/// to the format requested by their devices.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Temperature {
    /// Fahrenheit
    F(f64),
    /// Celcius
    C(f64),
}

impl Temperature {
    /// Get a temperature in Fahrenheit.
    pub fn as_f(&self) -> f64 {
        unimplemented!();
    }

    /// Get a temperature in Celcius.
    pub fn as_c(&self) -> f64 {
        unimplemented!();
    }
}

impl PartialOrd for Temperature {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.as_c().partial_cmp(&other.as_c())
    }
}

/// A color. Internal representation may vary. The FoxBox adapters are
/// expected to perform conversions to the format requested by their
/// device.
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
pub enum Color {
    RGBA(f64, f64, f64, f64, f64)
}

/// Representation of an object in JSON. It is often (albeit not
/// always) possible to choose a more precise data structure for
/// representing values send/accepted by a service. If possible,
/// adapters should rather pick such more precise data structure.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Json(pub serde_json::value::Value);

impl PartialOrd for Json {
    /// Two Json objects are never comparable to each other.
    fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
        None
    }
}

/// A data structure holding a numeric value of a type that has not
/// been standardized yet.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ExtNumeric {
    pub value: f64,

    /// The vendor. Used for namespacing purposes, to avoid
    /// confusing two incompatible extensions with similar
    /// names. For instance, "foxlink@mozilla.com".
    pub vendor: String,

    /// Identification of the adapter introducing this value.
    /// Designed to aid with tracing and debugging.
    pub adapter: String,

    /// A string describing the nature of the value, designed to
    /// aid with type-checking.
    ///
    /// Examples: `"GroundHumidity"`.
    pub kind: String,
}

impl PartialOrd for ExtNumeric {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        if self.vendor != other.vendor {
            return None;
        } else if self.kind != other.kind {
            return None;
        } else {
            self.value.partial_cmp(&other.value)
        }
    }
}

/// Representation of an actual value that can be sent to/received
/// from a service.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Value {
    Unit,
    Bool(bool),
    Duration(ValDuration),
    TimeStamp(TimeStamp),
    Temperature(Temperature),
    Color(Color),
    String(Arc<String>),

    // FIXME: Add more as we identify needs

    /// A numeric value representing a unit that has not been
    /// standardized yet into the API.
    ExtNumeric(ExtNumeric),

    /// A Json value. We put it behind an `Arc` to make sure that
    /// cloning remains unexpensive.
    Json(Arc<Json>),

    /// Binary data.
    Binary {
        /// The actual data. We put it behind an `Arc` to make sure
        /// that cloning remains unexpensive.
        data: Arc<Vec<u8>>,
        mimetype: String
    }
}

impl Value {
    pub fn get_type(&self) -> Type {
        match *self {
            Value::Unit => Type::Unit,
            Value::Bool(_) => Type::Bool,
            Value::String(_) => Type::String,
            Value::Duration(_) => Type::Duration,
            Value::TimeStamp(_) => Type::TimeStamp,
            Value::Temperature(_) => Type::Temperature,
            Value::Color(_) => Type::Color,
            Value::Json(_) => Type::Json,
            Value::Binary{..} => Type::Binary,
            Value::ExtNumeric(_) => Type::ExtNumeric,
        }
    }
}

impl PartialOrd for Value {
    /// Two values of the same type can be compared using the usual
    /// comparison for values of this type. Two values of distinct
    /// types cannot be compared.
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        use self::Value::*;
        use std::cmp::Ordering::*;
        match (self, other) {
            (&Unit, &Unit) => Some(Equal),
            (&Unit, _) => None,

            (&Bool(a), &Bool(b)) => a.partial_cmp(&b),
            (&Bool(_), _) => None,

            (&Duration(ref a), &Duration(ref b)) => a.partial_cmp(b),
            (&Duration(_), _) => None,

            (&TimeStamp(ref a), &TimeStamp(ref b)) => a.partial_cmp(b),
            (&TimeStamp(_), _) => None,

            (&Temperature(ref a), &Temperature(ref b)) => a.partial_cmp(b),
            (&Temperature(_), _) => None,

            (&Color(ref a), &Color(ref b)) => a.partial_cmp(b),
            (&Color(_), _) => None,

            (&ExtNumeric(ref a), &ExtNumeric(ref b)) => a.partial_cmp(b),
            (&ExtNumeric(_), _) => None,

            (&String(ref a), &String(ref b)) => a.partial_cmp(b),
            (&String(_), _) => None,

            (&Json(ref a), &Json(ref b)) => a.partial_cmp(b),
            (&Json(_), _) => None,

            (&Binary{mimetype: ref a_mimetype, data: ref a_data},
             &Binary{mimetype: ref b_mimetype, data: ref b_data}) if a_mimetype == b_mimetype => a_data.partial_cmp(b_data),
            (&Binary{..}, _) => None,
        }
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct ValDuration(Duration);
impl ValDuration {
    pub fn new(duration: Duration) -> Self {
        ValDuration(duration)
    }
}
impl Serialize for ValDuration {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        let as_ms : u64 = self.0.as_secs() * 1000
            + (self.0.subsec_nanos() as u64) / 1_000_000;
        as_ms.serialize(serializer)
    }
}
impl Deserialize for ValDuration {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer {
        let as_sec : f64 = try!(f64::deserialize(deserializer));
        Ok(ValDuration(Duration::new(as_sec as u64, as_sec.fract() as u32)))
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct TimeStamp(chrono::DateTime<chrono::Local>);
impl TimeStamp {
    pub fn from_s(s: i64) -> Self {
        use chrono::*;
        let naive = chrono::naive::datetime::NaiveDateTime::from_timestamp(s, 0);
        let offset = chrono::offset::fixed::FixedOffset::east(0);
        let date = DateTime::<Local>::from_utc(naive, offset);
        TimeStamp(date)
    }
}
impl Serialize for TimeStamp {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        let str = self.0.to_rfc3339();
        str.serialize(serializer)
    }
}
impl Deserialize for TimeStamp {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer {
        let str = try!(String::deserialize(deserializer));
        match chrono::DateTime::<chrono::Local>::from_str(&str) {
            Ok(dt) => Ok(TimeStamp(dt)),
            Err(_) => Err(D::Error::syntax("Invalid date"))
        }
    }
}

#[derive(Clone, Deserialize, Serialize)]
/// A comparison between two values.
pub enum Range {
    /// Leq(x) accepts any value v such that v <= x.
    Leq(Value),

    /// Geq(x) accepts any value v such that v >= x.
    Geq(Value),

    /// BetweenEq {min, max} accepts any value v such that `min <= v`
    /// and `v <= max`. If `max < min`, it never accepts anything.
    BetweenEq {min:Value, max:Value},

    /// OutOfStrict {min, max} accepts any value v such that `v < min`
    /// or `max < v`
    OutOfStrict {min:Value, max:Value},

    /// Eq(x) accespts any value v such that v == x
    Eq(Value),
}

impl Range {
    /// Determine if a value is accepted by this range.
    pub fn contains(&self, value: &Value) -> bool {
        use self::Range::*;
        match *self {
            Leq(ref max) => value <= max,
            Geq(ref min) => value >= min,
            BetweenEq {ref min, ref max} => min <= value && value <= max,
            OutOfStrict {ref min, ref max} => value < min || max < value,
            Eq(ref val) => value == val,
        }
    }

    /// Get the type associated to this range.
    ///
    /// If this range has a `min` and a `max` with conflicting types,
    /// produce an error.
    pub fn get_type(&self) -> Result<Type, ()> {
        use self::Range::*;
        match *self {
            Leq(ref v) | Geq(ref v) | Eq(ref v) => Ok(v.get_type()),
            BetweenEq{ref min, ref max} | OutOfStrict{ref min, ref max} => {
                let min_typ = min.get_type();
                let max_typ = max.get_type();
                if min_typ == max_typ {
                    Ok(min_typ)
                } else {
                    Err(())
                }
            }
        }
    }
}
<|endoftext|>