use std::pin::Pin;
use crate::{Publisher, Result, Subscriber, SubscriberImpl};
use futures::{FutureExt, Stream, future::BoxFuture, stream};
use super::Forwarder;
pub struct ForwarderImpl<Message>
where
Message: Send + 'static,
{
name: &'static str,
subscriber_name: Option<&'static str>,
subscriber: Option<SubscriberImpl<Message>>,
}
impl<Message> ForwarderImpl<Message>
where
Message: Send + 'static,
{
pub fn new(name: &'static str) -> Self {
Self {
name,
subscriber_name: None,
subscriber: Some(SubscriberImpl::new(name)),
}
}
}
impl<Message> Subscriber for ForwarderImpl<Message>
where
Message: Send + 'static,
{
type Message = Message;
fn get_name(&self) -> &'static str {
self.name
}
fn subscribe_to(&mut self, publisher: &mut dyn Publisher<Message = Message>) -> Result<()> {
let Some(subscriber) = self.subscriber.as_mut() else {
let subscriber_name = self
.subscriber_name
.expect("the subscriber name should be known at this point");
return Err(format!(
"{} forwarder has already been bound to {}, subscribe to {} before {} subscribes to it",
self.name,
subscriber_name,
self.name,
subscriber_name
)
.into());
};
subscriber.subscribe_to(publisher)
}
fn receive(&mut self) -> BoxFuture<Message> {
panic!("LoggingForwarder does not implement receive method")
}
}
impl<Message> Publisher for ForwarderImpl<Message>
where
Message: Send + 'static,
{
type Message = Message;
fn get_name(&self) -> &'static str {
self.name
}
fn publish(&self, _message: Message) -> futures::future::BoxFuture<Result<()>> {
async move { panic!("LoggingForwarder does not implement publish method") }.boxed()
}
fn get_message_stream(
&mut self,
subscriber_name: &'static str,
) -> Result<Pin<Box<dyn Stream<Item = Message> + Send + Sync + 'static>>> {
let Some(subscriber) = self.subscriber.take() else {
return Err(format!(
"{} forwarder can only be bound to one subscriber (already bound to {})",
self.name,
self.subscriber_name
.expect("the subscriber name should be known at this point")
)
.into());
};
self.subscriber_name = Some(subscriber_name);
let stream = Box::pin(stream::unfold(
subscriber,
move |mut subscriber| async move {
let message = subscriber.receive().await;
Some((message, subscriber))
},
));
Ok(stream)
}
}
impl<Message> Forwarder for ForwarderImpl<Message> where Message: Send + 'static {}