Skip to main content

ezno_checker/utilities/
range_map.rs

1use std::collections::BTreeMap;
2use std::fmt::Debug;
3use std::ops::Range;
4
5#[derive(Debug)]
6pub struct RangeMap<T> {
7	/// First u32 is the start, the second second pairing is the end
8	entries: BTreeMap<u32, Vec<(u32, T)>>,
9}
10
11impl<T> Default for RangeMap<T> {
12	fn default() -> Self {
13		Self { entries: BTreeMap::default() }
14	}
15}
16
17impl<T> RangeMap<T> {
18	#[must_use]
19	pub fn new() -> Self {
20		Self { entries: Default::default() }
21	}
22
23	pub fn push(&mut self, range: impl Into<Range<u32>>, item: T) {
24		let range = range.into();
25		if let Some(existing) = self.entries.get_mut(&range.start) {
26			existing.push((range.end, item));
27		} else {
28			self.entries.insert(range.start, vec![(range.end, item)]);
29		}
30	}
31
32	/// Get the top level entry at some point
33	#[must_use]
34	pub fn get(&self, point: u32) -> Option<&T> {
35		self.get_with_range(point).map(|(res, _)| res)
36	}
37
38	#[must_use]
39	pub fn get_with_range(&self, point: u32) -> Option<(&T, Range<u32>)> {
40		self.entries
41			.range(0..=point)
42			// very important to reverse
43			.rev()
44			.find_map(|(s, v)| v.iter().find_map(|(e, v)| (*e > point).then_some((v, (*s..*e)))))
45	}
46
47	/// TODO into custom iterator
48	pub fn get_many(&self, point: u32, cb: impl for<'a> Fn(&'a T)) {
49		let rev = &mut self
50			.entries
51			.range(0..=point)
52			// very important to reverse
53			.rev();
54
55		for (start, values) in rev {
56			debug_assert!(*start <= point);
57			for (end, value) in values {
58				if point <= *end {
59					cb(value);
60				}
61			}
62		}
63	}
64
65	/// Get at an exact range
66	pub fn get_exact(&self, range: impl Into<Range<u32>>) -> Option<&T> {
67		let range = range.into();
68		self.entries
69			.get(&range.start)
70			.and_then(|v| v.iter().find_map(|(e, v)| (*e == range.end).then_some(v)))
71	}
72}