Skip to main content

turbo_frozenmap/
map.rs

1use std::{
2    borrow::Borrow,
3    collections::{BTreeMap, HashMap},
4    fmt::{self, Debug},
5    hash::BuildHasher,
6    iter::FusedIterator,
7    marker::PhantomData,
8    ops::{Bound, Index, RangeBounds},
9};
10
11use bincode::{BorrowDecode, Decode, Encode};
12use indexmap::IndexMap;
13use serde::{
14    Deserialize, Serialize,
15    de::{MapAccess, Visitor},
16};
17
18/// A compact frozen (immutable) ordered map backed by a sorted boxed slice.
19///
20/// This is a read-only map that stores key-value pairs in a contiguous, sorted array. It provides
21/// efficient sorted iteration and binary search lookups, but cannot be modified after construction.
22///
23/// # Construction
24///
25/// If you're building a new map, and you don't expect many overlapping keys, consider pushing
26/// entries into a [`Vec<(K, V)>`] and calling [`FrozenMap::from`]. It is typically cheaper to
27/// collect into a [`Vec`] and sort the entries once at the end than it is to maintain a temporary
28/// map data structure.
29///
30/// If you already have a map, need to perform lookups during construction, or you have many
31/// overlapping keys that you don't want to temporarily hold onto, you can use the provided [`From`]
32/// trait implementations to create a [`FrozenMap`] from one of many common collections. You should
33/// prefer using a [`BTreeMap`], as it matches the sorted iteration order of [`FrozenMap`] and
34/// avoids a sort operation during conversion.
35///
36/// If you don't have an existing collection, you can use the [`FromIterator<(K, V)>`] trait
37/// implementation to [`.collect()`][Iterator::collect] tuples into a [`FrozenMap`].
38///
39/// Finally, if you have a list of pre-sorted tuples with unique keys, you can use the advanced
40/// [`FrozenMap::from_unique_sorted_box`] or [`FrozenMap::from_unique_sorted_box_unchecked`]
41/// constructors, which provide the cheapest possible construction.
42///
43/// Overlapping keys encountered during construction preserve the last overlapping entry, matching
44/// similar behavior for other maps in the standard library.
45#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Encode, Decode)]
46#[rustfmt::skip] // rustfmt breaks bincode's proc macro string processing
47#[bincode(
48    decode_bounds = "K: Decode<__Context> + 'static, V: Decode<__Context> + 'static",
49    borrow_decode_bounds = "K: BorrowDecode<'__de, __Context> + '__de, V: BorrowDecode<'__de, __Context> + '__de"
50)]
51pub struct FrozenMap<K, V> {
52    /// Invariant: entries are sorted by key in ascending order with no overlapping keys.
53    pub(crate) entries: Box<[(K, V)]>,
54}
55
56impl<K: Serialize, V: Serialize> Serialize for FrozenMap<K, V> {
57    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
58        serializer.collect_map(self.iter())
59    }
60}
61
62impl<'de, K, V> Deserialize<'de> for FrozenMap<K, V>
63where
64    K: Deserialize<'de> + Ord,
65    V: Deserialize<'de>,
66{
67    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
68        struct MapVisitor<K, V>(PhantomData<(K, V)>);
69
70        impl<'de, K, V> Visitor<'de> for MapVisitor<K, V>
71        where
72            K: Deserialize<'de> + Ord,
73            V: Deserialize<'de>,
74        {
75            type Value = FrozenMap<K, V>;
76
77            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
78                formatter.write_str("a map")
79            }
80
81            fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
82                let mut entries = Vec::with_capacity(map.size_hint().unwrap_or(0));
83                while let Some(entry) = map.next_entry()? {
84                    entries.push(entry);
85                }
86                Ok(FrozenMap::from(entries))
87            }
88        }
89
90        deserializer.deserialize_map(MapVisitor(PhantomData))
91    }
92}
93
94impl<K, V> FrozenMap<K, V> {
95    /// Creates an empty [`FrozenMap`]. Does not perform any heap allocations.
96    pub fn new() -> Self {
97        FrozenMap {
98            // Box does not perform heap allocations for zero-sized types.
99            // In theory this could even be `const` using `Unique::dangling`, but there's no way to
100            // construct a `Box` from a pointer during `const`.
101            entries: Box::from([]),
102        }
103    }
104}
105
106impl<K, V> FrozenMap<K, V>
107where
108    K: Ord,
109{
110    /// Creates a [`FrozenMap`] from a pre-sorted boxed slice with unique keys.
111    ///
112    /// Panics if the keys in `entries` are not unique and sorted.
113    pub fn from_unique_sorted_box(entries: Box<[(K, V)]>) -> Self {
114        assert_unique_sorted(&entries);
115        FrozenMap { entries }
116    }
117
118    /// Creates a [`FrozenMap`] from a pre-sorted boxed slice with unique keys.
119    ///
120    /// # Correctness
121    ///
122    /// The caller must ensure that:
123    /// - The entries are sorted by key in ascending order according to [`K: Ord`][Ord]
124    /// - There are no overlapping keys
125    ///
126    /// If these invariants are not upheld, the map will behave incorrectly (e.g.,
127    /// [`FrozenMap::get`] may fail to find keys that are present), but no memory unsafety will
128    /// occur.
129    ///
130    /// When `debug_assertions` is enabled, this will panic if an invariant is not upheld.
131    pub fn from_unique_sorted_box_unchecked(entries: Box<[(K, V)]>) -> Self {
132        debug_assert_unique_sorted(&entries);
133        FrozenMap { entries }
134    }
135
136    /// Helper: Sorts keys before constructing. Does not perform any assertions.
137    ///
138    /// The caller of this helper should provide a fast-path for empty collections.
139    pub(crate) fn from_unique_box_inner(mut entries: Box<[(K, V)]>) -> Self {
140        entries.sort_unstable_by(|a, b| a.0.cmp(&b.0));
141        Self::from_unique_sorted_box_unchecked(entries)
142    }
143
144    /// Helper: Sorts and deduplicates keys before constructing. Does not perform any assertions.
145    ///
146    /// The caller of this helper should provide a fast-path for empty collections.
147    pub(crate) fn from_vec_inner(mut entries: Vec<(K, V)>) -> Self {
148        // stable sort preserves insertion order for overlapping keys
149        entries.sort_by(|a, b| a.0.cmp(&b.0));
150        // Deduplicate, keeping the last value for each key.
151        // `dedup_by` removes the first argument when returning true, so we swap to keep the later
152        // (last) value in the earlier slot.
153        entries.dedup_by(|later, earlier| {
154            if later.0 == earlier.0 {
155                std::mem::swap(later, earlier);
156                true
157            } else {
158                false
159            }
160        });
161        Self::from_unique_sorted_box_unchecked(entries.into_boxed_slice())
162    }
163}
164
165#[track_caller]
166fn assert_unique_sorted<K: Ord, V>(entries: &[(K, V)]) {
167    assert!(
168        entries.is_sorted_by(|a, b| a.0 < b.0),
169        "FrozenMap entries must be unique and sorted",
170    )
171}
172
173#[track_caller]
174fn debug_assert_unique_sorted<K: Ord, V>(entries: &[(K, V)]) {
175    debug_assert!(
176        entries.is_sorted_by(|a, b| a.0 < b.0),
177        "FrozenMap entries must be unique and sorted",
178    )
179}
180
181impl<K: Ord, V> FromIterator<(K, V)> for FrozenMap<K, V> {
182    /// Creates a [`FrozenMap`] from an iterator of key-value pairs.
183    ///
184    /// If there are overlapping keys, the last entry for each key is kept.
185    fn from_iter<T: IntoIterator<Item = (K, V)>>(entries: T) -> Self {
186        let entries: Vec<_> = entries.into_iter().collect();
187        Self::from(entries)
188    }
189}
190
191impl<K, V> From<BTreeMap<K, V>> for FrozenMap<K, V> {
192    /// Creates a [`FrozenMap`] from a [`BTreeMap`].
193    ///
194    /// This is more efficient than `From<HashMap<K, V>>` because [`BTreeMap`] already iterates in
195    /// sorted order, so no re-sorting is needed.
196    fn from(map: BTreeMap<K, V>) -> Self {
197        if map.is_empty() {
198            return Self::new();
199        }
200        FrozenMap {
201            entries: map.into_iter().collect(),
202        }
203    }
204}
205
206impl<K, V, S> From<HashMap<K, V, S>> for FrozenMap<K, V>
207where
208    K: Ord,
209    S: BuildHasher,
210{
211    /// Creates a [`FrozenMap`] from a [`HashMap`].
212    ///
213    /// The entries are sorted by key during construction.
214    fn from(map: HashMap<K, V, S>) -> Self {
215        if map.is_empty() {
216            return Self::new();
217        }
218        Self::from_unique_box_inner(map.into_iter().collect())
219    }
220}
221
222impl<K, V, S> From<IndexMap<K, V, S>> for FrozenMap<K, V>
223where
224    K: Ord,
225    S: BuildHasher,
226{
227    /// Creates a [`FrozenMap`] from an [`IndexMap`].
228    ///
229    /// The entries are sorted by key during construction.
230    fn from(map: IndexMap<K, V, S>) -> Self {
231        if map.is_empty() {
232            return Self::new();
233        }
234        Self::from_unique_box_inner(map.into_iter().collect())
235    }
236}
237
238impl<K: Ord, V> From<Vec<(K, V)>> for FrozenMap<K, V> {
239    /// Creates a [`FrozenMap`] from a [`Vec`] of key-value pairs.
240    ///
241    /// If there are overlapping keys, the last entry for each key is kept.
242    fn from(entries: Vec<(K, V)>) -> Self {
243        if entries.is_empty() {
244            return Self::new();
245        }
246        Self::from_vec_inner(entries)
247    }
248}
249
250impl<K: Ord, V> From<Box<[(K, V)]>> for FrozenMap<K, V> {
251    /// Creates a [`FrozenMap`] from a boxed slice of key-value pairs.
252    ///
253    /// If there are overlapping keys, the last entry for each key is kept.
254    fn from(entries: Box<[(K, V)]>) -> Self {
255        if entries.is_empty() {
256            return Self::new();
257        }
258        Self::from_vec_inner(Vec::from(entries))
259    }
260}
261
262impl<K, V> From<&[(K, V)]> for FrozenMap<K, V>
263where
264    K: Ord + Clone,
265    V: Clone,
266{
267    /// Creates a [`FrozenMap`] from a slice of key-value pairs. Keys and values are cloned.
268    ///
269    /// If there are overlapping keys, the last entry for each key is kept.
270    fn from(entries: &[(K, V)]) -> Self {
271        if entries.is_empty() {
272            return Self::new();
273        }
274        Self::from_vec_inner(Vec::from(entries))
275    }
276}
277
278impl<K: Ord, V, const N: usize> From<[(K, V); N]> for FrozenMap<K, V> {
279    /// Creates a [`FrozenMap`] from an owned array of key-value pairs.
280    ///
281    /// If there are overlapping keys, the last entry for each key is kept.
282    fn from(entries: [(K, V); N]) -> Self {
283        if entries.is_empty() {
284            return Self::new();
285        }
286        Self::from_vec_inner(Vec::from(entries))
287    }
288}
289
290impl<K, V> FrozenMap<K, V> {
291    /// Returns the number of elements in the map.
292    pub const fn len(&self) -> usize {
293        self.entries.len()
294    }
295
296    /// Returns `true` if the map contains no elements.
297    pub const fn is_empty(&self) -> bool {
298        self.entries.is_empty()
299    }
300
301    /// Returns a reference to the underlying sorted slice.
302    pub const fn as_slice(&self) -> &[(K, V)] {
303        &self.entries
304    }
305
306    /// Returns a reference to the value corresponding to the key.
307    pub fn get<Q>(&self, key: &Q) -> Option<&V>
308    where
309        K: Borrow<Q> + Ord,
310        Q: Ord + ?Sized,
311    {
312        self.get_key_value(key).map(|(_, v)| v)
313    }
314
315    /// Returns the key-value pair corresponding to the supplied key.
316    pub fn get_key_value<Q>(&self, key: &Q) -> Option<(&K, &V)>
317    where
318        K: Borrow<Q> + Ord,
319        Q: Ord + ?Sized,
320    {
321        let idx = self
322            .entries
323            .binary_search_by(|(k, _)| k.borrow().cmp(key))
324            .ok()?;
325        let (k, v) = &self.entries[idx];
326        Some((k, v))
327    }
328
329    /// Returns `true` if the map contains a value for the specified key.
330    pub fn contains_key<Q>(&self, key: &Q) -> bool
331    where
332        K: Borrow<Q> + Ord,
333        Q: Ord + ?Sized,
334    {
335        self.entries
336            .binary_search_by(|(k, _)| k.borrow().cmp(key))
337            .is_ok()
338    }
339
340    /// Returns the first key-value pair in the map.
341    pub fn first_key_value(&self) -> Option<(&K, &V)> {
342        self.entries.first().map(|(k, v)| (k, v))
343    }
344
345    /// Returns the last key-value pair in the map.
346    pub fn last_key_value(&self) -> Option<(&K, &V)> {
347        self.entries.last().map(|(k, v)| (k, v))
348    }
349
350    /// Gets an iterator over the entries of the map, sorted by key.
351    pub fn iter(&self) -> Iter<'_, K, V> {
352        Iter {
353            inner: self.entries.iter(),
354        }
355    }
356
357    /// Gets an iterator over the keys of the map, in sorted order.
358    pub fn keys(&self) -> Keys<'_, K, V> {
359        Keys { inner: self.iter() }
360    }
361
362    /// Gets an iterator over the values of the map, in order by key.
363    pub fn values(&self) -> Values<'_, K, V> {
364        Values { inner: self.iter() }
365    }
366
367    /// Creates a consuming iterator visiting all the keys, in sorted order.
368    pub fn into_keys(self) -> IntoKeys<K, V> {
369        IntoKeys {
370            inner: self.into_iter(),
371        }
372    }
373
374    /// Creates a consuming iterator visiting all the values, in order by key.
375    pub fn into_values(self) -> IntoValues<K, V> {
376        IntoValues {
377            inner: self.into_iter(),
378        }
379    }
380
381    /// Constructs a double-ended iterator over a sub-range of entries in the map.
382    pub fn range<T, R>(&self, range: R) -> Range<'_, K, V>
383    where
384        T: Ord + ?Sized,
385        K: Borrow<T> + Ord,
386        R: RangeBounds<T>,
387    {
388        let start = match range.start_bound() {
389            Bound::Included(key) => self
390                .entries
391                .binary_search_by(|(k, _)| k.borrow().cmp(key))
392                .unwrap_or_else(|i| i),
393            Bound::Excluded(key) => {
394                match self.entries.binary_search_by(|(k, _)| k.borrow().cmp(key)) {
395                    Ok(i) => i + 1,
396                    Err(i) => i,
397                }
398            }
399            Bound::Unbounded => 0,
400        };
401
402        let end = match range.end_bound() {
403            Bound::Included(key) => {
404                match self.entries.binary_search_by(|(k, _)| k.borrow().cmp(key)) {
405                    Ok(i) => i + 1,
406                    Err(i) => i,
407                }
408            }
409            Bound::Excluded(key) => self
410                .entries
411                .binary_search_by(|(k, _)| k.borrow().cmp(key))
412                .unwrap_or_else(|i| i),
413            Bound::Unbounded => self.entries.len(),
414        };
415
416        let slice = if start <= end && end <= self.entries.len() {
417            &self.entries[start..end]
418        } else {
419            &[]
420        };
421
422        Range {
423            inner: slice.iter(),
424        }
425    }
426
427    /// Extend this [`FrozenMap`] by constructing a new map with the additional entries. New entries
428    /// with overlapping keys will overwrite existing ones.
429    #[must_use]
430    pub fn extend(&self, entries: impl IntoIterator<Item = (K, V)>) -> Self
431    where
432        K: Clone + Ord,
433        V: Clone,
434    {
435        self.as_slice().iter().cloned().chain(entries).collect()
436    }
437}
438
439// Manual implementation because the derive would add unnecessary `K: Default, V: Default` bounds.
440impl<K, V> Default for FrozenMap<K, V> {
441    fn default() -> Self {
442        Self::new()
443    }
444}
445
446impl<K: Debug, V: Debug> Debug for FrozenMap<K, V> {
447    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
448        f.debug_map().entries(self.iter()).finish()
449    }
450}
451
452impl<K, Q: ?Sized, V> Index<&Q> for FrozenMap<K, V>
453where
454    K: Borrow<Q> + Ord,
455    Q: Ord,
456{
457    type Output = V;
458
459    fn index(&self, key: &Q) -> &V {
460        self.get(key).expect("no entry found for key")
461    }
462}
463
464impl<K, V> AsRef<[(K, V)]> for FrozenMap<K, V> {
465    fn as_ref(&self) -> &[(K, V)] {
466        self.as_slice()
467    }
468}
469
470impl<K, V> From<FrozenMap<K, V>> for Box<[(K, V)]> {
471    fn from(map: FrozenMap<K, V>) -> Self {
472        map.entries
473    }
474}
475
476impl<'a, K, V> IntoIterator for &'a FrozenMap<K, V> {
477    type Item = (&'a K, &'a V);
478    type IntoIter = Iter<'a, K, V>;
479
480    fn into_iter(self) -> Iter<'a, K, V> {
481        self.iter()
482    }
483}
484
485impl<K, V> IntoIterator for FrozenMap<K, V> {
486    type Item = (K, V);
487    type IntoIter = IntoIter<K, V>;
488
489    fn into_iter(self) -> IntoIter<K, V> {
490        IntoIter {
491            inner: self.entries.into_vec().into_iter(),
492        }
493    }
494}
495
496/// An iterator over the entries of a [`FrozenMap`].
497pub struct Iter<'a, K, V> {
498    inner: std::slice::Iter<'a, (K, V)>,
499}
500
501impl<K: Debug, V: Debug> Debug for Iter<'_, K, V> {
502    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
503        f.debug_list()
504            .entries(self.inner.clone().map(|(k, v)| (k, v)))
505            .finish()
506    }
507}
508
509impl<'a, K, V> Iterator for Iter<'a, K, V> {
510    type Item = (&'a K, &'a V);
511
512    fn next(&mut self) -> Option<Self::Item> {
513        self.inner.next().map(|(k, v)| (k, v))
514    }
515
516    fn size_hint(&self) -> (usize, Option<usize>) {
517        self.inner.size_hint()
518    }
519
520    fn last(mut self) -> Option<Self::Item> {
521        self.next_back()
522    }
523
524    fn nth(&mut self, n: usize) -> Option<Self::Item> {
525        self.inner.nth(n).map(|(k, v)| (k, v))
526    }
527
528    fn count(self) -> usize {
529        self.inner.len()
530    }
531}
532
533impl<K, V> DoubleEndedIterator for Iter<'_, K, V> {
534    fn next_back(&mut self) -> Option<Self::Item> {
535        self.inner.next_back().map(|(k, v)| (k, v))
536    }
537
538    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
539        self.inner.nth_back(n).map(|(k, v)| (k, v))
540    }
541}
542
543impl<K, V> ExactSizeIterator for Iter<'_, K, V> {
544    fn len(&self) -> usize {
545        self.inner.len()
546    }
547}
548
549impl<K, V> FusedIterator for Iter<'_, K, V> {}
550
551// Manual implementation because the derive would add unnecessary `K: Clone, V: Clone` type bounds.
552impl<K, V> Clone for Iter<'_, K, V> {
553    fn clone(&self) -> Self {
554        Self {
555            inner: self.inner.clone(),
556        }
557    }
558}
559
560/// An owning iterator over the entries of a [`FrozenMap`].
561pub struct IntoIter<K, V> {
562    inner: std::vec::IntoIter<(K, V)>,
563}
564
565impl<K: Debug, V: Debug> Debug for IntoIter<K, V> {
566    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
567        f.debug_list().entries(self.inner.as_slice()).finish()
568    }
569}
570
571impl<K, V> Iterator for IntoIter<K, V> {
572    type Item = (K, V);
573
574    fn next(&mut self) -> Option<Self::Item> {
575        self.inner.next()
576    }
577
578    fn size_hint(&self) -> (usize, Option<usize>) {
579        self.inner.size_hint()
580    }
581
582    fn count(self) -> usize {
583        self.inner.len()
584    }
585}
586
587impl<K, V> DoubleEndedIterator for IntoIter<K, V> {
588    fn next_back(&mut self) -> Option<Self::Item> {
589        self.inner.next_back()
590    }
591}
592
593impl<K, V> ExactSizeIterator for IntoIter<K, V> {
594    fn len(&self) -> usize {
595        self.inner.len()
596    }
597}
598
599impl<K, V> FusedIterator for IntoIter<K, V> {}
600
601/// An iterator over the keys of a [`FrozenMap`].
602pub struct Keys<'a, K, V> {
603    inner: Iter<'a, K, V>,
604}
605
606impl<K: Debug, V> Debug for Keys<'_, K, V> {
607    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
608        f.debug_list()
609            .entries(self.inner.inner.clone().map(|(k, _)| k))
610            .finish()
611    }
612}
613
614impl<'a, K, V> Iterator for Keys<'a, K, V> {
615    type Item = &'a K;
616
617    fn next(&mut self) -> Option<Self::Item> {
618        self.inner.next().map(|(k, _)| k)
619    }
620
621    fn size_hint(&self) -> (usize, Option<usize>) {
622        self.inner.size_hint()
623    }
624
625    fn last(mut self) -> Option<Self::Item> {
626        self.next_back()
627    }
628
629    fn count(self) -> usize {
630        self.inner.len()
631    }
632}
633
634impl<K, V> DoubleEndedIterator for Keys<'_, K, V> {
635    fn next_back(&mut self) -> Option<Self::Item> {
636        self.inner.next_back().map(|(k, _)| k)
637    }
638}
639
640impl<K, V> ExactSizeIterator for Keys<'_, K, V> {
641    fn len(&self) -> usize {
642        self.inner.len()
643    }
644}
645
646impl<K, V> FusedIterator for Keys<'_, K, V> {}
647
648// Manual implementation because the derive would add unnecessary `K: Clone, V: Clone` type bounds.
649impl<K, V> Clone for Keys<'_, K, V> {
650    fn clone(&self) -> Self {
651        Self {
652            inner: self.inner.clone(),
653        }
654    }
655}
656
657/// An iterator over the values of a [`FrozenMap`].
658pub struct Values<'a, K, V> {
659    inner: Iter<'a, K, V>,
660}
661
662impl<K, V: Debug> Debug for Values<'_, K, V> {
663    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
664        f.debug_list()
665            .entries(self.inner.inner.clone().map(|(_, v)| v))
666            .finish()
667    }
668}
669
670impl<'a, K, V> Iterator for Values<'a, K, V> {
671    type Item = &'a V;
672
673    fn next(&mut self) -> Option<Self::Item> {
674        self.inner.next().map(|(_, v)| v)
675    }
676
677    fn size_hint(&self) -> (usize, Option<usize>) {
678        self.inner.size_hint()
679    }
680
681    fn last(mut self) -> Option<Self::Item> {
682        self.next_back()
683    }
684
685    fn count(self) -> usize {
686        self.inner.len()
687    }
688}
689
690impl<K, V> DoubleEndedIterator for Values<'_, K, V> {
691    fn next_back(&mut self) -> Option<Self::Item> {
692        self.inner.next_back().map(|(_, v)| v)
693    }
694}
695
696impl<K, V> ExactSizeIterator for Values<'_, K, V> {
697    fn len(&self) -> usize {
698        self.inner.len()
699    }
700}
701
702impl<K, V> FusedIterator for Values<'_, K, V> {}
703
704// Manual implementation because the derive would add unnecessary `K: Clone, V: Clone` type bounds.
705impl<K, V> Clone for Values<'_, K, V> {
706    fn clone(&self) -> Self {
707        Self {
708            inner: self.inner.clone(),
709        }
710    }
711}
712
713/// An owning iterator over the keys of a [`FrozenMap`].
714pub struct IntoKeys<K, V> {
715    inner: IntoIter<K, V>,
716}
717
718impl<K: Debug, V> Debug for IntoKeys<K, V> {
719    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
720        f.debug_list()
721            .entries(self.inner.inner.as_slice().iter().map(|(k, _)| k))
722            .finish()
723    }
724}
725
726impl<K, V> Iterator for IntoKeys<K, V> {
727    type Item = K;
728
729    fn next(&mut self) -> Option<Self::Item> {
730        self.inner.next().map(|(k, _)| k)
731    }
732
733    fn size_hint(&self) -> (usize, Option<usize>) {
734        self.inner.size_hint()
735    }
736
737    fn count(self) -> usize {
738        self.inner.len()
739    }
740}
741
742impl<K, V> DoubleEndedIterator for IntoKeys<K, V> {
743    fn next_back(&mut self) -> Option<Self::Item> {
744        self.inner.next_back().map(|(k, _)| k)
745    }
746}
747
748impl<K, V> ExactSizeIterator for IntoKeys<K, V> {
749    fn len(&self) -> usize {
750        self.inner.len()
751    }
752}
753
754impl<K, V> FusedIterator for IntoKeys<K, V> {}
755
756/// An owning iterator over the values of a [`FrozenMap`].
757pub struct IntoValues<K, V> {
758    inner: IntoIter<K, V>,
759}
760
761impl<K, V: Debug> Debug for IntoValues<K, V> {
762    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
763        f.debug_list()
764            .entries(self.inner.inner.as_slice().iter().map(|(_, v)| v))
765            .finish()
766    }
767}
768
769impl<K, V> Iterator for IntoValues<K, V> {
770    type Item = V;
771
772    fn next(&mut self) -> Option<Self::Item> {
773        self.inner.next().map(|(_, v)| v)
774    }
775
776    fn size_hint(&self) -> (usize, Option<usize>) {
777        self.inner.size_hint()
778    }
779
780    fn count(self) -> usize {
781        self.inner.len()
782    }
783}
784
785impl<K, V> DoubleEndedIterator for IntoValues<K, V> {
786    fn next_back(&mut self) -> Option<Self::Item> {
787        self.inner.next_back().map(|(_, v)| v)
788    }
789}
790
791impl<K, V> ExactSizeIterator for IntoValues<K, V> {
792    fn len(&self) -> usize {
793        self.inner.len()
794    }
795}
796
797impl<K, V> FusedIterator for IntoValues<K, V> {}
798
799/// An iterator over a sub-range of entries in a [`FrozenMap`].
800pub struct Range<'a, K, V> {
801    inner: std::slice::Iter<'a, (K, V)>,
802}
803
804impl<K: Debug, V: Debug> Debug for Range<'_, K, V> {
805    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
806        f.debug_list().entries(self.clone()).finish()
807    }
808}
809
810impl<'a, K, V> Iterator for Range<'a, K, V> {
811    type Item = (&'a K, &'a V);
812
813    fn next(&mut self) -> Option<Self::Item> {
814        self.inner.next().map(|(k, v)| (k, v))
815    }
816
817    fn size_hint(&self) -> (usize, Option<usize>) {
818        self.inner.size_hint()
819    }
820
821    fn last(mut self) -> Option<Self::Item> {
822        self.next_back()
823    }
824
825    fn count(self) -> usize {
826        self.inner.len()
827    }
828}
829
830impl<K, V> DoubleEndedIterator for Range<'_, K, V> {
831    fn next_back(&mut self) -> Option<Self::Item> {
832        self.inner.next_back().map(|(k, v)| (k, v))
833    }
834}
835
836impl<K, V> ExactSizeIterator for Range<'_, K, V> {
837    fn len(&self) -> usize {
838        self.inner.len()
839    }
840}
841
842impl<K, V> FusedIterator for Range<'_, K, V> {}
843
844// Manual implementation because the derive would add unnecessary `K: Clone, V: Clone` type bounds.
845impl<K, V> Clone for Range<'_, K, V> {
846    fn clone(&self) -> Self {
847        Self {
848            inner: self.inner.clone(),
849        }
850    }
851}
852
853#[cfg(test)]
854mod tests {
855    use super::*;
856
857    #[test]
858    fn serde_uses_map_shape() {
859        let map = FrozenMap::from([("b", 2), ("a", 1)]);
860        let json = serde_json::to_string(&map).unwrap();
861
862        assert_eq!(json, r#"{"a":1,"b":2}"#);
863        assert_eq!(
864            serde_json::from_str::<FrozenMap<&str, i32>>(r#"{"b":2, "a":1}"#).unwrap(),
865            map
866        );
867    }
868
869    #[test]
870    fn test_empty() {
871        let map = FrozenMap::<i32, i32>::new();
872        assert!(map.is_empty());
873        assert_eq!(map.len(), 0);
874        assert_eq!(map.get(&1), None);
875    }
876
877    #[test]
878    fn test_from_btreemap() {
879        let mut btree = BTreeMap::new();
880        btree.insert(3, "c");
881        btree.insert(1, "a");
882        btree.insert(2, "b");
883
884        let frozen = FrozenMap::from(btree);
885        assert_eq!(frozen.len(), 3);
886        assert_eq!(frozen.get(&1), Some(&"a"));
887        assert_eq!(frozen.get(&2), Some(&"b"));
888        assert_eq!(frozen.get(&3), Some(&"c"));
889
890        let keys: Vec<_> = frozen.keys().copied().collect();
891        assert_eq!(keys, vec![1, 2, 3]);
892    }
893
894    #[test]
895    fn test_from_overlapping_vec() {
896        let frozen = FrozenMap::from(vec![(1, "a"), (1, "b"), (2, "c")]);
897        assert_eq!(frozen.len(), 2);
898        // Last value wins for overlapping keys
899        assert_eq!(frozen.get(&1), Some(&"b"));
900        assert_eq!(frozen.get(&2), Some(&"c"));
901    }
902
903    #[test]
904    fn test_range() {
905        let frozen = FrozenMap::from([(1, "a"), (2, "b"), (3, "c"), (4, "d"), (5, "e")]);
906
907        let range: Vec<_> = frozen.range(2..4).collect();
908        assert_eq!(range, vec![(&2, &"b"), (&3, &"c")]);
909
910        let range: Vec<_> = frozen.range(2..=4).collect();
911        assert_eq!(range, vec![(&2, &"b"), (&3, &"c"), (&4, &"d")]);
912
913        let range: Vec<_> = frozen.range(..3).collect();
914        assert_eq!(range, vec![(&1, &"a"), (&2, &"b")]);
915    }
916
917    #[test]
918    fn test_index() {
919        let frozen = FrozenMap::from([(1, "a"), (2, "b")]);
920        assert_eq!(frozen[&1], "a");
921        assert_eq!(frozen[&2], "b");
922    }
923
924    #[test]
925    #[should_panic(expected = "no entry found for key")]
926    fn test_index_missing() {
927        let frozen = FrozenMap::from([(1, "a")]);
928        let _ = frozen[&2];
929    }
930
931    #[test]
932    fn test_first_last() {
933        let frozen = FrozenMap::from([(2, "b"), (1, "a"), (3, "c")]);
934        assert_eq!(frozen.first_key_value(), Some((&1, &"a")));
935        assert_eq!(frozen.last_key_value(), Some((&3, &"c")));
936
937        let empty = FrozenMap::<i32, i32>::new();
938        assert_eq!(empty.first_key_value(), None);
939        assert_eq!(empty.last_key_value(), None);
940    }
941
942    #[test]
943    fn test_as_ref() {
944        let frozen = FrozenMap::from([(2, "b"), (1, "a"), (3, "c")]);
945        let slice: &[(i32, &str)] = frozen.as_ref();
946        assert_eq!(slice, &[(1, "a"), (2, "b"), (3, "c")]);
947
948        let empty = FrozenMap::<i32, i32>::new();
949        let empty_slice: &[(i32, i32)] = empty.as_ref();
950        assert_eq!(empty_slice, &[]);
951    }
952
953    #[test]
954    fn test_from_hashmap() {
955        let mut map = HashMap::new();
956        map.insert(3, "c");
957        map.insert(1, "a");
958        map.insert(2, "b");
959
960        let frozen = FrozenMap::from(map);
961        assert_eq!(frozen.len(), 3);
962        assert_eq!(frozen.get(&1), Some(&"a"));
963        let keys: Vec<_> = frozen.keys().copied().collect();
964        assert_eq!(keys, vec![1, 2, 3]);
965    }
966
967    #[test]
968    fn test_from_unique_sorted_box() {
969        let frozen = FrozenMap::from_unique_sorted_box(Box::from([(1, "a"), (2, "b")]));
970        assert_eq!(frozen.len(), 2);
971        assert_eq!(frozen.get(&1), Some(&"a"));
972        assert_eq!(frozen.get(&2), Some(&"b"));
973    }
974
975    #[test]
976    #[should_panic(expected = "FrozenMap entries must be unique and sorted")]
977    fn test_from_unique_sorted_box_panics() {
978        let _ = FrozenMap::from_unique_sorted_box(Box::from([(1, "a"), (1, "b")]));
979    }
980}