act_zero/
macros.rs

1#[doc(hidden)]
2#[macro_export]
3macro_rules! __impl_send {
4    (
5        @parse $caller:tt receiver=[$($receiver:tt)*] tokens = [. $method:ident ($($args:expr),*)]
6    ) => {
7        $crate::__impl_send!(@move_args $caller args=[$($args),*] input=[$($receiver)*, $method])
8    };
9    (
10        @parse $caller:tt receiver=[$($receiver:tt)*] tokens = [$token:tt $($tokens:tt)*]
11    ) => {
12        $crate::__impl_send!(@parse $caller receiver=[$($receiver)* $token] tokens = [$($tokens)*])
13    };
14    (
15        @move_args $caller:tt args = [] input = $input:tt
16    ) => {
17        $crate::__impl_send!(@$caller args=[] moved=[] input=$input)
18    };
19    (
20        @move_args $caller:tt args = [$arg0:expr] input = $input:tt
21    ) => {
22        $crate::__impl_send!(@$caller args=[$arg0] moved=[arg0] input=$input)
23    };
24    (
25        @move_args $caller:tt args = [$arg0:expr, $arg1:expr] input = $input:tt
26    ) => {
27        $crate::__impl_send!(@$caller args=[$arg0, $arg1] moved=[arg0, arg1] input=$input)
28    };
29    (
30        @move_args $caller:tt args = [$arg0:expr, $arg1:expr, $arg2:expr] input = $input:tt
31    ) => {
32        $crate::__impl_send!(@$caller args=[$arg0, $arg1, $arg2] moved=[arg0, arg1, arg2] input=$input)
33    };
34    (
35        @move_args $caller:tt args = [$arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr] input = $input:tt
36    ) => {
37        $crate::__impl_send!(@$caller args=[$arg0, $arg1, $arg2, $arg3] moved=[arg0, arg1, arg2, arg3] input=$input)
38    };
39    (
40        @move_args $caller:tt args = [$arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr] input = $input:tt
41    ) => {
42        $crate::__impl_send!(@$caller args=[$arg0, $arg1, $arg2, $arg3, $arg4] moved=[arg0, arg1, arg2, arg3, arg4] input=$input)
43    };
44    (
45        @move_args $caller:tt args = [$arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr] input = $input:tt
46    ) => {
47        $crate::__impl_send!(@$caller args=[$arg0, $arg1, $arg2, $arg3, $arg4, $arg5] moved=[arg0, arg1, arg2, arg3, arg4, arg5] input=$input)
48    };
49    (
50        @move_args $caller:tt args = [$arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr, $arg6:expr] input = $input:tt
51    ) => {
52        $crate::__impl_send!(@$caller args=[$arg0, $arg1, $arg2, $arg3, $arg4, $arg5, $arg6] moved=[arg0, arg1, arg2, arg3, arg4, arg5, arg6] input=$input)
53    };
54    (
55        @move_args $caller:tt args = [$arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr, $arg6:expr, $arg7:expr] input = $input:tt
56    ) => {
57        $crate::__impl_send!(@$caller args=[$arg0, $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7] moved=[arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7] input=$input)
58    };
59    (
60        @move_args $caller:tt args = [$arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr, $arg6:expr, $arg7:expr, $arg8:expr] input = $input:tt
61    ) => {
62        $crate::__impl_send!(@$caller args=[$arg0, $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7, $arg8] moved=[arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8] input=$input)
63    };
64    (
65        @move_args $caller:tt args = [$arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr, $arg6:expr, $arg7:expr, $arg8:expr, $arg9:expr] input = $input:tt
66    ) => {
67        $crate::__impl_send!(@$caller args=[$arg0, $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7, $arg8, $arg9] moved=[arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9] input=$input)
68    };
69    (
70        @send args=[$($args:expr),*] moved=[$($moved:ident),*] input=[$addr:expr, $method:ident]
71    ) => {
72        {
73            $(
74                let $moved = $args;
75            )*
76            let addr = $crate::AsAddr::as_addr(&$addr);
77            let addr2 = addr.clone();
78            $crate::hidden::trace!("send!({}::{}(...))", $crate::hidden::type_name_of_addr(addr).as_display(), stringify!($method));
79            $crate::AddrLike::send_mut(addr, Box::new(move |x| {
80                $crate::hidden::trace!("{}::{}(...)", $crate::hidden::type_name_of_val(x).as_display(), stringify!($method));
81                $crate::hidden::FutureExt::boxed(async move {
82                    let _addr = addr2;
83                    if let Err(e) = $crate::IntoActorResult::into_actor_result(x.$method($($moved),*).await) {
84                        $crate::Actor::error(x, e).await
85                    } else {
86                        false
87                    }
88                })
89            }));
90        }
91    };
92    (
93        @call args=[$($args:expr),*] moved=[$($moved:ident),*] input=[$addr:expr, $method:ident]
94    ) => {
95        {
96            $(
97                let $moved = $args;
98            )*
99            let addr = $crate::AsAddr::as_addr(&$addr);
100            let addr2 = addr.clone();
101            $crate::hidden::trace!("call!({}::{}(...))", $crate::hidden::type_name_of_addr(addr).as_display(), stringify!($method));
102            let (tx, rx) = $crate::hidden::oneshot::channel();
103            $crate::AddrLike::send_mut(addr, Box::new(move |x| {
104                $crate::hidden::trace!("{}::{}(...)", $crate::hidden::type_name_of_val(x).as_display(), stringify!($method));
105                $crate::hidden::FutureExt::boxed(async move {
106                    let _addr = addr2;
107                    match $crate::IntoActorResult::into_actor_result(x.$method($($moved),*).await) {
108                        Ok(x) => {
109                            let _ = tx.send(x);
110                            false
111                        }
112                        Err(e) => $crate::Actor::error(x, e).await,
113                    }
114                })
115            }));
116            $crate::Produces::Deferred(rx)
117        }
118    };
119}
120
121/// Sends a method call to be executed by the actor.
122///
123/// ```ignore
124/// send!(addr.method(arg1, arg2))
125/// ```
126///
127/// Constraints:
128/// - The method must be an inherent method or trait method callable on the
129///   actor type.
130/// - The method must take `&mut self` as the receiver.
131/// - The method must return a future, with an output that implements `IntoActorResult`.
132/// - The arguments must be `Send + 'static`.
133#[macro_export]
134macro_rules! send {
135    ($($tokens:tt)*) => {
136        $crate::__impl_send!(@parse send receiver=[] tokens=[$($tokens)*])
137    };
138}
139
140/// Sends a method call to be executed by the actor, and returns a future that can
141/// be awaited to get back the result.
142///
143/// ```ignore
144/// call!(addr.method(arg1, arg2))
145/// ```
146///
147/// The same constraints as for the `send!(...)` macro apply.
148#[macro_export]
149macro_rules! call {
150    ($($tokens:tt)*) => {
151        $crate::__impl_send!(@parse call receiver=[] tokens=[$($tokens)*])
152    };
153}
154
155/// Converts an `Addr<T>` or `WeakAddr<T>` to an `Addr<dyn Trait>` or `WeakAddr<dyn Trait>`.
156///
157/// ```ignore
158/// let trait_addr: Addr<dyn Trait> = upcast!(addr);
159/// ```
160#[macro_export]
161macro_rules! upcast {
162    ($x:expr) => {
163        ($x).upcast(|x| x as _)
164    };
165}