threshold/set/below_ex.rs
1//! This module contains an implementation of a below-exception set.
2//!
3//! # Examples
4//! ```
5//! use threshold::*;
6//!
7//! let mut below_exset = BelowExSet::new();
8//! assert_eq!(below_exset.next_event(), 1);
9//! assert!(below_exset.is_event(1));
10//! assert!(!below_exset.is_event(2));
11//!
12//! let other = BelowExSet::from_event(3);
13//! assert!(!other.is_event(1));
14//! assert!(!other.is_event(2));
15//! assert!(other.is_event(3));
16//!
17//! below_exset.join(&other);
18//! assert!(below_exset.is_event(1));
19//! assert!(!below_exset.is_event(2));
20//! assert!(below_exset.is_event(3));
21//! ```
22
23use crate::EventSet;
24use serde::{Deserialize, Serialize};
25use std::cmp::{self, Ordering};
26use std::collections::HashSet;
27use std::fmt;
28use std::iter::FromIterator;
29
30#[derive(Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
31pub struct BelowExSet {
32 // Highest event seen
33 max: u64,
34 // Set of exceptions
35 exs: HashSet<u64>,
36}
37
38impl EventSet for BelowExSet {
39 type EventIter = EventIter;
40
41 /// Returns a new `BelowExSet` instance.
42 fn new() -> Self {
43 BelowExSet {
44 max: 0,
45 exs: HashSet::new(),
46 }
47 }
48
49 /// Generates the next event.
50 /// There should be no exceptions when calling this.
51 ///
52 /// # Examples
53 /// ```
54 /// use threshold::*;
55 ///
56 /// let mut below_exset = BelowExSet::new();
57 /// assert_eq!(below_exset.next_event(), 1);
58 /// assert_eq!(below_exset.next_event(), 2);
59 /// ```
60 fn next_event(&mut self) -> u64 {
61 debug_assert!(self.exs.is_empty());
62 self.max += 1;
63 self.max
64 }
65
66 /// Adds an event to the set.
67 ///
68 /// # Examples
69 /// ```
70 /// use threshold::*;
71 ///
72 /// let mut below_exset = BelowExSet::new();
73 ///
74 /// below_exset.add_event(1);
75 /// assert!(below_exset.is_event(1));
76 /// assert!(!below_exset.is_event(2));
77 ///
78 /// below_exset.add_event(3);
79 /// assert!(below_exset.is_event(1));
80 /// assert!(!below_exset.is_event(2));
81 /// assert!(below_exset.is_event(3));
82 ///
83 /// below_exset.add_event(2);
84 /// assert!(below_exset.is_event(1));
85 /// assert!(below_exset.is_event(2));
86 /// assert!(below_exset.is_event(3));
87 /// ```
88 fn add_event(&mut self, event: u64) -> bool {
89 match event.cmp(&self.max) {
90 Ordering::Less => {
91 // remove from exceptions (it might not be an exception though).
92 // the result is the same as the result of the remove in the
93 // exceptions:
94 // - if it was an exception, then it's also a new event
95 self.exs.remove(&event)
96 }
97 Ordering::Greater => {
98 // this event is now the new max, which might create exceptions
99 for new_ex in self.max + 1..event {
100 self.exs.insert(new_ex);
101 }
102 self.max = event;
103 // new event, so `true`
104 true
105 }
106 Ordering::Equal => {
107 // nothing to do since it is already an event
108 false
109 }
110 }
111 }
112
113 /// Checks if an event is part of the set.
114 ///
115 /// # Examples
116 /// ```
117 /// use threshold::*;
118 ///
119 /// let mut below_exset = BelowExSet::new();
120 /// let event = below_exset.next_event();
121 /// assert!(below_exset.is_event(event));
122 ///
123 /// below_exset.add_event(3);
124 /// assert!(!below_exset.is_event(2));
125 /// assert!(below_exset.is_event(3));
126 /// ```
127 fn is_event(&self, event: u64) -> bool {
128 event <= self.max && !self.exs.contains(&event)
129 }
130
131 /// Returns all events seen as a tuple.
132 /// The first component is the highest event seen, while the second is a
133 /// vector with the exceptions (in no specific order).
134 ///
135 /// # Examples
136 /// ```
137 /// use threshold::*;
138 ///
139 /// let mut below_exset = BelowExSet::new();
140 ///
141 /// below_exset.add_event(1);
142 /// assert_eq!(below_exset.events(), (1, vec![]));
143 ///
144 /// below_exset.add_event(3);
145 /// assert_eq!(below_exset.events(), (3, vec![2]));
146 ///
147 /// below_exset.add_event(2);
148 /// assert_eq!(below_exset.events(), (3, vec![]));
149 ///
150 /// below_exset.add_event(4);
151 /// assert_eq!(below_exset.events(), (4, vec![]));
152 ///
153 /// below_exset.add_event(6);
154 /// assert_eq!(below_exset.events(), (6, vec![5]));
155 /// ```
156 fn events(&self) -> (u64, Vec<u64>) {
157 (self.max, self.exs.clone().into_iter().collect())
158 }
159
160 /// Returns the frontier (the highest contiguous event seen).
161 ///
162 /// __Note:__ this method's implementation will sort all exceptions on each
163 /// call, and with that, the performance will not be great. If this
164 /// becomes a problem, we could cache the frontier (as in `AboveExSet`)
165 /// so that it doesn't have to be computed here on each call.
166 ///
167 /// # Examples
168 /// ```
169 /// use threshold::*;
170 ///
171 /// let mut below_exset = BelowExSet::new();
172 /// assert_eq!(below_exset.frontier(), 0);
173 ///
174 /// below_exset.add_event(1);
175 /// assert_eq!(below_exset.frontier(), 1);
176 ///
177 /// below_exset.add_event(3);
178 /// assert_eq!(below_exset.frontier(), 1);
179 ///
180 /// below_exset.add_event(2);
181 /// assert_eq!(below_exset.frontier(), 3);
182 ///
183 /// below_exset.add_event(4);
184 /// assert_eq!(below_exset.frontier(), 4);
185 ///
186 /// below_exset.add_event(6);
187 /// assert_eq!(below_exset.frontier(), 4);
188 /// ```
189 fn frontier(&self) -> u64 {
190 // if there are no exceptions, then the highest contiguous event is
191 // self.max otherwise, it's the smallest exception - 1
192 if self.exs.is_empty() {
193 self.max
194 } else {
195 // sort exceptions
196 let mut exs: Vec<_> = self.exs.iter().collect();
197 exs.sort_unstable();
198
199 // return the smallest one -1
200 (**exs.iter().next().unwrap()) - 1
201 }
202 }
203
204 /// Merges `other` `BelowExSet` into `self`.
205 ///
206 /// # Examples
207 /// ```
208 /// use threshold::*;
209 ///
210 /// let mut below_exset = BelowExSet::new();
211 /// below_exset.add_event(1);
212 /// below_exset.add_event(3);
213 /// below_exset.add_event(4);
214 /// assert_eq!(below_exset.events(), (4, vec![2]));
215 ///
216 /// below_exset.join(&BelowExSet::from_event(3));
217 /// assert_eq!(below_exset.events(), (4, vec![2]));
218 ///
219 /// below_exset.join(&BelowExSet::from_event(5));
220 /// assert_eq!(below_exset.events(), (5, vec![2]));
221 ///
222 /// let mut other = BelowExSet::new();
223 /// other.add_event(2);
224 /// other.add_event(7);
225 /// below_exset.join(&other);
226 /// assert_eq!(below_exset.events(), (7, vec![6]));
227 /// ```
228 fn join(&mut self, other: &Self) {
229 let before = self.clone();
230
231 // the new exceptions are a subset of the union of exceptions sets
232 // - this means that the join does not create new exceptions
233 //
234 // keep the local exceptions that are not remote events
235 self.exs.retain(|ex| !other.is_event(*ex));
236
237 // keep the remote exceptions that are not local events
238 other
239 .exs
240 .iter()
241 .filter(|&&ex| !before.is_event(ex))
242 .for_each(|&ex| {
243 self.exs.insert(ex);
244 });
245
246 // the new max value is the max of both max values
247 self.max = cmp::max(self.max, other.max);
248 }
249
250 fn meet(&mut self, _other: &Self) {
251 todo!("BelowExSet::meet not yet implemented")
252 }
253
254 fn subtracted(&self, _other: &Self) -> Vec<u64> {
255 todo!("BelowExSet::subtracted not yet implemented")
256 }
257
258 /// Returns a `BelowExSet` event iterator with all events from lowest to
259 /// highest.
260 ///
261 /// # Examples
262 /// ```
263 /// use threshold::*;
264 ///
265 /// let mut below_exset = BelowExSet::new();
266 /// below_exset.add_event(3);
267 /// below_exset.add_event(5);
268 ///
269 /// let mut iter = below_exset.event_iter();
270 /// assert_eq!(iter.next(), Some(3));
271 /// assert_eq!(iter.next(), Some(5));
272 /// assert_eq!(iter.next(), None);
273 /// ```
274 fn event_iter(self) -> Self::EventIter {
275 EventIter {
276 current: 0,
277 max: self.max,
278 exs: self.exs,
279 }
280 }
281}
282
283impl BelowExSet {
284 /// Creates a new instance from the highest event, and a sequence of
285 /// exceptions.
286 ///
287 /// # Examples
288 /// ```
289 /// use threshold::*;
290 ///
291 /// let below_exset = BelowExSet::from(5, vec![1, 3]);
292 /// assert!(!below_exset.is_event(1));
293 /// assert!(below_exset.is_event(2));
294 /// assert!(!below_exset.is_event(3));
295 /// assert!(below_exset.is_event(4));
296 /// assert!(below_exset.is_event(5));
297 /// assert!(!below_exset.is_event(6));
298 /// ```
299 pub fn from<I: IntoIterator<Item = u64>>(max: u64, iter: I) -> Self {
300 BelowExSet {
301 max,
302 exs: HashSet::from_iter(iter),
303 }
304 }
305}
306
307pub struct EventIter {
308 // Last value returned by the iterator
309 current: u64,
310 // Last value that should be returned by the iterator
311 max: u64,
312 // Set of exceptions to be skipped by the iterator
313 exs: HashSet<u64>,
314}
315
316impl Iterator for EventIter {
317 type Item = u64;
318
319 fn next(&mut self) -> Option<Self::Item> {
320 if self.current == self.max {
321 // we've reached the end of the iterator
322 None
323 } else {
324 // compute next value
325 self.current += 1;
326
327 if self.exs.contains(&self.current) {
328 // if the next value is an exception, skip it
329 self.next()
330 } else {
331 // otherwise, return it
332 Some(self.current)
333 }
334 }
335 }
336}
337
338impl fmt::Debug for BelowExSet {
339 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
340 if self.exs.is_empty() {
341 write!(f, "{}", self.max)
342 } else {
343 write!(f, "({} - {:?})", self.max, self.exs)
344 }
345 }
346}
347
348#[cfg(test)]
349mod tests {
350 use super::*;
351
352 #[test]
353 fn range() {
354 // add event 1 and 2 to eset
355 let mut eset = BelowExSet::new();
356 eset.add_event(1);
357 eset.add_event(2);
358
359 // create range
360 let start = 1;
361 let end = 2;
362
363 // check it's the same
364 assert_eq!(eset, BelowExSet::from_event_range(start, end));
365 }
366}