use async_channel;
enum Multiplex<T> {
Msg(T),
Close,
}
pub fn unbound<T>() -> (Writer<T>, Reader<T>) {
let (writer, reader) = async_channel::unbounded();
let closer = Closer::new(writer.clone());
(Writer::new(writer.clone()), Reader::new(reader, closer))
}
pub fn closer() -> (Closer<()>, CloserReader) {
let (writer, reader) = unbound::<()>();
(
Closer {
raw: writer.raw.clone(),
},
CloserReader {
raw: reader.raw,
closer: reader.closer,
},
)
}
pub type CloserReader = Reader<()>;
pub struct Closer<T> {
raw: async_channel::Sender<Multiplex<T>>,
}
impl<T> Closer<T> {
fn new(raw: async_channel::Sender<Multiplex<T>>) -> Closer<T> {
Closer { raw }
}
pub async fn close(self) {
let _ = self.raw.send(Multiplex::Close).await;
}
}
impl<T> Clone for Closer<T> {
fn clone(&self) -> Closer<T> {
Self {
raw: self.raw.clone(),
}
}
}
pub struct Reader<T> {
raw: async_channel::Receiver<Multiplex<T>>,
closer: Closer<T>,
}
impl<T> Reader<T> {
fn new(raw: async_channel::Receiver<Multiplex<T>>, closer: Closer<T>) -> Reader<T> {
Reader { raw, closer }
}
pub async fn read(&self) -> Option<T> {
loop {
match self.raw.recv().await {
Ok(item) => match item {
Multiplex::Msg(item) => return Some(item),
Multiplex::Close => return None,
},
Err(_) => return None,
}
}
}
pub fn closer(&self) -> Closer<T> {
self.closer.clone()
}
}
pub struct Writer<T> {
raw: async_channel::Sender<Multiplex<T>>,
}
impl<T> Clone for Writer<T> {
fn clone(&self) -> Writer<T> {
Writer {
raw: self.raw.clone(),
}
}
}
impl<T> Writer<T> {
fn new(raw: async_channel::Sender<Multiplex<T>>) -> Writer<T> {
Writer { raw }
}
pub async fn write(&self, t: T) -> bool {
match self.raw.send(Multiplex::Msg(t)).await {
Ok(_) => true,
Err(_) => false,
}
}
pub async fn close(self) {
let closer = self.closer();
closer.close().await;
}
pub fn closer(&self) -> Closer<T> {
Closer {
raw: self.raw.clone(),
}
}
}