#[macro_use]
extern crate zestors;
use zestors::{export::async_trait, prelude::*};
#[derive(Message, Debug)]
#[request(u32)]
pub struct PrintString {
val: String,
}
#[protocol]
#[derive(Debug)]
pub enum MyProtocol {
A(u32),
B(PrintString),
C(Action<MyHandler>),
}
#[derive(Debug)]
pub struct MyHandler {
handled: u32,
}
#[async_trait]
impl Handler for MyHandler {
type State = Inbox<MyProtocol>;
type Exception = eyre::Report;
type Stop = ();
type Exit = u32;
async fn handle_exit(
self,
_state: &mut Self::State,
reason: Result<Self::Stop, Self::Exception>,
) -> ExitFlow<Self> {
match reason {
Ok(()) => ExitFlow::Exit(self.handled),
Err(exception) => {
println!("[ERROR] Actor exited with an exception: {exception}");
ExitFlow::Exit(self.handled)
}
}
}
async fn handle_event(&mut self, state: &mut Self::State, event: Event) -> HandlerResult<Self> {
match event {
Event::Halted => {
state.close();
Ok(Flow::Continue)
}
Event::ClosedAndEmpty => Ok(Flow::Stop(())),
Event::Dead => Ok(Flow::Stop(())),
}
}
}
#[async_trait]
impl HandleMessage<u32> for MyHandler {
async fn handle_msg(
&mut self,
_state: &mut Self::State,
msg: u32,
) -> Result<Flow<Self>, Self::Exception> {
self.handled += msg;
Ok(Flow::Continue)
}
}
#[async_trait]
impl HandleMessage<PrintString> for MyHandler {
async fn handle_msg(
&mut self,
_state: &mut Self::State,
(msg, tx): (PrintString, Tx<u32>),
) -> Result<Flow<Self>, Self::Exception> {
println!("{}", msg.val);
let _ = tx.send(self.handled);
self.handled += 1;
Ok(Flow::Continue)
}
}
#[tokio::main]
async fn main() {
let (child, address) = MyHandler { handled: 0 }.spawn();
address.send(10u32).await.unwrap();
for i in 0..10 {
let response = address
.request(PrintString {
val: String::from("Printing a message"),
})
.await
.unwrap();
println!("Got response {i} = {response}");
}
child
.send(action!(|handler: &mut MyHandler, _state| async move {
println!("This is now 20: `{}`", handler.handled);
Ok(Flow::Continue)
}))
.await
.unwrap();
child.halt();
assert!(matches!(child.await, Ok(20)));
}