holly 0.5.3

A simplistic actor model library using futures.
Documentation
use futures::{future, prelude::*};

/// Send some [`Sink::SinkItem`] to the sink.
///
/// The returned future will send the item and return the [`Sink`].
/// In contrast to [`Sink::send`] the sink will not be flushed.
pub fn send<S: Sink>(s: S, x: S::SinkItem) -> impl Future<Item = S, Error = S::SinkError> {
    SendFuture { sink: Some(s), item: Some(x) }
}

/// Flush a [`Sink`] and return the sink when done.
///
/// Equivalent to [`Sink::flush`] and only provided to complement [`send`] and [`close`].
pub fn flush<S: Sink>(s: S) -> impl Future<Item = S, Error = S::SinkError> {
    s.flush()
}

/// Close and drop a [`Sink`].
pub fn close<S: Sink>(mut s: S) -> impl Future<Item = (), Error = S::SinkError> {
    future::poll_fn(move || s.close())
}

/// Future which sends an item to a [`Sink`] without flushing the sink afterwards.
struct SendFuture<S: Sink> {
    sink: Option<S>,
    item: Option<S::SinkItem>
}

impl<S: Sink> Future for SendFuture<S> {
    type Item = S;
    type Error = S::SinkError;

    fn poll(&mut self) -> Poll<S, S::SinkError> {
        let item = self.item.take().expect("SendFuture has not completed => item exists");
        let mut sink = self.sink.take().expect("SendFuture has not completed => sink exists");

        match sink.start_send(item)? {
            AsyncSink::Ready => Ok(Async::Ready(sink)),
            AsyncSink::NotReady(item) => {
                self.item = Some(item);
                self.sink = Some(sink);
                Ok(Async::NotReady)
            }
        }
    }
}