use std::fmt;
use tokio::sync::mpsc;
use crate::{ExternalEffect, ExternalEffectAPI, Name, Resources, SendData, types::MpscSender};
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct OutputEffect<Msg> {
pub name: Name,
pub msg: Msg,
sender: MpscSender<Msg>,
}
impl<Msg> OutputEffect<Msg> {
pub fn new(name: Name, msg: Msg, sender: mpsc::Sender<Msg>) -> Self {
Self { name, msg, sender: MpscSender { sender } }
}
pub fn fake(name: Name, msg: Msg) -> (Self, mpsc::Receiver<Msg>) {
let (tx, rx) = mpsc::channel(1);
(Self { name, msg, sender: MpscSender { sender: tx } }, rx)
}
}
impl<Msg: SendData> fmt::Debug for OutputEffect<Msg> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("OutputEffect")
.field("name", &self.name)
.field("msg", &self.msg)
.field("type", &self.msg.typetag_name())
.finish()
}
}
impl<Msg: SendData + PartialEq> PartialEq for OutputEffect<Msg> {
fn eq(&self, other: &Self) -> bool {
self.name == other.name && self.msg == other.msg
}
}
impl<Msg> ExternalEffect for OutputEffect<Msg>
where
Msg: SendData + PartialEq + serde::Serialize + serde::de::DeserializeOwned,
{
fn run(self: Box<Self>, _resources: Resources) -> crate::BoxFuture<'static, Box<dyn SendData>> {
Box::pin(async move {
if let Err(e) = self.sender.send(self.msg).await {
tracing::debug!("output `{}` failed to send message: {:?}", self.name, e.0);
}
Box::new(()) as Box<dyn SendData>
})
}
}
impl<Msg> ExternalEffectAPI for OutputEffect<Msg>
where
Msg: SendData + PartialEq + serde::Serialize + serde::de::DeserializeOwned,
{
type Response = ();
}