1use crate::effects::ChoreographyError;
7
8pub trait ProtocolObserver: Send {
13 fn on_phase_start(&mut self, protocol: &str, role: &str, phase: &str);
15
16 fn on_phase_end(&mut self, protocol: &str, role: &str, phase: &str);
18
19 fn on_send(&mut self, from: &str, to: &str, msg_type: &str, size: usize);
21
22 fn on_recv(&mut self, from: &str, to: &str, msg_type: &str, size: usize);
24
25 fn on_choice(&mut self, decider: &str, branch: &str);
27
28 fn on_offer(&mut self, from: &str, branch: &str);
30
31 fn on_error(&mut self, protocol: &str, role: &str, error: &ChoreographyError);
33
34 fn on_complete(&mut self, protocol: &str, role: &str);
36}
37
38#[derive(Debug, Default, Clone, Copy)]
42pub struct NullObserver;
43
44impl ProtocolObserver for NullObserver {
45 fn on_phase_start(&mut self, _protocol: &str, _role: &str, _phase: &str) {}
46 fn on_phase_end(&mut self, _protocol: &str, _role: &str, _phase: &str) {}
47 fn on_send(&mut self, _from: &str, _to: &str, _msg_type: &str, _size: usize) {}
48 fn on_recv(&mut self, _from: &str, _to: &str, _msg_type: &str, _size: usize) {}
49 fn on_choice(&mut self, _decider: &str, _branch: &str) {}
50 fn on_offer(&mut self, _from: &str, _branch: &str) {}
51 fn on_error(&mut self, _protocol: &str, _role: &str, _error: &ChoreographyError) {}
52 fn on_complete(&mut self, _protocol: &str, _role: &str) {}
53}
54
55#[derive(Debug, Clone)]
57pub enum ProtocolEvent {
58 PhaseStart {
60 protocol: String,
61 role: String,
62 phase: String,
63 },
64 PhaseEnd {
66 protocol: String,
67 role: String,
68 phase: String,
69 },
70 Send {
72 from: String,
73 to: String,
74 msg_type: String,
75 size: usize,
76 },
77 Recv {
79 from: String,
80 to: String,
81 msg_type: String,
82 size: usize,
83 },
84 Choice { decider: String, branch: String },
86 Offer { from: String, branch: String },
88 Error {
90 protocol: String,
91 role: String,
92 error: String,
93 },
94 Complete { protocol: String, role: String },
96}
97
98#[derive(Debug, Default)]
102pub struct RecordingObserver {
103 events: Vec<ProtocolEvent>,
104}
105
106impl RecordingObserver {
107 #[must_use]
109 pub fn new() -> Self {
110 Self { events: Vec::new() }
111 }
112
113 #[must_use]
115 pub fn events(&self) -> &[ProtocolEvent] {
116 &self.events
117 }
118
119 pub fn take_events(&mut self) -> Vec<ProtocolEvent> {
121 std::mem::take(&mut self.events)
122 }
123
124 pub fn clear(&mut self) {
126 self.events.clear();
127 }
128
129 #[must_use]
131 pub fn len(&self) -> usize {
132 self.events.len()
133 }
134
135 #[must_use]
137 pub fn is_empty(&self) -> bool {
138 self.events.is_empty()
139 }
140
141 pub fn sends(&self) -> impl Iterator<Item = &ProtocolEvent> {
143 self.events
144 .iter()
145 .filter(|e| matches!(e, ProtocolEvent::Send { .. }))
146 }
147
148 pub fn recvs(&self) -> impl Iterator<Item = &ProtocolEvent> {
150 self.events
151 .iter()
152 .filter(|e| matches!(e, ProtocolEvent::Recv { .. }))
153 }
154
155 pub fn errors(&self) -> impl Iterator<Item = &ProtocolEvent> {
157 self.events
158 .iter()
159 .filter(|e| matches!(e, ProtocolEvent::Error { .. }))
160 }
161}
162
163impl ProtocolObserver for RecordingObserver {
164 fn on_phase_start(&mut self, protocol: &str, role: &str, phase: &str) {
165 self.events.push(ProtocolEvent::PhaseStart {
166 protocol: protocol.to_string(),
167 role: role.to_string(),
168 phase: phase.to_string(),
169 });
170 }
171
172 fn on_phase_end(&mut self, protocol: &str, role: &str, phase: &str) {
173 self.events.push(ProtocolEvent::PhaseEnd {
174 protocol: protocol.to_string(),
175 role: role.to_string(),
176 phase: phase.to_string(),
177 });
178 }
179
180 fn on_send(&mut self, from: &str, to: &str, msg_type: &str, size: usize) {
181 self.events.push(ProtocolEvent::Send {
182 from: from.to_string(),
183 to: to.to_string(),
184 msg_type: msg_type.to_string(),
185 size,
186 });
187 }
188
189 fn on_recv(&mut self, from: &str, to: &str, msg_type: &str, size: usize) {
190 self.events.push(ProtocolEvent::Recv {
191 from: from.to_string(),
192 to: to.to_string(),
193 msg_type: msg_type.to_string(),
194 size,
195 });
196 }
197
198 fn on_choice(&mut self, decider: &str, branch: &str) {
199 self.events.push(ProtocolEvent::Choice {
200 decider: decider.to_string(),
201 branch: branch.to_string(),
202 });
203 }
204
205 fn on_offer(&mut self, from: &str, branch: &str) {
206 self.events.push(ProtocolEvent::Offer {
207 from: from.to_string(),
208 branch: branch.to_string(),
209 });
210 }
211
212 fn on_error(&mut self, protocol: &str, role: &str, error: &ChoreographyError) {
213 self.events.push(ProtocolEvent::Error {
214 protocol: protocol.to_string(),
215 role: role.to_string(),
216 error: error.to_string(),
217 });
218 }
219
220 fn on_complete(&mut self, protocol: &str, role: &str) {
221 self.events.push(ProtocolEvent::Complete {
222 protocol: protocol.to_string(),
223 role: role.to_string(),
224 });
225 }
226}
227
228pub struct MultiObserver<'a> {
230 observers: Vec<&'a mut dyn ProtocolObserver>,
231}
232
233impl<'a> MultiObserver<'a> {
234 pub fn new(observers: Vec<&'a mut dyn ProtocolObserver>) -> Self {
236 Self { observers }
237 }
238}
239
240impl ProtocolObserver for MultiObserver<'_> {
241 fn on_phase_start(&mut self, protocol: &str, role: &str, phase: &str) {
242 for obs in &mut self.observers {
243 obs.on_phase_start(protocol, role, phase);
244 }
245 }
246
247 fn on_phase_end(&mut self, protocol: &str, role: &str, phase: &str) {
248 for obs in &mut self.observers {
249 obs.on_phase_end(protocol, role, phase);
250 }
251 }
252
253 fn on_send(&mut self, from: &str, to: &str, msg_type: &str, size: usize) {
254 for obs in &mut self.observers {
255 obs.on_send(from, to, msg_type, size);
256 }
257 }
258
259 fn on_recv(&mut self, from: &str, to: &str, msg_type: &str, size: usize) {
260 for obs in &mut self.observers {
261 obs.on_recv(from, to, msg_type, size);
262 }
263 }
264
265 fn on_choice(&mut self, decider: &str, branch: &str) {
266 for obs in &mut self.observers {
267 obs.on_choice(decider, branch);
268 }
269 }
270
271 fn on_offer(&mut self, from: &str, branch: &str) {
272 for obs in &mut self.observers {
273 obs.on_offer(from, branch);
274 }
275 }
276
277 fn on_error(&mut self, protocol: &str, role: &str, error: &ChoreographyError) {
278 for obs in &mut self.observers {
279 obs.on_error(protocol, role, error);
280 }
281 }
282
283 fn on_complete(&mut self, protocol: &str, role: &str) {
284 for obs in &mut self.observers {
285 obs.on_complete(protocol, role);
286 }
287 }
288}
289
290#[cfg(test)]
291mod tests {
292 use super::*;
293
294 #[test]
295 fn test_null_observer() {
296 let mut obs = NullObserver;
297 obs.on_phase_start("Proto", "Role", "Phase");
299 obs.on_send("A", "B", "Msg", 100);
300 }
301
302 #[test]
303 fn test_recording_observer() {
304 let mut obs = RecordingObserver::new();
305
306 obs.on_phase_start("Proto", "Client", "handshake");
307 obs.on_send("Client", "Server", "Request", 50);
308 obs.on_recv("Server", "Client", "Response", 100);
309 obs.on_phase_end("Proto", "Client", "handshake");
310
311 assert_eq!(obs.len(), 4);
312 assert_eq!(obs.sends().count(), 1);
313 assert_eq!(obs.recvs().count(), 1);
314 }
315
316 #[test]
317 fn test_recording_observer_take() {
318 let mut obs = RecordingObserver::new();
319 obs.on_send("A", "B", "Msg", 10);
320
321 let events = obs.take_events();
322 assert_eq!(events.len(), 1);
323 assert!(obs.is_empty());
324 }
325}