use crate::Actor;
use async_channel::{Sender as MultiSender, WeakSender as WeakMultiSender};
use async_oneshot_channel::{Sender as OneshotSender, WeakSender as WeakOneshotSender};
#[derive(Debug)]
pub struct ActorRef<A: Actor> {
pub(crate) sender: MultiSender<A::Message>,
pub(crate) stop: OneshotSender<A::Message>,
}
impl<A: Actor> ActorRef<A> {
pub async fn send(&self, msg: A::Message) -> Result<(), A::Message> {
self.sender.send(msg).await.map_err(|e| e.0)
}
pub fn stop(&self, stop: A::Message) -> Result<(), A::Message> {
self.stop.send(stop)
}
pub fn downgrade(&self) -> WeakActorRef<A> {
WeakActorRef {
sender: self.sender.downgrade(),
stop: self.stop.downgrade(),
}
}
}
impl<A: Actor> Clone for ActorRef<A> {
fn clone(&self) -> Self {
Self {
sender: self.sender.clone(),
stop: self.stop.clone(),
}
}
}
#[derive(Debug)]
pub struct WeakActorRef<A: Actor> {
sender: WeakMultiSender<A::Message>,
stop: WeakOneshotSender<A::Message>,
}
impl<A: Actor> WeakActorRef<A> {
pub fn upgrade(&self) -> Option<ActorRef<A>> {
Some(ActorRef {
sender: self.sender.upgrade()?,
stop: self.stop.upgrade()?,
})
}
pub async fn send(&self, msg: A::Message) -> Result<(), A::Message> {
match self.upgrade() {
Some(actor_ref) => actor_ref.send(msg).await,
None => Err(msg),
}
}
pub fn stop(&self, stop: A::Message) -> Result<(), A::Message> {
self.stop.send(stop)
}
}
impl<A: Actor> Clone for WeakActorRef<A> {
fn clone(&self) -> Self {
Self {
sender: self.sender.clone(),
stop: self.stop.clone(),
}
}
}
impl<A: Actor> TryInto<ActorRef<A>> for WeakActorRef<A> {
type Error = ();
fn try_into(self) -> Result<ActorRef<A>, Self::Error> {
self.upgrade().ok_or(())
}
}