urchin 0.1.1

Multi-threaded userland task scheduling
Documentation
use std::rc::Rc;
use std::cell::RefCell;

/// State of a `Future` Result
#[derive(Debug)]
enum FutureState<T, E> {
    Promised,
    Ok(T),
    Err(E),
}

#[derive(Debug)]
pub struct FutureInner<T, E> {
    state: FutureState<T, E>,
}

impl<T, E> FutureInner<T, E> {
    fn promised() -> FutureInner<T, E> {
        FutureInner {
            state: FutureState::Promised,
        }
    }

    fn from_val(val: T) -> FutureInner<T, E> {
        FutureInner {
            state: FutureState::Ok(val),
        }
    }

    fn from_err(err: E) -> FutureInner<T, E> {
        FutureInner {
            state: FutureState::Err(err),
        }
    }

    fn unwrap(self) -> T {
        match self.state {
            FutureState::Ok(val) => val,
            _ => panic!("unwrap failed"),
        }
    }

    fn unwrap_err(self) -> E {
        match self.state {
            FutureState::Err(err) => err,
            _ => panic!("unwrap failed"),
        }
    }

    fn expect(self, _msg: &str) -> T {
        match self.state {
            FutureState::Ok(val) => val,
            _ => panic!("expect failed"),
        }
    }

    fn is_promised(&self) -> bool {
        match self.state {
            FutureState::Promised => true,
            _ => false,
        }
    }

    fn is_err(&self) -> bool {
        match self.state {
            FutureState::Err(_) => true,
            _ => false,
        }
    }

    fn is_ok(&self) -> bool {
        match self.state {
            FutureState::Ok(_) => true,
            _ => false,
        }
    }

    fn ok(self) -> Option<T> {
        match self.state {
            FutureState::Ok(val) => Some(val),
            _ => None,
        }
    }

    fn err(self) -> Option<E> {
        match self.state {
            FutureState::Err(err) => Some(err),
            _ => None,
        }
    }

    fn set_ok(&mut self, val: T) {
        assert!(self.is_promised());
        self.state = FutureState::Ok(val);
    }

    fn set_err(&mut self, err: E) {
        assert!(self.is_promised());
        self.state = FutureState::Err(err);
    }
}

/// `Future` result
pub struct Future<T, E> {
    inner: Rc<RefCell<FutureInner<T, E>>>,
}

/// `Future` provides something akin to a `Result<T, E>` where
/// the true value of the Result<T, E> may not yet me known.
impl<T, E> Future<T, E> {

    pub fn promised() -> (Future<T, E>, Promise<T, E>) {
        let inner = Rc::new(RefCell::new(FutureInner::promised()));
        let future = Future::new(inner.clone());
        let promise = Promise::new(inner);
        (future, promise)
    }

    pub fn from_val(val: T) -> Future<T, E> {
        let inner = Rc::new(RefCell::new(FutureInner::from_val(val)));
        Future::new(inner.clone())
    }

    pub fn from_err(err: E) -> Future<T, E> {
        Future::new(Rc::new(RefCell::new(FutureInner::from_err(err))))
    }

    fn new(inner: Rc<RefCell<FutureInner<T, E>>>) -> Future<T, E> {
        Future {
            inner: inner,
        }
    }

    /// Check if the Future is Promised
    pub fn is_promised(&self) -> bool {
        self.inner.borrow().is_promised()
    }


    /// Check if the Future is Ok
    pub fn is_ok(&self) -> bool {
        self.inner.borrow().is_ok()
    }

    /// Check if the Future is Err
    pub fn is_err(&self) -> bool {
        self.inner.borrow().is_err()
    }


    // Return the error if the state of the `Future` is Err otherwise None
    pub fn err(self) -> Option<E> {
        match Rc::try_unwrap(self.inner) {
            Ok(ref_cell) => ref_cell.into_inner().err(),
            _ => None
        }
    }

    // Return the value if the state of the `Future` is Ok otherwise None
    pub fn ok(self) -> Option<T> {
        match Rc::try_unwrap(self.inner) {
            Ok(ref_cell) => ref_cell.into_inner().ok(),
            _ => None
        }
    }


    // Unwrap the result error, panic if the result is anything but Err
    pub fn unwrap_err(self) -> E {
        match Rc::try_unwrap(self.inner) {
            Ok(ref_cell) => ref_cell.into_inner().unwrap_err(),
            _ => panic!("could not unwrap inner")
        }
    }

    // Unwrap the result, panic if the result is anything but Ok
    pub fn unwrap(self) -> T {
        match Rc::try_unwrap(self.inner) {
            Ok(ref_cell) => ref_cell.into_inner().unwrap(),
            _ => panic!("could not unwrap inner")
        }
    }
}


/// Promise provides a write only interface to a Future value which has been promised
/// The promise is used once resolved and may only be resolved once.
pub struct Promise<T, E> {
    inner: Rc<RefCell<FutureInner<T, E>>>,
}

/// `Promise` allows a single resolve call to be done which fulfills
/// a `Promise` for a `Future` result.
impl<T, E> Promise<T, E> {
    fn new(inner: Rc<RefCell<FutureInner<T, E>>>) -> Promise<T, E> {
        Promise {
            inner: inner,
        }
    }

    pub fn resolve(self, res: Result<T, E>) {
        match res {
            Ok(val) => self.inner.borrow_mut().set_ok(val),
            Err(err) => self.inner.borrow_mut().set_err(err),
        }
    }
}

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

    #[test]
    fn future_ok() {
        let f : Future<bool, ()> = Future::from_val(true);
        assert!(f.is_ok());
        assert!(!f.is_err());
        assert!(!f.is_promised());
        assert!(f.ok().unwrap());
    }

    #[test]
    fn future_unwrap() {
        let f : Future<bool, ()> = Future::from_val(true);
        assert!(f.unwrap());
    }

    #[test]
    fn future_err() {
        let f : Future<(), bool> = Future::from_err(true);
        assert!(f.is_err());
        assert!(!f.is_ok());
        assert!(!f.is_promised());
        assert!(f.err().unwrap());
    }

    #[test]
    fn future_unwrap_err() {
        let f : Future<(), bool> = Future::from_err(true);
        assert!(f.unwrap_err());
    }

    #[test]
    fn future_promise_ok() {
        let (f, p): (Future<bool, ()>, _) = Future::promised();
        assert!(f.is_promised());
        p.resolve(Ok(true));
        assert!(f.is_ok());
        assert!(f.unwrap());
    }

    #[test]
    fn future_promise_err() {
        let (f, p): (Future<(), bool>, _) = Future::promised();
        assert!(f.is_promised());
        p.resolve(Err(true));
        assert!(f.is_err());
        assert!(f.unwrap_err());
    }

    #[test]
    #[should_panic]
    fn future_ok_unwrap_err() {
        let f: Future<bool, ()> = Future::from_val(false);
        f.unwrap_err();
    }

    #[test]
    #[should_panic]
    fn future_promised_unwrap_err() {
        let (f, _): (Future<bool, ()>, _) = Future::promised();
        f.unwrap_err();
    }

    #[test]
    #[should_panic]
    fn future_err_unwrap() {
        let f: Future<(), bool>  = Future::from_err(false);
        f.unwrap();
    }

    #[test]
    #[should_panic]
    fn future_promised_unwrap() {
        let (f, _): (Future<bool, ()>, _) = Future::promised();
        f.unwrap();
    }
}