1use std::{future::Future, pin::Pin, sync::Arc};
2
3use crate::{
4 actors::{Actor, Address, Handler},
5 message::Message,
6};
7
8trait MailboxSender<T: Message>: Send + Sync {
9 fn send<'a>(&'a self, msg: T) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>>;
10 fn try_send(&self, msg: T);
11}
12
13impl<A, T> MailboxSender<T> for Address<A>
14where
15 A: 'static + Actor + Send + Handler<T>,
16 T: Message,
17{
18 fn send<'a>(&'a self, msg: T) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
19 Box::pin(Address::send(self, msg))
20 }
21
22 fn try_send(&self, msg: T) {
23 Address::try_send(self, msg);
24 }
25}
26
27pub struct Mailbox<T: Message> {
35 sender: Arc<dyn MailboxSender<T>>,
36}
37
38impl<T: Message> Clone for Mailbox<T> {
39 fn clone(&self) -> Self {
40 Self {
41 sender: Arc::clone(&self.sender),
42 }
43 }
44}
45
46impl<T: Message> std::fmt::Debug for Mailbox<T> {
47 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 f.debug_struct("Mailbox").finish_non_exhaustive()
49 }
50}
51
52impl<T: Message> Mailbox<T> {
53 pub async fn send(&self, msg: T) {
55 self.sender.send(msg).await
56 }
57
58 pub fn try_send(&self, msg: T) {
60 self.sender.try_send(msg);
61 }
62}
63
64impl<A> Address<A>
65where
66 A: 'static + Actor + Send,
67{
68 pub fn into_mailbox<T>(self) -> Mailbox<T>
72 where
73 A: Handler<T>,
74 T: Message,
75 {
76 Mailbox {
77 sender: Arc::new(self),
78 }
79 }
80}
81
82impl<A, T> From<Address<A>> for Mailbox<T>
83where
84 A: 'static + Actor + Send + Handler<T>,
85 T: Message,
86{
87 fn from(address: Address<A>) -> Self {
88 address.into_mailbox()
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use crate::{executor::Context, Executor};
95
96 use super::*;
97
98 struct Ping;
99 struct Pong;
100
101 struct MyActor;
102 impl Actor for MyActor {}
103
104 impl Handler<Ping> for MyActor {
105 async fn handle(&mut self, _msg: Ping, _ctx: &Context<Self>) {}
106 }
107
108 impl Handler<Pong> for MyActor {
109 async fn handle(&mut self, _msg: Pong, _ctx: &Context<Self>) {}
110 }
111
112 #[test]
113 fn into_mailbox_compiles() {
114 let (_executor, address) = Executor::new(MyActor);
115 let _mailbox: Mailbox<Ping> = address.into_mailbox();
116 }
117
118 #[test]
119 fn from_address_compiles() {
120 let (_executor, address) = Executor::new(MyActor);
121 let _mailbox: Mailbox<Pong> = Mailbox::from(address);
122 }
123
124 #[test]
125 fn mailbox_is_clone() {
126 let (_executor, address) = Executor::new(MyActor);
127 let mailbox: Mailbox<Ping> = address.into_mailbox();
128 let _ = mailbox.clone();
129 }
130
131 #[test]
132 fn mailbox_is_debug() {
133 let (_executor, address) = Executor::new(MyActor);
134 let mailbox: Mailbox<Ping> = address.into_mailbox();
135 let _ = format!("{:?}", mailbox);
136 }
137}