use alloc::sync::Arc;
use alloc::vec::Vec;
use core::ops::DerefMut;
use cgp::prelude::*;
use futures_core::stream::Stream;
use futures_util::stream::StreamExt;
use hermes_runtime_components::traits::channel::{
CanCreateChannels, CanStreamReceiver, CanUseChannels, HasChannelTypes,
};
use hermes_runtime_components::traits::mutex::HasMutex;
use hermes_runtime_components::traits::spawn::CanSpawnTask;
use hermes_runtime_components::traits::task::Task;
use crate::stream::traits::boxed::HasBoxedStreamType;
use crate::subscription::impls::multiplex::MultiplexingSubscription;
use crate::subscription::traits::subscription::Subscription;
pub trait CanStreamSubscription {
fn stream_subscription<S, T>(&self, stream: S) -> Arc<dyn Subscription<Item = T>>
where
S: Stream<Item = T> + Async,
T: Async + Clone;
}
pub struct StreamSubscriptionTask<Runtime, S, T>
where
Runtime: HasMutex + HasChannelTypes,
T: Async,
S: Stream<Item = T> + Async,
{
pub stream: S,
pub task_senders: Arc<Runtime::Mutex<Option<Vec<Runtime::Sender<T>>>>>,
}
impl<Runtime, S, T> Task for StreamSubscriptionTask<Runtime, S, T>
where
Runtime: HasMutex + CanCreateChannels + CanUseChannels + CanStreamReceiver + HasBoxedStreamType,
T: Clone + Async,
S: Stream<Item = T> + Async,
{
async fn run(self) {
let task_senders = &self.task_senders;
self.stream
.for_each(|item| async move {
let mut m_senders = Runtime::acquire_mutex(task_senders).await;
if let Some(senders) = m_senders.deref_mut() {
let mut new_senders = Vec::new();
for sender in senders.drain(..) {
let send_result = Runtime::send(&sender, item.clone()).await;
if send_result.is_ok() {
new_senders.push(sender);
}
}
*senders = new_senders;
}
})
.await;
let mut senders = Runtime::acquire_mutex(&self.task_senders).await;
*senders = None;
}
}
impl<Runtime> CanStreamSubscription for Runtime
where
Runtime: CanSpawnTask
+ HasMutex
+ CanCreateChannels
+ CanUseChannels
+ CanStreamReceiver
+ HasBoxedStreamType,
{
fn stream_subscription<S, T>(&self, stream: S) -> Arc<dyn Subscription<Item = T>>
where
S: Stream<Item = T> + Async,
T: Async + Clone,
{
let stream_senders = Arc::new(Runtime::new_mutex(Some(Vec::new())));
let task: StreamSubscriptionTask<Runtime, S, T> = StreamSubscriptionTask {
stream,
task_senders: stream_senders.clone(),
};
self.spawn_task(task);
let subscription: MultiplexingSubscription<Runtime, T> =
MultiplexingSubscription { stream_senders };
Arc::new(subscription)
}
}