use futures::{prelude::*, sync::{oneshot, mpsc}};
use void::Void;
pub fn stoppable<I: Clone, S: Stream>(id: I, s: S)
-> (KillCord, impl Stream<Item = Event<I, S::Item, S::Error>, Error = Void>)
{
Stoppable::new(Infallible::new(id, s))
}
pub fn closable<I: Clone, S: Stream + Close>(id: I, s: S)
-> (KillCord, impl Stream<Item = Event<I, S::Item, S::Error>, Error = Void>)
{
let (k, s) = Closable::new(s);
(k, Infallible::new(id, s))
}
#[derive(Debug)]
pub struct KillCord(oneshot::Sender<()>);
#[derive(Debug)]
struct Stoppable<S> {
stream: S,
killcord: oneshot::Receiver<()>,
}
impl<S: Stream> Stoppable<S> {
fn new(s: S) -> (KillCord, Self) {
let (tx, rx) = oneshot::channel();
let stream = Stoppable { stream: s, killcord: rx };
(KillCord(tx), stream)
}
}
impl<S: Stream> Stream for Stoppable<S> {
type Item = S::Item;
type Error = S::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
if let Ok(Async::NotReady) = self.killcord.poll() {
self.stream.poll()
} else {
Ok(Async::Ready(None))
}
}
}
pub trait Close {
fn close(&mut self);
}
impl<T> Close for mpsc::Receiver<T> {
fn close(&mut self) {
<mpsc::Receiver<T>>::close(self)
}
}
impl<T> Close for mpsc::UnboundedReceiver<T> {
fn close(&mut self) {
<mpsc::UnboundedReceiver<T>>::close(self)
}
}
impl<I, S: Stream + Close> Close for Infallible<I, S> {
fn close(&mut self) {
self.stream.close()
}
}
#[derive(Debug)]
pub(crate) struct Closable<S> {
stream: S,
killcord: oneshot::Receiver<()>,
closed: bool
}
impl<S: Stream + Close> Closable<S> {
pub(crate) fn new(s: S) -> (KillCord, Self) {
let (tx, rx) = oneshot::channel();
let stream = Closable { stream: s, killcord: rx, closed: false };
(KillCord(tx), stream)
}
}
impl<S: Stream + Close> Stream for Closable<S> {
type Item = S::Item;
type Error = S::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
if !self.closed {
match self.killcord.poll() {
Ok(Async::NotReady) => {}
Ok(Async::Ready(())) | Err(oneshot::Canceled) => {
self.stream.close();
self.closed = true
}
}
}
self.stream.poll()
}
}
#[derive(Debug, Clone)]
pub enum Event<I, T, E> {
Item(I, T),
End(I),
Error(I, E)
}
#[derive(Debug)]
struct Infallible<I, S>{
id: I,
stream: S,
done: bool }
impl<I: Clone, S: Stream> Infallible<I, S> {
fn new(id: I, stream: S) -> Self {
Infallible { id, stream, done: false }
}
}
impl<I: Clone, S: Stream> Stream for Infallible<I, S> {
type Item = Event<I, S::Item, S::Error>;
type Error = Void;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
if self.done {
return Ok(Async::Ready(None))
}
match self.stream.poll() {
Err(e) => Ok(Async::Ready(Some(Event::Error(self.id.clone(), e)))),
Ok(Async::NotReady) => Ok(Async::NotReady),
Ok(Async::Ready(None)) => {
self.done = true;
Ok(Async::Ready(Some(Event::End(self.id.clone()))))
}
Ok(Async::Ready(Some(x))) => Ok(Async::Ready(Some(Event::Item(self.id.clone(), x))))
}
}
}