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}