use crate::actors::handle::Respond;
use crate::actors::proxy::ActorProxy;
use crate::{Actor, ActorAssistant, Receive};
use async_channel::Sender;
use async_trait::async_trait;
use std::fmt::Debug;
use std::marker::PhantomData;
#[async_trait]
pub(crate) trait Envelope: Send + Debug {
type Actor: Actor;
async fn dispatch(&mut self, actor: &mut Self::Actor, assistant: &ActorAssistant<Self::Actor>);
}
#[derive(Debug)]
pub(crate) struct Letter<A, M: Debug> {
pub(crate) message: Option<M>,
pub(crate) phantom: PhantomData<A>,
}
impl<A: Receive<M> + Actor, M: Debug> Letter<A, M> {
pub fn new(message: M) -> Self
where
A: Receive<M>,
{
Letter {
message: Some(message),
phantom: PhantomData,
}
}
pub async fn dispatch(&mut self, actor: &mut A, assistant: &ActorAssistant<A>) {
if let Some(message) = self.message.take() {
<A as Receive<M>>::handle(actor, message, assistant).await;
}
}
}
#[async_trait]
impl<A: Actor + Receive<M>, M: Send + Debug> Envelope for Letter<A, M> {
type Actor = A;
async fn dispatch(&mut self, actor: &mut A, assistant: &ActorAssistant<A>) {
Letter::<A, M>::dispatch(self, actor, assistant).await
}
}
#[async_trait]
pub(crate) trait ManagerEnvelope: Send + Debug {
type Actor: Actor;
async fn deliver(&mut self, manager: &mut ActorProxy<Self::Actor>);
fn get_actor_id(&self) -> <<Self as ManagerEnvelope>::Actor as Actor>::Id;
}
#[derive(Debug)]
pub(crate) struct ManagerLetter<A: Actor, M: Debug> {
message: Option<M>,
actor_id: A::Id,
phantom: PhantomData<A>,
}
impl<A: Receive<M> + Actor, M: 'static + Send + Debug> ManagerLetter<A, M> {
pub fn new(actor_id: A::Id, message: M) -> Self
where
A: Receive<M>,
{
ManagerLetter {
message: Some(message),
actor_id,
phantom: PhantomData,
}
}
pub fn get_actor_id(&self) -> A::Id {
self.actor_id.clone()
}
pub async fn deliver(&mut self, manager: &mut ActorProxy<A>) {
if let Some(message) = self.message.take() {
manager.send(message).await;
}
}
}
#[async_trait]
impl<A: Actor + Receive<M>, M: 'static + Send + Debug> ManagerEnvelope for ManagerLetter<A, M> {
type Actor = A;
async fn deliver(&mut self, manager: &mut ActorProxy<Self::Actor>) {
ManagerLetter::<A, M>::deliver(self, manager).await
}
fn get_actor_id(&self) -> A::Id {
ManagerLetter::<A, M>::get_actor_id(self)
}
}
#[derive(Debug)]
pub(crate) struct LetterWithResponder<A: Respond<M>, M: Debug> {
message: Option<M>,
phantom_actor: PhantomData<A>,
phantom_response: PhantomData<<A as Respond<M>>::Response>,
responder: Sender<<A as Respond<M>>::Response>,
}
impl<A: Respond<M> + Actor, M: Debug> LetterWithResponder<A, M> {
pub fn new(message: M, responder: Sender<<A as Respond<M>>::Response>) -> Self {
LetterWithResponder {
message: Some(message),
phantom_actor: PhantomData,
phantom_response: PhantomData,
responder,
}
}
pub async fn dispatch(&mut self, actor: &mut A, assistant: &ActorAssistant<A>) {
if let Some(message) = self.message.take() {
let response = <A as Respond<M>>::handle(actor, message, assistant).await;
let _ = self.responder.send(response).await;
}
}
}
#[async_trait]
impl<A: Actor + Respond<M>, M: Send + Debug> Envelope for LetterWithResponder<A, M> {
type Actor = A;
async fn dispatch(&mut self, actor: &mut A, assistant: &ActorAssistant<A>) {
LetterWithResponder::<A, M>::dispatch(self, actor, assistant).await
}
}
#[derive(Debug)]
pub(crate) struct ManagerLetterWithResponder<A: Actor + Respond<M>, M: Debug> {
message: Option<M>,
actor_id: A::Id,
phantom_actor: PhantomData<<A as Respond<M>>::Response>,
phantom_response: PhantomData<A>,
responder: Option<Sender<<A as Respond<M>>::Response>>,
}
impl<A: Respond<M> + Actor, M: 'static + Send + Debug> ManagerLetterWithResponder<A, M> {
pub fn new(actor_id: A::Id, message: M, responder: Sender<<A as Respond<M>>::Response>) -> Self
where
A: Respond<M>,
{
ManagerLetterWithResponder {
message: Some(message),
actor_id,
phantom_actor: PhantomData,
phantom_response: PhantomData,
responder: Some(responder),
}
}
pub fn get_actor_id(&self) -> A::Id {
self.actor_id.clone()
}
pub async fn deliver(&mut self, manager: &mut ActorProxy<A>) {
if let Some(message) = self.message.take() {
if let Some(responder) = self.responder.take() {
manager.call(message, responder).await;
}
}
}
}
#[async_trait]
impl<A: Actor + Respond<M>, M: 'static + Send + Debug> ManagerEnvelope
for ManagerLetterWithResponder<A, M>
{
type Actor = A;
async fn deliver(&mut self, manager: &mut ActorProxy<Self::Actor>) {
ManagerLetterWithResponder::<A, M>::deliver(self, manager).await
}
fn get_actor_id(&self) -> A::Id {
ManagerLetterWithResponder::<A, M>::get_actor_id(self)
}
}