use std::{
any::{Any, TypeId},
pin::Pin,
};
use futures::Future;
use crate::{message::Msg, Error, Message};
enum ChannelItem<T> {
Value(T),
Close,
}
pub(crate) trait AbstractSender: Any + Send + Sync {
fn upcast(&self) -> &(dyn Any + Send + Sync);
fn close(&self);
fn message_type_id(&self) -> TypeId;
}
impl<M: Any + Send + Sync> AbstractSender for kanal::AsyncSender<M> {
fn upcast(&self) -> &(dyn Any + Send + Sync) {
self
}
fn close(&self) {
self.close();
}
fn message_type_id(&self) -> TypeId {
TypeId::of::<M>()
}
}
pub(crate) trait BusSenderClose: Any + Send + Sync {
fn upcast(&self) -> &(dyn Any + Send + Sync);
fn is_producer(&self) -> bool;
fn load(&self) -> (usize, usize);
fn stop(&self) -> Pin<Box<dyn Future<Output = Result<(), Error>> + '_>>;
fn terminate(&self) -> Result<(), Error>;
}
pub(crate) struct BusSender<M: Message> {
is_producer: bool,
tx: Sender<Msg<M>>,
}
impl<M: Message> BusSenderClose for BusSender<M> {
fn upcast(&self) -> &(dyn Any + Send + Sync) {
self
}
fn stop(&self) -> Pin<Box<dyn Future<Output = Result<(), Error>> + '_>> {
Box::pin(async move {
self.tx.stop().await?;
Ok(())
})
}
fn terminate(&self) -> Result<(), Error> {
self.tx.close()
}
fn is_producer(&self) -> bool {
self.is_producer
}
fn load(&self) -> (usize, usize) {
self.tx.load()
}
}
impl<M: Message> BusSender<M> {
pub async fn send(&self, m: Msg<M>) -> Result<(), Error> {
self.tx.send(m).await
}
#[inline]
pub(crate) fn new(is_producer: bool, tx: Sender<Msg<M>>) -> BusSender<M> {
Self { is_producer, tx }
}
}
#[derive(Clone)]
pub(crate) struct Sender<T> {
inner: kanal::AsyncSender<ChannelItem<T>>,
}
impl<T> Sender<T> {
pub async fn send(&self, msg: T) -> Result<(), Error> {
self.inner
.send(ChannelItem::Value(msg))
.await
.map_err(Error::SendError)
}
pub async fn stop(&self) -> Result<(), Error> {
self.inner
.send(ChannelItem::Close)
.await
.map_err(Error::SendError)
}
pub fn close(&self) -> Result<(), Error> {
self.inner.close();
Ok(())
}
pub fn load(&self) -> (usize, usize) {
(self.inner.len(), self.inner.capacity())
}
}
#[derive(Clone)]
pub(crate) struct Receiver<T> {
inner: kanal::AsyncReceiver<ChannelItem<T>>,
}
impl<T> Receiver<T> {
#[inline]
pub async fn recv(&self) -> Option<T> {
let Ok(item) = self.inner.recv().await else {
return None;
};
match item {
ChannelItem::Value(val) => Some(val),
ChannelItem::Close => None,
}
}
#[inline]
pub fn load(&self) -> (u32, u32) {
(self.inner.len() as _, self.inner.capacity() as _)
}
#[inline]
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
}
pub(crate) fn channel<T>(cap: usize) -> (Sender<T>, Receiver<T>) {
let (tx, rx) = kanal::bounded_async(cap);
(Sender { inner: tx }, Receiver { inner: rx })
}