use crate::EventSet;
use serde::{Deserialize, Serialize};
use std::cmp::{self, Ordering};
use std::collections::HashSet;
use std::fmt;
use std::iter::FromIterator;
#[derive(Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
pub struct BelowExSet {
max: u64,
exs: HashSet<u64>,
}
impl EventSet for BelowExSet {
type EventIter = EventIter;
fn new() -> Self {
BelowExSet {
max: 0,
exs: HashSet::new(),
}
}
fn next_event(&mut self) -> u64 {
debug_assert!(self.exs.is_empty());
self.max += 1;
self.max
}
fn add_event(&mut self, event: u64) -> bool {
match event.cmp(&self.max) {
Ordering::Less => {
self.exs.remove(&event)
}
Ordering::Greater => {
for new_ex in self.max + 1..event {
self.exs.insert(new_ex);
}
self.max = event;
true
}
Ordering::Equal => {
false
}
}
}
fn is_event(&self, event: u64) -> bool {
event <= self.max && !self.exs.contains(&event)
}
fn events(&self) -> (u64, Vec<u64>) {
(self.max, self.exs.clone().into_iter().collect())
}
fn frontier(&self) -> u64 {
if self.exs.is_empty() {
self.max
} else {
let mut exs: Vec<_> = self.exs.iter().collect();
exs.sort_unstable();
(**exs.iter().next().unwrap()) - 1
}
}
fn join(&mut self, other: &Self) {
let before = self.clone();
self.exs.retain(|ex| !other.is_event(*ex));
other
.exs
.iter()
.filter(|&&ex| !before.is_event(ex))
.for_each(|&ex| {
self.exs.insert(ex);
});
self.max = cmp::max(self.max, other.max);
}
fn meet(&mut self, _other: &Self) {
todo!("BelowExSet::meet not yet implemented")
}
fn subtracted(&self, _other: &Self) -> Vec<u64> {
todo!("BelowExSet::subtracted not yet implemented")
}
fn event_iter(self) -> Self::EventIter {
EventIter {
current: 0,
max: self.max,
exs: self.exs,
}
}
}
impl BelowExSet {
pub fn from<I: IntoIterator<Item = u64>>(max: u64, iter: I) -> Self {
BelowExSet {
max,
exs: HashSet::from_iter(iter),
}
}
}
pub struct EventIter {
current: u64,
max: u64,
exs: HashSet<u64>,
}
impl Iterator for EventIter {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
if self.current == self.max {
None
} else {
self.current += 1;
if self.exs.contains(&self.current) {
self.next()
} else {
Some(self.current)
}
}
}
}
impl fmt::Debug for BelowExSet {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.exs.is_empty() {
write!(f, "{}", self.max)
} else {
write!(f, "({} - {:?})", self.max, self.exs)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn range() {
let mut eset = BelowExSet::new();
eset.add_event(1);
eset.add_event(2);
let start = 1;
let end = 2;
assert_eq!(eset, BelowExSet::from_event_range(start, end));
}
}