use std::{
collections::BTreeMap,
ops::{Bound, Range, RangeBounds},
};
use crate::{interval::Interval, IndexType};
#[derive(Debug, Clone)]
pub struct IntervalMap<Ix = u32, V = ()> {
map: BTreeMap<Ix, (Ix, V)>,
}
impl<Ix: IndexType, V> Default for IntervalMap<Ix, V> {
fn default() -> Self {
Self::new()
}
}
impl<Ix: IndexType, V> IntervalMap<Ix, V> {
#[inline]
pub fn new() -> Self {
IntervalMap {
map: BTreeMap::new(),
}
}
#[inline]
pub fn len(&self) -> usize {
self.map.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
#[inline]
pub fn clear(&mut self) {
self.map.clear();
}
#[inline]
pub fn contains(&self, point: Ix) -> bool {
self.get(point).is_some()
}
pub fn get(&self, point: Ix) -> Option<&V> {
self.map
.range(..=point)
.next_back()
.filter(|(&start, &(end, _))| {
let interval = Interval::new(start, end);
interval.contains_point(point)
})
.map(|(_, (_, v))| v)
}
pub fn get_mut(&mut self, point: Ix) -> Option<&mut V> {
let start = self
.map
.range(..=point)
.next_back()
.filter(|(&start, &(end, _))| {
let interval = Interval::new(start, end);
interval.contains_point(point)
})
.map(|(&start, _)| start)?;
self.map.get_mut(&start).map(|(_, v)| v)
}
pub fn get_interval(&self, point: Ix) -> Option<(Range<Ix>, &V)> {
self.map
.range(..=point)
.next_back()
.filter(|(&start, &(end, _))| {
let interval = Interval::new(start, end);
interval.contains_point(point)
})
.map(|(&start, (end, v))| (start..*end, v))
}
pub fn iter(&self) -> Iter<'_, Ix, V> {
Iter {
inner: self.map.iter(),
}
}
pub fn first(&self) -> Option<(Range<Ix>, &V)> {
self.map
.iter()
.next()
.map(|(&start, (end, v))| (start..*end, v))
}
pub fn last(&self) -> Option<(Range<Ix>, &V)> {
self.map
.iter()
.next_back()
.map(|(&start, (end, v))| (start..*end, v))
}
pub fn span(&self) -> Option<Range<Ix>> {
let (first_range, _) = self.first()?;
let (last_range, _) = self.last()?;
Some(first_range.start..last_range.end)
}
pub(crate) fn remove_by_start(&mut self, start: Ix) {
self.map.remove(&start);
}
pub(crate) fn split_at(&mut self, point: Ix)
where
V: Clone,
{
if let Some((&start, &(end, ref value))) = self
.map
.range(..=point)
.next_back()
.filter(|(&start, &(end, _))| start < point && point < end)
{
let value = value.clone();
self.map.remove(&start);
self.map.insert(start, (point, value.clone()));
self.map.insert(point, (end, value));
}
}
fn range_to_interval<R: RangeBounds<Ix>>(&self, range: R) -> Interval<Ix>
where
Ix: num_traits::One + num_traits::Bounded,
{
let start = match range.start_bound() {
Bound::Included(&s) => s,
Bound::Excluded(&s) => s + Ix::one(),
Bound::Unbounded => Ix::min_value(),
};
let end = match range.end_bound() {
Bound::Included(&e) => e + Ix::one(),
Bound::Excluded(&e) => e,
Bound::Unbounded => Ix::max_value(),
};
Interval::new(start, end)
}
}
impl<Ix: IndexType + num_traits::One + num_traits::Bounded, V> IntervalMap<Ix, V> {
pub fn overlaps<R: RangeBounds<Ix>>(&self, range: R) -> bool {
let interval = self.range_to_interval(range);
if interval.is_empty() {
return false;
}
if let Some((_, &(end, _))) = self.map.range(..interval.start).next_back() {
if end > interval.start {
return true;
}
}
self.map
.range(interval.start..interval.end)
.next()
.is_some()
}
pub fn covers<R: RangeBounds<Ix>>(&self, range: R) -> bool {
let interval = self.range_to_interval(range);
if interval.is_empty() {
return true;
}
let mut covered_until = interval.start;
if let Some((_, &(end, _))) = self.map.range(..=interval.start).next_back() {
if end > interval.start {
covered_until = end;
}
}
if covered_until <= interval.start {
if let Some(&(end, _)) = self.map.get(&interval.start) {
covered_until = end;
}
else {
return false;
}
}
for (&start, &(end, _)) in self.map.range(interval.start..interval.end) {
if start > covered_until {
return false;
}
if end > covered_until {
covered_until = end;
}
}
covered_until >= interval.end
}
}
impl<Ix: IndexType + num_traits::One + num_traits::Bounded, V: Clone + PartialEq>
IntervalMap<Ix, V>
{
pub fn insert<R: RangeBounds<Ix>>(&mut self, range: R, value: V) {
let interval = self.range_to_interval(range);
if interval.is_empty() {
return;
}
self.insert_internal(interval, value);
}
fn insert_internal(&mut self, interval: Interval<Ix>, value: V) {
let overlapping = self.find_overlapping_or_touching(interval);
let mut fragments: Vec<(Interval<Ix>, V)> = Vec::new();
for (start, _) in overlapping {
if let Some((old_end, old_value)) = self.map.remove(&start) {
let old_interval = Interval::new(start, old_end);
if old_interval.start < interval.start {
fragments.push((
Interval::new(old_interval.start, interval.start),
old_value.clone(),
));
}
if old_interval.end > interval.end {
fragments.push((Interval::new(interval.end, old_interval.end), old_value));
}
}
}
self.map
.insert(interval.start, (interval.end, value.clone()));
for (frag_interval, frag_value) in fragments {
self.map
.insert(frag_interval.start, (frag_interval.end, frag_value));
}
self.merge_neighbors(interval.start, &value);
}
pub fn remove<R: RangeBounds<Ix>>(&mut self, range: R) {
let interval = self.range_to_interval(range);
if interval.is_empty() {
return;
}
self.remove_internal(interval);
}
fn remove_internal(&mut self, interval: Interval<Ix>) {
let overlapping = self.find_overlapping(interval);
for (start, _) in overlapping {
if let Some((old_end, old_value)) = self.map.remove(&start) {
let old_interval = Interval::new(start, old_end);
if old_interval.start < interval.start {
self.map
.insert(old_interval.start, (interval.start, old_value.clone()));
}
if old_interval.end > interval.end {
self.map.insert(interval.end, (old_interval.end, old_value));
}
}
}
}
fn find_overlapping(&self, interval: Interval<Ix>) -> Vec<(Ix, Ix)> {
let mut result = Vec::new();
if let Some((&start, &(end, _))) = self.map.range(..interval.start).next_back() {
if end > interval.start {
result.push((start, end));
}
}
for (&start, &(end, _)) in self.map.range(interval.start..interval.end) {
result.push((start, end));
}
result
}
fn find_overlapping_or_touching(&self, interval: Interval<Ix>) -> Vec<(Ix, Ix)> {
let mut result = Vec::new();
if let Some((&start, &(end, _))) = self.map.range(..interval.start).next_back() {
if end >= interval.start {
result.push((start, end));
}
}
for (&start, &(end, _)) in self.map.range(interval.start..=interval.end) {
result.push((start, end));
}
result
}
fn merge_neighbors(&mut self, start: Ix, value: &V) {
let Some(&(end, _)) = self.map.get(&start)
else {
return;
};
if let Some(&(next_end, ref next_value)) = self.map.get(&end) {
if next_value == value {
self.map.remove(&end);
self.map.insert(start, (next_end, value.clone()));
self.merge_neighbors(start, value);
return;
}
}
if let Some((&prev_start, &(prev_end, ref prev_value))) =
self.map.range(..start).next_back()
{
if prev_end == start && prev_value == value {
let current_end = self.map.get(&start).map(|(e, _)| *e).unwrap_or(end);
self.map.remove(&start);
self.map.insert(prev_start, (current_end, value.clone()));
}
}
}
}
pub struct Iter<'a, Ix, V> {
inner: std::collections::btree_map::Iter<'a, Ix, (Ix, V)>,
}
impl<'a, Ix: IndexType, V> Iterator for Iter<'a, Ix, V> {
type Item = (Range<Ix>, &'a V);
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|(&start, (end, v))| (start..*end, v))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, Ix: IndexType, V> ExactSizeIterator for Iter<'a, Ix, V> {}
impl<'a, Ix: IndexType, V> DoubleEndedIterator for Iter<'a, Ix, V> {
fn next_back(&mut self) -> Option<Self::Item> {
self.inner
.next_back()
.map(|(&start, (end, v))| (start..*end, v))
}
}
impl<'a, Ix: IndexType, V> IntoIterator for &'a IntervalMap<Ix, V> {
type Item = (Range<Ix>, &'a V);
type IntoIter = Iter<'a, Ix, V>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
pub struct IntoIter<Ix, V> {
inner: std::collections::btree_map::IntoIter<Ix, (Ix, V)>,
}
impl<Ix: IndexType, V> Iterator for IntoIter<Ix, V> {
type Item = (Range<Ix>, V);
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|(start, (end, v))| (start..end, v))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<Ix: IndexType, V> ExactSizeIterator for IntoIter<Ix, V> {}
impl<Ix: IndexType, V> IntoIterator for IntervalMap<Ix, V> {
type Item = (Range<Ix>, V);
type IntoIter = IntoIter<Ix, V>;
fn into_iter(self) -> Self::IntoIter {
IntoIter {
inner: self.map.into_iter(),
}
}
}
pub enum Entry<'a, Ix: IndexType, V> {
Vacant(VacantEntry<'a, Ix, V>),
Occupied(OccupiedEntry<'a, Ix, V>),
}
pub struct VacantEntry<'a, Ix: IndexType, V> {
map: &'a mut IntervalMap<Ix, V>,
point: Ix,
}
pub struct OccupiedEntry<'a, Ix: IndexType, V> {
map: &'a mut IntervalMap<Ix, V>,
interval_start: Ix,
}
impl<Ix: IndexType + num_traits::One + num_traits::Bounded, V: Clone + PartialEq>
IntervalMap<Ix, V>
{
pub fn entry(&mut self, point: Ix) -> Entry<'_, Ix, V> {
let interval_start = self
.map
.range(..=point)
.next_back()
.filter(|(&start, &(end, _))| {
let interval = Interval::new(start, end);
interval.contains_point(point)
})
.map(|(&start, _)| start);
match interval_start {
Some(start) => Entry::Occupied(OccupiedEntry {
map: self,
interval_start: start,
}),
None => Entry::Vacant(VacantEntry { map: self, point }),
}
}
}
impl<'a, Ix: IndexType + num_traits::One + num_traits::Bounded, V: Clone + PartialEq>
Entry<'a, Ix, V>
{
pub fn get(&self) -> Option<&V> {
match self {
Entry::Occupied(e) => Some(e.get()),
Entry::Vacant(_) => None,
}
}
pub fn or_insert<R: RangeBounds<Ix>>(self, range: R, default: V) -> &'a mut V {
match self {
Entry::Occupied(e) => e.into_mut(),
Entry::Vacant(e) => e.insert(range, default),
}
}
pub fn or_insert_with<R: RangeBounds<Ix>, F: FnOnce() -> V>(
self,
range: R,
default: F,
) -> &'a mut V {
match self {
Entry::Occupied(e) => e.into_mut(),
Entry::Vacant(e) => e.insert(range, default()),
}
}
}
impl<'a, Ix: IndexType, V> OccupiedEntry<'a, Ix, V> {
pub fn get(&self) -> &V {
&self.map.map.get(&self.interval_start).unwrap().1
}
pub fn get_mut(&mut self) -> &mut V {
&mut self.map.map.get_mut(&self.interval_start).unwrap().1
}
pub fn into_mut(self) -> &'a mut V {
&mut self.map.map.get_mut(&self.interval_start).unwrap().1
}
pub fn interval(&self) -> Range<Ix> {
let (end, _) = self.map.map.get(&self.interval_start).unwrap();
self.interval_start..*end
}
}
impl<'a, Ix: IndexType + num_traits::One + num_traits::Bounded, V: Clone + PartialEq>
VacantEntry<'a, Ix, V>
{
pub fn point(&self) -> Ix {
self.point
}
pub fn insert<R: RangeBounds<Ix>>(self, range: R, value: V) -> &'a mut V {
let interval = self.map.range_to_interval(range);
assert!(
interval.contains_point(self.point),
"inserted range must contain the queried point"
);
self.map.insert_internal(interval, value);
self.map.get_mut(self.point).unwrap()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_map_is_empty() {
let map: IntervalMap<u32, i32> = IntervalMap::new();
assert!(map.is_empty());
assert_eq!(map.len(), 0);
}
#[test]
fn test_insert_single_interval() {
let mut map = IntervalMap::new();
map.insert(0..10, "value");
assert_eq!(map.len(), 1);
assert_eq!(map.get(0), Some(&"value"));
assert_eq!(map.get(5), Some(&"value"));
assert_eq!(map.get(9), Some(&"value"));
assert_eq!(map.get(10), None);
}
#[test]
fn test_insert_non_overlapping() {
let mut map = IntervalMap::new();
map.insert(0..10, "a");
map.insert(20..30, "b");
assert_eq!(map.len(), 2);
assert_eq!(map.get(5), Some(&"a"));
assert_eq!(map.get(15), None);
assert_eq!(map.get(25), Some(&"b"));
}
#[test]
fn test_insert_overlapping_splits() {
let mut map = IntervalMap::new();
map.insert(0..10, "a");
map.insert(5..15, "b");
assert_eq!(map.len(), 2);
assert_eq!(map.get(3), Some(&"a"));
assert_eq!(map.get(5), Some(&"b"));
assert_eq!(map.get(12), Some(&"b"));
}
#[test]
fn test_insert_completely_overlapping() {
let mut map = IntervalMap::new();
map.insert(0..20, "a");
map.insert(5..15, "b");
assert_eq!(map.len(), 3);
assert_eq!(map.get(3), Some(&"a"));
assert_eq!(map.get(10), Some(&"b"));
assert_eq!(map.get(17), Some(&"a"));
}
#[test]
fn test_insert_merges_same_value() {
let mut map = IntervalMap::new();
map.insert(0..10, "a");
map.insert(10..20, "a");
assert_eq!(map.len(), 1);
assert_eq!(map.get(5), Some(&"a"));
assert_eq!(map.get(15), Some(&"a"));
}
#[test]
fn test_remove_middle() {
let mut map = IntervalMap::new();
map.insert(0..20, "value");
map.remove(5..15);
assert_eq!(map.len(), 2);
assert!(map.contains(3));
assert!(!map.contains(10));
assert!(map.contains(17));
}
#[test]
fn test_remove_entire() {
let mut map = IntervalMap::new();
map.insert(5..15, "value");
map.remove(0..20);
assert!(map.is_empty());
}
#[test]
fn test_get_interval() {
let mut map = IntervalMap::new();
map.insert(5..15, "value");
let (range, value) = map.get_interval(10).unwrap();
assert_eq!(range, 5..15);
assert_eq!(*value, "value");
assert!(map.get_interval(20).is_none());
}
#[test]
fn test_clear() {
let mut map = IntervalMap::new();
map.insert(0..10, "a");
map.insert(20..30, "b");
map.clear();
assert!(map.is_empty());
}
#[test]
fn test_iter() {
let mut map = IntervalMap::new();
map.insert(0..10, "a");
map.insert(20..30, "b");
let entries: Vec<_> = map.iter().collect();
assert_eq!(entries.len(), 2);
assert_eq!(entries[0], (0..10, &"a"));
assert_eq!(entries[1], (20..30, &"b"));
}
#[test]
fn test_entry_vacant() {
let mut map: IntervalMap<u32, i32> = IntervalMap::new();
match map.entry(5) {
Entry::Vacant(e) => {
e.insert(0..10, 42);
}
Entry::Occupied(_) => panic!("expected vacant"),
}
assert_eq!(map.get(5), Some(&42));
}
#[test]
fn test_entry_occupied() {
let mut map = IntervalMap::new();
map.insert(0..10, 42);
match map.entry(5) {
Entry::Vacant(_) => panic!("expected occupied"),
Entry::Occupied(mut e) => {
assert_eq!(*e.get(), 42);
*e.get_mut() = 100;
}
}
assert_eq!(map.get(5), Some(&100));
}
#[test]
fn test_entry_or_insert() {
let mut map: IntervalMap<u32, i32> = IntervalMap::new();
let val = map.entry(5).or_insert(0..10, 42);
assert_eq!(*val, 42);
let val = map.entry(5).or_insert(0..10, 100);
assert_eq!(*val, 42); }
}