1use crate::address::{Address, Envelope, MessageFor};
2use crate::agent::Agent;
3use crate::context::Context;
4use anyhow::{Error, Result, anyhow};
5use async_trait::async_trait;
6use crb_core::Tag;
7use crb_send::Recipient;
8
9pub trait EventExt<E: TheEvent> {
10 fn event(&self, event: E) -> Result<()>;
11}
12
13impl<A, E> EventExt<E> for Address<A>
14where
15 A: OnEvent<E>,
16 E: TheEvent,
17{
18 fn event(&self, event: E) -> Result<()> {
19 Address::event(self, event)
20 }
21}
22
23impl<A, E> EventExt<E> for Context<A>
24where
25 A: OnEvent<E>,
26 E: TheEvent,
27{
28 fn event(&self, event: E) -> Result<()> {
29 self.address().event(event)
30 }
31}
32
33pub trait TheEvent: Send + 'static {}
34
35impl<T> TheEvent for T where Self: Send + 'static {}
36
37impl<A: Agent> Address<A> {
38 pub fn event<E>(&self, event: E) -> Result<()>
39 where
40 A: OnEvent<E>,
41 E: TheEvent,
42 {
43 self.send(Event::new(event))
44 }
45
46 pub fn event_tagged<E, T>(&self, event: E, tag: T) -> Result<()>
47 where
48 A: OnEvent<E, T>,
49 E: TheEvent,
50 T: Tag,
51 {
52 self.send(Event::new_tagged(event, tag))
53 }
54
55 pub fn recipient<E>(&self) -> Recipient<E>
56 where
57 A: OnEvent<E>,
58 E: TheEvent,
59 {
60 Recipient::new(self.clone()).reform(Event::new)
61 }
62
63 pub fn recipient_tagged<E, T>(&self, tag: T) -> Recipient<E>
64 where
65 A: OnEvent<E, T>,
66 E: TheEvent,
67 T: Tag + Sync + Clone,
68 {
69 Recipient::new(self.clone()).reform(move |event| Event::new_tagged(event, tag.clone()))
70 }
71}
72
73impl<A: Agent> Context<A> {
74 pub fn event<E>(&self, event: E) -> Result<()>
75 where
76 A: OnEvent<E>,
77 E: TheEvent,
78 {
79 self.address().event(event)
80 }
81
82 pub fn event_tagged<E, T>(&self, event: E, tag: T) -> Result<()>
83 where
84 A: OnEvent<E, T>,
85 E: TheEvent,
86 T: Tag,
87 {
88 self.address().event_tagged(event, tag)
89 }
90
91 pub fn recipient<E>(&self) -> Recipient<E>
92 where
93 A: OnEvent<E>,
94 E: TheEvent,
95 {
96 self.address().recipient()
97 }
98
99 pub fn recipient_tagged<E, T>(&self, tag: T) -> Recipient<E>
100 where
101 A: OnEvent<E, T>,
102 E: TheEvent,
103 T: Tag + Sync + Clone,
104 {
105 self.address().recipient_tagged(tag)
106 }
107}
108
109#[async_trait]
111pub trait OnEvent<E: TheEvent, T: Tag = ()>: Agent {
112 async fn handle_tagged(&mut self, event: E, _tag: T, ctx: &mut Context<Self>) -> Result<()> {
116 self.handle(event, ctx).await
117 }
118
119 async fn handle(&mut self, _event: E, _ctx: &mut Context<Self>) -> Result<()> {
120 Err(anyhow!("The handle method in not implemented."))
121 }
122
123 async fn fallback(&mut self, err: Error, _ctx: &mut Context<Self>) -> Result<()> {
124 Err(err)
125 }
126}
127
128pub struct Event<E, T = ()> {
129 event: E,
130 tag: T,
131}
132
133impl<E> Event<E> {
134 pub fn new(event: E) -> Self {
135 Self { event, tag: () }
136 }
137
138 pub fn envelope<A>(event: E) -> Envelope<A>
139 where
140 A: OnEvent<E>,
141 E: TheEvent,
142 {
143 Self::new(event).into_envelope::<A>()
144 }
145}
146
147impl<E, T> Event<E, T> {
148 pub fn new_tagged(event: E, tag: T) -> Self {
149 Self { event, tag }
150 }
151}
152
153impl<E, T> Event<E, T>
154where
155 E: TheEvent,
156 T: Tag,
157{
158 pub fn into_envelope<A>(self) -> Envelope<A>
159 where
160 A: OnEvent<E, T>,
161 {
162 Box::new(self)
163 }
164}
165
166#[async_trait]
167impl<A, E, T> MessageFor<A> for Event<E, T>
168where
169 A: OnEvent<E, T>,
170 E: TheEvent,
171 T: Tag,
172{
173 async fn handle(self: Box<Self>, agent: &mut A, ctx: &mut Context<A>) -> Result<()> {
174 if let Err(err) = agent.handle_tagged(self.event, self.tag, ctx).await {
175 agent.fallback(err, ctx).await
176 } else {
177 Ok(())
178 }
179 }
180}