1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//! # abcgen - Actor's Boilerplate Code Generator
//! **abcgen** helps you to build Actor object by producing all the boilerplate code needed by this patter, meaning that all the code involved in defining/sending/raceiving/unwrapping messages and managing lifetime of the actor is hidden from user. <br>
//! The user should only focus on the logic of the service that the actor is going to provide.
//! **abcgen** produces Actor objects that are based on the `async`/`await` syntax and the **tokio** library.
//! The actor objects generated do not require any scheduler o manager to run, they are standalone and can be used in any (**tokio**) context.
//!
//! ## Basic example
//! The following example is minimale and does not shocase all the features of the library.
//! Check the [README] for more details.
//! ```rust
//! #[abcgen::actor_module]
//! #[allow(unused)]
//! mod actor {
//! use abcgen::{actor, message_handler, send_task, AbcgenError, PinnedFuture, Task};
//!
//! #[actor]
//! pub struct MyActor {
//! pub some_value: i32,
//! }
//!
//! impl MyActor {
//! pub async fn start(&mut self, task_sender: TaskSender) {
//! println!("Starting");
//! // here you can spawn some tasks using tokio::spawn
//! // or enqueue some tasks into the actor's main loop by sending them to task_sender
//! tokio::spawn(async move {
//! tokio::time::sleep(std::time::Duration::from_secs(1)).await;
//! send_task!( task_sender(this) => { this.example_task().await; } );
//! });
//! }
//! pub async fn shutdown(&mut self) {
//! println!("Shutting down");
//! }
//! #[message_handler]
//! async fn get_value(&mut self, name: &'static str) -> Result<i32, &'static str> {
//! match name {
//! "some_value" => Ok(self.some_value),
//! _ => Err("Invalid name"),
//! }
//! }
//!
//! async fn example_task(&mut self) {
//! println!("Example task executed");
//! }
//! }
//! }
//!
//! #[tokio::main]
//! async fn main() {
//! let actor: actor::MyActorProxy = actor::MyActor { some_value: 32 }.run();
//! let the_value = actor.get_value("some_value").await.unwrap();
//! assert!(matches!(the_value, Ok(32)));
//! let the_value = actor.get_value("some_other_value").await.unwrap();
//! assert!(matches!(the_value, Err("Invalid name")));
//! }
//!
//! ```
//! ## The user should provide:
//! - a struct or enum definition marked with `actor` attribute
//! - implement start(...) and shutdown(...) methods for the `actor`
//! - implement, for the `actor`, a set of methods marked with `message_handler` attribute; these are going to handle the messages that the `actor` can receive.
//! - optionally, an enum definition marked with `events` attribute to define the events that the `actor` can signal
//!
//! ## The procedural macro will generate:
//! - implementation of `run(self)` method for the `actor` which will return an ActorProxy
//! - implementation of message handling logic for the `actor`:
//! - calling the `start(...)` method before entering the `actor`'s loop
//! - calling the `shutdown(&mut self)` method after exiting the `actor`'s loop
//! - handling of stop signal
//! - handling of messages (support replies)
//! - handling of tasks (functions that can be enqueued to be invoked in the `actor`'s loop so the can access `&mut Actor`)
//! - an ActorProxy object that implements all of the methods that were marked with `message_handler` attribute
//! - a message enum that contains all the messages that the `actor` can receive (which is not meant to be used directly by the user)
//!
//! More details can be found in the [README] file.
//!
//! [README]: https://github.com/frabul/abcgen/blob/main/README.md
use ;
pub use *;
/// Helper type for async tasks
/// The tasks that are meant to be sent to the actor need to return this type
pub type PinnedFuture<'a, TResult> = ;
/// The type of the tasks that are sent to the actor
pub type Task<TActor> = ;
/// A macro to simplify sending tasks to the actor
/// Following below example you need to provide a refence to `task_sender` and
/// the name for the reference to the actor (`this` in the example).
/// The macro will create a closure that returx a `PinnedFuture` expressed with |this| Box::pin(async move { ... })
/// and send it trough the `task_sender`.
/// Example:
/// ```rust
/// send_task!(task_sender(this) => {
/// this.some_field = this.do_something().await;
/// });
/// ```
;
}
/// Error type for the code generated by the abcgen