Skip to main content

uactor/actor/
actor_ref.rs

1/// Example:
2/// ```
3///# use std::future::Future;
4/// use uactor::actor::abstract_actor::{Actor, HandleResult};
5/// use uactor::actor::context::Context;
6/// use uactor::system::System;
7/// let mut system = System::global();
8///
9/// use uactor::actor::message::Message;
10/// use uactor::message_impl;
11/// pub struct Ping;
12/// impl Message for Ping { fn static_name() -> &'static str { "Ping" } }
13///
14/// pub struct Actor1;
15/// impl Actor for Actor1 { type Context = Context;type RouteMessage = (); type Inject = (); type State = (); }
16/// let actor1 = Actor1;
17///
18/// impl uactor::actor::abstract_actor::Handler<Ping> for Actor1 { async fn handle(&mut self, inject: &mut Self::Inject, msg: Ping, ctx: &mut Self::Context, state: &Self::State) -> HandleResult { todo!() }  }
19///
20/// uactor::generate_actor_ref!(Actor1, { });
21/// ```
22/// let (mut actor1_ref, handle) = uactor::spawn_with_ref!(system, actor1: Actor1);
23#[macro_export]
24macro_rules! generate_actor_ref {
25    ($ActorType: ident, { $($Message: ident),* }) => {
26        uactor::paste! {
27            pub enum [<$ActorType Msg>] {
28                $($Message($Message)),*
29            }
30
31            impl uactor::actor::message::Message for [<$ActorType Msg>] {
32                fn static_name() -> &'static str {
33                    stringify!([<$ActorType Msg>])
34                }
35
36                fn name(&self) -> String {
37                    match self {
38                    $(
39                        Self::$Message(m) => m.name(),
40                    )*
41                        _ => Self::static_name().to_owned(),
42                    }
43                }
44            }
45
46            impl uactor::actor::abstract_actor::Handler<[<$ActorType Msg>]> for $ActorType {
47                async fn handle(
48                    &mut self,
49                    inject: &mut <Self as uactor::actor::abstract_actor::Actor>::Inject,
50                    msg: [<$ActorType Msg>],
51                    ctx: &mut <Self as uactor::actor::abstract_actor::Actor>::Context,
52                    state: &<$ActorType as uactor::actor::abstract_actor::Actor>::State,
53                ) -> uactor::actor::abstract_actor::HandleResult {
54                    match msg {
55                        $(
56                        [<$ActorType Msg>]::$Message(m) => {
57                            self.handle(inject, m, ctx, state).await?;
58                        }
59                        ),*
60                    }
61                    Ok(())
62                }
63            }
64
65            // Type alias for actor reference use: `UserMpscRef` insted of the full type: `UserRef<tokio::sync::mpsc::UnboundedSender<UserMsg>>`
66            pub type [<$ActorType MpscRef>] = [<$ActorType Ref>]<tokio::sync::mpsc::UnboundedSender<[<$ActorType Msg>]>>;
67
68            pub struct [<$ActorType Ref>]<T> where T: uactor::data::data_publisher::DataPublisher<Item=[<$ActorType Msg>]> + Clone {
69                name: std::sync::Arc<str>,
70                state: <$ActorType as uactor::actor::abstract_actor::Actor>::State,
71                sender: T,
72            }
73
74            impl<T> uactor::data::data_publisher::TryClone for [<$ActorType Ref>]<T> where T: uactor::data::data_publisher::DataPublisher<Item=[<$ActorType Msg>]> + Clone {
75                fn try_clone(&self) -> Result<Self, uactor::data::data_publisher::TryCloneError> {
76                    self.sender.try_clone().map(|sender| Self { name: self.name.clone(), sender, state: self.state.clone() })
77                }
78            }
79
80            impl Clone for [<$ActorType Ref>]<tokio::sync::mpsc::UnboundedSender<[<$ActorType Msg>]>> {
81                fn clone(&self) -> Self {
82                    [<$ActorType Ref>]::new(self.name.clone(), self.sender.clone(), self.state.clone())
83                }
84            }
85
86            impl From<(
87                uactor::aliases::ActorName,
88                tokio::sync::mpsc::UnboundedSender<[<$ActorType Msg>]>,
89                <$ActorType as uactor::actor::abstract_actor::Actor>::State
90            )> for [<$ActorType Ref>]<tokio::sync::mpsc::UnboundedSender<[<$ActorType Msg>]>>
91            {
92                fn from((name, sender, state): (
93                    uactor::aliases::ActorName,
94                    tokio::sync::mpsc::UnboundedSender<[<$ActorType Msg>]>,
95                    <$ActorType as uactor::actor::abstract_actor::Actor>::State
96                )) -> Self {
97                    Self {
98                        name,
99                        sender,
100                        state,
101                    }
102                }
103            }
104
105            // send [<$ActorType Msg>] to actor
106            impl [<$ActorType Ref>]<tokio::sync::mpsc::UnboundedSender<[<$ActorType Msg>]>> {
107                fn send_msg(&self, msg: [<$ActorType Msg>]) -> uactor::data::data_publisher::DataPublisherResult {
108                    uactor::data::data_publisher::DataPublisher::publish(&self.sender, msg)
109                }
110            }
111
112            // impliment MessageSender for each message variant ($Message)
113            $(
114                // #[cfg(not(feature = "async_sender"))]
115                impl <T>uactor::actor::abstract_actor::MessageSender<$Message> for [<$ActorType Ref>]<T> where T: uactor::data::data_publisher::DataPublisher<Item=[<$ActorType Msg>]> + Clone {
116                    fn send(&self, msg: $Message) -> uactor::data::data_publisher::DataPublisherResult {
117                        self.sender.publish([<$ActorType Msg>]::$Message(msg))
118                    }
119
120                    async fn ask<A>(&self, f: impl FnOnce(tokio::sync::oneshot::Sender<A>) -> $Message) -> Result<A, uactor::data::data_publisher::DataPublisherErrors> {
121                        let (tx, rx) = tokio::sync::oneshot::channel::<A>();
122                        let message = f(tx);
123                        self.sender.publish([<$ActorType Msg>]::$Message(message))?;
124                        rx.await.map_err(uactor::data::data_publisher::DataPublisherErrors::from)
125                    }
126                }
127
128                // #[cfg(feature = "async_sender")]
129                // impl <T>uactor::actor::abstract_actor::MessageSender<$Message> for [<$ActorType Ref>]<T> where T: uactor::data::data_publisher::DataPublisher<Item=[<$ActorType Msg>]> + Clone {
130                //     async fn send(&self, msg: $Message) -> uactor::data::data_publisher::DataPublisherResult {
131                //         self.sender.publish([<$ActorType Msg>]::$Message(msg)).await
132                //     }
133                //
134                //     async fn ask<A>(&self, f: impl FnOnce(tokio::sync::oneshot::Sender<A>) -> $Message) -> Result<A, uactor::data::data_publisher::DataPublisherErrors> {
135                //         let (tx, rx) = tokio::sync::oneshot::channel::<A>();
136                //         let message = f(tx);
137                //         self.sender.publish([<$ActorType Msg>]::$Message(message))?;
138                //         rx.await.map_err(uactor::data::data_publisher::DataPublisherErrors::from)
139                //     }
140                // }
141            )*
142
143            impl<T> [<$ActorType Ref>]<T> where T: uactor::data::data_publisher::DataPublisher<Item=[<$ActorType Msg>]> + Clone {
144                pub fn new(name: std::sync::Arc<str>, sender: T, state: <$ActorType as uactor::actor::abstract_actor::Actor>::State) -> Self {
145                    let name = std::sync::Arc::from(name);
146                    Self { name, sender, state }
147                }
148
149                pub fn name(&self) -> std::sync::Arc<str> {
150                    self.name.clone()
151                }
152
153                pub fn state(&self) -> &<$ActorType as uactor::actor::abstract_actor::Actor>::State {
154                    &self.state
155                }
156            }
157        }
158
159    };
160}