use crate::notifier::TypedNotifier;
use anyhow::Result;
use std::fmt;
use std::sync::Arc;
pub trait Sender<M>: Send + Sync {
fn send(&self, input: M) -> Result<()>;
fn notifier(self, message: M) -> TypedNotifier<M>
where
Self: Sized + 'static,
{
TypedNotifier::new(self, message)
}
}
#[derive(Debug)]
pub struct EmptySender;
impl<M> Sender<M> for EmptySender {
fn send(&self, _msg: M) -> Result<()> {
Ok(())
}
}
pub struct FuncSender<F>(F);
impl<F, IN> Sender<IN> for FuncSender<F>
where
F: Fn(IN) -> Result<()>,
F: Send + Sync,
{
fn send(&self, input: IN) -> Result<()> {
(self.0)(input)
}
}
pub struct Recipient<M> {
recipient: Arc<dyn Sender<M>>,
}
impl<M> Clone for Recipient<M> {
fn clone(&self) -> Self {
Self {
recipient: self.recipient.clone(),
}
}
}
impl<M> Sender<M> for Recipient<M> {
fn send(&self, msg: M) -> Result<()> {
self.recipient.send(msg)
}
}
impl<M> fmt::Debug for Recipient<M> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Recipient")
}
}
impl<M> Recipient<M> {
pub fn new<E>(sender: E) -> Self
where
E: Sender<M> + 'static,
{
Self {
recipient: Arc::new(sender),
}
}
pub fn reform<F, IN>(&self, func: F) -> Recipient<IN>
where
F: Fn(IN) -> M,
F: Send + Sync + 'static,
M: 'static,
{
let recipient = self.recipient.clone();
let func_sender = FuncSender(move |input| {
let output = func(input);
recipient.send(output)
});
Recipient::new(func_sender)
}
}