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;
26 use arena_trait::TrivialDrop;
28 use ocamlrep::FromOcamlRepIn;
29 use ocamlrep::ToOcamlRep;
30 use serde::Deserialize;
33 /// Perform a linear search for the last entry in the slice with the given key.
35 fn get_last_entry<'a, K, V, Q: ?Sized>(entries: &'a [(K, V)], key: &Q) -> Option<&'a (K, V)>
40 entries.iter().rev().find(|(k, _)| key == k.borrow())
43 /// Perform a linear search for the last entry in the slice with the given key
44 /// and return its index in the slice.
46 fn get_last_index<'a, K, V, Q: ?Sized>(entries: &'a [(K, V)], key: &Q) -> Option<usize>
55 .find(|(_, (k, _))| key == k.borrow())
59 /// A readonly associative array.
61 /// * Lookups run in linear time
62 /// * Entries with duplicate keys are permitted (but only observable using iterators)
63 #[derive(Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
64 pub struct AssocList<'a, K, V> {
65 entries: &'a [(K, V)],
68 impl<'a, K, V> AssocList<'a, K, V> {
69 /// Make a new `AssocList` containing the given key-value pairs.
74 /// use arena_collections::AssocList;
76 /// let entries = [(1, "a")];
77 /// let alist = AssocList::new(&entries[..]);
80 pub const fn new(entries: &'a [(K, V)]) -> Self {
84 /// Returns a reference to the value corresponding to the key.
86 /// The key may be any borrowed form of the list's key type, but the
87 /// ordering on the borrowed form *must* match the ordering on the key type.
89 /// If multiple entries in the map have keys equal to the given key, the
90 /// value corresponding to the last entry (the one with the larger index in
91 /// the slice passed to `AssocList::new`) will be returned.
96 /// use arena_collections::AssocList;
98 /// let entries = [(1, "a")];
99 /// let alist = AssocList::new(&entries[..]);
100 /// assert_eq!(alist.get(&1), Some(&"a"));
101 /// assert_eq!(alist.get(&2), None);
103 pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>
108 get_last_entry(self.entries, key).map(|(_, v)| v)
111 /// Returns the key-value pair corresponding to the supplied key.
113 /// The key may be any borrowed form of the list's key type, but the
114 /// ordering on the borrowed form *must* match the ordering on the key type.
116 /// If multiple entries in the map have keys equal to the given key, the
117 /// last entry (the one with the larger index in the slice passed to
118 /// `AssocList::new`) will be returned.
123 /// use arena_collections::AssocList;
125 /// let entries = [(1, "a")];
126 /// let alist = AssocList::new(&entries[..]);
127 /// assert_eq!(alist.get_key_value(&1), Some((&1, &"a")));
128 /// assert_eq!(alist.get_key_value(&2), None);
130 pub fn get_key_value<Q: ?Sized>(&self, key: &Q) -> Option<(&K, &V)>
135 get_last_entry(self.entries, key).map(|(k, v)| (k, v))
138 /// Returns `true` if the list contains a value for the specified key.
140 /// The key may be any borrowed form of the list's key type, but the
141 /// ordering on the borrowed form *must* match the ordering on the key type.
146 /// use arena_collections::AssocList;
148 /// let entries = [(1, "a")];
149 /// let alist = AssocList::new(&entries[..]);
150 /// assert_eq!(alist.contains_key(&1), true);
151 /// assert_eq!(alist.contains_key(&2), false);
153 pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
158 get_last_entry(self.entries, key).is_some()
161 /// Gets an iterator over the entries of the association list.
166 /// use arena_collections::AssocList;
168 /// let entries = [(1, "a"), (2, "b")];
169 /// let alist = AssocList::new(&entries[..]);
171 /// for (key, value) in alist.iter() {
172 /// println!("{}: {}", key, value);
175 /// let (first_key, first_value) = alist.iter().next().unwrap();
176 /// assert_eq!((*first_key, *first_value), (1, "a"));
178 pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
179 self.entries.iter().map(|(k, v)| (k, v))
182 /// Gets an iterator over the keys of the association list.
187 /// use arena_collections::AssocList;
189 /// let entries = [(1, "a"), (2, "b")];
190 /// let alist = AssocList::new(&entries[..]);
192 /// let keys: Vec<_> = alist.keys().copied().collect();
193 /// assert_eq!(keys, [1, 2]);
195 pub fn keys(&self) -> impl Iterator<Item = &K> {
196 self.entries.iter().map(|(k, _)| k)
199 /// Gets an iterator over the values of the association list.
204 /// use arena_collections::AssocList;
206 /// let entries = [(1, "hello"), (2, "goodbye")];
207 /// let alist = AssocList::new(&entries[..]);
209 /// let values: Vec<&str> = alist.values().copied().collect();
210 /// assert_eq!(values, ["hello", "goodbye"]);
212 pub fn values(&self) -> impl Iterator<Item = &V> {
213 self.entries.iter().map(|(_, v)| v)
216 /// Returns the number of entries in the list.
221 /// use arena_collections::AssocList;
223 /// let entries = [(1, "a")];
224 /// let alist = AssocList::new(&entries[0..entries]);
225 /// assert_eq!(alist.len(), 0);
226 /// let alist = AssocList::new(&entries[0..1]);
227 /// assert_eq!(alist.len(), 1);
229 pub fn len(&self) -> usize {
233 /// Returns `true` if the list contains no entries.
238 /// use arena_collections::AssocList;
240 /// let entries = [(1, "a")];
241 /// let alist = AssocList::new(&entries[0..entries]);
242 /// assert!(alist.is_empty());
243 /// let alist = AssocList::new(&entries[0..1]);
244 /// assert!(!alist.is_empty());
246 pub fn is_empty(&self) -> bool {
247 self.entries.is_empty()
251 impl<K, V> TrivialDrop for AssocList<'_, K, V> {}
252 impl<K, V> Copy for AssocList<'_, K, V> {}
253 impl<K, V> Clone for AssocList<'_, K, V> {
254 fn clone(&self) -> Self {
259 impl<K: Debug, V: Debug> Debug for AssocList<'_, K, V> {
260 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
261 fmt.debug_map().entries(self.iter()).finish()
265 impl<'a, K, V> From<AssocListMut<'a, K, V>> for AssocList<'a, K, V> {
267 fn from(alist: AssocListMut<'a, K, V>) -> Self {
268 AssocList::new(alist.entries.into_bump_slice())
272 /// A mutable associative array, allocated in a given arena.
274 /// * Lookups, replacements, and removals run in linear time
275 /// * Insertions run in constant time
276 /// * Entries with duplicate keys are permitted (but only observable using iterators)
277 #[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
278 pub struct AssocListMut<'bump, K, V> {
279 entries: bumpalo::collections::Vec<'bump, (K, V)>,
282 impl<'bump, K, V> AssocListMut<'bump, K, V> {
283 /// Constructs a new, empty `AssocListMut`.
285 /// The list will not allocate until entries are inserted.
290 /// use arena_collections::AssocListMut;
291 /// use bumpalo::Bump;
293 /// let b = Bump::new();
294 /// let mut alist: AssocListMut<i32> = AssocListMut::new_in(&b);
297 pub fn new_in(bump: &'bump Bump) -> Self {
299 entries: bumpalo::collections::Vec::new_in(bump),
303 /// Constructs a new, empty `AssocListMut` with the specified capacity.
305 /// The list will be able to hold exactly `capacity` elements without
306 /// reallocating. If `capacity` is 0, the list will not allocate.
308 /// It is important to note that although the returned list has the
309 /// *capacity* specified, the list will have a zero *length*.
314 /// use arena_collections::AssocListMut;
315 /// use bumpalo::Bump;
317 /// let b = Bump::new();
319 /// let mut alist = AssocListMut::with_capacity_in(10, &b);
321 /// // The list contains no items, even though it has capacity for more
322 /// assert_eq!(alist.len(), 0);
324 /// // These are all done without reallocating...
326 /// alist.insert(i, i);
329 /// // ...but this may make the list reallocate
330 /// alist.insert(11, 11);
333 pub fn with_capacity_in(capacity: usize, bump: &'bump Bump) -> Self {
335 entries: bumpalo::collections::Vec::with_capacity_in(capacity, bump),
339 /// Insert the given key-value pair into the association list.
341 /// If an entry with the given key already exists in the list, it will
342 /// remain there, but future calls to `AssocListMut::get` will return the
343 /// newly-inserted value instead of the extant one.
348 /// use arena_collections::AssocListMut;
349 /// use bumpalo::Bump;
351 /// let b = Bump::new();
352 /// let mut alist = AssocListMut::new_in(&b);
353 /// alist.insert(1, "a");
354 /// assert_eq!(alist.get(&1), Some(&"a"));
355 /// alist.insert(1, "b");
356 /// assert_eq!(alist.get(&1), Some(&"b"));
357 /// assert_eq!(alist.len(), 2);
360 pub fn insert(&mut self, key: K, value: V) {
361 self.entries.push((key, value))
364 /// Insert the given key-value pair into the association list.
366 /// If one entry with the given key already exists in the list, it will be
367 /// removed, and its value will be returned. If multiple entries with the
368 /// given key already exist in the list, only the most recently inserted one
374 /// use arena_collections::AssocListMut;
375 /// use bumpalo::Bump;
377 /// let b = Bump::new();
378 /// let mut alist = AssocListMut::new_in(&b);
379 /// alist.insert_or_replace(1, "a");
380 /// assert_eq!(alist.get(&1), Some(&"a"));
381 /// alist.insert_or_replace(1, "b");
382 /// assert_eq!(alist.get(&1), Some(&"b"));
383 /// assert_eq!(alist.len(), 1);
385 pub fn insert_or_replace(&mut self, key: K, value: V) -> Option<V>
389 match get_last_index(&self.entries, &key) {
391 self.insert(key, value);
395 let mut entry = (key, value);
396 std::mem::swap(&mut self.entries[idx], &mut entry);
402 /// Remove a key from the list, returning the value at the key if the key
403 /// was previously in the list.
405 /// The key may be any borrowed form of the list's key type, but the
406 /// ordering on the borrowed form *must* match the ordering on the key type.
408 /// If multiple entries with the given key exist in the list, only the last
409 /// will be removed (the one which would b returned by
410 /// `AssocListMut::get`).
415 /// use arena_collections::AssocListMut;
416 /// use bumpalo::Bump;
418 /// let b = Bump::new();
419 /// let mut alist = AssocListMut::new_in(&b);
420 /// alist.insert(1, "a");
421 /// alist.insert(1, "b");
422 /// assert_eq!(alist.get(&1), Some(&"b"));
423 /// alist.remove(&1);
424 /// assert_eq!(alist.get(&1), Some(&"a"));
425 /// alist.remove(&1);
426 /// assert_eq!(alist.get(&1), None);
428 pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
433 match get_last_index(&self.entries, key) {
435 Some(idx) => Some(self.entries.remove(idx).1),
439 /// Removes all entries with the given key from the list. Returns true if
440 /// any entries were removed.
442 /// The key may be any borrowed form of the list's key type, but the
443 /// ordering on the borrowed form *must* match the ordering on the key type.
448 /// use arena_collections::AssocListMut;
449 /// use bumpalo::Bump;
451 /// let b = Bump::new();
452 /// let mut alist = AssocListMut::new_in(&b);
453 /// alist.insert(1, "a");
454 /// alist.insert(1, "b");
455 /// assert_eq!(alist.get(&1), Some(&"b"));
456 /// alist.remove_all(&1);
457 /// assert_eq!(alist.get(&1), None);
459 pub fn remove_all<Q: ?Sized>(&mut self, key: &Q) -> bool
464 let len_before = self.len();
465 self.entries.retain(|(k, _)| key != k.borrow());
466 let len_after = self.len();
467 len_before != len_after
470 /// Returns a reference to the value corresponding to the key.
472 /// The key may be any borrowed form of the list's key type, but the
473 /// ordering on the borrowed form *must* match the ordering on the key type.
475 /// If multiple entries in the map have keys equal to the given key, the
476 /// value in the most recently inserted entry will be returned.
481 /// use arena_collections::AssocListMut;
482 /// use bumpalo::Bump;
484 /// let b = Bump::new();
485 /// let mut alist = AssocListMut::new_in(&b);
486 /// alist.insert(1, "a");
487 /// assert_eq!(alist.get(&1), Some(&"a"));
488 /// assert_eq!(alist.get(&2), None);
490 pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>
495 get_last_entry(&self.entries, key).map(|(_, v)| v)
498 /// Returns the key-value pair corresponding to the supplied key.
500 /// The key may be any borrowed form of the list's key type, but the
501 /// ordering on the borrowed form *must* match the ordering on the key type.
503 /// If multiple entries in the map have keys equal to the given key, the
504 /// most recently inserted entry will be returned.
509 /// use arena_collections::AssocListMut;
510 /// use bumpalo::Bump;
512 /// let b = Bump::new();
513 /// let mut alist = AssocListMut::new_in(&b);
514 /// alist.insert(1, "a");
515 /// assert_eq!(alist.get_key_value(&1), Some((&1, &"a")));
516 /// assert_eq!(alist.get_key_value(&2), None);
518 pub fn get_key_value<Q: ?Sized>(&self, key: &Q) -> Option<(&K, &V)>
523 get_last_entry(&self.entries, key).map(|(k, v)| (k, v))
526 /// Returns `true` if the list contains a value for the specified key.
528 /// The key may be any borrowed form of the list's key type, but the
529 /// ordering on the borrowed form *must* match the ordering on the key type.
534 /// use arena_collections::AssocListMut;
535 /// use bumpalo::Bump;
537 /// let b = Bump::new();
538 /// let mut alist = AssocListMut::new_in(&b);
539 /// alist.insert(1, "a");
540 /// assert_eq!(alist.contains_key(&1), true);
541 /// assert_eq!(alist.contains_key(&2), false);
543 pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
548 self.get(key).is_some()
551 /// Gets an iterator over the entries of the association list.
556 /// use arena_collections::AssocListMut;
557 /// use bumpalo::Bump;
559 /// let b = Bump::new();
560 /// let mut alist = AssocListMut::new_in(&b);
561 /// alist.insert(1, "a");
562 /// alist.insert(2, "b");
564 /// for (key, value) in alist.iter() {
565 /// println!("{}: {}", key, value);
568 /// let (first_key, first_value) = alist.iter().next().unwrap();
569 /// assert_eq!((*first_key, *first_value), (1, "a"));
571 pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
572 self.entries.iter().map(|(k, v)| (k, v))
575 /// Gets an iterator over the keys of the association list.
580 /// use arena_collections::AssocListMut;
581 /// use bumpalo::Bump;
583 /// let b = Bump::new();
584 /// let mut alist = AssocListMut::new_in(&b);
585 /// alist.insert(1, "a");
586 /// alist.insert(2, "b");
588 /// let keys: Vec<_> = alist.keys().copied().collect();
589 /// assert_eq!(keys, [1, 2]);
591 pub fn keys(&self) -> impl Iterator<Item = &K> {
592 self.entries.iter().map(|(k, _)| k)
595 /// Gets an iterator over the values of the association list.
600 /// use arena_collections::AssocListMut;
601 /// use bumpalo::Bump;
603 /// let b = Bump::new();
604 /// let mut alist = AssocListMut::new_in(&b);
605 /// alist.insert(1, "hello");
606 /// alist.insert(2, "goodbye");
608 /// let values: Vec<&str> = alist.values().copied().collect();
609 /// assert_eq!(values, ["hello", "goodbye"]);
611 pub fn values(&self) -> impl Iterator<Item = &V> {
612 self.entries.iter().map(|(_, v)| v)
615 /// Returns the number of entries in the list.
620 /// use arena_collections::AssocListMut;
621 /// use bumpalo::Bump;
623 /// let b = Bump::new();
624 /// let mut alist = AssocListMut::new_in(&b);
625 /// assert_eq!(alist.len(), 0);
626 /// alist.insert(1, "a");
627 /// assert_eq!(alist.len(), 1);
629 pub fn len(&self) -> usize {
633 /// Returns `true` if the list contains no entries.
638 /// use arena_collections::AssocListMut;
639 /// use bumpalo::Bump;
641 /// let b = Bump::new();
642 /// let mut alist = AssocListMut::new_in(&b);
643 /// assert!(alist.is_empty());
644 /// alist.insert(1, "a");
645 /// assert!(!alist.is_empty());
647 pub fn is_empty(&self) -> bool {
648 self.entries.is_empty()
652 impl<K: Debug, V: Debug> Debug for AssocListMut<'_, K, V> {
653 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
654 fmt.debug_map().entries(self.iter()).finish()
658 /// Get an entry in the slice with the given key. Performs a linear search on
659 /// small slices, and a binary search otherwise.
661 fn get_sorted_entry<'a, K, V, Q: ?Sized>(entries: &'a [(K, V)], key: &Q) -> Option<&'a (K, V)>
666 // TODO: tune this threshold based on perf results
667 const BINARY_SEARCH_LEN_THRESHOLD: usize = 32;
669 if entries.len() < BINARY_SEARCH_LEN_THRESHOLD {
670 entries.iter().find(|(k, _)| key == k.borrow())
673 .binary_search_by(|(k, _)| k.borrow().cmp(key))
675 Some(&entries[index])
679 /// A readonly associative array, sorted by key, containing no duplicate keys.
681 /// * Lookups run in log(n) time
682 /// * Entries with duplicate keys are not permitted. When constructing a
683 /// `SortedAssocList` from an `AssocListMut`, entries will be deduplicated by
684 /// key, and only the most recently inserted entry for each key will be
686 #[derive(Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
688 deserialize = "K: 'de + arena_deserializer::DeserializeInArena<'de>, V: 'de + arena_deserializer::DeserializeInArena<'de>"
690 pub struct SortedAssocList<'a, K, V> {
691 #[serde(deserialize_with = "arena_deserializer::arena", borrow)]
692 entries: &'a [(K, V)],
695 arena_deserializer::impl_deserialize_in_arena!(SortedAssocList<'arena, K, V>);
697 impl<'a, K, V> SortedAssocList<'a, K, V> {
698 /// Returns the empty association list.
699 pub fn empty() -> Self {
700 SortedAssocList { entries: &[] }
703 /// Returns a reference to the value corresponding to the key.
705 /// The key may be any borrowed form of the list's key type, but the
706 /// ordering on the borrowed form *must* match the ordering on the key type.
711 /// use arena_collections::AssocListMut;
712 /// use arena_collections::SortedAssocList;
713 /// use bumpalo::Bump;
715 /// let b = Bump::new();
716 /// let mut alist = AssocListMut::new_in(&b);
717 /// alist.insert(1, "a");
718 /// let alist = SortedAssocList::from(alist);
719 /// assert_eq!(alist.get(&1), Some(&"a"));
720 /// assert_eq!(alist.get(&2), None);
722 pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>
727 get_sorted_entry(self.entries, key).map(|(_, v)| v)
730 /// Returns the key-value pair corresponding to the supplied key.
732 /// The key may be any borrowed form of the list's key type, but the
733 /// ordering on the borrowed form *must* match the ordering on the key type.
738 /// use arena_collections::AssocListMut;
739 /// use arena_collections::SortedAssocList;
740 /// use bumpalo::Bump;
742 /// let b = Bump::new();
743 /// let mut alist = AssocListMut::new_in(&b);
744 /// alist.insert(1, "a");
745 /// let alist = SortedAssocList::from(alist);
746 /// assert_eq!(alist.get_key_value(&1), Some((&1, &"a")));
747 /// assert_eq!(alist.get_key_value(&2), None);
749 pub fn get_key_value<Q: ?Sized>(&self, key: &Q) -> Option<(&K, &V)>
754 get_sorted_entry(self.entries, key).map(|(k, v)| (k, v))
757 /// Returns `true` if the list contains a value for the specified key.
759 /// The key may be any borrowed form of the list's key type, but the
760 /// ordering on the borrowed form *must* match the ordering on the key type.
765 /// use arena_collections::AssocListMut;
766 /// use arena_collections::SortedAssocList;
767 /// use bumpalo::Bump;
769 /// let b = Bump::new();
770 /// let mut alist = AssocListMut::new_in(&b);
771 /// alist.insert(1, "a");
772 /// let alist = SortedAssocList::from(alist);
773 /// assert_eq!(alist.contains_key(&1), true);
774 /// assert_eq!(alist.contains_key(&2), false);
776 pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
781 get_sorted_entry(self.entries, key).is_some()
784 /// Gets an iterator over the entries of the association list, sorted by
790 /// use arena_collections::AssocListMut;
791 /// use arena_collections::SortedAssocList;
792 /// use bumpalo::Bump;
794 /// let b = Bump::new();
795 /// let mut alist = AssocListMut::new_in(&b);
797 /// alist.insert(1, "a");
798 /// alist.insert(2, "b");
800 /// let alist = SortedAssocList::from(alist);
802 /// for (key, value) in alist.iter() {
803 /// println!("{}: {}", key, value);
806 /// let (first_key, first_value) = alist.iter().next().unwrap();
807 /// assert_eq!((*first_key, *first_value), (1, "a"));
809 pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
810 self.entries.iter().map(|(k, v)| (k, v))
813 /// Gets an iterator over the keys of the association list, in sorted order.
818 /// use arena_collections::AssocListMut;
819 /// use arena_collections::SortedAssocList;
820 /// use bumpalo::Bump;
822 /// let b = Bump::new();
823 /// let mut alist = AssocListMut::new_in(&b);
825 /// alist.insert(1, "a");
826 /// alist.insert(2, "b");
828 /// let alist = SortedAssocList::from(alist);
829 /// let keys: Vec<_> = alist.keys().copied().collect();
830 /// assert_eq!(keys, [1, 2]);
832 pub fn keys(&self) -> impl Iterator<Item = &K> {
833 self.entries.iter().map(|(k, _)| k)
836 /// Gets an iterator over the values of the association list, in order by
842 /// use arena_collections::AssocListMut;
843 /// use arena_collections::SortedAssocList;
844 /// use bumpalo::Bump;
846 /// let b = Bump::new();
847 /// let mut alist = AssocListMut::new_in(&b);
849 /// alist.insert(1, "hello");
850 /// alist.insert(2, "goodbye");
852 /// let alist = SortedAssocList::from(alist);
853 /// let values: Vec<&str> = alist.values().copied().collect();
854 /// assert_eq!(values, ["hello", "goodbye"]);
856 pub fn values(&self) -> impl Iterator<Item = &V> {
857 self.entries.iter().map(|(_, v)| v)
860 /// Returns the number of entries in the list.
865 /// use arena_collections::AssocListMut;
866 /// use arena_collections::SortedAssocList;
867 /// use bumpalo::Bump;
869 /// let b = Bump::new();
870 /// let mut alist = AssocListMut::new_in(&b);
871 /// alist.insert(1, "a");
872 /// alist.insert(1, "b");
873 /// let alist = SortedAssocList::from(alist);
874 /// assert_eq!(alist.len(), 1);
876 pub fn len(&self) -> usize {
880 /// Returns `true` if the list contains no entries.
885 /// use arena_collections::AssocListMut;
886 /// use arena_collections::SortedAssocList;
887 /// use bumpalo::Bump;
889 /// let b = Bump::new();
890 /// let mut alist = AssocListMut::new_in(&b);
891 /// let alist = SortedAssocList::from(alist);
892 /// assert!(alist.is_empty());
894 pub fn is_empty(&self) -> bool {
895 self.entries.is_empty()
898 /// Make a new `SortedAssocList` containing the given key-value pairs.
900 /// Provided for the sake of creating empty const lists. Passing non-empty
901 /// slices is not recommended.
903 /// The values in the slice must be in ascending sorted order (by `K`'s
904 /// implementation of `Ord`). There must be no duplicate keys in the slice.
909 /// use arena_collections::AssocListMut;
910 /// use arena_collections::SortedAssocList;
911 /// use bumpalo::Bump;
913 /// let b = Bump::new();
914 /// let mut alist = AssocListMut::new_in(&b);
916 /// const EMPTY_ALIST: SortedAssocList<'_, usize> = SortedAssocList::from_slice(&[]);
917 /// assert!(EMPTY_ALIST.is_empty());
919 pub const fn from_slice(entries: &'a [(K, V)]) -> Self {
924 impl<K, V> TrivialDrop for SortedAssocList<'_, K, V> {}
925 impl<K, V> Copy for SortedAssocList<'_, K, V> {}
926 impl<K, V> Clone for SortedAssocList<'_, K, V> {
927 fn clone(&self) -> Self {
932 impl<K, V> Default for SortedAssocList<'_, K, V> {
933 fn default() -> Self {
934 Self::from_slice(&[])
938 impl<K: Debug, V: Debug> Debug for SortedAssocList<'_, K, V> {
939 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
940 fmt.debug_map().entries(self.iter()).finish()
944 impl<'a, K: Ord, V> From<AssocListMut<'a, K, V>> for SortedAssocList<'a, K, V> {
946 fn from(mut alist: AssocListMut<'a, K, V>) -> Self {
947 let entries_mut = alist.entries.as_mut_slice();
948 // Reverse the slice so the most recently inserted pairs appear first.
949 entries_mut.reverse();
950 // Keep recently-inserted pairs first with a stable sort. Allocates
951 // temporary storage half the size of the slice using the global
952 // allocator if the slice is larger than some threshold (20 elements at
954 entries_mut.sort_by(|(k1, _), (k2, _)| k1.cmp(k2));
955 // Remove all but the most recently inserted pair for each key.
956 alist.entries.dedup_by(|(k1, _), (k2, _)| k1 == k2);
958 entries: alist.entries.into_bump_slice(),
963 impl<K: ToOcamlRep + Ord, V: ToOcamlRep> ToOcamlRep for SortedAssocList<'_, K, V> {
964 fn to_ocamlrep<'a, A: ocamlrep::Allocator>(&'a self, alloc: &'a A) -> ocamlrep::Value<'a> {
965 let len = self.len();
968 .map(|(k, v)| (k.to_ocamlrep(alloc), v.to_ocamlrep(alloc)));
969 let (value, _) = ocamlrep::sorted_iter_to_ocaml_map(&mut iter, alloc, len);
974 impl<'a, K, V> FromOcamlRepIn<'a> for SortedAssocList<'a, K, V>
976 K: FromOcamlRepIn<'a> + Ord,
977 V: FromOcamlRepIn<'a>,
980 value: ocamlrep::Value<'_>,
981 alloc: &'a bumpalo::Bump,
982 ) -> Result<Self, ocamlrep::FromError> {
983 let mut entries = bumpalo::collections::Vec::new_in(alloc);
984 ocamlrep::vec_from_ocaml_map_in(value, &mut entries, alloc)?;
985 let entries = entries.into_bump_slice();