use crate::errors::ControllerResult;
#[allow(async_fn_in_trait)]
#[cfg_attr(feature = "async-trait", async_trait::async_trait)]
pub trait Controller<Tx, Rx = Tx>: AsyncSender<Tx> + AsyncReceiver<Rx>
where
Tx: Sized + Sync + Send,
Rx: Sized + Sync + Send,
{
}
pub trait AsyncSender<T: Sized + Send + Sync>: Sized + Send + Sync {
fn send(&self, x: T) -> ControllerResult<()>;
}
#[allow(async_fn_in_trait)]
#[cfg_attr(feature = "async-trait", async_trait::async_trait)]
pub trait AsyncReceiver<T: Sized + Send + Sync>: Sized + Send + Sync {
async fn recv(&self) -> ControllerResult<T> {
loop {
self.poll().await?;
if let Some(x) = self.try_recv().await? {
break Ok(x);
}
}
}
fn callback(&self, cb: impl Into<ControllerCallback<Self>>);
fn clear_callback(&self);
async fn poll(&self) -> ControllerResult<()>;
async fn try_recv(&self) -> ControllerResult<Option<T>>;
}
pub struct ControllerCallback<T>(pub Box<dyn Sync + Send + Fn(T)>);
impl<T> ControllerCallback<T> {
pub(crate) fn call(&self, x: T) {
self.0(x)
}
}
impl<T> std::fmt::Debug for ControllerCallback<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "ControllerCallback {{ {:p} }}", self.0)
}
}
impl<T, X: Sync + Send + Fn(T) + 'static> From<X> for ControllerCallback<T> {
fn from(value: X) -> Self {
Self(Box::new(value))
}
}