use either::Either::{self, *};
use std::{convert::Infallible, marker::PhantomData, ops::Deref};
use ufotofu::Producer;
use crate::TakeCell;
#[derive(Debug, Default)]
pub struct State<Item, Final> {
cell: TakeCell<Either<Item, Final>>,
}
impl<Item, Final> State<Item, Final> {
pub fn new() -> Self {
State {
cell: TakeCell::new(),
}
}
}
pub fn new_shelf<R, Item, Final>(state_ref: R) -> (Sender<R, Item, Final>, Receiver<R, Item, Final>)
where
R: Deref<Target = State<Item, Final>> + Clone,
{
(
Sender {
state: state_ref.clone(),
phantom: PhantomData,
},
Receiver {
state: state_ref,
phantom: PhantomData,
},
)
}
#[derive(Debug)]
pub struct Sender<R, Item, Final> {
state: R,
phantom: PhantomData<(Item, Final)>,
}
impl<R: Deref<Target = State<Item, Final>>, Item, Final> Sender<R, Item, Final> {
pub fn set(&self, item: Item) {
self.state.deref().cell.set(Left(item))
}
pub fn close(&mut self, fin: Final) {
self.state.deref().cell.set(Right(fin))
}
pub fn update(&self, with: impl FnOnce(Option<Either<Item, Final>>) -> Either<Item, Final>) {
self.state.deref().cell.update(with)
}
}
#[derive(Debug)]
pub struct Receiver<R, Item, Final> {
state: R,
phantom: PhantomData<(Item, Final)>,
}
impl<R: Deref<Target = State<Item, Final>>, Item, Final> Receiver<R, Item, Final> {
pub fn is_empty(&self) -> bool {
self.state.deref().cell.is_empty()
}
}
impl<R: Deref<Target = State<Item, Final>>, Item, Final> Producer for Receiver<R, Item, Final> {
type Item = Item;
type Final = Final;
type Error = Infallible;
async fn produce(&mut self) -> Result<Either<Self::Item, Self::Final>, Self::Error> {
Ok(self.state.deref().cell.take().await)
}
}