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

/** Task-local reference counted boxes

The `Rc` type provides shared ownership of an immutable value. Destruction is deterministic, and
will occur as soon as the last owner is gone. It is marked as non-sendable because it avoids the
overhead of atomic reference counting.

The `RcMut` type provides shared ownership of a mutable value. Since multiple owners prevent
inherited mutability, a dynamic freezing check is used to maintain the invariant that an `&mut`
reference is a unique handle and the type is marked as non-`Freeze`.

*/

use ptr::RawPtr;
use unstable::intrinsics::transmute;
use ops::Drop;
use kinds::{Freeze, Send};
use clone::{Clone, DeepClone};

struct RcBox<T> {
    value: T,
    count: uint
}

/// Immutable reference counted pointer type
#[unsafe_no_drop_flag]
#[no_send]
pub struct Rc<T> {
    priv ptr: *mut RcBox<T>
}

impl<T: Freeze> Rc<T> {
    /// Construct a new reference-counted box from a `Freeze` value
    #[inline]
    pub fn new(value: T) -> Rc<T> {
        unsafe {
            Rc::new_unchecked(value)
        }
    }
}

impl<T> Rc<T> {
    /// Unsafety construct a new reference-counted box from any value.
    ///
    /// If the type is not `Freeze`, the `Rc` box will incorrectly still be considered as a `Freeze`
    /// type. It is also possible to create cycles, which will leak, and may interact poorly with
    /// managed pointers.
    #[inline]
    pub unsafe fn new_unchecked(value: T) -> Rc<T> {
        Rc{ptr: transmute(~RcBox{value: value, count: 1})}
    }

    /// Borrow the value contained in the reference-counted box
    #[inline]
    pub fn borrow<'r>(&'r self) -> &'r T {
        unsafe { &(*self.ptr).value }
    }
}

impl<T> Clone for Rc<T> {
    #[inline]
    fn clone(&self) -> Rc<T> {
        unsafe {
            (*self.ptr).count += 1;
            Rc{ptr: self.ptr}
        }
    }
}

impl<T: DeepClone> DeepClone for Rc<T> {
    #[inline]
    fn deep_clone(&self) -> Rc<T> {
        unsafe { Rc::new_unchecked(self.borrow().deep_clone()) }
    }
}

#[unsafe_destructor]
impl<T> Drop for Rc<T> {
    fn drop(&mut self) {
        unsafe {
            if self.ptr.is_not_null() {
                (*self.ptr).count -= 1;
                if (*self.ptr).count == 0 {
                    let _: ~RcBox<T> = transmute(self.ptr);
                }
            }
        }
    }
}

#[cfg(test)]
mod test_rc {
    use super::*;
    use cell::Cell;

    #[test]
    fn test_clone() {
        unsafe {
            let x = Rc::new_unchecked(Cell::new(5));
            let y = x.clone();
            do x.borrow().with_mut_ref |inner| {
                *inner = 20;
            }
            assert_eq!(y.borrow().take(), 20);
        }
    }

    #[test]
    fn test_deep_clone() {
        unsafe {
            let x = Rc::new_unchecked(Cell::new(5));
            let y = x.deep_clone();
            do x.borrow().with_mut_ref |inner| {
                *inner = 20;
            }
            assert_eq!(y.borrow().take(), 5);
        }
    }

    #[test]
    fn test_simple() {
        let x = Rc::new(5);
        assert_eq!(*x.borrow(), 5);
    }

    #[test]
    fn test_simple_clone() {
        let x = Rc::new(5);
        let y = x.clone();
        assert_eq!(*x.borrow(), 5);
        assert_eq!(*y.borrow(), 5);
    }

    #[test]
    fn test_destructor() {
        unsafe {
            let x = Rc::new_unchecked(~5);
            assert_eq!(**x.borrow(), 5);
        }
    }
}

#[deriving(Eq)]
enum Borrow {
    Mutable,
    Immutable,
    Nothing
}

struct RcMutBox<T> {
    value: T,
    count: uint,
    borrow: Borrow
}

/// Mutable reference counted pointer type
#[no_send]
#[no_freeze]
#[unsafe_no_drop_flag]
pub struct RcMut<T> {
    priv ptr: *mut RcMutBox<T>,
}

impl<T: Freeze> RcMut<T> {
    /// Construct a new mutable reference-counted box from a `Freeze` value
    #[inline]
    pub fn new(value: T) -> RcMut<T> {
        unsafe { RcMut::new_unchecked(value) }
    }
}

impl<T: Send> RcMut<T> {
    /// Construct a new mutable reference-counted box from a `Send` value
    #[inline]
    pub fn from_send(value: T) -> RcMut<T> {
        unsafe { RcMut::new_unchecked(value) }
    }
}

impl<T> RcMut<T> {
    /// Unsafety construct a new mutable reference-counted box from any value.
    ///
    /// It is possible to create cycles, which will leak, and may interact
    /// poorly with managed pointers.
    #[inline]
    pub unsafe fn new_unchecked(value: T) -> RcMut<T> {
        RcMut{ptr: transmute(~RcMutBox{value: value, count: 1, borrow: Nothing})}
    }
}

impl<T> RcMut<T> {
    /// Fails if there is already a mutable borrow of the box
    #[inline]
    pub fn with_borrow<U>(&self, f: &fn(&T) -> U) -> U {
        unsafe {
            assert!((*self.ptr).borrow != Mutable);
            let previous = (*self.ptr).borrow;
            (*self.ptr).borrow = Immutable;
            let res = f(&(*self.ptr).value);
            (*self.ptr).borrow = previous;
            res
        }
    }

    /// Fails if there is already a mutable or immutable borrow of the box
    #[inline]
    pub fn with_mut_borrow<U>(&self, f: &fn(&mut T) -> U) -> U {
        unsafe {
            assert_eq!((*self.ptr).borrow, Nothing);
            (*self.ptr).borrow = Mutable;
            let res = f(&mut (*self.ptr).value);
            (*self.ptr).borrow = Nothing;
            res
        }
    }
}

#[unsafe_destructor]
impl<T> Drop for RcMut<T> {
    fn drop(&mut self) {
        unsafe {
            if self.ptr.is_not_null() {
                (*self.ptr).count -= 1;
                if (*self.ptr).count == 0 {
                    let _: ~RcMutBox<T> = transmute(self.ptr);
                }
            }
        }
    }
}

impl<T> Clone for RcMut<T> {
    /// Return a shallow copy of the reference counted pointer.
    #[inline]
    fn clone(&self) -> RcMut<T> {
        unsafe {
            (*self.ptr).count += 1;
            RcMut{ptr: self.ptr}
        }
    }
}

impl<T: DeepClone> DeepClone for RcMut<T> {
    /// Return a deep copy of the reference counted pointer.
    #[inline]
    fn deep_clone(&self) -> RcMut<T> {
        do self.with_borrow |x| {
            // FIXME: #6497: should avoid freeze (slow)
            unsafe { RcMut::new_unchecked(x.deep_clone()) }
        }
    }
}

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

    #[test]
    fn test_clone() {
        let x = RcMut::from_send(5);
        let y = x.clone();
        do x.with_mut_borrow |value| {
            *value = 20;
        }
        do y.with_borrow |value| {
            assert_eq!(*value, 20);
        }
    }

    #[test]
    fn test_deep_clone() {
        let x = RcMut::new(5);
        let y = x.deep_clone();
        do x.with_mut_borrow |value| {
            *value = 20;
        }
        do y.with_borrow |value| {
            assert_eq!(*value, 5);
        }
    }

    #[test]
    fn borrow_many() {
        let x = RcMut::from_send(5);
        let y = x.clone();

        do x.with_borrow |a| {
            assert_eq!(*a, 5);
            do y.with_borrow |b| {
                assert_eq!(*b, 5);
                do x.with_borrow |c| {
                    assert_eq!(*c, 5);
                }
            }
        }
    }

    #[test]
    fn modify() {
        let x = RcMut::new(5);
        let y = x.clone();

        do y.with_mut_borrow |a| {
            assert_eq!(*a, 5);
            *a = 6;
        }

        do x.with_borrow |a| {
            assert_eq!(*a, 6);
        }
    }

    #[test]
    fn release_immutable() {
        let x = RcMut::from_send(5);
        do x.with_borrow |_| {}
        do x.with_mut_borrow |_| {}
    }

    #[test]
    fn release_mutable() {
        let x = RcMut::new(5);
        do x.with_mut_borrow |_| {}
        do x.with_borrow |_| {}
    }

    #[test]
    #[should_fail]
    fn frozen() {
        let x = RcMut::from_send(5);
        let y = x.clone();

        do x.with_borrow |_| {
            do y.with_mut_borrow |_| {
            }
        }
    }

    #[test]
    #[should_fail]
    fn mutable_dupe() {
        let x = RcMut::new(5);
        let y = x.clone();

        do x.with_mut_borrow |_| {
            do y.with_mut_borrow |_| {
            }
        }
    }

    #[test]
    #[should_fail]
    fn mutable_freeze() {
        let x = RcMut::from_send(5);
        let y = x.clone();

        do x.with_mut_borrow |_| {
            do y.with_borrow |_| {
            }
        }
    }

    #[test]
    #[should_fail]
    fn restore_freeze() {
        let x = RcMut::new(5);
        let y = x.clone();

        do x.with_borrow |_| {
            do x.with_borrow |_| {}
            do y.with_mut_borrow |_| {}
        }
    }
}
<commit_msg>auto merge of #9825 : thestinger/rust/rc, r=thestinger<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*! Task-local reference counted boxes

The `Rc` type provides shared ownership of an immutable value. Destruction is deterministic, and
will occur as soon as the last owner is gone. It is marked as non-sendable because it avoids the
overhead of atomic reference counting.

The `RcMut` type provides shared ownership of a mutable value. Since multiple owners prevent
inherited mutability, a dynamic freezing check is used to maintain the invariant that an `&mut`
reference is a unique handle and the type is marked as non-`Freeze`.

*/

use ptr::RawPtr;
use unstable::intrinsics::transmute;
use ops::Drop;
use kinds::{Freeze, Send};
use clone::{Clone, DeepClone};

struct RcBox<T> {
    value: T,
    count: uint
}

/// Immutable reference counted pointer type
#[unsafe_no_drop_flag]
#[no_send]
pub struct Rc<T> {
    priv ptr: *mut RcBox<T>
}

impl<T: Freeze> Rc<T> {
    /// Construct a new reference-counted box from a `Freeze` value
    #[inline]
    pub fn new(value: T) -> Rc<T> {
        unsafe {
            Rc::new_unchecked(value)
        }
    }
}

impl<T> Rc<T> {
    /// Unsafety construct a new reference-counted box from any value.
    ///
    /// If the type is not `Freeze`, the `Rc` box will incorrectly still be considered as a `Freeze`
    /// type. It is also possible to create cycles, which will leak, and may interact poorly with
    /// managed pointers.
    #[inline]
    pub unsafe fn new_unchecked(value: T) -> Rc<T> {
        Rc{ptr: transmute(~RcBox{value: value, count: 1})}
    }

    /// Borrow the value contained in the reference-counted box
    #[inline]
    pub fn borrow<'r>(&'r self) -> &'r T {
        unsafe { &(*self.ptr).value }
    }
}

impl<T> Clone for Rc<T> {
    #[inline]
    fn clone(&self) -> Rc<T> {
        unsafe {
            (*self.ptr).count += 1;
            Rc{ptr: self.ptr}
        }
    }
}

impl<T: DeepClone> DeepClone for Rc<T> {
    #[inline]
    fn deep_clone(&self) -> Rc<T> {
        unsafe { Rc::new_unchecked(self.borrow().deep_clone()) }
    }
}

#[unsafe_destructor]
impl<T> Drop for Rc<T> {
    fn drop(&mut self) {
        unsafe {
            if self.ptr.is_not_null() {
                (*self.ptr).count -= 1;
                if (*self.ptr).count == 0 {
                    let _: ~RcBox<T> = transmute(self.ptr);
                }
            }
        }
    }
}

#[cfg(test)]
mod test_rc {
    use super::*;
    use cell::Cell;

    #[test]
    fn test_clone() {
        unsafe {
            let x = Rc::new_unchecked(Cell::new(5));
            let y = x.clone();
            do x.borrow().with_mut_ref |inner| {
                *inner = 20;
            }
            assert_eq!(y.borrow().take(), 20);
        }
    }

    #[test]
    fn test_deep_clone() {
        unsafe {
            let x = Rc::new_unchecked(Cell::new(5));
            let y = x.deep_clone();
            do x.borrow().with_mut_ref |inner| {
                *inner = 20;
            }
            assert_eq!(y.borrow().take(), 5);
        }
    }

    #[test]
    fn test_simple() {
        let x = Rc::new(5);
        assert_eq!(*x.borrow(), 5);
    }

    #[test]
    fn test_simple_clone() {
        let x = Rc::new(5);
        let y = x.clone();
        assert_eq!(*x.borrow(), 5);
        assert_eq!(*y.borrow(), 5);
    }

    #[test]
    fn test_destructor() {
        unsafe {
            let x = Rc::new_unchecked(~5);
            assert_eq!(**x.borrow(), 5);
        }
    }
}

#[deriving(Eq)]
enum Borrow {
    Mutable,
    Immutable,
    Nothing
}

struct RcMutBox<T> {
    value: T,
    count: uint,
    borrow: Borrow
}

/// Mutable reference counted pointer type
#[no_send]
#[no_freeze]
#[unsafe_no_drop_flag]
pub struct RcMut<T> {
    priv ptr: *mut RcMutBox<T>,
}

impl<T: Freeze> RcMut<T> {
    /// Construct a new mutable reference-counted box from a `Freeze` value
    #[inline]
    pub fn new(value: T) -> RcMut<T> {
        unsafe { RcMut::new_unchecked(value) }
    }
}

impl<T: Send> RcMut<T> {
    /// Construct a new mutable reference-counted box from a `Send` value
    #[inline]
    pub fn from_send(value: T) -> RcMut<T> {
        unsafe { RcMut::new_unchecked(value) }
    }
}

impl<T> RcMut<T> {
    /// Unsafety construct a new mutable reference-counted box from any value.
    ///
    /// It is possible to create cycles, which will leak, and may interact
    /// poorly with managed pointers.
    #[inline]
    pub unsafe fn new_unchecked(value: T) -> RcMut<T> {
        RcMut{ptr: transmute(~RcMutBox{value: value, count: 1, borrow: Nothing})}
    }
}

impl<T> RcMut<T> {
    /// Fails if there is already a mutable borrow of the box
    #[inline]
    pub fn with_borrow<U>(&self, f: &fn(&T) -> U) -> U {
        unsafe {
            assert!((*self.ptr).borrow != Mutable);
            let previous = (*self.ptr).borrow;
            (*self.ptr).borrow = Immutable;
            let res = f(&(*self.ptr).value);
            (*self.ptr).borrow = previous;
            res
        }
    }

    /// Fails if there is already a mutable or immutable borrow of the box
    #[inline]
    pub fn with_mut_borrow<U>(&self, f: &fn(&mut T) -> U) -> U {
        unsafe {
            assert_eq!((*self.ptr).borrow, Nothing);
            (*self.ptr).borrow = Mutable;
            let res = f(&mut (*self.ptr).value);
            (*self.ptr).borrow = Nothing;
            res
        }
    }
}

#[unsafe_destructor]
impl<T> Drop for RcMut<T> {
    fn drop(&mut self) {
        unsafe {
            if self.ptr.is_not_null() {
                (*self.ptr).count -= 1;
                if (*self.ptr).count == 0 {
                    let _: ~RcMutBox<T> = transmute(self.ptr);
                }
            }
        }
    }
}

impl<T> Clone for RcMut<T> {
    /// Return a shallow copy of the reference counted pointer.
    #[inline]
    fn clone(&self) -> RcMut<T> {
        unsafe {
            (*self.ptr).count += 1;
            RcMut{ptr: self.ptr}
        }
    }
}

impl<T: DeepClone> DeepClone for RcMut<T> {
    /// Return a deep copy of the reference counted pointer.
    #[inline]
    fn deep_clone(&self) -> RcMut<T> {
        do self.with_borrow |x| {
            // FIXME: #6497: should avoid freeze (slow)
            unsafe { RcMut::new_unchecked(x.deep_clone()) }
        }
    }
}

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

    #[test]
    fn test_clone() {
        let x = RcMut::from_send(5);
        let y = x.clone();
        do x.with_mut_borrow |value| {
            *value = 20;
        }
        do y.with_borrow |value| {
            assert_eq!(*value, 20);
        }
    }

    #[test]
    fn test_deep_clone() {
        let x = RcMut::new(5);
        let y = x.deep_clone();
        do x.with_mut_borrow |value| {
            *value = 20;
        }
        do y.with_borrow |value| {
            assert_eq!(*value, 5);
        }
    }

    #[test]
    fn borrow_many() {
        let x = RcMut::from_send(5);
        let y = x.clone();

        do x.with_borrow |a| {
            assert_eq!(*a, 5);
            do y.with_borrow |b| {
                assert_eq!(*b, 5);
                do x.with_borrow |c| {
                    assert_eq!(*c, 5);
                }
            }
        }
    }

    #[test]
    fn modify() {
        let x = RcMut::new(5);
        let y = x.clone();

        do y.with_mut_borrow |a| {
            assert_eq!(*a, 5);
            *a = 6;
        }

        do x.with_borrow |a| {
            assert_eq!(*a, 6);
        }
    }

    #[test]
    fn release_immutable() {
        let x = RcMut::from_send(5);
        do x.with_borrow |_| {}
        do x.with_mut_borrow |_| {}
    }

    #[test]
    fn release_mutable() {
        let x = RcMut::new(5);
        do x.with_mut_borrow |_| {}
        do x.with_borrow |_| {}
    }

    #[test]
    #[should_fail]
    fn frozen() {
        let x = RcMut::from_send(5);
        let y = x.clone();

        do x.with_borrow |_| {
            do y.with_mut_borrow |_| {
            }
        }
    }

    #[test]
    #[should_fail]
    fn mutable_dupe() {
        let x = RcMut::new(5);
        let y = x.clone();

        do x.with_mut_borrow |_| {
            do y.with_mut_borrow |_| {
            }
        }
    }

    #[test]
    #[should_fail]
    fn mutable_freeze() {
        let x = RcMut::from_send(5);
        let y = x.clone();

        do x.with_mut_borrow |_| {
            do y.with_borrow |_| {
            }
        }
    }

    #[test]
    #[should_fail]
    fn restore_freeze() {
        let x = RcMut::new(5);
        let y = x.clone();

        do x.with_borrow |_| {
            do x.with_borrow |_| {}
            do y.with_mut_borrow |_| {}
        }
    }
}
<|endoftext|>


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

//! A unique pointer type.

use core::any::{Any, AnyRefExt};
use core::clone::Clone;
use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering};
use core::default::Default;
use core::fmt;
use core::hash::{mod, Hash};
use core::kinds::Sized;
use core::mem;
use core::option::Option;
use core::raw::TraitObject;
use core::result::Result;
use core::result::Result::{Ok, Err};

/// A value that represents the global exchange heap. This is the default
/// place that the `box` keyword allocates into when no place is supplied.
///
/// The following two examples are equivalent:
///
/// ```rust
/// use std::boxed::HEAP;
///
/// # struct Bar;
/// # impl Bar { fn new(_a: int) { } }
/// let foo = box(HEAP) Bar::new(2);
/// let foo = box Bar::new(2);
/// ```
#[lang = "exchange_heap"]
#[experimental = "may be renamed; uncertain about custom allocator design"]
pub static HEAP: () = ();

/// A type that represents a uniquely-owned value.
#[lang = "owned_box"]
#[unstable = "custom allocators will add an additional type parameter (with default)"]
pub struct Box<T>(*mut T);

#[stable]
impl<T: Default> Default for Box<T> {
    #[stable]
    fn default() -> Box<T> { box Default::default() }
}

#[stable]
impl<T> Default for Box<[T]> {
    #[stable]
    fn default() -> Box<[T]> { box [] }
}

#[unstable]
impl<T: Clone> Clone for Box<T> {
    /// Returns a copy of the owned box.
    #[inline]
    fn clone(&self) -> Box<T> { box {(**self).clone()} }

    /// Performs copy-assignment from `source` by reusing the existing allocation.
    #[inline]
    fn clone_from(&mut self, source: &Box<T>) {
        (**self).clone_from(&(**source));
    }
}

impl<Sized? T: PartialEq> PartialEq for Box<T> {
    #[inline]
    fn eq(&self, other: &Box<T>) -> bool { PartialEq::eq(&**self, &**other) }
    #[inline]
    fn ne(&self, other: &Box<T>) -> bool { PartialEq::ne(&**self, &**other) }
}
impl<Sized? T: PartialOrd> PartialOrd for Box<T> {
    #[inline]
    fn partial_cmp(&self, other: &Box<T>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
    #[inline]
    fn lt(&self, other: &Box<T>) -> bool { PartialOrd::lt(&**self, &**other) }
    #[inline]
    fn le(&self, other: &Box<T>) -> bool { PartialOrd::le(&**self, &**other) }
    #[inline]
    fn ge(&self, other: &Box<T>) -> bool { PartialOrd::ge(&**self, &**other) }
    #[inline]
    fn gt(&self, other: &Box<T>) -> bool { PartialOrd::gt(&**self, &**other) }
}
impl<Sized? T: Ord> Ord for Box<T> {
    #[inline]
    fn cmp(&self, other: &Box<T>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}
impl<Sized? T: Eq> Eq for Box<T> {}

impl<S: hash::Writer, Sized? T: Hash<S>> Hash<S> for Box<T> {
    #[inline]
    fn hash(&self, state: &mut S) {
        (**self).hash(state);
    }
}

/// Extension methods for an owning `Any` trait object.
#[unstable = "post-DST and coherence changes, this will not be a trait but \
              rather a direct `impl` on `Box<Any>`"]
pub trait BoxAny {
    /// Returns the boxed value if it is of type `T`, or
    /// `Err(Self)` if it isn't.
    #[unstable = "naming conventions around accessing innards may change"]
    fn downcast<T: 'static>(self) -> Result<Box<T>, Self>;
}

#[stable]
impl BoxAny for Box<Any> {
    #[inline]
    fn downcast<T: 'static>(self) -> Result<Box<T>, Box<Any>> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let to: TraitObject =
                    mem::transmute::<Box<Any>, TraitObject>(self);

                // Extract the data pointer
                Ok(mem::transmute(to.data))
            }
        } else {
            Err(self)
        }
    }
}

impl<Sized? T: fmt::Show> fmt::Show for Box<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        (**self).fmt(f)
    }
}

impl fmt::Show for Box<Any+'static> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Box<Any>")
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn test_owned_clone() {
        let a = box 5i;
        let b: Box<int> = a.clone();
        assert!(a == b);
    }

    #[test]
    fn any_move() {
        let a = box 8u as Box<Any>;
        let b = box Test as Box<Any>;

        match a.downcast::<uint>() {
            Ok(a) => { assert!(a == box 8u); }
            Err(..) => panic!()
        }
        match b.downcast::<Test>() {
            Ok(a) => { assert!(a == box Test); }
            Err(..) => panic!()
        }

        let a = box 8u as Box<Any>;
        let b = box Test as Box<Any>;

        assert!(a.downcast::<Box<Test>>().is_err());
        assert!(b.downcast::<Box<uint>>().is_err());
    }

    #[test]
    fn test_show() {
        let a = box 8u as Box<Any>;
        let b = box Test as Box<Any>;
        let a_str = a.to_str();
        let b_str = b.to_str();
        assert_eq!(a_str, "Box<Any>");
        assert_eq!(b_str, "Box<Any>");

        let a = &8u as &Any;
        let b = &Test as &Any;
        let s = format!("{}", a);
        assert_eq!(s, "&Any");
        let s = format!("{}", b);
        assert_eq!(s, "&Any");
    }
}
<commit_msg>rollup merge of #20052: barosl/deref-for-box<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A unique pointer type.

use core::any::{Any, AnyRefExt};
use core::clone::Clone;
use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering};
use core::default::Default;
use core::fmt;
use core::hash::{mod, Hash};
use core::kinds::Sized;
use core::mem;
use core::option::Option;
use core::raw::TraitObject;
use core::result::Result;
use core::result::Result::{Ok, Err};
use core::ops::{Deref, DerefMut};

/// A value that represents the global exchange heap. This is the default
/// place that the `box` keyword allocates into when no place is supplied.
///
/// The following two examples are equivalent:
///
/// ```rust
/// use std::boxed::HEAP;
///
/// # struct Bar;
/// # impl Bar { fn new(_a: int) { } }
/// let foo = box(HEAP) Bar::new(2);
/// let foo = box Bar::new(2);
/// ```
#[lang = "exchange_heap"]
#[experimental = "may be renamed; uncertain about custom allocator design"]
pub static HEAP: () = ();

/// A type that represents a uniquely-owned value.
#[lang = "owned_box"]
#[unstable = "custom allocators will add an additional type parameter (with default)"]
pub struct Box<T>(*mut T);

#[stable]
impl<T: Default> Default for Box<T> {
    #[stable]
    fn default() -> Box<T> { box Default::default() }
}

#[stable]
impl<T> Default for Box<[T]> {
    #[stable]
    fn default() -> Box<[T]> { box [] }
}

#[unstable]
impl<T: Clone> Clone for Box<T> {
    /// Returns a copy of the owned box.
    #[inline]
    fn clone(&self) -> Box<T> { box {(**self).clone()} }

    /// Performs copy-assignment from `source` by reusing the existing allocation.
    #[inline]
    fn clone_from(&mut self, source: &Box<T>) {
        (**self).clone_from(&(**source));
    }
}

impl<Sized? T: PartialEq> PartialEq for Box<T> {
    #[inline]
    fn eq(&self, other: &Box<T>) -> bool { PartialEq::eq(&**self, &**other) }
    #[inline]
    fn ne(&self, other: &Box<T>) -> bool { PartialEq::ne(&**self, &**other) }
}
impl<Sized? T: PartialOrd> PartialOrd for Box<T> {
    #[inline]
    fn partial_cmp(&self, other: &Box<T>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
    #[inline]
    fn lt(&self, other: &Box<T>) -> bool { PartialOrd::lt(&**self, &**other) }
    #[inline]
    fn le(&self, other: &Box<T>) -> bool { PartialOrd::le(&**self, &**other) }
    #[inline]
    fn ge(&self, other: &Box<T>) -> bool { PartialOrd::ge(&**self, &**other) }
    #[inline]
    fn gt(&self, other: &Box<T>) -> bool { PartialOrd::gt(&**self, &**other) }
}
impl<Sized? T: Ord> Ord for Box<T> {
    #[inline]
    fn cmp(&self, other: &Box<T>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}
impl<Sized? T: Eq> Eq for Box<T> {}

impl<S: hash::Writer, Sized? T: Hash<S>> Hash<S> for Box<T> {
    #[inline]
    fn hash(&self, state: &mut S) {
        (**self).hash(state);
    }
}

/// Extension methods for an owning `Any` trait object.
#[unstable = "post-DST and coherence changes, this will not be a trait but \
              rather a direct `impl` on `Box<Any>`"]
pub trait BoxAny {
    /// Returns the boxed value if it is of type `T`, or
    /// `Err(Self)` if it isn't.
    #[unstable = "naming conventions around accessing innards may change"]
    fn downcast<T: 'static>(self) -> Result<Box<T>, Self>;
}

#[stable]
impl BoxAny for Box<Any> {
    #[inline]
    fn downcast<T: 'static>(self) -> Result<Box<T>, Box<Any>> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let to: TraitObject =
                    mem::transmute::<Box<Any>, TraitObject>(self);

                // Extract the data pointer
                Ok(mem::transmute(to.data))
            }
        } else {
            Err(self)
        }
    }
}

impl<Sized? T: fmt::Show> fmt::Show for Box<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        (**self).fmt(f)
    }
}

impl fmt::Show for Box<Any+'static> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Box<Any>")
    }
}

impl<Sized? T> Deref<T> for Box<T> {
    fn deref(&self) -> &T { &**self }
}

impl<Sized? T> DerefMut<T> for Box<T> {
    fn deref_mut(&mut self) -> &mut T { &mut **self }
}

#[cfg(test)]
mod test {
    #[test]
    fn test_owned_clone() {
        let a = box 5i;
        let b: Box<int> = a.clone();
        assert!(a == b);
    }

    #[test]
    fn any_move() {
        let a = box 8u as Box<Any>;
        let b = box Test as Box<Any>;

        match a.downcast::<uint>() {
            Ok(a) => { assert!(a == box 8u); }
            Err(..) => panic!()
        }
        match b.downcast::<Test>() {
            Ok(a) => { assert!(a == box Test); }
            Err(..) => panic!()
        }

        let a = box 8u as Box<Any>;
        let b = box Test as Box<Any>;

        assert!(a.downcast::<Box<Test>>().is_err());
        assert!(b.downcast::<Box<uint>>().is_err());
    }

    #[test]
    fn test_show() {
        let a = box 8u as Box<Any>;
        let b = box Test as Box<Any>;
        let a_str = a.to_str();
        let b_str = b.to_str();
        assert_eq!(a_str, "Box<Any>");
        assert_eq!(b_str, "Box<Any>");

        let a = &8u as &Any;
        let b = &Test as &Any;
        let s = format!("{}", a);
        assert_eq!(s, "&Any");
        let s = format!("{}", b);
        assert_eq!(s, "&Any");
    }

    #[test]
    fn deref() {
        fn homura<T: Deref<i32>>(_: T) { }
        homura(box 765i32);
    }
}
<|endoftext|>


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

//! Utilities that leverage libuv's `uv_timer_*` API

use core::prelude::*;

use uv;
use uv::iotask;
use uv::iotask::IoTask;

use core::cast::transmute;
use core::cast;
use core::comm::{stream, Chan, SharedChan, Port, select2i};
use core::either;
use core::libc::c_void;
use core::libc;

/**
 * Wait for timeout period then send provided value over a channel
 *
 * This call returns immediately. Useful as the building block for a number
 * of higher-level timer functions.
 *
 * Is not guaranteed to wait for exactly the specified time, but will wait
 * for *at least* that period of time.
 *
 * # Arguments
 *
 * * `hl_loop` - a `uv::hl::high_level_loop` that the tcp request will run on
 * * msecs - a timeout period, in milliseconds, to wait
 * * ch - a channel of type T to send a `val` on
 * * val - a value of type T to send over the provided `ch`
 */
pub fn delayed_send<T:Owned>(iotask: &IoTask,
                              msecs: uint,
                              ch: &Chan<T>,
                              val: T) {
    let (timer_done_po, timer_done_ch) = stream::<()>();
    let timer_done_ch = SharedChan::new(timer_done_ch);
    let timer = uv::ll::timer_t();
    let timer_ptr: *uv::ll::uv_timer_t = &timer;
    do iotask::interact(iotask) |loop_ptr| {
        unsafe {
            let init_result = uv::ll::timer_init(loop_ptr, timer_ptr);
            if (init_result == 0i32) {
                let start_result = uv::ll::timer_start(
                    timer_ptr, delayed_send_cb, msecs, 0u);
                if (start_result == 0i32) {
                    // Note: putting the channel into a ~
                    // to cast to *c_void
                    let timer_done_ch_clone = ~timer_done_ch.clone();
                    let timer_done_ch_ptr = transmute::<
                        ~SharedChan<()>, *c_void>(
                        timer_done_ch_clone);
                    uv::ll::set_data_for_uv_handle(
                        timer_ptr,
                        timer_done_ch_ptr);
                } else {
                    let error_msg = uv::ll::get_last_err_info(
                        loop_ptr);
                    fail!("timer::delayed_send() start failed: %s", error_msg);
                }
            } else {
                let error_msg = uv::ll::get_last_err_info(loop_ptr);
                fail!("timer::delayed_send() init failed: %s", error_msg);
            }
        }
    };
    // delayed_send_cb has been processed by libuv
    timer_done_po.recv();
    // notify the caller immediately
    ch.send(val);
    // uv_close for this timer has been processed
    timer_done_po.recv();
}

/**
 * Blocks the current task for (at least) the specified time period.
 *
 * Is not guaranteed to sleep for exactly the specified time, but will sleep
 * for *at least* that period of time.
 *
 * # Arguments
 *
 * * `iotask` - a `uv::iotask` that the tcp request will run on
 * * msecs - an amount of time, in milliseconds, for the current task to block
 */
pub fn sleep(iotask: &IoTask, msecs: uint) {
    let (exit_po, exit_ch) = stream::<()>();
    delayed_send(iotask, msecs, &exit_ch, ());
    exit_po.recv();
}

/**
 * Receive on a port for (up to) a specified time, then return an `Option<T>`
 *
 * This call will block to receive on the provided port for up to the
 * specified timeout. Depending on whether the provided port receives in that
 * time period, `recv_timeout` will return an `Option<T>` representing the
 * result.
 *
 * # Arguments
 *
 * * `iotask' - `uv::iotask` that the tcp request will run on
 * * msecs - an mount of time, in milliseconds, to wait to receive
 * * wait_port - a `core::comm::port<T>` to receive on
 *
 * # Returns
 *
 * An `Option<T>` representing the outcome of the call. If the call `recv`'d
 * on the provided port in the allotted timeout period, then the result will
 * be a `Some(T)`. If not, then `None` will be returned.
 */
pub fn recv_timeout<T:Copy + Owned>(iotask: &IoTask,
                                   msecs: uint,
                                   wait_po: &Port<T>)
                                   -> Option<T> {
    let mut (timeout_po, timeout_ch) = stream::<()>();
    delayed_send(iotask, msecs, &timeout_ch, ());

    // XXX: Workaround due to ports and channels not being &mut. They should
    // be.
    unsafe {
        let wait_po = cast::transmute_mut(wait_po);

        // FIXME: This could be written clearer (#2618)
        either::either(
            |_| {
                None
            }, |_| {
                Some(wait_po.recv())
            }, &select2i(&mut timeout_po, wait_po)
        )
    }
}

// INTERNAL API
extern fn delayed_send_cb(handle: *uv::ll::uv_timer_t, status: libc::c_int) {
    unsafe {
        debug!(
            "delayed_send_cb handle %? status %?", handle, status);
        // Faking a borrowed pointer to our ~SharedChan
        let timer_done_ch_ptr: &*c_void = &uv::ll::get_data_for_uv_handle(
            handle);
        let timer_done_ch_ptr = transmute::<&*c_void, &~SharedChan<()>>(
            timer_done_ch_ptr);
        let stop_result = uv::ll::timer_stop(handle);
        if (stop_result == 0i32) {
            timer_done_ch_ptr.send(());
            uv::ll::close(handle, delayed_send_close_cb);
        } else {
            let loop_ptr = uv::ll::get_loop_for_uv_handle(handle);
            let error_msg = uv::ll::get_last_err_info(loop_ptr);
            fail!("timer::sleep() init failed: %s", error_msg);
        }
    }
}

extern fn delayed_send_close_cb(handle: *uv::ll::uv_timer_t) {
    unsafe {
        debug!("delayed_send_close_cb handle %?", handle);
        let timer_done_ch_ptr = uv::ll::get_data_for_uv_handle(handle);
        let timer_done_ch = transmute::<*c_void, ~SharedChan<()>>(
            timer_done_ch_ptr);
        timer_done_ch.send(());
    }
}

#[cfg(test)]
mod test {
    use core::prelude::*;

    use timer::*;
    use uv;

    use core::cell::Cell;
    use core::pipes::{stream, SharedChan};
    use core::rand::RngUtil;
    use core::rand;
    use core::task;

    #[test]
    fn test_gl_timer_simple_sleep_test() {
        let hl_loop = &uv::global_loop::get();
        sleep(hl_loop, 1u);
    }

    #[test]
    fn test_gl_timer_sleep_stress1() {
        let hl_loop = &uv::global_loop::get();
        for 50u.times {
            sleep(hl_loop, 1u);
        }
    }

    #[test]
    fn test_gl_timer_sleep_stress2() {
        let (po, ch) = stream();
        let ch = SharedChan::new(ch);
        let hl_loop = &uv::global_loop::get();

        let repeat = 20u;
        let spec = {

            ~[(1u,  20u),
             (10u, 10u),
             (20u, 2u)]

        };

        for repeat.times {
            let ch = ch.clone();
            for spec.each |spec| {
                let (times, maxms) = *spec;
                let ch = ch.clone();
                let hl_loop_clone = hl_loop.clone();
                do task::spawn {
                    use core::rand::*;
                    let mut rng = rng();
                    for times.times {
                        sleep(&hl_loop_clone, rng.next() as uint % maxms);
                    }
                    ch.send(());
                }
            }
        }

        for (repeat * spec.len()).times {
            po.recv()
        }
    }

    // Because valgrind serializes multithreaded programs it can
    // make timing-sensitive tests fail in wierd ways. In these
    // next test we run them many times and expect them to pass
    // the majority of tries.

    #[test]
    #[cfg(ignore)]
    fn test_gl_timer_recv_timeout_before_time_passes() {
        let times = 100;
        let mut successes = 0;
        let mut failures = 0;
        let hl_loop = uv::global_loop::get();

        for (times as uint).times {
            task::yield();

            let expected = rand::rng().gen_str(16u);
            let (test_po, test_ch) = stream::<~str>();

            do task::spawn() {
                delayed_send(hl_loop, 1u, &test_ch, expected);
            };

            match recv_timeout(hl_loop, 10u, &test_po) {
              Some(val) => {
                assert_eq!(val, expected);
                successes += 1;
              }
              _ => failures += 1
            };
        }

        assert!(successes > times / 2);
    }

    #[test]
    fn test_gl_timer_recv_timeout_after_time_passes() {
        let times = 100;
        let mut successes = 0;
        let mut failures = 0;
        let hl_loop = uv::global_loop::get();

        for (times as uint).times {
            let mut rng = rand::rng();
            let expected = Cell::new(rng.gen_str(16u));
            let (test_po, test_ch) = stream::<~str>();
            let hl_loop_clone = hl_loop.clone();
            do task::spawn() {
                delayed_send(&hl_loop_clone, 50u, &test_ch, expected.take());
            };

            match recv_timeout(&hl_loop, 1u, &test_po) {
              None => successes += 1,
              _ => failures += 1
            };
        }

        assert!(successes > times / 2);
    }
}
<commit_msg>Remove 'this could be clearer' FIXME. Looks fine. Close #2618.<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Utilities that leverage libuv's `uv_timer_*` API

use core::prelude::*;

use uv;
use uv::iotask;
use uv::iotask::IoTask;

use core::cast::transmute;
use core::cast;
use core::comm::{stream, Chan, SharedChan, Port, select2i};
use core::either;
use core::libc::c_void;
use core::libc;

/**
 * Wait for timeout period then send provided value over a channel
 *
 * This call returns immediately. Useful as the building block for a number
 * of higher-level timer functions.
 *
 * Is not guaranteed to wait for exactly the specified time, but will wait
 * for *at least* that period of time.
 *
 * # Arguments
 *
 * * `hl_loop` - a `uv::hl::high_level_loop` that the tcp request will run on
 * * msecs - a timeout period, in milliseconds, to wait
 * * ch - a channel of type T to send a `val` on
 * * val - a value of type T to send over the provided `ch`
 */
pub fn delayed_send<T:Owned>(iotask: &IoTask,
                              msecs: uint,
                              ch: &Chan<T>,
                              val: T) {
    let (timer_done_po, timer_done_ch) = stream::<()>();
    let timer_done_ch = SharedChan::new(timer_done_ch);
    let timer = uv::ll::timer_t();
    let timer_ptr: *uv::ll::uv_timer_t = &timer;
    do iotask::interact(iotask) |loop_ptr| {
        unsafe {
            let init_result = uv::ll::timer_init(loop_ptr, timer_ptr);
            if (init_result == 0i32) {
                let start_result = uv::ll::timer_start(
                    timer_ptr, delayed_send_cb, msecs, 0u);
                if (start_result == 0i32) {
                    // Note: putting the channel into a ~
                    // to cast to *c_void
                    let timer_done_ch_clone = ~timer_done_ch.clone();
                    let timer_done_ch_ptr = transmute::<
                        ~SharedChan<()>, *c_void>(
                        timer_done_ch_clone);
                    uv::ll::set_data_for_uv_handle(
                        timer_ptr,
                        timer_done_ch_ptr);
                } else {
                    let error_msg = uv::ll::get_last_err_info(
                        loop_ptr);
                    fail!("timer::delayed_send() start failed: %s", error_msg);
                }
            } else {
                let error_msg = uv::ll::get_last_err_info(loop_ptr);
                fail!("timer::delayed_send() init failed: %s", error_msg);
            }
        }
    };
    // delayed_send_cb has been processed by libuv
    timer_done_po.recv();
    // notify the caller immediately
    ch.send(val);
    // uv_close for this timer has been processed
    timer_done_po.recv();
}

/**
 * Blocks the current task for (at least) the specified time period.
 *
 * Is not guaranteed to sleep for exactly the specified time, but will sleep
 * for *at least* that period of time.
 *
 * # Arguments
 *
 * * `iotask` - a `uv::iotask` that the tcp request will run on
 * * msecs - an amount of time, in milliseconds, for the current task to block
 */
pub fn sleep(iotask: &IoTask, msecs: uint) {
    let (exit_po, exit_ch) = stream::<()>();
    delayed_send(iotask, msecs, &exit_ch, ());
    exit_po.recv();
}

/**
 * Receive on a port for (up to) a specified time, then return an `Option<T>`
 *
 * This call will block to receive on the provided port for up to the
 * specified timeout. Depending on whether the provided port receives in that
 * time period, `recv_timeout` will return an `Option<T>` representing the
 * result.
 *
 * # Arguments
 *
 * * `iotask' - `uv::iotask` that the tcp request will run on
 * * msecs - an mount of time, in milliseconds, to wait to receive
 * * wait_port - a `core::comm::port<T>` to receive on
 *
 * # Returns
 *
 * An `Option<T>` representing the outcome of the call. If the call `recv`'d
 * on the provided port in the allotted timeout period, then the result will
 * be a `Some(T)`. If not, then `None` will be returned.
 */
pub fn recv_timeout<T:Copy + Owned>(iotask: &IoTask,
                                   msecs: uint,
                                   wait_po: &Port<T>)
                                   -> Option<T> {
    let mut (timeout_po, timeout_ch) = stream::<()>();
    delayed_send(iotask, msecs, &timeout_ch, ());

    // XXX: Workaround due to ports and channels not being &mut. They should
    // be.
    unsafe {
        let wait_po = cast::transmute_mut(wait_po);

        either::either(
            |_| {
                None
            }, |_| {
                Some(wait_po.recv())
            }, &select2i(&mut timeout_po, wait_po)
        )
    }
}

// INTERNAL API
extern fn delayed_send_cb(handle: *uv::ll::uv_timer_t, status: libc::c_int) {
    unsafe {
        debug!(
            "delayed_send_cb handle %? status %?", handle, status);
        // Faking a borrowed pointer to our ~SharedChan
        let timer_done_ch_ptr: &*c_void = &uv::ll::get_data_for_uv_handle(
            handle);
        let timer_done_ch_ptr = transmute::<&*c_void, &~SharedChan<()>>(
            timer_done_ch_ptr);
        let stop_result = uv::ll::timer_stop(handle);
        if (stop_result == 0i32) {
            timer_done_ch_ptr.send(());
            uv::ll::close(handle, delayed_send_close_cb);
        } else {
            let loop_ptr = uv::ll::get_loop_for_uv_handle(handle);
            let error_msg = uv::ll::get_last_err_info(loop_ptr);
            fail!("timer::sleep() init failed: %s", error_msg);
        }
    }
}

extern fn delayed_send_close_cb(handle: *uv::ll::uv_timer_t) {
    unsafe {
        debug!("delayed_send_close_cb handle %?", handle);
        let timer_done_ch_ptr = uv::ll::get_data_for_uv_handle(handle);
        let timer_done_ch = transmute::<*c_void, ~SharedChan<()>>(
            timer_done_ch_ptr);
        timer_done_ch.send(());
    }
}

#[cfg(test)]
mod test {
    use core::prelude::*;

    use timer::*;
    use uv;

    use core::cell::Cell;
    use core::pipes::{stream, SharedChan};
    use core::rand::RngUtil;
    use core::rand;
    use core::task;

    #[test]
    fn test_gl_timer_simple_sleep_test() {
        let hl_loop = &uv::global_loop::get();
        sleep(hl_loop, 1u);
    }

    #[test]
    fn test_gl_timer_sleep_stress1() {
        let hl_loop = &uv::global_loop::get();
        for 50u.times {
            sleep(hl_loop, 1u);
        }
    }

    #[test]
    fn test_gl_timer_sleep_stress2() {
        let (po, ch) = stream();
        let ch = SharedChan::new(ch);
        let hl_loop = &uv::global_loop::get();

        let repeat = 20u;
        let spec = {

            ~[(1u,  20u),
             (10u, 10u),
             (20u, 2u)]

        };

        for repeat.times {
            let ch = ch.clone();
            for spec.each |spec| {
                let (times, maxms) = *spec;
                let ch = ch.clone();
                let hl_loop_clone = hl_loop.clone();
                do task::spawn {
                    use core::rand::*;
                    let mut rng = rng();
                    for times.times {
                        sleep(&hl_loop_clone, rng.next() as uint % maxms);
                    }
                    ch.send(());
                }
            }
        }

        for (repeat * spec.len()).times {
            po.recv()
        }
    }

    // Because valgrind serializes multithreaded programs it can
    // make timing-sensitive tests fail in wierd ways. In these
    // next test we run them many times and expect them to pass
    // the majority of tries.

    #[test]
    #[cfg(ignore)]
    fn test_gl_timer_recv_timeout_before_time_passes() {
        let times = 100;
        let mut successes = 0;
        let mut failures = 0;
        let hl_loop = uv::global_loop::get();

        for (times as uint).times {
            task::yield();

            let expected = rand::rng().gen_str(16u);
            let (test_po, test_ch) = stream::<~str>();

            do task::spawn() {
                delayed_send(hl_loop, 1u, &test_ch, expected);
            };

            match recv_timeout(hl_loop, 10u, &test_po) {
              Some(val) => {
                assert_eq!(val, expected);
                successes += 1;
              }
              _ => failures += 1
            };
        }

        assert!(successes > times / 2);
    }

    #[test]
    fn test_gl_timer_recv_timeout_after_time_passes() {
        let times = 100;
        let mut successes = 0;
        let mut failures = 0;
        let hl_loop = uv::global_loop::get();

        for (times as uint).times {
            let mut rng = rand::rng();
            let expected = Cell::new(rng.gen_str(16u));
            let (test_po, test_ch) = stream::<~str>();
            let hl_loop_clone = hl_loop.clone();
            do task::spawn() {
                delayed_send(&hl_loop_clone, 50u, &test_ch, expected.take());
            };

            match recv_timeout(&hl_loop, 1u, &test_po) {
              None => successes += 1,
              _ => failures += 1
            };
        }

        assert!(successes > times / 2);
    }
}
<|endoftext|>


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

/*!

The standard module imported by default into all Rust modules

Many programming languages have a 'prelude': a particular subset of the
libraries that come with the language. Every program imports the prelude by
default. The prelude imports various core parts of the library that are
generally useful to many Rust programs.

*/

// Reexported core operators
pub use kinds::{Freeze, Pod, Send, Sized};
pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
pub use ops::{BitAnd, BitOr, BitXor};
pub use ops::{Drop};
pub use ops::{Shl, Shr, Index};
pub use option::{Option, Some, None};
pub use result::{Result, Ok, Err};

// Reexported functions
pub use from_str::from_str;
pub use iter::range;
pub use mem::drop;

// Reexported types and traits

pub use any::{Any, AnyOwnExt, AnyRefExt, AnyMutRefExt};
pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr, IntoBytes};
pub use bool::Bool;
pub use c_str::ToCStr;
pub use char::Char;
pub use clone::{Clone, DeepClone};
pub use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater, Equiv};
pub use container::{Container, Mutable, Map, MutableMap, Set, MutableSet};
pub use default::Default;
pub use from_str::FromStr;
pub use hash::Hash;
pub use iter::{FromIterator, Extendable};
pub use iter::{Iterator, DoubleEndedIterator, RandomAccessIterator, CloneableIterator};
pub use iter::{OrdIterator, MutableDoubleEndedIterator, ExactSize};
pub use num::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul};
pub use num::{Signed, Unsigned, Round};
pub use num::{Primitive, Int, Float, ToStrRadix, ToPrimitive, FromPrimitive};
pub use path::{GenericPath, Path, PosixPath, WindowsPath};
pub use ptr::RawPtr;
pub use io::{Buffer, Writer, Reader, Seek};
pub use str::{Str, StrVector, StrSlice, OwnedStr, IntoMaybeOwned};
pub use to_bytes::IterBytes;
pub use to_str::{ToStr, IntoStr};
pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4};
pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12};
pub use vec::{ImmutableEqVector, ImmutableTotalOrdVector, ImmutableCloneableVector};
pub use vec::{OwnedVector, OwnedCloneableVector,OwnedEqVector};
pub use vec::{MutableVector, MutableTotalOrdVector};
pub use vec::{Vector, VectorVector, CloneableVector, ImmutableVector};

// Reexported runtime types
pub use comm::{Port, Chan};
pub use task::spawn;

// Reexported statics
#[cfg(not(test))]
pub use gc::GC;
<commit_msg>std: minor whitespace cleanup<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

The standard module imported by default into all Rust modules

Many programming languages have a 'prelude': a particular subset of the
libraries that come with the language. Every program imports the prelude by
default. The prelude imports various core parts of the library that are
generally useful to many Rust programs.

*/

// Reexported core operators
pub use kinds::{Freeze, Pod, Send, Sized};
pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
pub use ops::{BitAnd, BitOr, BitXor};
pub use ops::{Drop};
pub use ops::{Shl, Shr, Index};
pub use option::{Option, Some, None};
pub use result::{Result, Ok, Err};

// Reexported functions
pub use from_str::from_str;
pub use iter::range;
pub use mem::drop;

// Reexported types and traits

pub use any::{Any, AnyOwnExt, AnyRefExt, AnyMutRefExt};
pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr, IntoBytes};
pub use bool::Bool;
pub use c_str::ToCStr;
pub use char::Char;
pub use clone::{Clone, DeepClone};
pub use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater, Equiv};
pub use container::{Container, Mutable, Map, MutableMap, Set, MutableSet};
pub use default::Default;
pub use from_str::FromStr;
pub use hash::Hash;
pub use iter::{FromIterator, Extendable};
pub use iter::{Iterator, DoubleEndedIterator, RandomAccessIterator, CloneableIterator};
pub use iter::{OrdIterator, MutableDoubleEndedIterator, ExactSize};
pub use num::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul};
pub use num::{Signed, Unsigned, Round};
pub use num::{Primitive, Int, Float, ToStrRadix, ToPrimitive, FromPrimitive};
pub use path::{GenericPath, Path, PosixPath, WindowsPath};
pub use ptr::RawPtr;
pub use io::{Buffer, Writer, Reader, Seek};
pub use str::{Str, StrVector, StrSlice, OwnedStr, IntoMaybeOwned};
pub use to_bytes::IterBytes;
pub use to_str::{ToStr, IntoStr};
pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4};
pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12};
pub use vec::{ImmutableEqVector, ImmutableTotalOrdVector, ImmutableCloneableVector};
pub use vec::{OwnedVector, OwnedCloneableVector, OwnedEqVector};
pub use vec::{MutableVector, MutableTotalOrdVector};
pub use vec::{Vector, VectorVector, CloneableVector, ImmutableVector};

// Reexported runtime types
pub use comm::{Port, Chan};
pub use task::spawn;

// Reexported statics
#[cfg(not(test))]
pub use gc::GC;
<|endoftext|>


<commit_before>use std::path::PathBuf;

use chrono::prelude::*;
use chrono::Duration;
use chrono_english::*;
use clap::Clap;

use pueue_lib::network::message::Signal;

#[derive(Clap, Debug)]
pub enum SubCommand {
    /// Enqueue a task for execution.
    Add {
        /// The command to be added.
        #[clap(required = true)]
        command: Vec<String>,

        /// Escape any special shell characters (" ", "&", "!", etc.).
        /// Beware: This implicitly disables nearly all shell specific syntax ("&&", "&>").
        #[clap(short, long)]
        escape: bool,

        /// Immediately start the task.
        #[clap(name = "immediate", short, long, conflicts_with = "stashed")]
        start_immediately: bool,

        /// Create the task in Stashed state.
        /// Useful to avoid immediate execution if the queue is empty.
        #[clap(name = "stashed", short, long, conflicts_with = "immediate")]
        stashed: bool,

        /// Prevents the task from being enqueued until <delay> elapses. See "enqueue" for accepted formats.
        #[clap(name = "delay", short, long, conflicts_with = "immediate", parse(try_from_str=parse_delay_until))]
        delay_until: Option<DateTime<Local>>,

        /// Assign the task to a group. Groups kind of act as separate queues.
        /// I.e. all groups run in parallel and you can specify the amount of parallel tasks for each group.
        /// If no group is specified, the default group will be used.
        #[clap(name = "group", short, long)]
        group: Option<String>,

        /// Start the task once all specified tasks have successfully finished.
        /// As soon as one of the dependencies fails, this task will fail as well.
        #[clap(name = "after", short, long)]
        dependencies: Vec<usize>,

        /// Add some information for yourself.
        /// This string will be shown in the "status" table.
        /// There's no additional logic connected to it.
        #[clap(short, long)]
        label: Option<String>,

        /// Only return the task id instead of a text.
        /// This is useful when scripting and working with dependencies.
        #[clap(short, long)]
        print_task_id: bool,
    },
    /// Remove tasks from the list.
    /// Running or paused tasks need to be killed first.
    Remove {
        /// The task ids to be removed.
        #[clap(required = true)]
        task_ids: Vec<usize>,
    },
    /// Switches the queue position of two commands.
    /// Only works on queued and stashed commands.
    Switch {
        /// The first task id.
        task_id_1: usize,
        /// The second task id.
        task_id_2: usize,
    },
    /// Stashed tasks won't be automatically started.
    /// You have to enqueue them or start them by hand.
    Stash {
        /// Stash these specific tasks.
        #[clap(required = true)]
        task_ids: Vec<usize>,
    },
    /// Enqueue stashed tasks. They'll be handled normally afterwards.
    #[clap(after_help = "DELAY FORMAT:

    The --delay argument must be either a number of seconds or a \"date expression\" similar to GNU \
    \"date -d\" with some extensions. It does not attempt to parse all natural language, but is \
    incredibly flexible. Here are some supported examples.

    2020-04-01T18:30:00   // RFC 3339 timestamp
    2020-4-1 18:2:30      // Optional leading zeros
    2020-4-1 5:30pm       // Informal am/pm time
    2020-4-1 5pm          // Optional minutes and seconds
    April 1 2020 18:30:00 // English months
    1 Apr 8:30pm          // Implies current year
    4/1                   // American form date
    wednesday 10:30pm     // The closest wednesday in the future at 22:30
    wednesday             // The closest wednesday in the future
    4 months              // 4 months from today at 00:00:00
    1 week                // 1 week at the current time
    1days                 // 1 day from today at the current time
    1d 03:00              // The closest 3:00 after 1 day (24 hours)
    3h                    // 3 hours from now
    3600s                 // 3600 seconds from now
")]
    Enqueue {
        /// Enqueue these specific tasks.
        task_ids: Vec<usize>,

        /// Delay enqueuing these tasks until <delay> elapses. See DELAY FORMAT below.
        #[clap(name = "delay", short, long, parse(try_from_str=parse_delay_until))]
        delay_until: Option<DateTime<Local>>,
    },

    /// Resume operation of specific tasks or groups of tasks.
    /// By default, this resumes the default group and all its tasks.
    /// Can also be used force-start specific tasks.
    #[clap(verbatim_doc_comment)]
    Start {
        /// Start these specific tasks. Paused tasks will resumed.
        /// Queued or Stashed tasks will be force-started.
        task_ids: Vec<usize>,

        /// Resume a specific group and all paused tasks in it.
        /// The group will be set to running and its paused tasks will be resumed.
        #[clap(short, long, conflicts_with = "all")]
        group: Option<String>,

        /// Resume all groups!
        /// All groups will be set to running and paused tasks will be resumed.
        #[clap(short, long)]
        all: bool,

        /// Also resume direct child processes of your paused tasks.
        /// By default only the main process will get a SIGSTART.
        #[clap(short, long)]
        children: bool,
    },

    /// Restart task(s).
    /// Identical tasks will be created and by default enqueued.
    /// By default, a new task will be created.
    Restart {
        /// Restart these specific tasks.
        task_ids: Vec<usize>,

        /// Restart all failed tasks accross all groups.
        /// Nice to use in combination with `-i/--in-place`.
        #[clap(short, long)]
        all_failed: bool,

        /// Like `--all-failed`, but only restart tasks failed tasks of a specific group.
        /// The group will be set to running and its paused tasks will be resumed.
        #[clap(short = 'g', long, conflicts_with = "all_failed")]
        failed_in_group: Option<String>,

        /// Immediately start the tasks, no matter how many open slots there are.
        /// This will ignore any dependencies tasks may have.
        #[clap(short = 'k', long, conflicts_with = "stashed")]
        start_immediately: bool,

        /// Set the restarted task to a "Stashed" state.
        /// Useful to avoid immediate execution.
        #[clap(short, long)]
        stashed: bool,

        /// Restart the task by reusing the already existing tasks.
        /// This will overwrite any previous logs of the restarted tasks.
        #[clap(short, long)]
        in_place: bool,

        /// Edit the tasks' command before restarting.
        #[clap(short, long)]
        edit: bool,

        /// Edit the tasks' path before restarting.
        #[clap(short = 'p', long)]
        edit_path: bool,
    },

    /// Either pause running tasks or specific groups of tasks.
    /// By default, pauses the default group and all its tasks.
    /// A paused queue (group) won't start any new tasks.
    #[clap(verbatim_doc_comment)]
    Pause {
        /// Pause these specific tasks.
        /// Does not affect the default group, groups or any other tasks.
        task_ids: Vec<usize>,

        /// Pause a specific group.
        #[clap(short, long, conflicts_with = "all")]
        group: Option<String>,

        /// Pause all groups!
        #[clap(short, long)]
        all: bool,

        /// Only pause the specified group and let already running tasks finish by themselves.
        #[clap(short, long)]
        wait: bool,

        /// Also pause direct child processes of a task's main process.
        /// By default only the main process will get a SIGSTOP.
        /// This is useful when calling bash scripts, which start other processes themselves.
        /// This operation is not recursive!
        #[clap(short, long)]
        children: bool,
    },

    /// Kill specific running tasks or whole task groups.
    /// Kills all tasks of the default group when no ids are provided.
    Kill {
        /// Kill these specific tasks.
        task_ids: Vec<usize>,

        /// Kill all running tasks in a group. This also pauses the group.
        #[clap(short, long, conflicts_with = "all")]
        group: Option<String>,

        /// Kill all running tasks across ALL groups. This also pauses all groups.
        #[clap(short, long)]
        all: bool,

        /// Send the SIGTERM signal to all children as well.
        /// Useful when working with shell scripts.
        #[clap(short, long)]
        children: bool,

        /// Send a UNIX signal instead of simply killing the process.
        /// DISCLAIMER: This bypasses Pueue's process handling logic!
        ///     You might enter weird invalid states, use at your own descretion.
        #[clap(short, long, case_insensitive(true))]
        signal: Option<Signal>,
    },

    /// Send something to a task. Useful for sending confirmations such as 'y\n'.
    Send {
        /// The id of the task.
        task_id: usize,

        /// The input that should be sent to the process.
        input: String,
    },

    /// Edit the command or path of a stashed or queued task.
    /// The command is edited by default.
    #[clap(verbatim_doc_comment)]
    Edit {
        /// The id of the task.
        task_id: usize,

        /// Edit the path of the task.
        #[clap(short, long)]
        path: bool,
    },

    /// Use this to add or remove groups.
    /// By default, this will simply display all known groups.
    Group {
        /// Add a group by name.
        #[clap(short, long, conflicts_with = "remove")]
        add: Option<String>,

        /// Remove a group by name.
        /// This will move all tasks in this group to the default group!
        #[clap(short, long)]
        remove: Option<String>,
    },

    /// Display the current status of all tasks.
    Status {
        /// Print the current state as json to stdout.
        /// This does not include stdout/stderr of tasks.
        /// Use `log -j` if you want everything.
        #[clap(short, long)]
        json: bool,

        #[clap(short, long)]
        /// Only show tasks of a specific group
        group: Option<String>,
    },

    /// Display the log output of finished tasks.
    /// Prints either all logs or only the logs of specified tasks.
    ///
    /// When looking at multiple logs, only the last few lines will be shown
    Log {
        /// View the task output of these specific tasks.
        task_ids: Vec<usize>,
        /// Print the resulting tasks and output as json.
        /// By default only the last stdout/-err lines will be returned unless --full is provided.
        /// Take care, as the json cannot be streamed!
        /// If your logs are really huge, using --full can use all of your machine's RAM.
        #[clap(short, long)]
        json: bool,

        /// Only print the last X lines of each task's output.
        /// This is done by default if you're looking at multiple tasks.
        #[clap(short, long, conflicts_with = "full")]
        lines: Option<usize>,

        /// Show the whole stdout and stderr output.
        /// This is the default if only a single task is being looked at.
        #[clap(short, long)]
        full: bool,
    },

    /// Follow the output of a currently running task.
    /// This command works like tail -f.
    Follow {
        /// The id of the task you want to watch.
        /// If no or multiple tasks are running, you have to specify the id.
        /// If only a single task is running, you can omit the id.
        task_id: Option<usize>,

        /// Show stderr instead of stdout.
        #[clap(short, long)]
        err: bool,
    },

    /// Wait until tasks are finished. This can be quite useful for scripting.
    /// By default, this will wait for all tasks in the default group to finish.
    /// Note: This will also wait for all tasks that aren't somehow 'Done'.
    /// Includes: [Paused, Stashed, Locked, Queued, ...]
    Wait {
        /// This allows you to wait for specific tasks to finish.
        task_ids: Vec<usize>,

        /// Wait for all tasks in a specific group
        #[clap(short, long, conflicts_with = "all")]
        group: Option<String>,

        /// Wait for all tasks across all groups and the default group.
        #[clap(short, long)]
        all: bool,

        /// Don't show any log output while waiting
        #[clap(short, long)]
        quiet: bool,
    },

    /// Remove all finished tasks from the list.
    Clean {
        /// Only clean tasks that finished successfully.
        #[clap(short, long)]
        successful_only: bool,
    },

    /// Kill all tasks, clean up afterwards and reset EVERYTHING!
    Reset {
        /// Send the SIGTERM signal to all children as well.
        /// Useful when working with shell scripts.
        #[clap(short, long)]
        children: bool,

        /// Don't ask for any confirmation.
        #[clap(short, long)]
        force: bool,
    },

    /// Remotely shut down the daemon. Should only be used if the daemon isn't started by a service manager.
    Shutdown,

    /// Set the amount of allowed parallel tasks.
    /// By default, adjusts the amount of the default group.
    Parallel {
        /// The amount of allowed parallel tasks.
        #[clap(validator=min_one)]
        parallel_tasks: usize,

        /// Set the amount for a specific group.
        #[clap(name = "group", short, long)]
        group: Option<String>,
    },

    /// Generates shell completion files.
    /// This can be ignored during normal operations.
    Completions {
        /// The target shell.
        #[clap(arg_enum)]
        shell: Shell,
        /// The output directory to which the file should be written.
        output_directory: PathBuf,
    },
}

#[derive(Clap, Debug, PartialEq)]
pub enum Shell {
    Bash,
    Elvish,
    Fish,
    PowerShell,
    Zsh,
}

#[derive(Clap, Debug)]
#[clap(
    name = "Pueue client",
    about = "Interact with the Pueue daemon",
    author = env!("CARGO_PKG_AUTHORS"),
    version = env!("CARGO_PKG_VERSION")
)]
pub struct CliArguments {
    /// Verbose mode (-v, -vv, -vvv)
    #[clap(short, long, parse(from_occurrences))]
    pub verbose: u8,

    /// Path to a specific pueue config file to use.
    /// This ignores all other config files.
    #[clap(short, long)]
    pub config: Option<PathBuf>,

    #[clap(subcommand)]
    pub cmd: SubCommand,
}

fn parse_delay_until(src: &str) -> Result<DateTime<Local>, String> {
    if let Ok(seconds) = src.parse::<i64>() {
        let delay_until = Local::now() + Duration::seconds(seconds);
        return Ok(delay_until);
    }

    if let Ok(date_time) = parse_date_string(src, Local::now(), Dialect::Us) {
        return Ok(date_time);
    }

    Err(String::from(
        "could not parse as seconds or date expression",
    ))
}

/// Validator function. The input string has to be parsable as int and bigger than 0
fn min_one(value: &str) -> Result<(), String> {
    match value.parse::<usize>() {
        Ok(value) => {
            if value < 1 {
                return Err("You must provide a value that's bigger than 0".into());
            }
            Ok(())
        }
        Err(_) => Err("Failed to parse integer".into()),
    }
}
<commit_msg>bug: Fix cli parameter conflict name<commit_after>use std::path::PathBuf;

use chrono::prelude::*;
use chrono::Duration;
use chrono_english::*;
use clap::Clap;

use pueue_lib::network::message::Signal;

#[derive(Clap, Debug)]
pub enum SubCommand {
    /// Enqueue a task for execution.
    Add {
        /// The command to be added.
        #[clap(required = true)]
        command: Vec<String>,

        /// Escape any special shell characters (" ", "&", "!", etc.).
        /// Beware: This implicitly disables nearly all shell specific syntax ("&&", "&>").
        #[clap(short, long)]
        escape: bool,

        /// Immediately start the task.
        #[clap(name = "immediate", short, long, conflicts_with = "stashed")]
        start_immediately: bool,

        /// Create the task in Stashed state.
        /// Useful to avoid immediate execution if the queue is empty.
        #[clap(name = "stashed", short, long, conflicts_with = "immediate")]
        stashed: bool,

        /// Prevents the task from being enqueued until <delay> elapses. See "enqueue" for accepted formats.
        #[clap(name = "delay", short, long, conflicts_with = "immediate", parse(try_from_str=parse_delay_until))]
        delay_until: Option<DateTime<Local>>,

        /// Assign the task to a group. Groups kind of act as separate queues.
        /// I.e. all groups run in parallel and you can specify the amount of parallel tasks for each group.
        /// If no group is specified, the default group will be used.
        #[clap(name = "group", short, long)]
        group: Option<String>,

        /// Start the task once all specified tasks have successfully finished.
        /// As soon as one of the dependencies fails, this task will fail as well.
        #[clap(name = "after", short, long)]
        dependencies: Vec<usize>,

        /// Add some information for yourself.
        /// This string will be shown in the "status" table.
        /// There's no additional logic connected to it.
        #[clap(short, long)]
        label: Option<String>,

        /// Only return the task id instead of a text.
        /// This is useful when scripting and working with dependencies.
        #[clap(short, long)]
        print_task_id: bool,
    },
    /// Remove tasks from the list.
    /// Running or paused tasks need to be killed first.
    Remove {
        /// The task ids to be removed.
        #[clap(required = true)]
        task_ids: Vec<usize>,
    },
    /// Switches the queue position of two commands.
    /// Only works on queued and stashed commands.
    Switch {
        /// The first task id.
        task_id_1: usize,
        /// The second task id.
        task_id_2: usize,
    },
    /// Stashed tasks won't be automatically started.
    /// You have to enqueue them or start them by hand.
    Stash {
        /// Stash these specific tasks.
        #[clap(required = true)]
        task_ids: Vec<usize>,
    },
    /// Enqueue stashed tasks. They'll be handled normally afterwards.
    #[clap(after_help = "DELAY FORMAT:

    The --delay argument must be either a number of seconds or a \"date expression\" similar to GNU \
    \"date -d\" with some extensions. It does not attempt to parse all natural language, but is \
    incredibly flexible. Here are some supported examples.

    2020-04-01T18:30:00   // RFC 3339 timestamp
    2020-4-1 18:2:30      // Optional leading zeros
    2020-4-1 5:30pm       // Informal am/pm time
    2020-4-1 5pm          // Optional minutes and seconds
    April 1 2020 18:30:00 // English months
    1 Apr 8:30pm          // Implies current year
    4/1                   // American form date
    wednesday 10:30pm     // The closest wednesday in the future at 22:30
    wednesday             // The closest wednesday in the future
    4 months              // 4 months from today at 00:00:00
    1 week                // 1 week at the current time
    1days                 // 1 day from today at the current time
    1d 03:00              // The closest 3:00 after 1 day (24 hours)
    3h                    // 3 hours from now
    3600s                 // 3600 seconds from now
")]
    Enqueue {
        /// Enqueue these specific tasks.
        task_ids: Vec<usize>,

        /// Delay enqueuing these tasks until <delay> elapses. See DELAY FORMAT below.
        #[clap(name = "delay", short, long, parse(try_from_str=parse_delay_until))]
        delay_until: Option<DateTime<Local>>,
    },

    /// Resume operation of specific tasks or groups of tasks.
    /// By default, this resumes the default group and all its tasks.
    /// Can also be used force-start specific tasks.
    #[clap(verbatim_doc_comment)]
    Start {
        /// Start these specific tasks. Paused tasks will resumed.
        /// Queued or Stashed tasks will be force-started.
        task_ids: Vec<usize>,

        /// Resume a specific group and all paused tasks in it.
        /// The group will be set to running and its paused tasks will be resumed.
        #[clap(short, long, conflicts_with = "all")]
        group: Option<String>,

        /// Resume all groups!
        /// All groups will be set to running and paused tasks will be resumed.
        #[clap(short, long)]
        all: bool,

        /// Also resume direct child processes of your paused tasks.
        /// By default only the main process will get a SIGSTART.
        #[clap(short, long)]
        children: bool,
    },

    /// Restart task(s).
    /// Identical tasks will be created and by default enqueued.
    /// By default, a new task will be created.
    Restart {
        /// Restart these specific tasks.
        task_ids: Vec<usize>,

        /// Restart all failed tasks accross all groups.
        /// Nice to use in combination with `-i/--in-place`.
        #[clap(short, long)]
        all_failed: bool,

        /// Like `--all-failed`, but only restart tasks failed tasks of a specific group.
        /// The group will be set to running and its paused tasks will be resumed.
        #[clap(short = 'g', long, conflicts_with = "all-failed")]
        failed_in_group: Option<String>,

        /// Immediately start the tasks, no matter how many open slots there are.
        /// This will ignore any dependencies tasks may have.
        #[clap(short = 'k', long, conflicts_with = "stashed")]
        start_immediately: bool,

        /// Set the restarted task to a "Stashed" state.
        /// Useful to avoid immediate execution.
        #[clap(short, long)]
        stashed: bool,

        /// Restart the task by reusing the already existing tasks.
        /// This will overwrite any previous logs of the restarted tasks.
        #[clap(short, long)]
        in_place: bool,

        /// Edit the tasks' command before restarting.
        #[clap(short, long)]
        edit: bool,

        /// Edit the tasks' path before restarting.
        #[clap(short = 'p', long)]
        edit_path: bool,
    },

    /// Either pause running tasks or specific groups of tasks.
    /// By default, pauses the default group and all its tasks.
    /// A paused queue (group) won't start any new tasks.
    #[clap(verbatim_doc_comment)]
    Pause {
        /// Pause these specific tasks.
        /// Does not affect the default group, groups or any other tasks.
        task_ids: Vec<usize>,

        /// Pause a specific group.
        #[clap(short, long, conflicts_with = "all")]
        group: Option<String>,

        /// Pause all groups!
        #[clap(short, long)]
        all: bool,

        /// Only pause the specified group and let already running tasks finish by themselves.
        #[clap(short, long)]
        wait: bool,

        /// Also pause direct child processes of a task's main process.
        /// By default only the main process will get a SIGSTOP.
        /// This is useful when calling bash scripts, which start other processes themselves.
        /// This operation is not recursive!
        #[clap(short, long)]
        children: bool,
    },

    /// Kill specific running tasks or whole task groups.
    /// Kills all tasks of the default group when no ids are provided.
    Kill {
        /// Kill these specific tasks.
        task_ids: Vec<usize>,

        /// Kill all running tasks in a group. This also pauses the group.
        #[clap(short, long, conflicts_with = "all")]
        group: Option<String>,

        /// Kill all running tasks across ALL groups. This also pauses all groups.
        #[clap(short, long)]
        all: bool,

        /// Send the SIGTERM signal to all children as well.
        /// Useful when working with shell scripts.
        #[clap(short, long)]
        children: bool,

        /// Send a UNIX signal instead of simply killing the process.
        /// DISCLAIMER: This bypasses Pueue's process handling logic!
        ///     You might enter weird invalid states, use at your own descretion.
        #[clap(short, long, case_insensitive(true))]
        signal: Option<Signal>,
    },

    /// Send something to a task. Useful for sending confirmations such as 'y\n'.
    Send {
        /// The id of the task.
        task_id: usize,

        /// The input that should be sent to the process.
        input: String,
    },

    /// Edit the command or path of a stashed or queued task.
    /// The command is edited by default.
    #[clap(verbatim_doc_comment)]
    Edit {
        /// The id of the task.
        task_id: usize,

        /// Edit the path of the task.
        #[clap(short, long)]
        path: bool,
    },

    /// Use this to add or remove groups.
    /// By default, this will simply display all known groups.
    Group {
        /// Add a group by name.
        #[clap(short, long, conflicts_with = "remove")]
        add: Option<String>,

        /// Remove a group by name.
        /// This will move all tasks in this group to the default group!
        #[clap(short, long)]
        remove: Option<String>,
    },

    /// Display the current status of all tasks.
    Status {
        /// Print the current state as json to stdout.
        /// This does not include stdout/stderr of tasks.
        /// Use `log -j` if you want everything.
        #[clap(short, long)]
        json: bool,

        #[clap(short, long)]
        /// Only show tasks of a specific group
        group: Option<String>,
    },

    /// Display the log output of finished tasks.
    /// Prints either all logs or only the logs of specified tasks.
    ///
    /// When looking at multiple logs, only the last few lines will be shown
    Log {
        /// View the task output of these specific tasks.
        task_ids: Vec<usize>,
        /// Print the resulting tasks and output as json.
        /// By default only the last stdout/-err lines will be returned unless --full is provided.
        /// Take care, as the json cannot be streamed!
        /// If your logs are really huge, using --full can use all of your machine's RAM.
        #[clap(short, long)]
        json: bool,

        /// Only print the last X lines of each task's output.
        /// This is done by default if you're looking at multiple tasks.
        #[clap(short, long, conflicts_with = "full")]
        lines: Option<usize>,

        /// Show the whole stdout and stderr output.
        /// This is the default if only a single task is being looked at.
        #[clap(short, long)]
        full: bool,
    },

    /// Follow the output of a currently running task.
    /// This command works like tail -f.
    Follow {
        /// The id of the task you want to watch.
        /// If no or multiple tasks are running, you have to specify the id.
        /// If only a single task is running, you can omit the id.
        task_id: Option<usize>,

        /// Show stderr instead of stdout.
        #[clap(short, long)]
        err: bool,
    },

    /// Wait until tasks are finished. This can be quite useful for scripting.
    /// By default, this will wait for all tasks in the default group to finish.
    /// Note: This will also wait for all tasks that aren't somehow 'Done'.
    /// Includes: [Paused, Stashed, Locked, Queued, ...]
    Wait {
        /// This allows you to wait for specific tasks to finish.
        task_ids: Vec<usize>,

        /// Wait for all tasks in a specific group
        #[clap(short, long, conflicts_with = "all")]
        group: Option<String>,

        /// Wait for all tasks across all groups and the default group.
        #[clap(short, long)]
        all: bool,

        /// Don't show any log output while waiting
        #[clap(short, long)]
        quiet: bool,
    },

    /// Remove all finished tasks from the list.
    Clean {
        /// Only clean tasks that finished successfully.
        #[clap(short, long)]
        successful_only: bool,
    },

    /// Kill all tasks, clean up afterwards and reset EVERYTHING!
    Reset {
        /// Send the SIGTERM signal to all children as well.
        /// Useful when working with shell scripts.
        #[clap(short, long)]
        children: bool,

        /// Don't ask for any confirmation.
        #[clap(short, long)]
        force: bool,
    },

    /// Remotely shut down the daemon. Should only be used if the daemon isn't started by a service manager.
    Shutdown,

    /// Set the amount of allowed parallel tasks.
    /// By default, adjusts the amount of the default group.
    Parallel {
        /// The amount of allowed parallel tasks.
        #[clap(validator=min_one)]
        parallel_tasks: usize,

        /// Set the amount for a specific group.
        #[clap(name = "group", short, long)]
        group: Option<String>,
    },

    /// Generates shell completion files.
    /// This can be ignored during normal operations.
    Completions {
        /// The target shell.
        #[clap(arg_enum)]
        shell: Shell,
        /// The output directory to which the file should be written.
        output_directory: PathBuf,
    },
}

#[derive(Clap, Debug, PartialEq)]
pub enum Shell {
    Bash,
    Elvish,
    Fish,
    PowerShell,
    Zsh,
}

#[derive(Clap, Debug)]
#[clap(
    name = "Pueue client",
    about = "Interact with the Pueue daemon",
    author = env!("CARGO_PKG_AUTHORS"),
    version = env!("CARGO_PKG_VERSION")
)]
pub struct CliArguments {
    /// Verbose mode (-v, -vv, -vvv)
    #[clap(short, long, parse(from_occurrences))]
    pub verbose: u8,

    /// Path to a specific pueue config file to use.
    /// This ignores all other config files.
    #[clap(short, long)]
    pub config: Option<PathBuf>,

    #[clap(subcommand)]
    pub cmd: SubCommand,
}

fn parse_delay_until(src: &str) -> Result<DateTime<Local>, String> {
    if let Ok(seconds) = src.parse::<i64>() {
        let delay_until = Local::now() + Duration::seconds(seconds);
        return Ok(delay_until);
    }

    if let Ok(date_time) = parse_date_string(src, Local::now(), Dialect::Us) {
        return Ok(date_time);
    }

    Err(String::from(
        "could not parse as seconds or date expression",
    ))
}

/// Validator function. The input string has to be parsable as int and bigger than 0
fn min_one(value: &str) -> Result<(), String> {
    match value.parse::<usize>() {
        Ok(value) => {
            if value < 1 {
                return Err("You must provide a value that's bigger than 0".into());
            }
            Ok(())
        }
        Err(_) => Err("Failed to parse integer".into()),
    }
}
<|endoftext|>


<commit_before>//! Nursery for slog-rs
//!
//! This crate is forever unstable, and contains things that
//! at a given moment are useful but not final.
#![warn(missing_docs)]

extern crate slog;

use slog::*;
use std::result;

/// `Drain` that switches destination of error
///
/// Logs everything to drain `D1`, but in case of it reporting an error,
/// switching to `D2`. If `D2` returns an error too, `Failover` will return
/// an error.
pub struct Failover<D1: Drain, D2: Drain>
{
    drain1: D1,
    drain2: D2,
}

impl<D1: Drain, D2: Drain, O, E2> Failover<D1, D2>
    where
    D1 : Drain<Ok = O>,
    D2 : Drain<Err = E2, Ok = O>,
{
    /// Create `Failover`
    pub fn new(drain1: D1, drain2: D2) -> Self {
        Failover {
            drain1: drain1,
            drain2: drain2,
        }
    }
}

impl<D1, D2, E2, O> Drain for Failover<D1, D2>
    where
    D1 : Drain<Ok = O>,
    D2 : Drain<Err = E2, Ok = O>,
{
    type Ok = O;
    type Err = D2::Err;
    fn log(&self,
           info: &Record,
           logger_values: &OwnedKVList)
           -> result::Result<Self::Ok, Self::Err> {
        match self.drain1.log(info, logger_values) {
            Ok(ok) => Ok(ok),
            Err(_) => self.drain2.log(info, logger_values),
        }
    }
}

/// Failover logging to secondary drain on primary's failure
///
/// Create `Failover` drain
pub fn failover<D1: Drain, D2: Drain, O, E2>(d1: D1, d2: D2) -> Failover<D1, D2>
    where
    D1 : Drain<Ok = O>,
    D2 : Drain<Err = E2, Ok = O>,
{
    Failover::new(d1, d2)
}
<commit_msg>Removed redundant type binding<commit_after>//! Nursery for slog-rs
//!
//! This crate is forever unstable, and contains things that
//! at a given moment are useful but not final.
#![warn(missing_docs)]

extern crate slog;

use slog::*;
use std::result;

/// `Drain` that switches destination of error
///
/// Logs everything to drain `D1`, but in case of it reporting an error,
/// switching to `D2`. If `D2` returns an error too, `Failover` will return
/// an error.
pub struct Failover<D1: Drain, D2: Drain>
{
    drain1: D1,
    drain2: D2,
}

impl<D1: Drain, D2: Drain, O> Failover<D1, D2>
    where
    D1 : Drain<Ok = O>,
    D2 : Drain<Ok = O>,
{
    /// Create `Failover`
    pub fn new(drain1: D1, drain2: D2) -> Self {
        Failover {
            drain1: drain1,
            drain2: drain2,
        }
    }
}

impl<D1, D2, E2, O> Drain for Failover<D1, D2>
    where
    D1 : Drain<Ok = O>,
    D2 : Drain<Ok = O>,
{
    type Ok = O;
    type Err = D2::Err;
    fn log(&self,
           info: &Record,
           logger_values: &OwnedKVList)
           -> result::Result<Self::Ok, Self::Err> {
        match self.drain1.log(info, logger_values) {
            Ok(ok) => Ok(ok),
            Err(_) => self.drain2.log(info, logger_values),
        }
    }
}

/// Failover logging to secondary drain on primary's failure
///
/// Create `Failover` drain
pub fn failover<D1: Drain, D2: Drain, O>(d1: D1, d2: D2) -> Failover<D1, D2>
    where
    D1 : Drain<Ok = O>,
    D2 : Drain<Ok = O>,
{
    Failover::new(d1, d2)
}
<|endoftext|>