3 //! Implements a map from integer indices to data.
4 //! Rather than storing data for every index, internally, this maps entire ranges to the data.
5 //! To this end, the APIs all work on ranges, not on individual integers. Ranges are split as
6 //! necessary (e.g. when [0,5) is first associated with X, and then [1,2) is mutated).
7 //! Users must not depend on whether a range is coalesced or not, even though this is observable
8 //! via the iteration APIs.
9 use std::collections::BTreeMap;
12 use rustc::ty::layout::Size;
14 #[derive(Clone, Debug, PartialEq, Eq)]
15 pub struct RangeMap<T> {
16 map: BTreeMap<Range, T>,
19 impl<T> Default for RangeMap<T> {
21 fn default() -> Self {
26 // The derived `Ord` impl sorts first by the first field, then, if the fields are the same,
27 // by the second field.
28 // This is exactly what we need for our purposes, since a range query on a BTReeSet/BTreeMap will give us all
29 // `MemoryRange`s whose `start` is <= than the one we're looking for, but not > the end of the range we're checking.
30 // At the same time the `end` is irrelevant for the sorting and range searching, but used for the check.
31 // This kind of search breaks, if `end < start`, so don't do that!
32 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
35 end: u64, // Invariant: end > start
39 /// Compute a range of ranges that contains all ranges overlaping with [offset, offset+len)
40 fn range(offset: u64, len: u64) -> ops::Range<Range> {
42 // We can produce an empty range, nothing overlaps with this.
43 let r = Range { start: 0, end: 1 };
46 // We select all elements that are within
47 // the range given by the offset into the allocation and the length.
48 // This is sound if all ranges that intersect with the argument range, are in the
49 // resulting range of ranges.
51 // lowest range to include `offset`
56 // lowest (valid) range not to include `offset+len`
58 end: offset + len + 1,
63 /// Tests if any element of [offset, offset+len) is contained in this range.
65 fn overlaps(&self, offset: u64, len: u64) -> bool {
67 // `offset` totally does not matter, we cannot overlap with an empty interval
70 offset < self.end && offset.checked_add(len).unwrap() >= self.start
77 pub fn new() -> RangeMap<T> {
78 RangeMap { map: BTreeMap::new() }
81 fn iter_with_range<'a>(
85 ) -> impl Iterator<Item = (&'a Range, &'a T)> + 'a {
86 self.map.range(Range::range(offset, len)).filter_map(
87 move |(range, data)| {
88 debug_assert!(len > 0);
89 if range.overlaps(offset, len) {
98 pub fn iter<'a>(&'a self, offset: Size, len: Size) -> impl Iterator<Item = &'a T> + 'a {
99 self.iter_with_range(offset.bytes(), len.bytes()).map(|(_, data)| data)
102 pub fn iter_mut_all<'a>(&'a mut self) -> impl Iterator<Item = &'a mut T> + 'a {
103 self.map.values_mut()
106 fn split_entry_at(&mut self, offset: u64)
110 let range = match self.iter_with_range(offset, 1).next() {
111 Some((&range, _)) => range,
115 range.start <= offset && range.end > offset,
116 "We got a range that doesn't even contain what we asked for."
118 // There is an entry overlapping this position, see if we have to split it
119 if range.start < offset {
120 let data = self.map.remove(&range).unwrap();
121 let old = self.map.insert(
128 assert!(old.is_none());
129 let old = self.map.insert(
136 assert!(old.is_none());
140 /// Provide mutable iteration over everything in the given range. As a side-effect,
141 /// this will split entries in the map that are only partially hit by the given range,
142 /// to make sure that when they are mutated, the effect is constrained to the given range.
143 /// If there are gaps, leave them be.
144 pub fn iter_mut_with_gaps<'a>(
148 ) -> impl Iterator<Item = &'a mut T> + 'a
152 let offset = offset.bytes();
153 let len = len.bytes();
156 // Preparation: Split first and last entry as needed.
157 self.split_entry_at(offset);
158 self.split_entry_at(offset + len);
160 // Now we can provide a mutable iterator
161 self.map.range_mut(Range::range(offset, len)).filter_map(
162 move |(&range, data)| {
163 debug_assert!(len > 0);
164 if range.overlaps(offset, len) {
166 offset <= range.start && offset + len >= range.end,
167 "The splitting went wrong"
178 /// Provide a mutable iterator over everything in the given range, with the same side-effects as
179 /// iter_mut_with_gaps. Furthermore, if there are gaps between ranges, fill them with the given default
180 /// before yielding them in the iterator.
181 /// This is also how you insert.
182 pub fn iter_mut<'a>(&'a mut self, offset: Size, len: Size) -> impl Iterator<Item = &'a mut T> + 'a
187 let offset = offset.bytes();
188 let len = len.bytes();
190 // Do a first iteration to collect the gaps
191 let mut gaps = Vec::new();
192 let mut last_end = offset;
193 for (range, _) in self.iter_with_range(offset, len) {
194 if last_end < range.start {
200 last_end = range.end;
202 if last_end < offset + len {
209 // Add default for all gaps
211 let old = self.map.insert(gap, Default::default());
212 assert!(old.is_none());
216 // Now provide mutable iteration
217 self.iter_mut_with_gaps(offset, len)
220 pub fn retain<F>(&mut self, mut f: F)
222 F: FnMut(&T) -> bool,
224 let mut remove = Vec::new();
225 for (range, data) in &self.map {
231 for range in remove {
232 self.map.remove(&range);
241 /// Query the map at every offset in the range and collect the results.
242 fn to_vec<T: Copy>(map: &RangeMap<T>, offset: u64, len: u64, default: Option<T>) -> Vec<T> {
243 (offset..offset + len)
246 .iter(Size::from_bytes(i), Size::from_bytes(1))
257 let mut map = RangeMap::<i32>::new();
259 for x in map.iter_mut(Size::from_bytes(10), Size::from_bytes(1)) {
263 assert_eq!(to_vec(&map, 10, 1, None), vec![42]);
265 // Insert with size 0
266 for x in map.iter_mut(Size::from_bytes(10), Size::from_bytes(0)) {
269 for x in map.iter_mut(Size::from_bytes(11), Size::from_bytes(0)) {
272 assert_eq!(to_vec(&map, 10, 2, Some(-1)), vec![42, -1]);
277 let mut map = RangeMap::<i32>::new();
278 for x in map.iter_mut(Size::from_bytes(11), Size::from_bytes(1)) {
281 for x in map.iter_mut(Size::from_bytes(15), Size::from_bytes(1)) {
285 to_vec(&map, 10, 10, Some(-1)),
286 vec![-1, 42, -1, -1, -1, 43, -1, -1, -1, -1]
289 // Now request a range that needs three gaps filled
290 for x in map.iter_mut(Size::from_bytes(10), Size::from_bytes(10)) {
297 to_vec(&map, 10, 10, None),
298 vec![23, 42, 23, 23, 23, 43, 23, 23, 23, 23]
300 assert_eq!(to_vec(&map, 13, 5, None), vec![23, 23, 43, 23, 23]);