use crate::EventSet;
use serde::{Deserialize, Serialize};
use std::cmp;
use std::cmp::Ordering;
use std::collections::btree_map::{self, BTreeMap};
use std::collections::HashMap;
use std::fmt;
use std::iter::FromIterator;
#[derive(Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
pub struct AboveRangeSet {
max: u64,
ranges: Ranges,
}
#[derive(Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
pub struct Ranges {
ranges: HashMap<u64, u64>,
}
impl EventSet for AboveRangeSet {
type EventIter = EventIter;
fn new() -> Self {
AboveRangeSet {
max: 0,
ranges: Ranges::new(),
}
}
fn next_event(&mut self) -> u64 {
debug_assert!(self.ranges.is_empty());
self.max += 1;
self.max
}
fn add_event(&mut self, event: u64) -> bool {
let next_max = self.max + 1;
match event.cmp(&next_max) {
Ordering::Equal => {
self.max = event;
self.try_compress();
true
}
Ordering::Greater => {
self.ranges.add(event, event);
true
}
Ordering::Less => {
false
}
}
}
fn add_event_range(&mut self, start: u64, end: u64) -> bool {
if start <= self.max + 1 && end > self.max {
self.max = end;
self.try_compress();
true
} else if start > self.max + 1 {
self.ranges.add(start, end);
true
} else {
false
}
}
fn is_event(&self, event: u64) -> bool {
event <= self.max || self.ranges.contains(&event)
}
fn events(&self) -> (u64, Vec<u64>) {
(self.max, self.ranges.clone().event_iter().collect())
}
fn frontier(&self) -> u64 {
self.max
}
fn join(&mut self, other: &Self) {
self.max = cmp::max(self.max, other.max);
self.ranges.join(&other.ranges, self.max);
self.try_compress();
}
fn meet(&mut self, _other: &Self) {
todo!("AboveRangeSet::meet not yet implemented")
}
fn subtracted(&self, _other: &Self) -> Vec<u64> {
todo!("AboveRangeSet::subtracted not yet implemented")
}
fn event_iter(self) -> Self::EventIter {
EventIter {
current: 0,
max: self.max,
ranges: self.ranges.event_iter(),
}
}
}
impl AboveRangeSet {
fn try_compress(&mut self) {
while let Some(new_max) = self.ranges.try_drop(self.max + 1) {
self.max = new_max;
}
}
pub fn from<I: IntoIterator<Item = u64>>(max: u64, iter: I) -> Self {
let ranges = Ranges::from::<I>(iter);
AboveRangeSet { max, ranges }
}
}
pub struct EventIter {
current: u64,
max: u64,
ranges: RangesIter,
}
impl Iterator for EventIter {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
if self.current == self.max {
self.ranges.next()
} else {
self.current += 1;
Some(self.current)
}
}
}
impl fmt::Debug for AboveRangeSet {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.ranges.is_empty() {
write!(f, "{}", self.max)
} else {
write!(f, "({} + {:?})", self.max, self.ranges)
}
}
}
impl Ranges {
fn new() -> Self {
Ranges {
ranges: HashMap::new(),
}
}
fn is_empty(&self) -> bool {
self.ranges.is_empty()
}
fn add(&mut self, start: u64, end: u64) {
self.ranges.insert(start, end);
}
fn contains(&self, event: &u64) -> bool {
self.ranges
.iter()
.any(|(start, end)| start <= event && event <= end)
}
fn join(&mut self, other: &Self, max: u64) {
let mut result = Ranges::new();
for event in self.clone().event_iter() {
if event > max {
result.add(event, event);
}
}
for event in other.clone().event_iter() {
if event > max && !result.contains(&event) {
result.add(event, event);
}
}
self.ranges = result.ranges;
}
fn event_iter(self) -> RangesIter {
RangesIter {
current: None,
ranges: BTreeMap::from_iter(self.ranges).into_iter(),
}
}
fn from<I: IntoIterator<Item = u64>>(iter: I) -> Self {
let mut result = Ranges::new();
for event in iter {
result.add(event, event);
}
result
}
fn try_drop(&mut self, next: u64) -> Option<u64> {
self.ranges.remove(&next)
}
}
pub struct RangesIter {
current: Option<(u64, u64)>,
ranges: btree_map::IntoIter<u64, u64>,
}
impl Iterator for RangesIter {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
if let Some((val, end)) = self.current {
if val <= end {
self.current = Some((val + 1, end));
return Some(val);
}
}
self.current = self.ranges.next();
if self.current.is_none() {
None
} else {
self.next()
}
}
}
impl fmt::Debug for Ranges {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self.ranges)
}
}