nitinol-process 0.1.0

Pseudo-actor type process library for Nitinol using green thread of tokio
Documentation
use std::any::Any;
use tokio::sync::mpsc::UnboundedSender;
use tokio::sync::oneshot;
use nitinol_core::command::Command;
use nitinol_core::event::Event;

use crate::channel::{ProcessApplier, CommandReceptor, ApplicativeReceptor, TryApplicativeReceptor, NonBlockingEntrustHandler};
use crate::errors::ChannelDropped;
use crate::{EventApplicator, Process, CommandHandler, TryEventApplicator};

pub mod any;

use self::any::DynRef;

#[derive(Debug)]
pub struct Receptor<T: Process> {
    pub(crate) channel: UnboundedSender<Box<dyn ProcessApplier<T>>>
}

#[rustfmt::skip]
impl<T: Process> Receptor<T> {
    pub async fn handle<C: Command>(&self, command: C) -> Result<Result<T::Event, T::Rejection>, ChannelDropped>
    where
        T: CommandHandler<C>,
    {
        let (tx, rx) = oneshot::channel();
        self.channel
            .send(Box::new(CommandReceptor {
                command,
                oneshot: tx,
            }))
            .map_err(|_| ChannelDropped)?;

        rx.await.map_err(|_| ChannelDropped)
    }

    pub async fn apply<E: Event>(&self, event: E) -> Result<(), ChannelDropped>
    where
        T: EventApplicator<E>,
    {
        let (tx, rx) = oneshot::channel();
        self.channel
            .send(Box::new(ApplicativeReceptor { event, oneshot: tx }))
            .map_err(|_| ChannelDropped)?;

        rx.await.map_err(|_| ChannelDropped)
    }
    
    pub async fn try_apply<E: Event>(&self, event: E) -> Result<Result<(), T::Rejection>, ChannelDropped>
    where
        T: TryEventApplicator<E>,
    {
        let (tx, rx) = oneshot::channel();
        self.channel
            .send(Box::new(TryApplicativeReceptor { event, oneshot: tx }))
            .map_err(|_| ChannelDropped)?;
        
        rx.await.map_err(|_| ChannelDropped)
    }
    
    pub async fn entrust<C: Command>(&self, cmd: C) -> Result<(), ChannelDropped>
    where
        T: CommandHandler<C>,
        T: EventApplicator<<T as CommandHandler<C>>::Event>,
    {
        self.channel
            .send(Box::new(NonBlockingEntrustHandler { command: cmd }))
            .map_err(|_| ChannelDropped)?;
        
        Ok(())
    }
}

impl<T: Process> Clone for Receptor<T> {
    fn clone(&self) -> Self {
        Self { 
            channel: self.channel.clone()
        }
    }
}

impl<T: Process> DynRef for Receptor<T> {
    fn as_any(&self) -> &dyn Any {
        self
    }
}