use crate::actors::envelope::Letter;
use crate::services::handle::Listen;
use crate::services::handle::Serve;
use crate::services::service::Service;
use crate::services::system_facade::ServiceAssistant;
use async_channel::Sender;
use std::fmt::Debug;
use std::marker::PhantomData;
#[async_trait::async_trait]
pub(crate) trait ServiceEnvelope: Send + Debug {
type Service: Service;
async fn dispatch(&mut self, service: &Self::Service, system: &ServiceAssistant<Self::Service>);
}
impl<S: Service + Listen<M>, M: Debug> Letter<S, M> {
pub fn new_for_service(message: M) -> Self
where
S: Listen<M>,
Self: ServiceEnvelope,
{
Letter {
message: Some(message),
phantom: PhantomData,
}
}
pub async fn dispatch_service(&mut self, service: &S, system: &ServiceAssistant<S>) {
if let Some(message) = self.message.take() {
<S as Listen<M>>::handle(service, message, system).await;
}
}
}
#[async_trait::async_trait]
impl<S: Service + Listen<M>, M: Debug + Send> ServiceEnvelope for Letter<S, M> {
type Service = S;
async fn dispatch(
&mut self,
service: &Self::Service,
system: &ServiceAssistant<Self::Service>,
) {
Letter::<S, M>::dispatch_service(self, service, system).await;
}
}
#[derive(Debug)]
pub(crate) struct ServiceLetterWithResponders<S: Service + Serve<M>, M: Debug> {
message: Option<M>,
responder: Option<Sender<<S as Serve<M>>::Response>>,
phantom: PhantomData<S>,
}
impl<S: Service + Serve<M>, M: Debug> ServiceLetterWithResponders<S, M> {
pub fn new(message: M, responder: Sender<<S as Serve<M>>::Response>) -> Self
where
S: Serve<M>,
{
ServiceLetterWithResponders {
message: Some(message),
phantom: PhantomData,
responder: Some(responder),
}
}
async fn dispatch(&mut self, service: &S, system: &ServiceAssistant<S>) {
if let Some(message) = self.message.take() {
if let Some(responder) = self.responder.take() {
let result = <S as Serve<M>>::handle(service, message, system).await;
let _ = responder.send(result).await;
}
}
}
}
#[async_trait::async_trait]
impl<S: Service + Serve<M>, M: Debug + Send> ServiceEnvelope for ServiceLetterWithResponders<S, M> {
type Service = S;
async fn dispatch(&mut self, service: &Self::Service, system: &ServiceAssistant<S>) {
ServiceLetterWithResponders::<S, M>::dispatch(self, service, system).await;
}
}