libpetri_event/
event_store.rs1use crate::net_event::NetEvent;
2
3pub trait EventStore: Default + Send {
19 const ENABLED: bool;
20
21 const CAPTURES_TOKENS: bool = false;
25
26 fn append(&mut self, event: NetEvent);
27 fn events(&self) -> &[NetEvent];
28 fn size(&self) -> usize;
29 fn is_empty(&self) -> bool;
30}
31
32#[derive(Debug, Default)]
37pub struct NoopEventStore;
38
39impl EventStore for NoopEventStore {
40 const ENABLED: bool = false;
41
42 #[inline(always)]
43 fn append(&mut self, _event: NetEvent) {}
44
45 #[inline(always)]
46 fn events(&self) -> &[NetEvent] {
47 &[]
48 }
49
50 #[inline(always)]
51 fn size(&self) -> usize {
52 0
53 }
54
55 #[inline(always)]
56 fn is_empty(&self) -> bool {
57 true
58 }
59}
60
61#[derive(Debug, Default)]
63pub struct InMemoryEventStore {
64 events: Vec<NetEvent>,
65}
66
67impl InMemoryEventStore {
68 pub fn new() -> Self {
69 Self { events: Vec::new() }
70 }
71
72 pub fn filter(&self, predicate: impl Fn(&NetEvent) -> bool) -> Vec<&NetEvent> {
74 self.events.iter().filter(|e| predicate(e)).collect()
75 }
76
77 pub fn transition_events(&self, name: &str) -> Vec<&NetEvent> {
79 self.filter(|e| e.transition_name() == Some(name))
80 }
81
82 pub fn failures(&self) -> Vec<&NetEvent> {
84 self.filter(|e| e.is_failure())
85 }
86}
87
88impl EventStore for InMemoryEventStore {
89 const ENABLED: bool = true;
90
91 fn append(&mut self, event: NetEvent) {
92 self.events.push(event);
93 }
94
95 fn events(&self) -> &[NetEvent] {
96 &self.events
97 }
98
99 fn size(&self) -> usize {
100 self.events.len()
101 }
102
103 fn is_empty(&self) -> bool {
104 self.events.is_empty()
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111 use std::sync::Arc;
112
113 #[test]
114 fn noop_store_is_always_empty() {
115 let mut store = NoopEventStore;
116 store.append(NetEvent::ExecutionStarted {
117 net_name: Arc::from("test"),
118 timestamp: 0,
119 });
120 assert!(store.is_empty());
121 assert_eq!(store.size(), 0);
122 assert!(store.events().is_empty());
123 }
124
125 #[test]
126 fn in_memory_store_records_events() {
127 let mut store = InMemoryEventStore::new();
128 store.append(NetEvent::ExecutionStarted {
129 net_name: Arc::from("test"),
130 timestamp: 0,
131 });
132 store.append(NetEvent::TransitionStarted {
133 transition_name: Arc::from("t1"),
134 timestamp: 1,
135 });
136 assert_eq!(store.size(), 2);
137 assert!(!store.is_empty());
138 }
139
140 #[test]
141 fn in_memory_store_transition_events() {
142 let mut store = InMemoryEventStore::new();
143 store.append(NetEvent::TransitionStarted {
144 transition_name: Arc::from("t1"),
145 timestamp: 1,
146 });
147 store.append(NetEvent::TransitionCompleted {
148 transition_name: Arc::from("t1"),
149 timestamp: 2,
150 });
151 store.append(NetEvent::TransitionStarted {
152 transition_name: Arc::from("t2"),
153 timestamp: 3,
154 });
155 assert_eq!(store.transition_events("t1").len(), 2);
156 assert_eq!(store.transition_events("t2").len(), 1);
157 }
158
159 #[test]
160 fn enabled_constants() {
161 const { assert!(!NoopEventStore::ENABLED) };
162 const { assert!(InMemoryEventStore::ENABLED) };
163 }
164
165 #[test]
166 fn capture_tokens_defaults_off() {
167 const { assert!(!NoopEventStore::CAPTURES_TOKENS) };
171 const { assert!(!InMemoryEventStore::CAPTURES_TOKENS) };
172 }
173}