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.
11 use std::num::NonZeroU64;
13 use rustc::ty::layout::Size;
15 #[derive(Clone, Debug)]
17 range: ops::Range<u64>, // the range covered by this element, never empty
20 #[derive(Clone, Debug)]
21 pub struct RangeMap<T> {
26 /// Create a new RangeMap for the given size, and with the given initial value used for
29 pub fn new(size: Size, init: T) -> RangeMap<T> {
30 let size = size.bytes();
31 let mut map = RangeMap { v: Vec::new() };
41 /// Find the index containing the given offset.
42 fn find_offset(&self, offset: u64) -> usize {
43 debug_assert!(self.v.len() > 0);
44 let mut left = 0usize; // inclusive
45 let mut right = self.v.len(); // exclusive
47 let candidate = left.checked_add(right).unwrap() / 2;
48 let elem = &self.v[candidate];
49 if offset < elem.range.start {
50 // we are too far right (offset is further left)
51 debug_assert!(candidate < right); // we are making progress
53 } else if offset >= elem.range.end {
54 // we are too far left (offset is further right)
55 debug_assert!(candidate >= left); // we are making progress
57 debug_assert!(left < right, "find_offset: offset {} is out-of-bounds", offset);
65 /// Provide read-only iteration over everything in the given range. This does
66 /// *not* split items if they overlap with the edges. Do not use this to mutate
67 /// through interior mutability.
68 pub fn iter<'a>(&'a self, offset: Size, len: Size) -> impl Iterator<Item = &'a T> + 'a {
69 let offset = offset.bytes();
70 let len = len.bytes();
71 // Compute a slice starting with the elements we care about
72 let slice: &[Elem<T>] = if len == 0 {
73 // We just need any empty iterator. We don't even want to
74 // yield the element that surrounds this position.
77 let first_idx = self.find_offset(offset);
80 let end = offset + len; // the first offset that is not included any more
82 .take_while(move |elem| elem.range.start < end)
83 .map(|elem| &elem.data)
86 pub fn iter_mut_all<'a>(&'a mut self) -> impl Iterator<Item = &'a mut T> + 'a {
87 self.v.iter_mut().map(|elem| &mut elem.data)
90 // Split the element situated at the given `index`, such that the 2nd one starts at offset `split_offset`.
91 // Do nothing if the element already starts there.
92 // Return whether a split was necessary.
93 fn split_index(&mut self, index: usize, split_offset: u64) -> bool
97 let elem = &mut self.v[index];
98 if split_offset == elem.range.start || split_offset == elem.range.end {
102 debug_assert!(elem.range.contains(&split_offset),
103 "The split_offset is not in the element to be split");
105 // Now we really have to split. Reduce length of first element.
106 let second_range = split_offset..elem.range.end;
107 elem.range.end = split_offset;
108 // Copy the data, and insert 2nd element
111 data: elem.data.clone(),
113 self.v.insert(index+1, second);
117 /// Provide mutable iteration over everything in the given range. As a side-effect,
118 /// this will split entries in the map that are only partially hit by the given range,
119 /// to make sure that when they are mutated, the effect is constrained to the given range.
124 ) -> impl Iterator<Item = &'a mut T> + 'a
126 T: Clone + PartialEq,
128 let offset = offset.bytes();
129 let len = len.bytes();
130 // Compute a slice containing exactly the elements we care about
131 let slice: &mut [Elem<T>] = if len == 0 {
132 // We just need any empty iterator. We don't even want to
133 // yield the element that surrounds this position, nor do
137 // Make sure we got a clear beginning
138 let mut first_idx = self.find_offset(offset);
139 if self.split_index(first_idx, offset) {
140 // The newly created 2nd element is ours
143 let first_idx = first_idx; // no more mutation
144 // Find our end. Linear scan, but that's okay because the iteration
145 // is doing the same linear scan anyway -- no increase in complexity.
146 // We combine this scan with a scan for duplicates that we can merge, to reduce
147 // the number of elements.
148 let mut equal_since_idx = first_idx;
149 let mut end_idx = first_idx; // when the loop is done, this is the first excluded element.
151 // Compute if `end` is the last element we need to look at.
152 let done = (self.v[end_idx].range.end >= offset+len);
153 // We definitely need to include `end`, so move the index.
155 debug_assert!(done || end_idx < self.v.len(), "iter_mut: end-offset {} is out-of-bounds", offset+len);
156 // see if we want to merge everything in `equal_since..end` (exclusive at the end!)
157 if done || self.v[end_idx].data != self.v[equal_since_idx].data {
158 // Everything in `equal_since..end` was equal. Make them just one element covering
160 let equal_elems = end_idx - equal_since_idx; // number of equal elements
162 // Adjust the range of the first element to cover all of them.
163 let equal_until = self.v[end_idx - 1].range.end; // end of range of last of the equal elements
164 self.v[equal_since_idx].range.end = equal_until;
165 // Delete the rest of them.
166 self.v.splice(equal_since_idx+1..end_idx, std::iter::empty());
167 // Adjust `end_idx` because we made the list shorter.
168 end_idx -= (equal_elems - 1);
171 equal_since_idx = end_idx;
173 // Leave loop if this is the last element.
178 let end_idx = end_idx-1; // Move to last included instead of first excluded index.
179 // We need to split the end as well. Even if this performs a
180 // split, we don't have to adjust our index as we only care about
181 // the first part of the split.
182 self.split_index(end_idx, offset+len);
183 // Now we yield the slice. `end` is inclusive.
184 &mut self.v[first_idx..=end_idx]
186 slice.iter_mut().map(|elem| &mut elem.data)
194 /// Query the map at every offset in the range and collect the results.
195 fn to_vec<T: Copy>(map: &RangeMap<T>, offset: u64, len: u64) -> Vec<T> {
196 (offset..offset + len)
199 .iter(Size::from_bytes(i), Size::from_bytes(1))
209 let mut map = RangeMap::<i32>::new(Size::from_bytes(20), -1);
211 for x in map.iter_mut(Size::from_bytes(10), Size::from_bytes(1)) {
215 assert_eq!(to_vec(&map, 10, 1), vec![42]);
216 assert_eq!(map.v.len(), 3);
218 // Insert with size 0
219 for x in map.iter_mut(Size::from_bytes(10), Size::from_bytes(0)) {
222 for x in map.iter_mut(Size::from_bytes(11), Size::from_bytes(0)) {
225 assert_eq!(to_vec(&map, 10, 2), vec![42, -1]);
226 assert_eq!(map.v.len(), 3);
231 let mut map = RangeMap::<i32>::new(Size::from_bytes(20), -1);
232 for x in map.iter_mut(Size::from_bytes(11), Size::from_bytes(1)) {
235 for x in map.iter_mut(Size::from_bytes(15), Size::from_bytes(1)) {
238 assert_eq!(map.v.len(), 5);
240 to_vec(&map, 10, 10),
241 vec![-1, 42, -1, -1, -1, 43, -1, -1, -1, -1]
244 for x in map.iter_mut(Size::from_bytes(10), Size::from_bytes(10)) {
249 assert_eq!(map.v.len(), 6);
251 to_vec(&map, 10, 10),
252 vec![23, 42, 23, 23, 23, 43, 23, 23, 23, 23]
254 assert_eq!(to_vec(&map, 13, 5), vec![23, 23, 43, 23, 23]);
257 for x in map.iter_mut(Size::from_bytes(15), Size::from_bytes(5)) {
260 assert_eq!(map.v.len(), 6);
262 to_vec(&map, 10, 10),
263 vec![23, 42, 23, 23, 23, 19, 19, 19, 19, 19]
265 // Should be seeing two blocks with 19
266 assert_eq!(map.iter(Size::from_bytes(15), Size::from_bytes(2))
267 .map(|&t| t).collect::<Vec<_>>(), vec![19, 19]);
269 // a NOP iter_mut should trigger merging
270 for x in map.iter_mut(Size::from_bytes(15), Size::from_bytes(5)) { }
271 assert_eq!(map.v.len(), 5);
273 to_vec(&map, 10, 10),
274 vec![23, 42, 23, 23, 23, 19, 19, 19, 19, 19]