rustc_data_structures/
sorted_map.rs

1use std::borrow::Borrow;
2use std::fmt::Debug;
3use std::mem;
4use std::ops::{Bound, Index, IndexMut, RangeBounds};
5
6use rustc_macros::{Decodable_Generic, Encodable_Generic};
7
8use crate::stable_hasher::{HashStable, StableHasher, StableOrd};
9
10mod index_map;
11
12pub use index_map::SortedIndexMultiMap;
13
14/// `SortedMap` is a data structure with similar characteristics as BTreeMap but
15/// slightly different trade-offs: lookup is *O*(log(*n*)), insertion and removal
16/// are *O*(*n*) but elements can be iterated in order cheaply.
17///
18/// `SortedMap` can be faster than a `BTreeMap` for small sizes (<50) since it
19/// stores data in a more compact way. It also supports accessing contiguous
20/// ranges of elements as a slice, and slices of already sorted elements can be
21/// inserted efficiently.
22#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable_Generic, Decodable_Generic)]
23pub struct SortedMap<K, V> {
24    data: Vec<(K, V)>,
25}
26
27impl<K, V> Default for SortedMap<K, V> {
28    #[inline]
29    fn default() -> SortedMap<K, V> {
30        SortedMap { data: Vec::new() }
31    }
32}
33
34impl<K, V> SortedMap<K, V> {
35    #[inline]
36    pub const fn new() -> SortedMap<K, V> {
37        SortedMap { data: Vec::new() }
38    }
39}
40
41impl<K: Ord, V> SortedMap<K, V> {
42    /// Construct a `SortedMap` from a presorted set of elements. This is faster
43    /// than creating an empty map and then inserting the elements individually.
44    ///
45    /// It is up to the caller to make sure that the elements are sorted by key
46    /// and that there are no duplicates.
47    #[inline]
48    pub fn from_presorted_elements(elements: Vec<(K, V)>) -> SortedMap<K, V> {
49        debug_assert!(elements.array_windows().all(|[fst, snd]| fst.0 < snd.0));
50
51        SortedMap { data: elements }
52    }
53
54    #[inline]
55    pub fn insert(&mut self, key: K, value: V) -> Option<V> {
56        match self.lookup_index_for(&key) {
57            Ok(index) => {
58                let slot = unsafe { self.data.get_unchecked_mut(index) };
59                Some(mem::replace(&mut slot.1, value))
60            }
61            Err(index) => {
62                self.data.insert(index, (key, value));
63                None
64            }
65        }
66    }
67
68    #[inline]
69    pub fn remove(&mut self, key: &K) -> Option<V> {
70        match self.lookup_index_for(key) {
71            Ok(index) => Some(self.data.remove(index).1),
72            Err(_) => None,
73        }
74    }
75
76    #[inline]
77    pub fn get<Q>(&self, key: &Q) -> Option<&V>
78    where
79        K: Borrow<Q>,
80        Q: Ord + ?Sized,
81    {
82        match self.lookup_index_for(key) {
83            Ok(index) => unsafe { Some(&self.data.get_unchecked(index).1) },
84            Err(_) => None,
85        }
86    }
87
88    #[inline]
89    pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
90    where
91        K: Borrow<Q>,
92        Q: Ord + ?Sized,
93    {
94        match self.lookup_index_for(key) {
95            Ok(index) => unsafe { Some(&mut self.data.get_unchecked_mut(index).1) },
96            Err(_) => None,
97        }
98    }
99
100    /// Gets a mutable reference to the value in the entry, or insert a new one.
101    #[inline]
102    pub fn get_mut_or_insert_default(&mut self, key: K) -> &mut V
103    where
104        K: Eq,
105        V: Default,
106    {
107        let index = match self.lookup_index_for(&key) {
108            Ok(index) => index,
109            Err(index) => {
110                self.data.insert(index, (key, V::default()));
111                index
112            }
113        };
114        unsafe { &mut self.data.get_unchecked_mut(index).1 }
115    }
116
117    #[inline]
118    pub fn clear(&mut self) {
119        self.data.clear();
120    }
121
122    /// Iterate over elements, sorted by key
123    #[inline]
124    pub fn iter(&self) -> std::slice::Iter<'_, (K, V)> {
125        self.data.iter()
126    }
127
128    /// Iterate over the keys, sorted
129    #[inline]
130    pub fn keys(&self) -> impl ExactSizeIterator<Item = &K> + DoubleEndedIterator {
131        self.data.iter().map(|(k, _)| k)
132    }
133
134    /// Iterate over values, sorted by key
135    #[inline]
136    pub fn values(&self) -> impl ExactSizeIterator<Item = &V> + DoubleEndedIterator {
137        self.data.iter().map(|(_, v)| v)
138    }
139
140    #[inline]
141    pub fn len(&self) -> usize {
142        self.data.len()
143    }
144
145    #[inline]
146    pub fn is_empty(&self) -> bool {
147        self.len() == 0
148    }
149
150    #[inline]
151    pub fn range<R>(&self, range: R) -> &[(K, V)]
152    where
153        R: RangeBounds<K>,
154    {
155        let (start, end) = self.range_slice_indices(range);
156        &self.data[start..end]
157    }
158
159    #[inline]
160    pub fn remove_range<R>(&mut self, range: R)
161    where
162        R: RangeBounds<K>,
163    {
164        let (start, end) = self.range_slice_indices(range);
165        self.data.splice(start..end, std::iter::empty());
166    }
167
168    /// Mutate all keys with the given function `f`. This mutation must not
169    /// change the sort-order of keys.
170    #[inline]
171    pub fn offset_keys<F>(&mut self, f: F)
172    where
173        F: Fn(&mut K),
174    {
175        self.data.iter_mut().map(|(k, _)| k).for_each(f);
176    }
177
178    /// Inserts a presorted range of elements into the map. If the range can be
179    /// inserted as a whole in between to existing elements of the map, this
180    /// will be faster than inserting the elements individually.
181    ///
182    /// It is up to the caller to make sure that the elements are sorted by key
183    /// and that there are no duplicates.
184    #[inline]
185    pub fn insert_presorted(&mut self, elements: Vec<(K, V)>) {
186        if elements.is_empty() {
187            return;
188        }
189
190        debug_assert!(elements.array_windows().all(|[fst, snd]| fst.0 < snd.0));
191
192        let start_index = self.lookup_index_for(&elements[0].0);
193
194        let elements = match start_index {
195            Ok(index) => {
196                let mut elements = elements.into_iter();
197                self.data[index] = elements.next().unwrap();
198                elements
199            }
200            Err(index) => {
201                if index == self.data.len() || elements.last().unwrap().0 < self.data[index].0 {
202                    // We can copy the whole range without having to mix with
203                    // existing elements.
204                    self.data.splice(index..index, elements);
205                    return;
206                }
207
208                let mut elements = elements.into_iter();
209                self.data.insert(index, elements.next().unwrap());
210                elements
211            }
212        };
213
214        // Insert the rest
215        for (k, v) in elements {
216            self.insert(k, v);
217        }
218    }
219
220    /// Looks up the key in `self.data` via `slice::binary_search()`.
221    #[inline(always)]
222    fn lookup_index_for<Q>(&self, key: &Q) -> Result<usize, usize>
223    where
224        K: Borrow<Q>,
225        Q: Ord + ?Sized,
226    {
227        self.data.binary_search_by(|(x, _)| x.borrow().cmp(key))
228    }
229
230    #[inline]
231    fn range_slice_indices<R>(&self, range: R) -> (usize, usize)
232    where
233        R: RangeBounds<K>,
234    {
235        let start = match range.start_bound() {
236            Bound::Included(k) => match self.lookup_index_for(k) {
237                Ok(index) | Err(index) => index,
238            },
239            Bound::Excluded(k) => match self.lookup_index_for(k) {
240                Ok(index) => index + 1,
241                Err(index) => index,
242            },
243            Bound::Unbounded => 0,
244        };
245
246        let end = match range.end_bound() {
247            Bound::Included(k) => match self.lookup_index_for(k) {
248                Ok(index) => index + 1,
249                Err(index) => index,
250            },
251            Bound::Excluded(k) => match self.lookup_index_for(k) {
252                Ok(index) | Err(index) => index,
253            },
254            Bound::Unbounded => self.data.len(),
255        };
256
257        (start, end)
258    }
259
260    #[inline]
261    pub fn contains_key<Q>(&self, key: &Q) -> bool
262    where
263        K: Borrow<Q>,
264        Q: Ord + ?Sized,
265    {
266        self.get(key).is_some()
267    }
268}
269
270impl<K: Ord, V> IntoIterator for SortedMap<K, V> {
271    type Item = (K, V);
272    type IntoIter = std::vec::IntoIter<(K, V)>;
273
274    fn into_iter(self) -> Self::IntoIter {
275        self.data.into_iter()
276    }
277}
278
279impl<'a, K, Q, V> Index<&'a Q> for SortedMap<K, V>
280where
281    K: Ord + Borrow<Q>,
282    Q: Ord + ?Sized,
283{
284    type Output = V;
285
286    fn index(&self, key: &Q) -> &Self::Output {
287        self.get(key).expect("no entry found for key")
288    }
289}
290
291impl<'a, K, Q, V> IndexMut<&'a Q> for SortedMap<K, V>
292where
293    K: Ord + Borrow<Q>,
294    Q: Ord + ?Sized,
295{
296    fn index_mut(&mut self, key: &Q) -> &mut Self::Output {
297        self.get_mut(key).expect("no entry found for key")
298    }
299}
300
301impl<K: Ord, V> FromIterator<(K, V)> for SortedMap<K, V> {
302    fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
303        let mut data: Vec<(K, V)> = iter.into_iter().collect();
304
305        data.sort_unstable_by(|(k1, _), (k2, _)| k1.cmp(k2));
306        data.dedup_by(|(k1, _), (k2, _)| k1 == k2);
307
308        SortedMap { data }
309    }
310}
311
312impl<K: HashStable<CTX> + StableOrd, V: HashStable<CTX>, CTX> HashStable<CTX> for SortedMap<K, V> {
313    #[inline]
314    fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
315        self.data.hash_stable(ctx, hasher);
316    }
317}
318
319impl<K: Debug, V: Debug> Debug for SortedMap<K, V> {
320    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
321        f.debug_map().entries(self.data.iter().map(|(a, b)| (a, b))).finish()
322    }
323}
324
325#[cfg(test)]
326mod tests;