1 // Copyright (c) Facebook, Inc. and its affiliates.
3 // This source code is licensed under the MIT license found in the
4 // LICENSE file in the "hack" directory of this source tree.
6 //! Associative array types.
8 //! At the moment, we are using the bumpalo allocator for arena allocation.
9 //! Because the stdlib types do not yet provide the ability to choose the
10 //! allocator used when they are allocated or resized, the bumpalo library
11 //! provides its own growable Vec and String types. Since bumpalo does not
12 //! provide its own map or set types, we must define our own if we want to
13 //! control where they are allocated.
15 //! This module defines map types backed by bumpalo's Vec. It is useful for maps
16 //! which are built all at once, and never modified thereafter (e.g., maps in
17 //! ASTs). When immutable semantics are desired, but updating is necessary,
18 //! consider the `arena_collections::map` submodule instead, for an immutable
19 //! balanced binary tree. The Vec-backed maps in this module may benefit from
20 //! better cache efficiency, and so may outperform the balanced tree
21 //! implementation in some circumstances.
23 use std::borrow::Borrow;
27 use serde::{Deserialize, Serialize};
29 use arena_trait::TrivialDrop;
30 use ocamlrep::{FromOcamlRepIn, ToOcamlRep};
32 /// Perform a linear search for the last entry in the slice with the given key.
34 fn get_last_entry<'a, K, V, Q: ?Sized>(entries: &'a [(K, V)], key: &Q) -> Option<&'a (K, V)>
39 entries.iter().rev().find(|(k, _)| key == k.borrow())
42 /// Perform a linear search for the last entry in the slice with the given key
43 /// and return its index in the slice.
45 fn get_last_index<'a, K, V, Q: ?Sized>(entries: &'a [(K, V)], key: &Q) -> Option<usize>
54 .find(|(_, (k, _))| key == k.borrow())
58 /// A readonly associative array.
60 /// * Lookups run in linear time
61 /// * Entries with duplicate keys are permitted (but only observable using iterators)
62 #[derive(Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
63 pub struct AssocList<'a, K, V> {
64 entries: &'a [(K, V)],
67 impl<'a, K, V> AssocList<'a, K, V> {
68 /// Make a new `AssocList` containing the given key-value pairs.
73 /// use arena_collections::AssocList;
75 /// let entries = [(1, "a")];
76 /// let alist = AssocList::new(&entries[..]);
79 pub const fn new(entries: &'a [(K, V)]) -> Self {
83 /// Returns a reference to the value corresponding to the key.
85 /// The key may be any borrowed form of the list's key type, but the
86 /// ordering on the borrowed form *must* match the ordering on the key type.
88 /// If multiple entries in the map have keys equal to the given key, the
89 /// value corresponding to the last entry (the one with the larger index in
90 /// the slice passed to `AssocList::new`) will be returned.
95 /// use arena_collections::AssocList;
97 /// let entries = [(1, "a")];
98 /// let alist = AssocList::new(&entries[..]);
99 /// assert_eq!(alist.get(&1), Some(&"a"));
100 /// assert_eq!(alist.get(&2), None);
102 pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>
107 get_last_entry(self.entries, key).map(|(_, v)| v)
110 /// Returns the key-value pair corresponding to the supplied key.
112 /// The key may be any borrowed form of the list's key type, but the
113 /// ordering on the borrowed form *must* match the ordering on the key type.
115 /// If multiple entries in the map have keys equal to the given key, the
116 /// last entry (the one with the larger index in the slice passed to
117 /// `AssocList::new`) will be returned.
122 /// use arena_collections::AssocList;
124 /// let entries = [(1, "a")];
125 /// let alist = AssocList::new(&entries[..]);
126 /// assert_eq!(alist.get_key_value(&1), Some((&1, &"a")));
127 /// assert_eq!(alist.get_key_value(&2), None);
129 pub fn get_key_value<Q: ?Sized>(&self, key: &Q) -> Option<(&K, &V)>
134 get_last_entry(self.entries, key).map(|(k, v)| (k, v))
137 /// Returns `true` if the list contains a value for the specified key.
139 /// The key may be any borrowed form of the list's key type, but the
140 /// ordering on the borrowed form *must* match the ordering on the key type.
145 /// use arena_collections::AssocList;
147 /// let entries = [(1, "a")];
148 /// let alist = AssocList::new(&entries[..]);
149 /// assert_eq!(alist.contains_key(&1), true);
150 /// assert_eq!(alist.contains_key(&2), false);
152 pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
157 get_last_entry(self.entries, key).is_some()
160 /// Gets an iterator over the entries of the association list.
165 /// use arena_collections::AssocList;
167 /// let entries = [(1, "a"), (2, "b")];
168 /// let alist = AssocList::new(&entries[..]);
170 /// for (key, value) in alist.iter() {
171 /// println!("{}: {}", key, value);
174 /// let (first_key, first_value) = alist.iter().next().unwrap();
175 /// assert_eq!((*first_key, *first_value), (1, "a"));
177 pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
178 self.entries.iter().map(|(k, v)| (k, v))
181 /// Gets an iterator over the keys of the association list.
186 /// use arena_collections::AssocList;
188 /// let entries = [(1, "a"), (2, "b")];
189 /// let alist = AssocList::new(&entries[..]);
191 /// let keys: Vec<_> = alist.keys().copied().collect();
192 /// assert_eq!(keys, [1, 2]);
194 pub fn keys(&self) -> impl Iterator<Item = &K> {
195 self.entries.iter().map(|(k, _)| k)
198 /// Gets an iterator over the values of the association list.
203 /// use arena_collections::AssocList;
205 /// let entries = [(1, "hello"), (2, "goodbye")];
206 /// let alist = AssocList::new(&entries[..]);
208 /// let values: Vec<&str> = alist.values().copied().collect();
209 /// assert_eq!(values, ["hello", "goodbye"]);
211 pub fn values(&self) -> impl Iterator<Item = &V> {
212 self.entries.iter().map(|(_, v)| v)
215 /// Returns the number of entries in the list.
220 /// use arena_collections::AssocList;
222 /// let entries = [(1, "a")];
223 /// let alist = AssocList::new(&entries[0..entries]);
224 /// assert_eq!(alist.len(), 0);
225 /// let alist = AssocList::new(&entries[0..1]);
226 /// assert_eq!(alist.len(), 1);
228 pub fn len(&self) -> usize {
232 /// Returns `true` if the list contains no entries.
237 /// use arena_collections::AssocList;
239 /// let entries = [(1, "a")];
240 /// let alist = AssocList::new(&entries[0..entries]);
241 /// assert!(alist.is_empty());
242 /// let alist = AssocList::new(&entries[0..1]);
243 /// assert!(!alist.is_empty());
245 pub fn is_empty(&self) -> bool {
246 self.entries.is_empty()
250 impl<K, V> TrivialDrop for AssocList<'_, K, V> {}
251 impl<K, V> Copy for AssocList<'_, K, V> {}
252 impl<K, V> Clone for AssocList<'_, K, V> {
253 fn clone(&self) -> Self {
258 impl<K: Debug, V: Debug> Debug for AssocList<'_, K, V> {
259 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
260 fmt.debug_map().entries(self.iter()).finish()
264 impl<'a, K, V> From<AssocListMut<'a, K, V>> for AssocList<'a, K, V> {
266 fn from(alist: AssocListMut<'a, K, V>) -> Self {
267 AssocList::new(alist.entries.into_bump_slice())
271 /// A mutable associative array, allocated in a given arena.
273 /// * Lookups, replacements, and removals run in linear time
274 /// * Insertions run in constant time
275 /// * Entries with duplicate keys are permitted (but only observable using iterators)
276 #[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
277 pub struct AssocListMut<'bump, K, V> {
278 entries: bumpalo::collections::Vec<'bump, (K, V)>,
281 impl<'bump, K, V> AssocListMut<'bump, K, V> {
282 /// Constructs a new, empty `AssocListMut`.
284 /// The list will not allocate until entries are inserted.
289 /// use bumpalo::Bump;
290 /// use arena_collections::AssocListMut;
292 /// let b = Bump::new();
293 /// let mut alist: AssocListMut<i32> = AssocListMut::new_in(&b);
296 pub fn new_in(bump: &'bump Bump) -> Self {
298 entries: bumpalo::collections::Vec::new_in(bump),
302 /// Constructs a new, empty `AssocListMut` with the specified capacity.
304 /// The list will be able to hold exactly `capacity` elements without
305 /// reallocating. If `capacity` is 0, the list will not allocate.
307 /// It is important to note that although the returned list has the
308 /// *capacity* specified, the list will have a zero *length*.
313 /// use bumpalo::Bump;
314 /// use arena_collections::AssocListMut;
316 /// let b = Bump::new();
318 /// let mut alist = AssocListMut::with_capacity_in(10, &b);
320 /// // The list contains no items, even though it has capacity for more
321 /// assert_eq!(alist.len(), 0);
323 /// // These are all done without reallocating...
325 /// alist.insert(i, i);
328 /// // ...but this may make the list reallocate
329 /// alist.insert(11, 11);
332 pub fn with_capacity_in(capacity: usize, bump: &'bump Bump) -> Self {
334 entries: bumpalo::collections::Vec::with_capacity_in(capacity, bump),
338 /// Insert the given key-value pair into the association list.
340 /// If an entry with the given key already exists in the list, it will
341 /// remain there, but future calls to `AssocListMut::get` will return the
342 /// newly-inserted value instead of the extant one.
347 /// use bumpalo::Bump;
348 /// use arena_collections::AssocListMut;
350 /// let b = Bump::new();
351 /// let mut alist = AssocListMut::new_in(&b);
352 /// alist.insert(1, "a");
353 /// assert_eq!(alist.get(&1), Some(&"a"));
354 /// alist.insert(1, "b");
355 /// assert_eq!(alist.get(&1), Some(&"b"));
356 /// assert_eq!(alist.len(), 2);
359 pub fn insert(&mut self, key: K, value: V) {
360 self.entries.push((key, value))
363 /// Insert the given key-value pair into the association list.
365 /// If one entry with the given key already exists in the list, it will be
366 /// removed, and its value will be returned. If multiple entries with the
367 /// given key already exist in the list, only the most recently inserted one
373 /// use bumpalo::Bump;
374 /// use arena_collections::AssocListMut;
376 /// let b = Bump::new();
377 /// let mut alist = AssocListMut::new_in(&b);
378 /// alist.insert_or_replace(1, "a");
379 /// assert_eq!(alist.get(&1), Some(&"a"));
380 /// alist.insert_or_replace(1, "b");
381 /// assert_eq!(alist.get(&1), Some(&"b"));
382 /// assert_eq!(alist.len(), 1);
384 pub fn insert_or_replace(&mut self, key: K, value: V) -> Option<V>
388 match get_last_index(&self.entries, &key) {
390 self.insert(key, value);
394 let mut entry = (key, value);
395 std::mem::swap(&mut self.entries[idx], &mut entry);
401 /// Remove a key from the list, returning the value at the key if the key
402 /// was previously in the list.
404 /// The key may be any borrowed form of the list's key type, but the
405 /// ordering on the borrowed form *must* match the ordering on the key type.
407 /// If multiple entries with the given key exist in the list, only the last
408 /// will be removed (the one which would b returned by
409 /// `AssocListMut::get`).
414 /// use bumpalo::Bump;
415 /// use arena_collections::AssocListMut;
417 /// let b = Bump::new();
418 /// let mut alist = AssocListMut::new_in(&b);
419 /// alist.insert(1, "a");
420 /// alist.insert(1, "b");
421 /// assert_eq!(alist.get(&1), Some(&"b"));
422 /// alist.remove(&1);
423 /// assert_eq!(alist.get(&1), Some(&"a"));
424 /// alist.remove(&1);
425 /// assert_eq!(alist.get(&1), None);
427 pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
432 match get_last_index(&self.entries, key) {
434 Some(idx) => Some(self.entries.remove(idx).1),
438 /// Removes all entries with the given key from the list. Returns true if
439 /// any entries were removed.
441 /// The key may be any borrowed form of the list's key type, but the
442 /// ordering on the borrowed form *must* match the ordering on the key type.
447 /// use bumpalo::Bump;
448 /// use arena_collections::AssocListMut;
450 /// let b = Bump::new();
451 /// let mut alist = AssocListMut::new_in(&b);
452 /// alist.insert(1, "a");
453 /// alist.insert(1, "b");
454 /// assert_eq!(alist.get(&1), Some(&"b"));
455 /// alist.remove_all(&1);
456 /// assert_eq!(alist.get(&1), None);
458 pub fn remove_all<Q: ?Sized>(&mut self, key: &Q) -> bool
463 let len_before = self.len();
464 self.entries.retain(|(k, _)| key != k.borrow());
465 let len_after = self.len();
466 len_before != len_after
469 /// Returns a reference to the value corresponding to the key.
471 /// The key may be any borrowed form of the list's key type, but the
472 /// ordering on the borrowed form *must* match the ordering on the key type.
474 /// If multiple entries in the map have keys equal to the given key, the
475 /// value in the most recently inserted entry will be returned.
480 /// use bumpalo::Bump;
481 /// use arena_collections::AssocListMut;
483 /// let b = Bump::new();
484 /// let mut alist = AssocListMut::new_in(&b);
485 /// alist.insert(1, "a");
486 /// assert_eq!(alist.get(&1), Some(&"a"));
487 /// assert_eq!(alist.get(&2), None);
489 pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>
494 get_last_entry(&self.entries, key).map(|(_, v)| v)
497 /// Returns the key-value pair corresponding to the supplied key.
499 /// The key may be any borrowed form of the list's key type, but the
500 /// ordering on the borrowed form *must* match the ordering on the key type.
502 /// If multiple entries in the map have keys equal to the given key, the
503 /// most recently inserted entry will be returned.
508 /// use bumpalo::Bump;
509 /// use arena_collections::AssocListMut;
511 /// let b = Bump::new();
512 /// let mut alist = AssocListMut::new_in(&b);
513 /// alist.insert(1, "a");
514 /// assert_eq!(alist.get_key_value(&1), Some((&1, &"a")));
515 /// assert_eq!(alist.get_key_value(&2), None);
517 pub fn get_key_value<Q: ?Sized>(&self, key: &Q) -> Option<(&K, &V)>
522 get_last_entry(&self.entries, key).map(|(k, v)| (k, v))
525 /// Returns `true` if the list contains a value for the specified key.
527 /// The key may be any borrowed form of the list's key type, but the
528 /// ordering on the borrowed form *must* match the ordering on the key type.
533 /// use bumpalo::Bump;
534 /// use arena_collections::AssocListMut;
536 /// let b = Bump::new();
537 /// let mut alist = AssocListMut::new_in(&b);
538 /// alist.insert(1, "a");
539 /// assert_eq!(alist.contains_key(&1), true);
540 /// assert_eq!(alist.contains_key(&2), false);
542 pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
547 self.get(key).is_some()
550 /// Gets an iterator over the entries of the association list.
555 /// use bumpalo::Bump;
556 /// use arena_collections::AssocListMut;
558 /// let b = Bump::new();
559 /// let mut alist = AssocListMut::new_in(&b);
560 /// alist.insert(1, "a");
561 /// alist.insert(2, "b");
563 /// for (key, value) in alist.iter() {
564 /// println!("{}: {}", key, value);
567 /// let (first_key, first_value) = alist.iter().next().unwrap();
568 /// assert_eq!((*first_key, *first_value), (1, "a"));
570 pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
571 self.entries.iter().map(|(k, v)| (k, v))
574 /// Gets an iterator over the keys of the association list.
579 /// use bumpalo::Bump;
580 /// use arena_collections::AssocListMut;
582 /// let b = Bump::new();
583 /// let mut alist = AssocListMut::new_in(&b);
584 /// alist.insert(1, "a");
585 /// alist.insert(2, "b");
587 /// let keys: Vec<_> = alist.keys().copied().collect();
588 /// assert_eq!(keys, [1, 2]);
590 pub fn keys(&self) -> impl Iterator<Item = &K> {
591 self.entries.iter().map(|(k, _)| k)
594 /// Gets an iterator over the values of the association list.
599 /// use bumpalo::Bump;
600 /// use arena_collections::AssocListMut;
602 /// let b = Bump::new();
603 /// let mut alist = AssocListMut::new_in(&b);
604 /// alist.insert(1, "hello");
605 /// alist.insert(2, "goodbye");
607 /// let values: Vec<&str> = alist.values().copied().collect();
608 /// assert_eq!(values, ["hello", "goodbye"]);
610 pub fn values(&self) -> impl Iterator<Item = &V> {
611 self.entries.iter().map(|(_, v)| v)
614 /// Returns the number of entries in the list.
619 /// use bumpalo::Bump;
620 /// use arena_collections::AssocListMut;
622 /// let b = Bump::new();
623 /// let mut alist = AssocListMut::new_in(&b);
624 /// assert_eq!(alist.len(), 0);
625 /// alist.insert(1, "a");
626 /// assert_eq!(alist.len(), 1);
628 pub fn len(&self) -> usize {
632 /// Returns `true` if the list contains no entries.
637 /// use bumpalo::Bump;
638 /// use arena_collections::AssocListMut;
640 /// let b = Bump::new();
641 /// let mut alist = AssocListMut::new_in(&b);
642 /// assert!(alist.is_empty());
643 /// alist.insert(1, "a");
644 /// assert!(!alist.is_empty());
646 pub fn is_empty(&self) -> bool {
647 self.entries.is_empty()
651 impl<K: Debug, V: Debug> Debug for AssocListMut<'_, K, V> {
652 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
653 fmt.debug_map().entries(self.iter()).finish()
657 /// Get an entry in the slice with the given key. Performs a linear search on
658 /// small slices, and a binary search otherwise.
660 fn get_sorted_entry<'a, K, V, Q: ?Sized>(entries: &'a [(K, V)], key: &Q) -> Option<&'a (K, V)>
665 // TODO: tune this threshold based on perf results
666 const BINARY_SEARCH_LEN_THRESHOLD: usize = 32;
668 if entries.len() < BINARY_SEARCH_LEN_THRESHOLD {
669 entries.iter().find(|(k, _)| key == k.borrow())
672 .binary_search_by(|(k, _)| k.borrow().cmp(key))
674 Some(&entries[index])
678 /// A readonly associative array, sorted by key, containing no duplicate keys.
680 /// * Lookups run in log(n) time
681 /// * Entries with duplicate keys are not permitted. When constructing a
682 /// `SortedAssocList` from an `AssocListMut`, entries will be deduplicated by
683 /// key, and only the most recently inserted entry for each key will be
685 #[derive(Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
687 deserialize = "K: 'de + arena_deserializer::DeserializeInArena<'de>, V: 'de + arena_deserializer::DeserializeInArena<'de>"
689 pub struct SortedAssocList<'a, K, V> {
690 #[serde(deserialize_with = "arena_deserializer::arena", borrow)]
691 entries: &'a [(K, V)],
694 arena_deserializer::impl_deserialize_in_arena!(SortedAssocList<'arena, K, V>);
696 impl<'a, K, V> SortedAssocList<'a, K, V> {
697 /// Returns the empty association list.
698 pub fn empty() -> Self {
699 SortedAssocList { entries: &[] }
702 /// Returns a reference to the value corresponding to the key.
704 /// The key may be any borrowed form of the list's key type, but the
705 /// ordering on the borrowed form *must* match the ordering on the key type.
710 /// use bumpalo::Bump;
711 /// use arena_collections::{AssocListMut, SortedAssocList};
713 /// let b = Bump::new();
714 /// let mut alist = AssocListMut::new_in(&b);
715 /// alist.insert(1, "a");
716 /// let alist = SortedAssocList::from(alist);
717 /// assert_eq!(alist.get(&1), Some(&"a"));
718 /// assert_eq!(alist.get(&2), None);
720 pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>
725 get_sorted_entry(self.entries, key).map(|(_, v)| v)
728 /// Returns the key-value pair corresponding to the supplied key.
730 /// The key may be any borrowed form of the list's key type, but the
731 /// ordering on the borrowed form *must* match the ordering on the key type.
736 /// use bumpalo::Bump;
737 /// use arena_collections::{AssocListMut, SortedAssocList};
739 /// let b = Bump::new();
740 /// let mut alist = AssocListMut::new_in(&b);
741 /// alist.insert(1, "a");
742 /// let alist = SortedAssocList::from(alist);
743 /// assert_eq!(alist.get_key_value(&1), Some((&1, &"a")));
744 /// assert_eq!(alist.get_key_value(&2), None);
746 pub fn get_key_value<Q: ?Sized>(&self, key: &Q) -> Option<(&K, &V)>
751 get_sorted_entry(self.entries, key).map(|(k, v)| (k, v))
754 /// Returns `true` if the list contains a value for the specified key.
756 /// The key may be any borrowed form of the list's key type, but the
757 /// ordering on the borrowed form *must* match the ordering on the key type.
762 /// use bumpalo::Bump;
763 /// use arena_collections::{AssocListMut, SortedAssocList};
765 /// let b = Bump::new();
766 /// let mut alist = AssocListMut::new_in(&b);
767 /// alist.insert(1, "a");
768 /// let alist = SortedAssocList::from(alist);
769 /// assert_eq!(alist.contains_key(&1), true);
770 /// assert_eq!(alist.contains_key(&2), false);
772 pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
777 get_sorted_entry(self.entries, key).is_some()
780 /// Gets an iterator over the entries of the association list, sorted by
786 /// use bumpalo::Bump;
787 /// use arena_collections::{AssocListMut, SortedAssocList};
789 /// let b = Bump::new();
790 /// let mut alist = AssocListMut::new_in(&b);
792 /// alist.insert(1, "a");
793 /// alist.insert(2, "b");
795 /// let alist = SortedAssocList::from(alist);
797 /// for (key, value) in alist.iter() {
798 /// println!("{}: {}", key, value);
801 /// let (first_key, first_value) = alist.iter().next().unwrap();
802 /// assert_eq!((*first_key, *first_value), (1, "a"));
804 pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
805 self.entries.iter().map(|(k, v)| (k, v))
808 /// Gets an iterator over the keys of the association list, in sorted order.
813 /// use bumpalo::Bump;
814 /// use arena_collections::{AssocListMut, SortedAssocList};
816 /// let b = Bump::new();
817 /// let mut alist = AssocListMut::new_in(&b);
819 /// alist.insert(1, "a");
820 /// alist.insert(2, "b");
822 /// let alist = SortedAssocList::from(alist);
823 /// let keys: Vec<_> = alist.keys().copied().collect();
824 /// assert_eq!(keys, [1, 2]);
826 pub fn keys(&self) -> impl Iterator<Item = &K> {
827 self.entries.iter().map(|(k, _)| k)
830 /// Gets an iterator over the values of the association list, in order by
836 /// use bumpalo::Bump;
837 /// use arena_collections::{AssocListMut, SortedAssocList};
839 /// let b = Bump::new();
840 /// let mut alist = AssocListMut::new_in(&b);
842 /// alist.insert(1, "hello");
843 /// alist.insert(2, "goodbye");
845 /// let alist = SortedAssocList::from(alist);
846 /// let values: Vec<&str> = alist.values().copied().collect();
847 /// assert_eq!(values, ["hello", "goodbye"]);
849 pub fn values(&self) -> impl Iterator<Item = &V> {
850 self.entries.iter().map(|(_, v)| v)
853 /// Returns the number of entries in the list.
858 /// use bumpalo::Bump;
859 /// use arena_collections::{AssocListMut, SortedAssocList};
861 /// let b = Bump::new();
862 /// let mut alist = AssocListMut::new_in(&b);
863 /// alist.insert(1, "a");
864 /// alist.insert(1, "b");
865 /// let alist = SortedAssocList::from(alist);
866 /// assert_eq!(alist.len(), 1);
868 pub fn len(&self) -> usize {
872 /// Returns `true` if the list contains no entries.
877 /// use bumpalo::Bump;
878 /// use arena_collections::{AssocListMut, SortedAssocList};
880 /// let b = Bump::new();
881 /// let mut alist = AssocListMut::new_in(&b);
882 /// let alist = SortedAssocList::from(alist);
883 /// assert!(alist.is_empty());
885 pub fn is_empty(&self) -> bool {
886 self.entries.is_empty()
889 /// Make a new `SortedAssocList` containing the given key-value pairs.
891 /// Provided for the sake of creating empty const lists. Passing non-empty
892 /// slices is not recommended.
894 /// The values in the slice must be in ascending sorted order (by `K`'s
895 /// implementation of `Ord`). There must be no duplicate keys in the slice.
900 /// use bumpalo::Bump;
901 /// use arena_collections::{AssocListMut, SortedAssocList};
903 /// let b = Bump::new();
904 /// let mut alist = AssocListMut::new_in(&b);
906 /// const EMPTY_ALIST: SortedAssocList<'_, usize> = SortedAssocList::from_slice(&[]);
907 /// assert!(EMPTY_ALIST.is_empty());
909 pub const fn from_slice(entries: &'a [(K, V)]) -> Self {
914 impl<K, V> TrivialDrop for SortedAssocList<'_, K, V> {}
915 impl<K, V> Copy for SortedAssocList<'_, K, V> {}
916 impl<K, V> Clone for SortedAssocList<'_, K, V> {
917 fn clone(&self) -> Self {
922 impl<K, V> Default for SortedAssocList<'_, K, V> {
923 fn default() -> Self {
924 Self::from_slice(&[])
928 impl<K: Debug, V: Debug> Debug for SortedAssocList<'_, K, V> {
929 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
930 fmt.debug_map().entries(self.iter()).finish()
934 impl<'a, K: Ord, V> From<AssocListMut<'a, K, V>> for SortedAssocList<'a, K, V> {
936 fn from(mut alist: AssocListMut<'a, K, V>) -> Self {
937 let entries_mut = alist.entries.as_mut_slice();
938 // Reverse the slice so the most recently inserted pairs appear first.
939 entries_mut.reverse();
940 // Keep recently-inserted pairs first with a stable sort. Allocates
941 // temporary storage half the size of the slice using the global
942 // allocator if the slice is larger than some threshold (20 elements at
944 entries_mut.sort_by(|(k1, _), (k2, _)| k1.cmp(k2));
945 // Remove all but the most recently inserted pair for each key.
946 alist.entries.dedup_by(|(k1, _), (k2, _)| k1 == k2);
948 entries: alist.entries.into_bump_slice(),
953 impl<K: ToOcamlRep + Ord, V: ToOcamlRep> ToOcamlRep for SortedAssocList<'_, K, V> {
954 fn to_ocamlrep<'a, A: ocamlrep::Allocator>(
957 ) -> ocamlrep::OpaqueValue<'a> {
958 let len = self.len();
959 let mut iter = self.iter();
960 let (value, _) = ocamlrep::sorted_iter_to_ocaml_map(&mut iter, alloc, len);
965 impl<'a, K, V> FromOcamlRepIn<'a> for SortedAssocList<'a, K, V>
967 K: FromOcamlRepIn<'a> + Ord,
968 V: FromOcamlRepIn<'a>,
971 value: ocamlrep::Value<'_>,
972 alloc: &'a bumpalo::Bump,
973 ) -> Result<Self, ocamlrep::FromError> {
974 let mut entries = bumpalo::collections::Vec::new_in(alloc);
975 ocamlrep::vec_from_ocaml_map_in(value, &mut entries, alloc)?;
976 let entries = entries.into_bump_slice();