#[doc(hidden)]
pub mod bounds;
#[doc(hidden)]
pub mod span;
use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::ops::RangeBounds;
use bounds::LeftBound;
use span::Span;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SpanMap<K, V>
where
K: Clone + Ord,
V: Clone + Ord,
{
m: BTreeMap<LeftBound<K>, BTreeSet<V>>,
}
impl<K, V> Default for SpanMap<K, V>
where
K: Clone + Ord,
V: Clone + Ord,
{
fn default() -> Self {
Self::new()
}
}
impl<K, V> SpanMap<K, V>
where
K: Clone + Ord,
V: Clone + Ord,
{
pub fn new() -> Self {
let mut m = BTreeMap::new();
m.insert(LeftBound::Unbounded, BTreeSet::new());
Self { m }
}
}
impl<K, V> SpanMap<K, V>
where
K: Clone + Ord,
V: Clone + Ord,
{
pub fn get(&self, key: &K) -> impl Iterator<Item = &V> {
let last_less_equal = self
.m
.range(..=LeftBound::Included(key.clone()))
.next_back()
.unwrap();
let (_bound, set) = last_less_equal;
set.iter()
}
pub fn insert<R>(&mut self, range: R, value: V)
where
R: RangeBounds<K>,
{
self.insert_span(Span::from_range(range), value);
}
pub fn remove<R>(&mut self, range: R, value: V)
where
R: RangeBounds<K>,
{
self.remove_span(Span::from_range(range), value);
}
#[doc(hidden)]
pub fn insert_span(&mut self, range: Span<K>, value: V) {
self.update_set_in_span(range, |set| {
set.insert(value.clone());
});
}
#[doc(hidden)]
pub fn remove_span(&mut self, range: Span<K>, value: V) {
self.update_set_in_span(range, |set| {
set.remove(&value);
});
}
fn update_set_in_span(&mut self, span: Span<K>, f: impl Fn(&mut BTreeSet<V>)) {
let start = span.left.clone();
self.ensure_boundary(start.clone());
let end = span.right.adjacent_left();
if let Some(end) = end.clone() {
self.ensure_boundary(end);
}
for (b, set) in self.m.range_mut(span.left..) {
if span.right < *b {
break;
}
f(set);
}
self.merge_adjacent_left(start);
if let Some(end) = end {
self.merge_adjacent_left(end);
}
}
fn ensure_boundary(&mut self, bound: LeftBound<K>) {
let last_less_equal = self.m.range(..=bound.clone()).next_back();
if let Some((b, set)) = last_less_equal {
if *b == bound {
} else {
self.m.insert(bound, set.clone());
}
} else {
self.m.insert(bound, BTreeSet::new());
}
}
fn merge_adjacent_left(&mut self, bound: LeftBound<K>) {
let mut it = self.m.range(..=bound.clone()).rev();
let Some((right_bound, right_set)) = it.next() else {
return;
};
let Some((_left_bound, left_set)) = it.next() else {
return;
};
if left_set == right_set {
let right_bound = right_bound.clone();
self.m.remove(&right_bound);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::bounds::RightBound;
#[test]
fn test_get_empty_map() {
let map = SpanMap::<i32, i32>::new();
assert_eq!(map.get(&5).count(), 0);
}
#[test]
fn test_get_single_range() {
let mut map = SpanMap::<i32, i32>::new();
map.insert_span(
Span::new(LeftBound::Included(1), RightBound::Included(5)),
10,
);
assert_eq!(map.get(&0).count(), 0);
let values: Vec<_> = map.get(&1).collect();
assert_eq!(values, vec![&10]);
let values: Vec<_> = map.get(&3).collect();
assert_eq!(values, vec![&10]);
let values: Vec<_> = map.get(&5).collect();
assert_eq!(values, vec![&10]);
assert_eq!(map.get(&6).count(), 0);
}
#[test]
fn test_get_overlapping_ranges() {
let mut map = SpanMap::<i32, i32>::new();
map.insert_span(
Span::new(LeftBound::Included(1), RightBound::Included(5)),
10,
);
map.insert_span(
Span::new(LeftBound::Included(3), RightBound::Included(7)),
20,
);
assert_eq!(map.get(&0).count(), 0);
let values: Vec<_> = map.get(&2).collect();
assert_eq!(values, vec![&10]);
let mut values: Vec<_> = map.get(&4).collect();
values.sort(); assert_eq!(values, vec![&10, &20]);
let mut values: Vec<_> = map.get(&5).collect();
values.sort(); assert_eq!(values, vec![&10, &20]);
let values: Vec<_> = map.get(&6).collect();
assert_eq!(values, vec![&20]);
assert_eq!(map.get(&8).count(), 0);
}
#[test]
fn test_get_multiple_values() {
let mut map = SpanMap::<i32, i32>::new();
map.insert_span(
Span::new(LeftBound::Included(1), RightBound::Included(5)),
10,
);
map.insert_span(
Span::new(LeftBound::Included(1), RightBound::Included(5)),
20,
);
map.insert_span(
Span::new(LeftBound::Included(1), RightBound::Included(5)),
30,
);
let mut values: Vec<_> = map.get(&3).collect();
values.sort();
assert_eq!(values, vec![&10, &20, &30]);
}
#[test]
fn test_get_with_excluded_bounds() {
let mut map = SpanMap::<i32, i32>::new();
map.insert_span(
Span::new(LeftBound::Excluded(1), RightBound::Excluded(5)),
10,
);
assert_eq!(map.get(&1).count(), 0);
assert_eq!(map.get(&5).count(), 0);
let values: Vec<_> = map.get(&3).collect();
assert_eq!(values, vec![&10]);
}
#[test]
fn test_get_with_unbounded() {
let mut map = SpanMap::<i32, i32>::new();
map.insert_span(Span::new(LeftBound::Unbounded, RightBound::Included(5)), 10);
let values: Vec<_> = map.get(&i32::MIN).collect();
assert_eq!(values, vec![&10]);
let values: Vec<_> = map.get(&0).collect();
assert_eq!(values, vec![&10]);
assert_eq!(map.get(&6).count(), 0);
}
#[test]
fn test_get_point_range() {
let mut map = SpanMap::<i32, i32>::new();
map.insert_span(
Span::new(LeftBound::Included(5), RightBound::Included(5)),
10,
);
assert_eq!(map.get(&4).count(), 0);
let values: Vec<_> = map.get(&5).collect();
assert_eq!(values, vec![&10]);
assert_eq!(map.get(&6).count(), 0);
}
#[test]
fn test_insert_std_range() {
let mut map = SpanMap::<i32, &str>::new();
map.insert(1..=5, "a");
map.insert(3..7, "b");
assert_eq!(map.get(&0).count(), 0);
assert_eq!(map.get(&1).copied().collect::<Vec<_>>(), vec!["a"]);
assert_eq!(map.get(&3).copied().collect::<Vec<_>>(), vec!["a", "b"]);
assert_eq!(map.get(&6).copied().collect::<Vec<_>>(), vec!["b"]);
assert_eq!(map.get(&7).count(), 0);
}
#[test]
fn test_insert_empty_map() {
let mut map = SpanMap::<i32, i32>::new();
map.insert_span(
Span::new(LeftBound::Included(1), RightBound::Included(5)),
10,
);
assert_eq!(map.m.len(), 3);
assert!(map.m.contains_key(&LeftBound::Included(1)));
assert!(map.m.contains_key(&LeftBound::Excluded(5))); assert_eq!(
map.m.get(&LeftBound::Included(1)).unwrap(),
&BTreeSet::from([10])
);
}
#[test]
fn test_insert_overlapping_ranges() {
let mut map = SpanMap::<i32, i32>::new();
map.insert_span(
Span::new(LeftBound::Included(1), RightBound::Included(5)),
10,
);
map.insert_span(
Span::new(LeftBound::Included(3), RightBound::Included(7)),
20,
);
assert_eq!(
map.m.get(&LeftBound::Included(1)).unwrap(),
&BTreeSet::from([10])
);
assert_eq!(
map.m.get(&LeftBound::Included(3)).unwrap(),
&BTreeSet::from([10, 20])
);
assert_eq!(
map.m.get(&LeftBound::Excluded(5)).unwrap(),
&BTreeSet::from([20])
);
assert_eq!(
map.m.get(&LeftBound::Excluded(7)).unwrap(),
&BTreeSet::from([])
);
}
#[test]
fn test_insert_adjacent_ranges() {
let mut map = SpanMap::<i32, i32>::new();
map.insert_span(
Span::new(LeftBound::Included(1), RightBound::Included(5)),
10,
);
map.insert_span(
Span::new(LeftBound::Excluded(5), RightBound::Included(10)),
10,
);
assert_eq!(map.m.len(), 3); assert_eq!(
map.m.get(&LeftBound::Included(1)).unwrap(),
&BTreeSet::from([10])
);
}
#[test]
fn test_insert_with_excluded_bounds() {
let mut map = SpanMap::<i32, i32>::new();
map.insert_span(
Span::new(LeftBound::Excluded(1), RightBound::Excluded(5)),
10,
);
assert!(map.m.contains_key(&LeftBound::Excluded(1)));
assert!(map.m.contains_key(&LeftBound::Included(5)));
}
#[test]
fn test_insert_with_unbounded() {
let mut map = SpanMap::<i32, i32>::new();
map.insert_span(Span::new(LeftBound::Unbounded, RightBound::Included(5)), 10);
assert!(map.m.contains_key(&LeftBound::Unbounded));
assert!(map.m.contains_key(&LeftBound::Excluded(5)));
map.insert_span(
Span::new(LeftBound::Included(10), RightBound::Unbounded),
20,
);
assert!(map.m.contains_key(&LeftBound::Included(10)));
}
#[test]
fn test_insert_multiple_values() {
let mut map = SpanMap::<i32, i32>::new();
map.insert_span(
Span::new(LeftBound::Included(1), RightBound::Included(10)),
10,
);
map.insert_span(
Span::new(LeftBound::Included(1), RightBound::Included(10)),
20,
);
map.insert_span(
Span::new(LeftBound::Included(1), RightBound::Included(10)),
30,
);
assert_eq!(
map.m.get(&LeftBound::Included(1)).unwrap(),
&BTreeSet::from([10, 20, 30])
);
}
#[test]
fn test_insert_point_range() {
let mut map = SpanMap::<i32, i32>::new();
map.insert_span(
Span::new(LeftBound::Included(5), RightBound::Included(5)),
10,
);
assert!(map.m.contains_key(&LeftBound::Included(5)));
assert!(map.m.contains_key(&LeftBound::Excluded(5)));
assert_eq!(
map.m.get(&LeftBound::Included(5)).unwrap(),
&BTreeSet::from([10])
);
}
#[test]
fn test_insert_with_string_keys() {
let mut map = SpanMap::<String, i32>::new();
map.insert_span(
Span::new(
LeftBound::Included("a".to_string()),
RightBound::Included("c".to_string()),
),
10,
);
assert!(map.m.contains_key(&LeftBound::Included("a".to_string())));
assert!(map.m.contains_key(&LeftBound::Excluded("c".to_string()))); assert_eq!(
map.m.get(&LeftBound::Included("a".to_string())).unwrap(),
&BTreeSet::from([10])
);
}
#[test]
fn test_remove_std_range() {
let mut map = SpanMap::<i32, &str>::new();
map.insert(1..=10, "a");
map.insert(1..=10, "b");
map.remove(3..=7, "a");
assert_eq!(map.get(&2).copied().collect::<Vec<_>>(), vec!["a", "b"]);
assert_eq!(map.get(&5).copied().collect::<Vec<_>>(), vec!["b"]);
assert_eq!(map.get(&8).copied().collect::<Vec<_>>(), vec!["a", "b"]);
}
#[test]
fn test_remove_empty_map() {
let mut map = SpanMap::<i32, i32>::new();
map.remove_span(
Span::new(LeftBound::Included(1), RightBound::Included(5)),
10,
);
assert_eq!(map.m.len(), 1); assert_eq!(map.get(&1).collect::<Vec<_>>(), Vec::<&i32>::new());
}
#[test]
fn test_remove_single_value() {
let mut map = SpanMap::<i32, i32>::new();
map.insert_span(
Span::new(LeftBound::Included(1), RightBound::Included(5)),
10,
);
map.remove_span(
Span::new(LeftBound::Included(1), RightBound::Included(5)),
10,
);
assert_eq!(map.m.get(&LeftBound::Included(1)), None);
assert_eq!(map.m.get(&LeftBound::Excluded(5)), None);
}
#[test]
fn test_remove_partial_range() {
let mut map = SpanMap::<i32, i32>::new();
map.insert_span(
Span::new(LeftBound::Included(1), RightBound::Included(5)),
10,
);
map.remove_span(
Span::new(LeftBound::Included(2), RightBound::Included(4)),
10,
);
assert_eq!(
map.m.get(&LeftBound::Included(1)).unwrap(),
&BTreeSet::from([10])
);
assert_eq!(
map.m.get(&LeftBound::Included(2)).unwrap(),
&BTreeSet::new()
);
assert_eq!(
map.m.get(&LeftBound::Excluded(4)).unwrap(),
&BTreeSet::from([10])
);
}
#[test]
fn test_remove_from_multiple_values() {
let mut map = SpanMap::<i32, i32>::new();
map.insert_span(
Span::new(LeftBound::Included(1), RightBound::Included(5)),
10,
);
map.insert_span(
Span::new(LeftBound::Included(1), RightBound::Included(5)),
20,
);
map.insert_span(
Span::new(LeftBound::Included(1), RightBound::Included(5)),
30,
);
map.remove_span(
Span::new(LeftBound::Included(1), RightBound::Included(5)),
20,
);
assert_eq!(
map.m.get(&LeftBound::Included(1)).unwrap(),
&BTreeSet::from([10, 30])
);
}
#[test]
fn test_remove_overlapping_ranges() {
let mut map = SpanMap::<i32, i32>::new();
map.insert_span(
Span::new(LeftBound::Included(1), RightBound::Included(5)),
10,
);
map.insert_span(
Span::new(LeftBound::Included(3), RightBound::Included(7)),
20,
);
map.remove_span(
Span::new(LeftBound::Included(1), RightBound::Included(5)),
10,
);
assert_eq!(map.m.get(&LeftBound::Included(1)), None);
assert_eq!(
map.m.get(&LeftBound::Included(3)).unwrap(),
&BTreeSet::from([20])
);
}
#[test]
fn test_remove_with_excluded_bounds() {
let mut map = SpanMap::<i32, i32>::new();
map.insert_span(
Span::new(LeftBound::Excluded(1), RightBound::Excluded(5)),
10,
);
map.remove_span(
Span::new(LeftBound::Excluded(1), RightBound::Excluded(5)),
10,
);
assert_eq!(map.m.get(&LeftBound::Excluded(1)), None);
assert_eq!(map.m.get(&LeftBound::Included(5)), None);
}
#[test]
fn test_remove_with_unbounded() {
let mut map = SpanMap::<i32, i32>::new();
map.insert_span(Span::new(LeftBound::Unbounded, RightBound::Included(5)), 10);
map.remove_span(Span::new(LeftBound::Unbounded, RightBound::Included(5)), 10);
assert_eq!(map.m.get(&LeftBound::Unbounded).unwrap(), &BTreeSet::new());
assert_eq!(map.m.get(&LeftBound::Excluded(5)), None);
}
#[test]
fn test_remove_nonexistent_value() {
let mut map = SpanMap::<i32, i32>::new();
map.insert_span(
Span::new(LeftBound::Included(1), RightBound::Included(5)),
10,
);
map.remove_span(
Span::new(LeftBound::Included(1), RightBound::Included(5)),
20,
);
assert_eq!(
map.m.get(&LeftBound::Included(1)).unwrap(),
&BTreeSet::from([10])
);
}
#[test]
fn test_ensure_boundary_empty_map() {
use LeftBound::*;
let mut map = SpanMap::<i32, i32>::new();
map.ensure_boundary(Included(5));
assert_eq!(map.m.len(), 2);
assert!(map.m.contains_key(&Included(5)));
assert!(map.m.get(&Included(5)).unwrap().is_empty());
}
#[test]
fn test_ensure_boundary_existing_boundary() {
use LeftBound::*;
let mut map = SpanMap::<i32, i32>::new();
map.m.insert(Included(5), BTreeSet::from([1]));
map.ensure_boundary(Included(5));
assert_eq!(map.m.len(), 2);
assert_eq!(map.m.get(&Included(5)).unwrap(), &BTreeSet::from([1]));
}
#[test]
fn test_ensure_boundary_split_point() {
use LeftBound::*;
let mut map = SpanMap::<i32, i32>::new();
map.m.insert(Included(3), BTreeSet::from([1, 2]));
map.ensure_boundary(Included(5));
assert_eq!(map.m.len(), 3);
assert_eq!(map.m.get(&Unbounded).unwrap(), &BTreeSet::from([]));
assert_eq!(map.m.get(&Included(3)).unwrap(), &BTreeSet::from([1, 2]));
assert_eq!(map.m.get(&Included(5)).unwrap(), &BTreeSet::from([1, 2]));
}
#[test]
fn test_ensure_boundary_multiple_existing() {
use LeftBound::*;
let mut map = SpanMap::<i32, i32>::new();
map.m.insert(Included(1), BTreeSet::from([1]));
map.m.insert(Included(3), BTreeSet::from([2]));
map.m.insert(Included(5), BTreeSet::from([3]));
map.ensure_boundary(Included(2));
assert_eq!(map.m.len(), 5);
assert_eq!(map.m.get(&Unbounded).unwrap(), &BTreeSet::from([]));
assert_eq!(map.m.get(&Included(1)).unwrap(), &BTreeSet::from([1]));
assert_eq!(map.m.get(&Included(2)).unwrap(), &BTreeSet::from([1]));
assert_eq!(map.m.get(&Included(3)).unwrap(), &BTreeSet::from([2]));
assert_eq!(map.m.get(&Included(5)).unwrap(), &BTreeSet::from([3]));
}
#[test]
fn test_ensure_boundary_different_bound_types() {
use LeftBound::*;
let mut map = SpanMap::<i32, i32>::new();
map.ensure_boundary(Excluded(5));
assert!(map.m.contains_key(&Excluded(5)));
map.ensure_boundary(Included(5));
assert!(map.m.contains_key(&Included(5)));
assert_eq!(map.m.len(), 3);
}
#[test]
fn test_ensure_boundary_unbounded() {
use LeftBound::*;
let mut map = SpanMap::<i32, i32>::new();
map.ensure_boundary(Unbounded);
assert!(map.m.contains_key(&Unbounded));
assert_eq!(map.m.len(), 1);
map.ensure_boundary(Included(5));
assert_eq!(map.m.len(), 2);
assert!(map.m.contains_key(&Included(5)));
}
#[test]
fn test_ensure_boundary_ordering() {
use LeftBound::*;
let mut map = SpanMap::<i32, i32>::new();
map.ensure_boundary(Included(5));
map.ensure_boundary(Included(1));
map.ensure_boundary(Included(3));
let keys: Vec<_> = map.m.keys().cloned().collect();
assert_eq!(keys, vec![Unbounded, Included(1), Included(3), Included(5)]);
}
#[test]
fn test_ensure_boundary_with_string_keys() {
use LeftBound::*;
let mut map = SpanMap::<String, i32>::new();
map.ensure_boundary(Included("a".to_string()));
assert!(map.m.contains_key(&Included("a".to_string())));
map.ensure_boundary(Included("b".to_string()));
assert_eq!(map.m.len(), 3);
assert!(map.m.contains_key(&Included("b".to_string())));
}
#[test]
fn test_merge_adjacent_left() {
use LeftBound::*;
let mut map = SpanMap::new();
let set12: BTreeSet<i32> = vec![1, 2].into_iter().collect();
let set23: BTreeSet<i32> = vec![2, 3].into_iter().collect();
map.m.insert(Unbounded, set12.clone());
map.m.insert(Included(5), set12.clone());
map.merge_adjacent_left(Included(5));
assert_eq!(map.m.len(), 1);
assert_eq!(map.m.get(&Unbounded), Some(&set12));
let mut map = SpanMap::new();
map.m.insert(Unbounded, set12.clone());
map.m.insert(Included(5), set23.clone());
map.merge_adjacent_left(Included(5));
assert_eq!(map.m.len(), 2);
assert!(map.m.contains_key(&Included(5)));
let mut map = SpanMap::new();
map.m.insert(Included(5), set12.clone());
map.merge_adjacent_left(Included(5));
assert_eq!(map.m.len(), 2);
assert!(map.m.contains_key(&Included(5)));
let mut map: SpanMap<i32, i32> = SpanMap::new();
map.merge_adjacent_left(Included(5));
assert_eq!(map.m.len(), 1);
let mut map = SpanMap::new();
map.m.insert(Unbounded, set12.clone());
map.m.insert(Included(5), set12.clone());
map.m.insert(Included(10), set23);
map.merge_adjacent_left(Included(5));
assert_eq!(map.m.len(), 2);
assert!(!map.m.contains_key(&Included(5)));
assert!(map.m.contains_key(&Included(10)));
}
}