yaaf 0.2.0

Yet Another Actor Framework
Documentation
use crate::{
    error::AddressError,
    handler::{detail::HandlesList, Handler},
    message::{detail::MessageList, Message},
    router::{ConcreteRouter, Router},
};
use ::std::{any::TypeId, collections::HashMap, marker::PhantomData, sync::Arc};

pub trait Actor: Sized + HandlesList<<Self as Actor>::Handles> {
    type Publishes: MessageList;
    type Handles: MessageList;
}

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct ActorId(pub(crate) u32);

#[derive(Debug)]
pub struct ActorAddress<A: Actor> {
    actor_id: ActorId,
    routers: HashMap<TypeId, Arc<dyn Router>>,
    _actor: PhantomData<Arc<A>>,
}

impl<A: Actor> Clone for ActorAddress<A> {
    fn clone(&self) -> Self {
        ActorAddress {
            actor_id: self.actor_id,
            routers: self.routers.clone(),
            _actor: PhantomData,
        }
    }
}

impl<A: Actor> ActorAddress<A> {
    pub(crate) fn new(actor_id: ActorId, routers: HashMap<TypeId, Arc<dyn Router>>) -> Self {
        ActorAddress {
            actor_id,
            routers,
            _actor: PhantomData,
        }
    }
}

pub trait Tell<M: Message> {
    fn tell(&self, message: M) -> Result<(), AddressError>;
}

impl<H, M> Tell<M> for ActorAddress<H>
where
    H: Handler<M>,
    M: Message,
{
    fn tell(&self, message: M) -> Result<(), AddressError> {
        let router = self
            .routers
            .get(&TypeId::of::<M>())
            .ok_or(AddressError::RouterLookupError)?;
        let r: &ConcreteRouter<M> = router
            .as_any()
            .downcast_ref()
            .ok_or(AddressError::RouterLookupError)?;
        r.tell(self.actor_id, message)
            .map_err(|source| AddressError::TellFailure {
                source: source.into(),
            })?;
        Ok(())
    }
}