tube 0.0.2

This crate was renamed to 'tubez'. Please use that crate instead.
Documentation
use std::future;
use std::sync::Arc;
use std::sync::Mutex;

#[derive(Debug)]
pub struct InvertedFutureContext<T> {
    resolution: Option<T>,
    waker: Option<std::task::Waker>,
}

#[derive(Debug)]
pub struct InvertedFutureResolver<T> {
    ctx: Arc<Mutex<InvertedFutureContext<T>>>,
}
impl<T> InvertedFutureResolver<T> {
    pub fn resolve(&mut self, v: T) {
        let mut ctx = self.ctx.lock().unwrap();
        ctx.resolution = Some(v);
        if let Some(waker) = ctx.waker.take() {
            waker.wake();
        }
    }
}

#[derive(Clone,Debug)]
pub struct InvertedFuture<T> {
    ctx: Arc<Mutex<InvertedFutureContext<T>>>,
}
impl<T> InvertedFuture<T> {
    pub fn new() -> (Self, InvertedFutureResolver<T>) {
        let ctx = Arc::new(Mutex::new(InvertedFutureContext {
            resolution: None,
            waker: None,
        }));

        let resolver = InvertedFutureResolver { ctx: ctx.clone() };
        let future = InvertedFuture { ctx };

        (future, resolver)
    }
}
impl<T> future::Future for InvertedFuture<T> {
    type Output = T;

    fn poll(
        self: std::pin::Pin<&mut Self>, 
        cx: &mut std::task::Context<'_>,
    ) -> std::task::Poll<Self::Output> {
        let mut ctx = self.ctx.lock().unwrap();
        ctx.waker = Some(cx.waker().clone());

        if let Some(res) = ctx.resolution.take() {
            std::task::Poll::Ready(res)
        } else {
            std::task::Poll::Pending
        }
    }
}

#[cfg(test)]
mod inverted_future_tests {
    use futures::FutureExt;

    use super::InvertedFuture;

    #[tokio::test]
    async fn unresolved_on_construction() {
        let (future, _resolver) = InvertedFuture::<()>::new();
        assert_eq!(None, future.now_or_never());
    }

    #[tokio::test]
    async fn resolves_after_call_to_resolve() {
        let (future, mut resolver) = InvertedFuture::<u8>::new();
        resolver.resolve(42);
        assert_eq!(Some(42), future.now_or_never());
    }
}