messagebus 0.15.2

MessageBus allows intercommunicate with messages between modules
Documentation
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 })
}