use std::ops::RangeInclusive;
#[derive(Debug, Clone, Default)]
pub struct SortedRangeMap<K, V> {
entries: Vec<(RangeInclusive<K>, V)>,
max_end: Vec<K>,
}
impl<K: Ord + Copy, V> SortedRangeMap<K, V> {
pub fn new(mut entries: Vec<(RangeInclusive<K>, V)>) -> Self {
entries.sort_by(|a, b| a.0.start().cmp(b.0.start()));
let mut max_end = Vec::with_capacity(entries.len());
let mut running_max = None::<K>;
for (range, _) in &entries {
let new_max = match running_max {
Some(m) => m.max(*range.end()),
None => *range.end(),
};
running_max = Some(new_max);
max_end.push(new_max);
}
Self { entries, max_end }
}
#[inline]
pub fn query(&self, query: RangeInclusive<K>) -> OverlapIter<'_, K, V> {
let start_idx = self.find_first_possible(&query);
OverlapIter {
map: self,
query,
idx: start_idx,
}
}
#[inline]
fn find_first_possible(&self, query: &RangeInclusive<K>) -> usize {
self.max_end.partition_point(|max| *max < *query.start())
}
#[inline]
#[cfg_attr(not(test), expect(dead_code))] pub fn len(&self) -> usize {
self.entries.len()
}
#[inline]
#[cfg_attr(not(test), expect(dead_code))] pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
}
#[derive(Debug, Clone)]
pub struct OverlapIter<'a, K, V> {
map: &'a SortedRangeMap<K, V>,
query: RangeInclusive<K>,
idx: usize,
}
impl<'a, K: Ord + Copy, V> Iterator for OverlapIter<'a, K, V> {
type Item = (&'a RangeInclusive<K>, &'a V);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
while self.idx < self.map.entries.len() {
let (range, value) = &self.map.entries[self.idx];
if self.query.end() < range.start() {
return None;
}
self.idx += 1;
if self.query.start() <= range.end() {
return Some((range, value));
}
}
None
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(self.map.entries.len().saturating_sub(self.idx)))
}
}
impl<K: Ord + Copy, V> std::iter::FusedIterator for OverlapIter<'_, K, V> {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_basic_overlap() {
let map = SortedRangeMap::new(vec![
(0..=10, "a"),
(5..=15, "b"),
(20..=30, "c"),
(25..=35, "d"),
]);
let results: Vec<_> = map.query(7..=12).collect();
assert_eq!(results, vec![(&(0..=10), &"a"), (&(5..=15), &"b")]);
let results: Vec<_> = map.query(16..=19).collect();
assert!(results.is_empty());
let results: Vec<_> = map.query(27..=32).collect();
assert_eq!(results, vec![(&(20..=30), &"c"), (&(25..=35), &"d")]);
}
#[test]
fn test_inclusive_boundaries() {
let map = SortedRangeMap::new(vec![(10..=20, "x")]);
let results: Vec<_> = map.query(0..=10).collect();
assert_eq!(results, vec![(&(10..=20), &"x")]);
let results: Vec<_> = map.query(20..=30).collect();
assert_eq!(results, vec![(&(10..=20), &"x")]);
assert!(map.query(0..=9).next().is_none());
assert!(map.query(21..=30).next().is_none());
}
#[test]
fn test_point_queries() {
let map = SortedRangeMap::new(vec![(0..=10, "a"), (10..=20, "b"), (20..=30, "c")]);
let results: Vec<_> = map.query(10..=10).collect();
assert_eq!(results, vec![(&(0..=10), &"a"), (&(10..=20), &"b")]);
let results: Vec<_> = map.query(20..=20).collect();
assert_eq!(results, vec![(&(10..=20), &"b"), (&(20..=30), &"c")]);
let results: Vec<_> = map.query(5..=5).collect();
assert_eq!(results, vec![(&(0..=10), &"a")]);
}
#[test]
fn test_fully_contained() {
let map = SortedRangeMap::new(vec![
(0..=100, "outer"),
(20..=30, "inner1"),
(40..=50, "inner2"),
]);
let results: Vec<_> = map.query(25..=45).collect();
assert_eq!(
results,
vec![
(&(0..=100), &"outer"),
(&(20..=30), &"inner1"),
(&(40..=50), &"inner2"),
]
);
let results: Vec<_> = map.query(31..=39).collect();
assert_eq!(results, vec![(&(0..=100), &"outer")]);
}
#[test]
fn test_empty_map() {
let map: SortedRangeMap<i32, ()> = SortedRangeMap::new(vec![]);
assert!(map.query(0..=100).next().is_none());
assert!(map.is_empty());
assert_eq!(map.len(), 0);
}
#[test]
fn test_single_element() {
let map = SortedRangeMap::new(vec![(50..=60, "only")]);
assert!(map.query(0..=49).next().is_none());
assert!(map.query(61..=100).next().is_none());
assert_eq!(map.query(50..=60).count(), 1);
assert_eq!(map.query(55..=55).count(), 1);
}
#[test]
fn test_many_overlapping() {
let map = SortedRangeMap::new(vec![
(0..=10, 0),
(1..=11, 1),
(2..=12, 2),
(3..=13, 3),
(4..=14, 4),
]);
let results: Vec<_> = map.query(5..=5).collect();
assert_eq!(results.len(), 5);
let starts: Vec<_> = results.iter().map(|(r, _)| *r.start()).collect();
assert_eq!(starts, vec![0, 1, 2, 3, 4]);
}
#[test]
fn test_disjoint_ranges() {
let map = SortedRangeMap::new(vec![
(0..=10, "a"),
(20..=30, "b"),
(40..=50, "c"),
(60..=70, "d"),
(80..=90, "e"),
]);
assert!(map.query(11..=19).next().is_none());
assert!(map.query(31..=39).next().is_none());
assert!(map.query(51..=59).next().is_none());
assert!(map.query(71..=79).next().is_none());
let results: Vec<_> = map.query(25..=65).collect();
assert_eq!(
results,
vec![(&(20..=30), &"b"), (&(40..=50), &"c"), (&(60..=70), &"d")]
);
}
#[test]
fn test_query_larger_than_all() {
let map = SortedRangeMap::new(vec![(10..=20, "a"), (30..=40, "b"), (50..=60, "c")]);
let results: Vec<_> = map.query(0..=100).collect();
assert_eq!(results.len(), 3);
}
#[test]
fn test_unsorted_input() {
let map = SortedRangeMap::new(vec![(50..=60, "c"), (10..=20, "a"), (30..=40, "b")]);
let results: Vec<_> = map.query(0..=100).collect();
let values: Vec<_> = results.iter().map(|(_, v)| **v).collect();
assert_eq!(values, vec!["a", "b", "c"]);
}
#[test]
fn test_duplicate_starts() {
let map = SortedRangeMap::new(vec![(10..=20, "a"), (10..=30, "b"), (10..=15, "c")]);
let results: Vec<_> = map.query(12..=12).collect();
assert_eq!(results.len(), 3);
}
}