1use crate::store::*;
6#[cfg(feature = "alloc")]
7use alloc::boxed::Box;
8#[cfg(feature = "alloc")]
9use alloc::vec::Vec;
10use core::borrow::Borrow;
11use core::cmp::Ordering;
12use core::fmt::Debug;
13use core::iter::FromIterator;
14use core::marker::PhantomData;
15use core::mem;
16use core::ops::{Index, IndexMut, Range};
17
18macro_rules! litemap_impl(
19 ($cfg:meta, $store:ident $(=$defaultty:ty)?) => {
20 #[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
26 #[cfg_attr(feature = "yoke", derive(yoke::Yokeable))]
27 #[cfg($cfg)]
28 pub struct LiteMap<K: ?Sized, V: ?Sized, $store $(= $defaultty)?> {
29 pub(crate) values: $store,
30 pub(crate) _key_type: PhantomData<K>,
31 pub(crate) _value_type: PhantomData<V>,
32 }
33 };
34
35);
36litemap_impl!(feature = "alloc", S = alloc::vec::Vec<(K, V)>);
39pub struct LiteMap<K: ?Sized, V: ?Sized, S> {
pub(crate) values: S,
pub(crate) _key_type: PhantomData<K>,
pub(crate) _value_type: PhantomData<V>,
}
#[automatically_derived]
impl<K: ::core::clone::Clone + ?Sized, V: ::core::clone::Clone + ?Sized,
S: ::core::clone::Clone> ::core::clone::Clone for LiteMap<K, V, S> {
#[inline]
fn clone(&self) -> LiteMap<K, V, S> {
LiteMap {
values: ::core::clone::Clone::clone(&self.values),
_key_type: ::core::clone::Clone::clone(&self._key_type),
_value_type: ::core::clone::Clone::clone(&self._value_type),
}
}
}
#[automatically_derived]
impl<K: ::core::fmt::Debug + ?Sized, V: ::core::fmt::Debug + ?Sized,
S: ::core::fmt::Debug> ::core::fmt::Debug for LiteMap<K, V, S> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "LiteMap",
"values", &self.values, "_key_type", &self._key_type,
"_value_type", &&self._value_type)
}
}
#[automatically_derived]
impl<K: ?Sized, V: ?Sized, S> ::core::marker::StructuralPartialEq for
LiteMap<K, V, S> {
}
#[automatically_derived]
impl<K: ::core::cmp::PartialEq + ?Sized, V: ::core::cmp::PartialEq + ?Sized,
S: ::core::cmp::PartialEq> ::core::cmp::PartialEq for LiteMap<K, V, S> {
#[inline]
fn eq(&self, other: &LiteMap<K, V, S>) -> bool {
self.values == other.values && self._key_type == other._key_type &&
self._value_type == other._value_type
}
}
#[automatically_derived]
impl<K: ::core::cmp::Eq + ?Sized, V: ::core::cmp::Eq + ?Sized,
S: ::core::cmp::Eq> ::core::cmp::Eq for LiteMap<K, V, S> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<S>;
let _: ::core::cmp::AssertParamIsEq<PhantomData<K>>;
let _: ::core::cmp::AssertParamIsEq<PhantomData<V>>;
}
}
#[automatically_derived]
impl<K: ::core::hash::Hash + ?Sized, V: ::core::hash::Hash + ?Sized,
S: ::core::hash::Hash> ::core::hash::Hash for LiteMap<K, V, S> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
::core::hash::Hash::hash(&self.values, state);
::core::hash::Hash::hash(&self._key_type, state);
::core::hash::Hash::hash(&self._value_type, state)
}
}
#[automatically_derived]
impl<K: ::core::cmp::PartialOrd + ?Sized, V: ::core::cmp::PartialOrd + ?Sized,
S: ::core::cmp::PartialOrd> ::core::cmp::PartialOrd for LiteMap<K, V, S> {
#[inline]
fn partial_cmp(&self, other: &LiteMap<K, V, S>)
-> ::core::option::Option<::core::cmp::Ordering> {
match ::core::cmp::PartialOrd::partial_cmp(&self.values,
&other.values) {
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
match ::core::cmp::PartialOrd::partial_cmp(&self._key_type,
&other._key_type) {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
=>
::core::cmp::PartialOrd::partial_cmp(&self._value_type,
&other._value_type),
cmp => cmp,
},
cmp => cmp,
}
}
}
#[automatically_derived]
impl<K: ::core::cmp::Ord + ?Sized, V: ::core::cmp::Ord + ?Sized,
S: ::core::cmp::Ord> ::core::cmp::Ord for LiteMap<K, V, S> {
#[inline]
fn cmp(&self, other: &LiteMap<K, V, S>) -> ::core::cmp::Ordering {
match ::core::cmp::Ord::cmp(&self.values, &other.values) {
::core::cmp::Ordering::Equal =>
match ::core::cmp::Ord::cmp(&self._key_type, &other._key_type)
{
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(&self._value_type,
&other._value_type),
cmp => cmp,
},
cmp => cmp,
}
}
}litemap_impl!(not(feature = "alloc"), S);
40
41#[cfg(feature = "alloc")]
42impl<K, V> LiteMap<K, V> {
43 pub const fn new_vec() -> Self {
47 Self {
48 values: alloc::vec::Vec::new(),
49 _key_type: PhantomData,
50 _value_type: PhantomData,
51 }
52 }
53}
54
55impl<K, V, S> LiteMap<K, V, S> {
56 pub const fn from_sorted_store_unchecked(values: S) -> Self {
60 Self {
61 values,
62 _key_type: PhantomData,
63 _value_type: PhantomData,
64 }
65 }
66}
67
68#[cfg(feature = "alloc")]
69impl<K, V> LiteMap<K, V, Vec<(K, V)>> {
70 #[inline]
74 pub fn into_tuple_vec(self) -> Vec<(K, V)> {
75 self.values
76 }
77}
78
79impl<K: ?Sized, V: ?Sized, S> LiteMap<K, V, S>
80where
81 S: StoreConstEmpty<K, V>,
82{
83 pub const fn new() -> Self {
85 Self {
86 values: S::EMPTY,
87 _key_type: PhantomData,
88 _value_type: PhantomData,
89 }
90 }
91}
92
93impl<K: ?Sized, V: ?Sized, S> LiteMap<K, V, S>
94where
95 S: Store<K, V>,
96{
97 pub fn len(&self) -> usize {
99 self.values.lm_len()
100 }
101
102 pub fn is_empty(&self) -> bool {
104 self.values.lm_is_empty()
105 }
106
107 #[inline]
111 pub fn get_indexed(&self, index: usize) -> Option<(&K, &V)> {
112 self.values.lm_get(index)
113 }
114
115 #[inline]
128 pub fn first(&self) -> Option<(&K, &V)> {
129 self.values.lm_get(0)
130 }
131
132 #[inline]
145 pub fn last(&self) -> Option<(&K, &V)> {
146 self.values.lm_last()
147 }
148
149 #[cfg(feature = "alloc")]
169 pub fn to_boxed_keys_values<KB: ?Sized, VB: ?Sized, SB>(&self) -> LiteMap<Box<KB>, Box<VB>, SB>
170 where
171 SB: StoreMut<Box<KB>, Box<VB>>,
172 K: Borrow<KB>,
173 V: Borrow<VB>,
174 Box<KB>: for<'a> From<&'a KB>,
175 Box<VB>: for<'a> From<&'a VB>,
176 {
177 let mut values = SB::lm_with_capacity(self.len());
178 for i in 0..self.len() {
179 #[expect(clippy::unwrap_used)] let (k, v) = self.values.lm_get(i).unwrap();
181 values.lm_push(Box::from(k.borrow()), Box::from(v.borrow()))
182 }
183 LiteMap {
184 values,
185 _key_type: PhantomData,
186 _value_type: PhantomData,
187 }
188 }
189
190 #[cfg(feature = "alloc")]
210 pub fn to_boxed_keys<KB: ?Sized, SB>(&self) -> LiteMap<Box<KB>, V, SB>
211 where
212 V: Clone,
213 SB: StoreMut<Box<KB>, V>,
214 K: Borrow<KB>,
215 Box<KB>: for<'a> From<&'a KB>,
216 {
217 let mut values = SB::lm_with_capacity(self.len());
218 for i in 0..self.len() {
219 #[expect(clippy::unwrap_used)] let (k, v) = self.values.lm_get(i).unwrap();
221 values.lm_push(Box::from(k.borrow()), v.clone())
222 }
223 LiteMap {
224 values,
225 _key_type: PhantomData,
226 _value_type: PhantomData,
227 }
228 }
229
230 #[cfg(feature = "alloc")]
250 pub fn to_boxed_values<VB: ?Sized, SB>(&self) -> LiteMap<K, Box<VB>, SB>
251 where
252 K: Clone,
253 SB: StoreMut<K, Box<VB>>,
254 V: Borrow<VB>,
255 Box<VB>: for<'a> From<&'a VB>,
256 {
257 let mut values = SB::lm_with_capacity(self.len());
258 for i in 0..self.len() {
259 #[expect(clippy::unwrap_used)] let (k, v) = self.values.lm_get(i).unwrap();
261 values.lm_push(k.clone(), Box::from(v.borrow()))
262 }
263 LiteMap {
264 values,
265 _key_type: PhantomData,
266 _value_type: PhantomData,
267 }
268 }
269}
270
271impl<K: ?Sized, V: ?Sized, S> LiteMap<K, V, S>
272where
273 K: Ord,
274 S: Store<K, V>,
275{
276 pub fn get<Q>(&self, key: &Q) -> Option<&V>
288 where
289 K: Borrow<Q>,
290 Q: Ord + ?Sized,
291 {
292 match self.find_index(key) {
293 #[expect(clippy::unwrap_used)] Ok(found) => Some(self.values.lm_get(found).unwrap().1),
295 Err(_) => None,
296 }
297 }
298
299 pub fn get_by(&self, predicate: impl FnMut(&K) -> Ordering) -> Option<&V> {
301 let index = self.values.lm_binary_search_by(predicate).ok()?;
302 self.values.lm_get(index).map(|(_, v)| v)
303 }
304
305 pub fn contains_key<Q>(&self, key: &Q) -> bool
317 where
318 K: Borrow<Q>,
319 Q: Ord + ?Sized,
320 {
321 self.find_index(key).is_ok()
322 }
323
324 #[inline]
332 pub fn find_index<Q>(&self, key: &Q) -> Result<usize, usize>
333 where
334 K: Borrow<Q>,
335 Q: Ord + ?Sized,
336 {
337 self.values.lm_binary_search_by(|k| k.borrow().cmp(key))
338 }
339}
340
341impl<K: ?Sized, V: ?Sized, S> LiteMap<K, V, S>
342where
343 S: StoreSlice<K, V>,
344{
345 pub fn get_indexed_range(&self, range: Range<usize>) -> Option<LiteMap<K, V, &S::Slice>> {
363 let subslice = self.values.lm_get_range(range)?;
364 Some(LiteMap {
365 values: subslice,
366 _key_type: PhantomData,
367 _value_type: PhantomData,
368 })
369 }
370
371 pub fn as_sliced(&self) -> LiteMap<K, V, &S::Slice> {
390 #[expect(clippy::unwrap_used)]
392 let subslice = self.values.lm_get_range(0..self.len()).unwrap();
393 LiteMap {
394 values: subslice,
395 _key_type: PhantomData,
396 _value_type: PhantomData,
397 }
398 }
399
400 pub fn as_slice(&self) -> &S::Slice {
417 #[expect(clippy::unwrap_used)]
419 self.values.lm_get_range(0..self.len()).unwrap()
420 }
421}
422
423impl<'a, K: 'a, V: 'a, S> LiteMap<K, V, S>
424where
425 S: Store<K, V>,
426{
427 pub fn to_borrowed_keys_values<KB: ?Sized, VB: ?Sized, SB>(
443 &'a self,
444 ) -> LiteMap<&'a KB, &'a VB, SB>
445 where
446 K: Borrow<KB>,
447 V: Borrow<VB>,
448 SB: StoreMut<&'a KB, &'a VB>,
449 {
450 let mut values = SB::lm_with_capacity(self.len());
451 for i in 0..self.len() {
452 #[expect(clippy::unwrap_used)] let (k, v) = self.values.lm_get(i).unwrap();
454 values.lm_push(k.borrow(), v.borrow())
455 }
456 LiteMap {
457 values,
458 _key_type: PhantomData,
459 _value_type: PhantomData,
460 }
461 }
462
463 pub fn to_borrowed_keys<KB: ?Sized, SB>(&'a self) -> LiteMap<&'a KB, V, SB>
479 where
480 K: Borrow<KB>,
481 V: Clone,
482 SB: StoreMut<&'a KB, V>,
483 {
484 let mut values = SB::lm_with_capacity(self.len());
485 for i in 0..self.len() {
486 #[expect(clippy::unwrap_used)] let (k, v) = self.values.lm_get(i).unwrap();
488 values.lm_push(k.borrow(), v.clone())
489 }
490 LiteMap {
491 values,
492 _key_type: PhantomData,
493 _value_type: PhantomData,
494 }
495 }
496
497 pub fn to_borrowed_values<VB: ?Sized, SB>(&'a self) -> LiteMap<K, &'a VB, SB>
513 where
514 K: Clone,
515 V: Borrow<VB>,
516 SB: StoreMut<K, &'a VB>,
517 {
518 let mut values = SB::lm_with_capacity(self.len());
519 for i in 0..self.len() {
520 #[expect(clippy::unwrap_used)] let (k, v) = self.values.lm_get(i).unwrap();
522 values.lm_push(k.clone(), v.borrow())
523 }
524 LiteMap {
525 values,
526 _key_type: PhantomData,
527 _value_type: PhantomData,
528 }
529 }
530}
531
532impl<K, V, S> LiteMap<K, V, S>
533where
534 S: StoreMut<K, V>,
535{
536 pub fn with_capacity(capacity: usize) -> Self {
538 Self {
539 values: S::lm_with_capacity(capacity),
540 _key_type: PhantomData,
541 _value_type: PhantomData,
542 }
543 }
544
545 pub fn clear(&mut self) {
547 self.values.lm_clear()
548 }
549
550 pub fn reserve(&mut self, additional: usize) {
557 self.values.lm_reserve(additional)
558 }
559}
560
561impl<K, V, S> LiteMap<K, V, S>
562where
563 K: Ord,
564 S: StoreMut<K, V>,
565{
566 pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
580 where
581 K: Borrow<Q>,
582 Q: Ord + ?Sized,
583 {
584 match self.find_index(key) {
585 #[expect(clippy::unwrap_used)] Ok(found) => Some(self.values.lm_get_mut(found).unwrap().1),
587 Err(_) => None,
588 }
589 }
590
591 #[must_use]
620 pub fn try_append(&mut self, key: K, value: V) -> Option<(K, V)> {
621 if let Some(last) = self.values.lm_last() {
622 if last.0 >= &key {
623 return Some((key, value));
624 }
625 }
626
627 self.values.lm_push(key, value);
628 None
629 }
630
631 pub fn insert(&mut self, key: K, value: V) -> Option<V> {
643 self.insert_save_key(key, value).map(|(_, v)| v)
644 }
645
646 fn insert_save_key(&mut self, key: K, value: V) -> Option<(K, V)> {
648 match self.values.lm_binary_search_by(|k| k.cmp(&key)) {
649 #[expect(clippy::unwrap_used)] Ok(found) => Some((
651 key,
652 mem::replace(self.values.lm_get_mut(found).unwrap().1, value),
653 )),
654 Err(ins) => {
655 self.values.lm_insert(ins, key, value);
656 None
657 }
658 }
659 }
660
661 pub fn try_insert(&mut self, key: K, value: V) -> Option<(K, V)> {
685 match self.values.lm_binary_search_by(|k| k.cmp(&key)) {
686 Ok(_) => Some((key, value)),
687 Err(ins) => {
688 self.values.lm_insert(ins, key, value);
689 None
690 }
691 }
692 }
693
694 pub fn try_get_or_insert<E>(
736 &mut self,
737 key: K,
738 value: impl FnOnce(&K) -> Result<V, E>,
739 ) -> Result<(usize, &V), E> {
740 let idx = match self.values.lm_binary_search_by(|k| k.cmp(&key)) {
741 Ok(idx) => idx,
742 Err(idx) => {
743 let value = value(&key)?;
744 self.values.lm_insert(idx, key, value);
745 idx
746 }
747 };
748 #[expect(clippy::unwrap_used)] Ok((idx, self.values.lm_get(idx).unwrap().1))
750 }
751
752 pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
764 where
765 K: Borrow<Q>,
766 Q: Ord + ?Sized,
767 {
768 match self.values.lm_binary_search_by(|k| k.borrow().cmp(key)) {
769 Ok(found) => Some(self.values.lm_remove(found).1),
770 Err(_) => None,
771 }
772 }
773}
774
775impl<K, V, S> LiteMap<K, V, S>
776where
777 K: Ord,
778 S: StoreIntoIterator<K, V> + StoreFromIterator<K, V>,
779{
780 pub fn extend_from_litemap(&mut self, other: Self) -> Option<Self> {
813 if self.is_empty() {
814 self.values = other.values;
815 return None;
816 }
817 if other.is_empty() {
818 return None;
819 }
820 if self.last().map(|(k, _)| k) < other.first().map(|(k, _)| k) {
821 self.values.lm_extend_end(other.values);
823 None
824 } else if self.first().map(|(k, _)| k) > other.last().map(|(k, _)| k) {
825 self.values.lm_extend_start(other.values);
827 None
828 } else {
829 let leftover_tuples = other
831 .values
832 .lm_into_iter()
833 .filter_map(|(k, v)| self.insert_save_key(k, v))
834 .collect();
835 let ret = LiteMap {
836 values: leftover_tuples,
837 _key_type: PhantomData,
838 _value_type: PhantomData,
839 };
840 if ret.is_empty() {
841 None
842 } else {
843 Some(ret)
844 }
845 }
846 }
847}
848
849impl<K, V, S> Default for LiteMap<K, V, S>
850where
851 S: Store<K, V> + Default,
852{
853 fn default() -> Self {
854 Self {
855 values: S::default(),
856 _key_type: PhantomData,
857 _value_type: PhantomData,
858 }
859 }
860}
861impl<K, V, S> Index<&'_ K> for LiteMap<K, V, S>
862where
863 K: Ord,
864 S: Store<K, V>,
865{
866 type Output = V;
867 fn index(&self, key: &K) -> &V {
868 #[expect(clippy::panic)] match self.get(key) {
870 Some(v) => v,
871 None => { ::core::panicking::panic_fmt(format_args!("no entry found for key")); }panic!("no entry found for key"),
872 }
873 }
874}
875impl<K, V, S> IndexMut<&'_ K> for LiteMap<K, V, S>
876where
877 K: Ord,
878 S: StoreMut<K, V>,
879{
880 fn index_mut(&mut self, key: &K) -> &mut V {
881 #[expect(clippy::panic)] match self.get_mut(key) {
883 Some(v) => v,
884 None => { ::core::panicking::panic_fmt(format_args!("no entry found for key")); }panic!("no entry found for key"),
885 }
886 }
887}
888impl<K, V, S> FromIterator<(K, V)> for LiteMap<K, V, S>
889where
890 K: Ord,
891 S: StoreFromIterable<K, V>,
892{
893 fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
894 let values = S::lm_sort_from_iter(iter);
895 Self::from_sorted_store_unchecked(values)
896 }
897}
898
899impl<'a, K: 'a, V: 'a, S> LiteMap<K, V, S>
900where
901 S: StoreIterable<'a, K, V>,
902{
903 pub fn iter(&'a self) -> impl DoubleEndedIterator<Item = (&'a K, &'a V)> {
905 self.values.lm_iter()
906 }
907
908 #[deprecated = "use keys() instead"]
910 pub fn iter_keys(&'a self) -> impl DoubleEndedIterator<Item = &'a K> {
911 self.values.lm_iter().map(|val| val.0)
912 }
913
914 #[deprecated = "use values() instead"]
916 pub fn iter_values(&'a self) -> impl DoubleEndedIterator<Item = &'a V> {
917 self.values.lm_iter().map(|val| val.1)
918 }
919
920 pub fn keys(&'a self) -> impl DoubleEndedIterator<Item = &'a K> {
922 self.values.lm_iter().map(|val| val.0)
923 }
924
925 pub fn values(&'a self) -> impl DoubleEndedIterator<Item = &'a V> {
927 self.values.lm_iter().map(|val| val.1)
928 }
929}
930
931impl<'a, K: 'a, V: 'a, S> LiteMap<K, V, S>
932where
933 S: StoreIterableMut<'a, K, V>,
934{
935 pub fn iter_mut(&'a mut self) -> impl DoubleEndedIterator<Item = (&'a K, &'a mut V)> {
937 self.values.lm_iter_mut()
938 }
939}
940
941impl<K, V, S> IntoIterator for LiteMap<K, V, S>
942where
943 S: StoreIntoIterator<K, V>,
944{
945 type Item = (K, V);
946 type IntoIter = S::KeyValueIntoIter;
947
948 fn into_iter(self) -> Self::IntoIter {
949 self.values.lm_into_iter()
950 }
951}
952
953impl<'a, K, V, S> IntoIterator for &'a LiteMap<K, V, S>
954where
955 S: StoreIterable<'a, K, V>,
956{
957 type Item = (&'a K, &'a V);
958 type IntoIter = S::KeyValueIter;
959
960 fn into_iter(self) -> Self::IntoIter {
961 self.values.lm_iter()
962 }
963}
964
965impl<'a, K, V, S> IntoIterator for &'a mut LiteMap<K, V, S>
966where
967 S: StoreIterableMut<'a, K, V>,
968{
969 type Item = (&'a K, &'a mut V);
970 type IntoIter = S::KeyValueIterMut;
971
972 fn into_iter(self) -> Self::IntoIter {
973 self.values.lm_iter_mut()
974 }
975}
976
977impl<K, V, S> LiteMap<K, V, S>
978where
979 S: StoreBulkMut<K, V>,
980{
981 #[inline]
1002 pub fn retain<F>(&mut self, predicate: F)
1003 where
1004 F: FnMut(&K, &V) -> bool,
1005 {
1006 self.values.lm_retain(predicate)
1007 }
1008}
1009
1010impl<'a, K, V> LiteMap<K, V, &'a [(K, V)]> {
1011 #[inline]
1025 pub const fn const_len(&self) -> usize {
1026 self.values.len()
1027 }
1028
1029 #[inline]
1043 pub const fn const_is_empty(&self) -> bool {
1044 self.values.is_empty()
1045 }
1046
1047 #[inline]
1065 #[expect(clippy::indexing_slicing)] pub const fn const_get_indexed_or_panic(&self, index: usize) -> &'a (K, V) {
1067 &self.values[index]
1068 }
1069}
1070
1071const fn const_cmp_bytes(a: &[u8], b: &[u8]) -> Ordering {
1072 let (max, default) = if a.len() == b.len() {
1073 (a.len(), Ordering::Equal)
1074 } else if a.len() < b.len() {
1075 (a.len(), Ordering::Less)
1076 } else {
1077 (b.len(), Ordering::Greater)
1078 };
1079 let mut i = 0;
1080 #[expect(clippy::indexing_slicing)] while i < max {
1082 if a[i] == b[i] {
1083 i += 1;
1084 continue;
1085 } else if a[i] < b[i] {
1086 return Ordering::Less;
1087 } else {
1088 return Ordering::Greater;
1089 }
1090 }
1091 default
1092}
1093
1094impl<'a, V> LiteMap<&'a str, V, &'a [(&'a str, V)]> {
1095 pub const fn const_get_with_index(&self, key: &str) -> Option<(usize, &'a V)> {
1120 let mut i = 0;
1121 let mut j = self.const_len();
1122 while i < j {
1123 let mid = (i + j) / 2;
1124 #[expect(clippy::indexing_slicing)] let x = &self.values[mid];
1126 match const_cmp_bytes(key.as_bytes(), x.0.as_bytes()) {
1127 Ordering::Equal => return Some((mid, &x.1)),
1128 Ordering::Greater => i = mid + 1,
1129 Ordering::Less => j = mid,
1130 };
1131 }
1132 None
1133 }
1134}
1135
1136impl<'a, V> LiteMap<&'a [u8], V, &'a [(&'a [u8], V)]> {
1137 pub const fn const_get_with_index(&self, key: &[u8]) -> Option<(usize, &'a V)> {
1162 let mut i = 0;
1163 let mut j = self.const_len();
1164 while i < j {
1165 let mid = (i + j) / 2;
1166 #[expect(clippy::indexing_slicing)] let x = &self.values[mid];
1168 match const_cmp_bytes(key, x.0) {
1169 Ordering::Equal => return Some((mid, &x.1)),
1170 Ordering::Greater => i = mid + 1,
1171 Ordering::Less => j = mid,
1172 };
1173 }
1174 None
1175 }
1176}
1177
1178macro_rules! impl_const_get_with_index_for_integer {
1179 ($integer:ty) => {
1180 impl<'a, V> LiteMap<$integer, V, &'a [($integer, V)]> {
1181 pub const fn const_get_with_index(&self, key: $integer) -> Option<(usize, &'a V)> {
1187 let mut i = 0;
1188 let mut j = self.const_len();
1189 while i < j {
1190 let mid = (i + j) / 2;
1191 #[expect(clippy::indexing_slicing)] let x = &self.values[mid];
1193 if key == x.0 {
1194 return Some((mid, &x.1));
1195 } else if key > x.0 {
1196 i = mid + 1;
1197 } else {
1198 j = mid;
1199 }
1200 }
1201 return None;
1202 }
1203 }
1204 };
1205}
1206
1207impl<'a, V> LiteMap<u8, V, &'a [(u8, V)]> {
pub const fn const_get_with_index(&self, key: u8)
-> Option<(usize, &'a V)> {
let mut i = 0;
let mut j = self.const_len();
while i < j {
let mid = (i + j) / 2;
#[expect(clippy :: indexing_slicing)]
let x = &self.values[mid];
if key == x.0 {
return Some((mid, &x.1));
} else if key > x.0 { i = mid + 1; } else { j = mid; }
}
return None;
}
}impl_const_get_with_index_for_integer!(u8);
1208impl<'a, V> LiteMap<u16, V, &'a [(u16, V)]> {
pub const fn const_get_with_index(&self, key: u16)
-> Option<(usize, &'a V)> {
let mut i = 0;
let mut j = self.const_len();
while i < j {
let mid = (i + j) / 2;
#[expect(clippy :: indexing_slicing)]
let x = &self.values[mid];
if key == x.0 {
return Some((mid, &x.1));
} else if key > x.0 { i = mid + 1; } else { j = mid; }
}
return None;
}
}impl_const_get_with_index_for_integer!(u16);
1209impl<'a, V> LiteMap<u32, V, &'a [(u32, V)]> {
pub const fn const_get_with_index(&self, key: u32)
-> Option<(usize, &'a V)> {
let mut i = 0;
let mut j = self.const_len();
while i < j {
let mid = (i + j) / 2;
#[expect(clippy :: indexing_slicing)]
let x = &self.values[mid];
if key == x.0 {
return Some((mid, &x.1));
} else if key > x.0 { i = mid + 1; } else { j = mid; }
}
return None;
}
}impl_const_get_with_index_for_integer!(u32);
1210impl<'a, V> LiteMap<u64, V, &'a [(u64, V)]> {
pub const fn const_get_with_index(&self, key: u64)
-> Option<(usize, &'a V)> {
let mut i = 0;
let mut j = self.const_len();
while i < j {
let mid = (i + j) / 2;
#[expect(clippy :: indexing_slicing)]
let x = &self.values[mid];
if key == x.0 {
return Some((mid, &x.1));
} else if key > x.0 { i = mid + 1; } else { j = mid; }
}
return None;
}
}impl_const_get_with_index_for_integer!(u64);
1211impl<'a, V> LiteMap<u128, V, &'a [(u128, V)]> {
pub const fn const_get_with_index(&self, key: u128)
-> Option<(usize, &'a V)> {
let mut i = 0;
let mut j = self.const_len();
while i < j {
let mid = (i + j) / 2;
#[expect(clippy :: indexing_slicing)]
let x = &self.values[mid];
if key == x.0 {
return Some((mid, &x.1));
} else if key > x.0 { i = mid + 1; } else { j = mid; }
}
return None;
}
}impl_const_get_with_index_for_integer!(u128);
1212impl<'a, V> LiteMap<usize, V, &'a [(usize, V)]> {
pub const fn const_get_with_index(&self, key: usize)
-> Option<(usize, &'a V)> {
let mut i = 0;
let mut j = self.const_len();
while i < j {
let mid = (i + j) / 2;
#[expect(clippy :: indexing_slicing)]
let x = &self.values[mid];
if key == x.0 {
return Some((mid, &x.1));
} else if key > x.0 { i = mid + 1; } else { j = mid; }
}
return None;
}
}impl_const_get_with_index_for_integer!(usize);
1213impl<'a, V> LiteMap<i8, V, &'a [(i8, V)]> {
pub const fn const_get_with_index(&self, key: i8)
-> Option<(usize, &'a V)> {
let mut i = 0;
let mut j = self.const_len();
while i < j {
let mid = (i + j) / 2;
#[expect(clippy :: indexing_slicing)]
let x = &self.values[mid];
if key == x.0 {
return Some((mid, &x.1));
} else if key > x.0 { i = mid + 1; } else { j = mid; }
}
return None;
}
}impl_const_get_with_index_for_integer!(i8);
1214impl<'a, V> LiteMap<i16, V, &'a [(i16, V)]> {
pub const fn const_get_with_index(&self, key: i16)
-> Option<(usize, &'a V)> {
let mut i = 0;
let mut j = self.const_len();
while i < j {
let mid = (i + j) / 2;
#[expect(clippy :: indexing_slicing)]
let x = &self.values[mid];
if key == x.0 {
return Some((mid, &x.1));
} else if key > x.0 { i = mid + 1; } else { j = mid; }
}
return None;
}
}impl_const_get_with_index_for_integer!(i16);
1215impl<'a, V> LiteMap<i32, V, &'a [(i32, V)]> {
pub const fn const_get_with_index(&self, key: i32)
-> Option<(usize, &'a V)> {
let mut i = 0;
let mut j = self.const_len();
while i < j {
let mid = (i + j) / 2;
#[expect(clippy :: indexing_slicing)]
let x = &self.values[mid];
if key == x.0 {
return Some((mid, &x.1));
} else if key > x.0 { i = mid + 1; } else { j = mid; }
}
return None;
}
}impl_const_get_with_index_for_integer!(i32);
1216impl<'a, V> LiteMap<i64, V, &'a [(i64, V)]> {
pub const fn const_get_with_index(&self, key: i64)
-> Option<(usize, &'a V)> {
let mut i = 0;
let mut j = self.const_len();
while i < j {
let mid = (i + j) / 2;
#[expect(clippy :: indexing_slicing)]
let x = &self.values[mid];
if key == x.0 {
return Some((mid, &x.1));
} else if key > x.0 { i = mid + 1; } else { j = mid; }
}
return None;
}
}impl_const_get_with_index_for_integer!(i64);
1217impl<'a, V> LiteMap<i128, V, &'a [(i128, V)]> {
pub const fn const_get_with_index(&self, key: i128)
-> Option<(usize, &'a V)> {
let mut i = 0;
let mut j = self.const_len();
while i < j {
let mid = (i + j) / 2;
#[expect(clippy :: indexing_slicing)]
let x = &self.values[mid];
if key == x.0 {
return Some((mid, &x.1));
} else if key > x.0 { i = mid + 1; } else { j = mid; }
}
return None;
}
}impl_const_get_with_index_for_integer!(i128);
1218impl<'a, V> LiteMap<isize, V, &'a [(isize, V)]> {
pub const fn const_get_with_index(&self, key: isize)
-> Option<(usize, &'a V)> {
let mut i = 0;
let mut j = self.const_len();
while i < j {
let mid = (i + j) / 2;
#[expect(clippy :: indexing_slicing)]
let x = &self.values[mid];
if key == x.0 {
return Some((mid, &x.1));
} else if key > x.0 { i = mid + 1; } else { j = mid; }
}
return None;
}
}impl_const_get_with_index_for_integer!(isize);
1219
1220#[allow(clippy::exhaustive_enums)]
1222pub enum Entry<'a, K, V, S> {
1223 Occupied(OccupiedEntry<'a, K, V, S>),
1224 Vacant(VacantEntry<'a, K, V, S>),
1225}
1226
1227impl<K, V, S> Debug for Entry<'_, K, V, S> {
1228 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1229 match self {
1230 Self::Occupied(arg0) => f.debug_tuple("Occupied").field(arg0).finish(),
1231 Self::Vacant(arg0) => f.debug_tuple("Vacant").field(arg0).finish(),
1232 }
1233 }
1234}
1235
1236pub struct OccupiedEntry<'a, K, V, S> {
1238 map: &'a mut LiteMap<K, V, S>,
1239 index: usize,
1240}
1241
1242impl<K, V, S> Debug for OccupiedEntry<'_, K, V, S> {
1243 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1244 f.debug_struct("OccupiedEntry")
1245 .field("index", &self.index)
1246 .finish()
1247 }
1248}
1249
1250pub struct VacantEntry<'a, K, V, S> {
1252 map: &'a mut LiteMap<K, V, S>,
1253 key: K,
1254 index: usize,
1255}
1256
1257impl<K, V, S> Debug for VacantEntry<'_, K, V, S> {
1258 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1259 f.debug_struct("VacantEntry")
1260 .field("index", &self.index)
1261 .finish()
1262 }
1263}
1264
1265impl<'a, K, V, S> Entry<'a, K, V, S>
1266where
1267 K: Ord,
1268 S: StoreMut<K, V>,
1269{
1270 pub fn or_insert(self, default: V) -> &'a mut V {
1273 match self {
1274 Entry::Occupied(entry) => entry.into_mut(),
1275 Entry::Vacant(entry) => entry.insert(default),
1276 }
1277 }
1278
1279 pub fn or_default(self) -> &'a mut V
1282 where
1283 V: Default,
1284 {
1285 self.or_insert(V::default())
1286 }
1287
1288 pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
1291 match self {
1292 Entry::Occupied(entry) => entry.into_mut(),
1293 Entry::Vacant(entry) => entry.insert(default()),
1294 }
1295 }
1296
1297 pub fn and_modify<F>(self, f: F) -> Self
1300 where
1301 F: FnOnce(&mut V),
1302 {
1303 match self {
1304 Entry::Occupied(mut entry) => {
1305 f(entry.get_mut());
1306 Entry::Occupied(entry)
1307 }
1308 Entry::Vacant(entry) => Entry::Vacant(entry),
1309 }
1310 }
1311}
1312
1313impl<'a, K, V, S> OccupiedEntry<'a, K, V, S>
1314where
1315 K: Ord,
1316 S: StoreMut<K, V>,
1317{
1318 pub fn key(&self) -> &K {
1320 #[expect(clippy::unwrap_used)] self.map.values.lm_get(self.index).unwrap().0
1322 }
1323
1324 pub fn get(&self) -> &V {
1326 #[expect(clippy::unwrap_used)] self.map.values.lm_get(self.index).unwrap().1
1328 }
1329
1330 pub fn get_mut(&mut self) -> &mut V {
1332 #[expect(clippy::unwrap_used)] self.map.values.lm_get_mut(self.index).unwrap().1
1334 }
1335
1336 pub fn into_mut(self) -> &'a mut V {
1338 #[expect(clippy::unwrap_used)] self.map.values.lm_get_mut(self.index).unwrap().1
1340 }
1341
1342 pub fn insert(&mut self, value: V) -> V {
1344 mem::replace(self.get_mut(), value)
1345 }
1346
1347 pub fn remove(self) -> V {
1349 self.map.values.lm_remove(self.index).1
1350 }
1351}
1352
1353impl<'a, K, V, S> VacantEntry<'a, K, V, S>
1354where
1355 K: Ord,
1356 S: StoreMut<K, V>,
1357{
1358 pub fn key(&self) -> &K {
1360 &self.key
1361 }
1362
1363 pub fn insert(self, value: V) -> &'a mut V {
1365 self.map.values.lm_insert(self.index, self.key, value);
1368 #[expect(clippy::unwrap_used)] self.map.values.lm_get_mut(self.index).unwrap().1
1370 }
1371}
1372
1373impl<K, V, S> LiteMap<K, V, S>
1374where
1375 K: Ord,
1376 S: StoreMut<K, V>,
1377{
1378 pub fn entry(&mut self, key: K) -> Entry<'_, K, V, S> {
1380 match self.values.lm_binary_search_by(|k| k.cmp(&key)) {
1381 Ok(index) => Entry::Occupied(OccupiedEntry { map: self, index }),
1382 Err(index) => Entry::Vacant(VacantEntry {
1383 map: self,
1384 key,
1385 index,
1386 }),
1387 }
1388 }
1389}
1390
1391impl<K, V, S> Extend<(K, V)> for LiteMap<K, V, S>
1392where
1393 K: Ord,
1394 S: StoreBulkMut<K, V>,
1395{
1396 fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
1397 self.values.lm_extend(iter)
1398 }
1399}
1400
1401#[cfg(test)]
1402mod test {
1403 use super::*;
1404
1405 #[test]
1406 fn from_iterator() {
1407 let mut expected = LiteMap::with_capacity(4);
1408 expected.insert(1, "updated-one");
1409 expected.insert(2, "original-two");
1410 expected.insert(3, "original-three");
1411 expected.insert(4, "updated-four");
1412
1413 let actual = [
1414 (1, "original-one"),
1415 (2, "original-two"),
1416 (4, "original-four"),
1417 (4, "updated-four"),
1418 (1, "updated-one"),
1419 (3, "original-three"),
1420 ]
1421 .into_iter()
1422 .collect::<LiteMap<_, _>>();
1423
1424 assert_eq!(expected, actual);
1425 }
1426
1427 #[test]
1428 fn extend() {
1429 let mut expected: LiteMap<i32, &str> = LiteMap::with_capacity(4);
1430 expected.insert(1, "updated-one");
1431 expected.insert(2, "original-two");
1432 expected.insert(3, "original-three");
1433 expected.insert(4, "updated-four");
1434
1435 let mut actual: LiteMap<i32, &str> = LiteMap::new();
1436 actual.insert(1, "original-one");
1437 actual.extend([
1438 (2, "original-two"),
1439 (4, "original-four"),
1440 (4, "updated-four"),
1441 (1, "updated-one"),
1442 (3, "original-three"),
1443 ]);
1444
1445 assert_eq!(expected, actual);
1446 }
1447
1448 #[test]
1449 fn extend2() {
1450 let mut map: LiteMap<usize, &str> = LiteMap::new();
1451 map.extend(make_13());
1452 map.extend(make_24());
1453 map.extend(make_24());
1454 map.extend(make_46());
1455 map.extend(make_13());
1456 map.extend(make_46());
1457 assert_eq!(map.len(), 5);
1458 }
1459
1460 fn make_13() -> LiteMap<usize, &'static str> {
1461 let mut result = LiteMap::new();
1462 result.insert(1, "one");
1463 result.insert(3, "three");
1464 result
1465 }
1466
1467 fn make_24() -> LiteMap<usize, &'static str> {
1468 let mut result = LiteMap::new();
1469 result.insert(2, "TWO");
1470 result.insert(4, "FOUR");
1471 result
1472 }
1473
1474 fn make_46() -> LiteMap<usize, &'static str> {
1475 let mut result = LiteMap::new();
1476 result.insert(4, "four");
1477 result.insert(6, "six");
1478 result
1479 }
1480
1481 #[test]
1482 fn extend_from_litemap_append() {
1483 let mut map = LiteMap::new();
1484 map.extend_from_litemap(make_13())
1485 .ok_or(())
1486 .expect_err("Append to empty map");
1487 map.extend_from_litemap(make_46())
1488 .ok_or(())
1489 .expect_err("Append to lesser map");
1490 assert_eq!(map.len(), 4);
1491 }
1492
1493 #[test]
1494 fn extend_from_litemap_prepend() {
1495 let mut map = LiteMap::new();
1496 map.extend_from_litemap(make_46())
1497 .ok_or(())
1498 .expect_err("Prepend to empty map");
1499 map.extend_from_litemap(make_13())
1500 .ok_or(())
1501 .expect_err("Prepend to lesser map");
1502 assert_eq!(map.len(), 4);
1503 }
1504
1505 #[test]
1506 fn extend_from_litemap_insert() {
1507 let mut map = LiteMap::new();
1508 map.extend_from_litemap(make_13())
1509 .ok_or(())
1510 .expect_err("Append to empty map");
1511 map.extend_from_litemap(make_24())
1512 .ok_or(())
1513 .expect_err("Insert with no conflict");
1514 map.extend_from_litemap(make_46())
1515 .ok_or(())
1516 .expect("Insert with conflict");
1517 assert_eq!(map.len(), 5);
1518 }
1519
1520 #[test]
1521 fn test_const_cmp_bytes() {
1522 let strs = &["a", "aa", "abc", "abde", "bcd", "bcde"];
1523 for i in 0..strs.len() {
1524 for j in 0..strs.len() {
1525 let a = strs[i].as_bytes();
1526 let b = strs[j].as_bytes();
1527 assert_eq!(a.cmp(b), const_cmp_bytes(a, b));
1528 }
1529 }
1530 }
1531
1532 #[test]
1533 fn into_iterator() {
1534 let mut map = LiteMap::<_, _, Vec<(_, _)>>::new();
1535 map.insert(4, "four");
1536 map.insert(6, "six");
1537 let mut reference = vec![(6, "six"), (4, "four")];
1538
1539 for i in map {
1540 let r = reference.pop().unwrap();
1541 assert_eq!(r, i);
1542 }
1543 assert!(reference.is_empty());
1544 }
1545
1546 #[test]
1547 fn entry_insert() {
1548 let mut map: LiteMap<i32, &str> = LiteMap::new();
1549 assert!(matches!(map.entry(1), Entry::Vacant(_)));
1550 map.entry(1).or_insert("one");
1551 assert!(matches!(map.entry(1), Entry::Occupied(_)));
1552 assert_eq!(map.get(&1), Some(&"one"));
1553 }
1554
1555 #[test]
1556 fn entry_insert_with() {
1557 let mut map: LiteMap<i32, &str> = LiteMap::new();
1558 assert!(matches!(map.entry(1), Entry::Vacant(_)));
1559 map.entry(1).or_insert_with(|| "one");
1560 assert!(matches!(map.entry(1), Entry::Occupied(_)));
1561 assert_eq!(map.get(&1), Some(&"one"));
1562 }
1563
1564 #[test]
1565 fn entry_vacant_insert() {
1566 let mut map: LiteMap<i32, &str> = LiteMap::new();
1567 if let Entry::Vacant(entry) = map.entry(1) {
1568 entry.insert("one");
1569 }
1570 assert_eq!(map.get(&1), Some(&"one"));
1571 }
1572
1573 #[test]
1574 fn entry_occupied_get_mut() {
1575 let mut map: LiteMap<i32, &str> = LiteMap::new();
1576 map.insert(1, "one");
1577 if let Entry::Occupied(mut entry) = map.entry(1) {
1578 *entry.get_mut() = "uno";
1579 }
1580 assert_eq!(map.get(&1), Some(&"uno"));
1581 }
1582
1583 #[test]
1584 fn entry_occupied_remove() {
1585 let mut map: LiteMap<i32, &str> = LiteMap::new();
1586 map.insert(1, "one");
1587 if let Entry::Occupied(entry) = map.entry(1) {
1588 entry.remove();
1589 }
1590 assert_eq!(map.get(&1), None);
1591 }
1592
1593 #[test]
1594 fn entry_occupied_key() {
1595 let mut map: LiteMap<i32, &str> = LiteMap::new();
1596 map.insert(1, "one");
1597 if let Entry::Occupied(entry) = map.entry(1) {
1598 assert_eq!(entry.key(), &1);
1599 }
1600 }
1601
1602 #[test]
1603 fn entry_occupied_get() {
1604 let mut map: LiteMap<i32, &str> = LiteMap::new();
1605 map.insert(1, "one");
1606 if let Entry::Occupied(entry) = map.entry(1) {
1607 assert_eq!(entry.get(), &"one");
1608 }
1609 }
1610
1611 #[test]
1612 fn entry_occupied_insert() {
1613 let mut map: LiteMap<i32, &str> = LiteMap::new();
1614 map.insert(1, "one");
1615 if let Entry::Occupied(mut entry) = map.entry(1) {
1616 assert_eq!(entry.insert("uno"), "one");
1617 }
1618 assert_eq!(map.get(&1), Some(&"uno"));
1619 }
1620
1621 #[test]
1622 fn entry_vacant_key() {
1623 let mut map: LiteMap<i32, &str> = LiteMap::new();
1624 if let Entry::Vacant(entry) = map.entry(1) {
1625 assert_eq!(entry.key(), &1);
1626 }
1627 }
1628
1629 #[test]
1630 fn entry_or_insert() {
1631 let mut map: LiteMap<i32, &str> = LiteMap::new();
1632 map.entry(1).or_insert("one");
1633 assert_eq!(map.get(&1), Some(&"one"));
1634 map.entry(1).or_insert("uno");
1635 assert_eq!(map.get(&1), Some(&"one"));
1636 }
1637
1638 #[test]
1639 fn entry_or_insert_with() {
1640 let mut map: LiteMap<i32, &str> = LiteMap::new();
1641 map.entry(1).or_insert_with(|| "one");
1642 assert_eq!(map.get(&1), Some(&"one"));
1643 map.entry(1).or_insert_with(|| "uno");
1644 assert_eq!(map.get(&1), Some(&"one"));
1645 }
1646
1647 #[test]
1648 fn entry_or_default() {
1649 let mut map: LiteMap<i32, String> = LiteMap::new();
1650 map.entry(1).or_default();
1651 assert_eq!(map.get(&1), Some(&String::new()));
1652 }
1653
1654 #[test]
1655 fn entry_and_modify() {
1656 let mut map: LiteMap<i32, i32> = LiteMap::new();
1657 map.entry(1).or_insert(10);
1658 map.entry(1).and_modify(|v| *v += 5);
1659 assert_eq!(map.get(&1), Some(&15));
1660 map.entry(2).and_modify(|v| *v += 5).or_insert(20);
1661 assert_eq!(map.get(&2), Some(&20));
1662 }
1663}