litemap/map.rs
1// This file is part of ICU4X. For terms of use, please see the file
2// called LICENSE at the top level of the ICU4X source tree
3// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4
5use 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 /// A simple "flat" map based on a sorted vector
21 ///
22 /// See the [module level documentation][super] for why one should use this.
23 ///
24 /// The API is roughly similar to that of [`std::collections::BTreeMap`].
25 #[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);
36// You can't `cfg()` a default generic parameter, and we don't want to write this type twice
37// and keep them in sync so we use a small macro
38litemap_impl!(feature = "alloc", S = alloc::vec::Vec<(K, V)>);
39litemap_impl!(not(feature = "alloc"), S);
40
41#[cfg(feature = "alloc")]
42impl<K, V> LiteMap<K, V> {
43 /// Construct a new [`LiteMap`] backed by Vec
44 pub const fn new_vec() -> Self {
45 Self {
46 values: alloc::vec::Vec::new(),
47 _key_type: PhantomData,
48 _value_type: PhantomData,
49 }
50 }
51}
52
53impl<K, V, S> LiteMap<K, V, S> {
54 /// Construct a new [`LiteMap`] using the given values
55 ///
56 /// The store must be sorted and have no duplicate keys.
57 pub const fn from_sorted_store_unchecked(values: S) -> Self {
58 Self {
59 values,
60 _key_type: PhantomData,
61 _value_type: PhantomData,
62 }
63 }
64}
65
66#[cfg(feature = "alloc")]
67impl<K, V> LiteMap<K, V, Vec<(K, V)>> {
68 /// Convert a [`LiteMap`] into a sorted `Vec<(K, V)>`.
69 #[inline]
70 pub fn into_tuple_vec(self) -> Vec<(K, V)> {
71 self.values
72 }
73}
74
75impl<K: ?Sized, V: ?Sized, S> LiteMap<K, V, S>
76where
77 S: StoreConstEmpty<K, V>,
78{
79 /// Create a new empty [`LiteMap`]
80 pub const fn new() -> Self {
81 Self {
82 values: S::EMPTY,
83 _key_type: PhantomData,
84 _value_type: PhantomData,
85 }
86 }
87}
88
89impl<K: ?Sized, V: ?Sized, S> LiteMap<K, V, S>
90where
91 S: Store<K, V>,
92{
93 /// The number of elements in the [`LiteMap`]
94 pub fn len(&self) -> usize {
95 self.values.lm_len()
96 }
97
98 /// Whether the [`LiteMap`] is empty
99 pub fn is_empty(&self) -> bool {
100 self.values.lm_is_empty()
101 }
102
103 /// Get the key-value pair residing at a particular index
104 ///
105 /// In most cases, prefer [`LiteMap::get()`] over this method.
106 #[inline]
107 pub fn get_indexed(&self, index: usize) -> Option<(&K, &V)> {
108 self.values.lm_get(index)
109 }
110
111 /// Get the lowest-rank key/value pair from the `LiteMap`, if it exists.
112 ///
113 /// # Examples
114 ///
115 /// ```rust
116 /// use litemap::LiteMap;
117 ///
118 /// let mut map =
119 /// LiteMap::<i32, &str, Vec<_>>::from_iter([(1, "uno"), (3, "tres")]);
120 ///
121 /// assert_eq!(map.first(), Some((&1, &"uno")));
122 /// ```
123 #[inline]
124 pub fn first(&self) -> Option<(&K, &V)> {
125 self.values.lm_get(0)
126 }
127
128 /// Get the highest-rank key/value pair from the `LiteMap`, if it exists.
129 ///
130 /// # Examples
131 ///
132 /// ```rust
133 /// use litemap::LiteMap;
134 ///
135 /// let mut map =
136 /// LiteMap::<i32, &str, Vec<_>>::from_iter([(1, "uno"), (3, "tres")]);
137 ///
138 /// assert_eq!(map.last(), Some((&3, &"tres")));
139 /// ```
140 #[inline]
141 pub fn last(&self) -> Option<(&K, &V)> {
142 self.values.lm_last()
143 }
144
145 /// Returns a new [`LiteMap`] with owned keys and values.
146 ///
147 /// The trait bounds allow transforming most slice and string types.
148 ///
149 /// # Examples
150 ///
151 /// ```
152 /// use litemap::LiteMap;
153 ///
154 /// let mut map: LiteMap<&str, &str> = LiteMap::new_vec();
155 /// map.insert("one", "uno");
156 /// map.insert("two", "dos");
157 ///
158 /// let boxed_map: LiteMap<Box<str>, Box<str>> = map.to_boxed_keys_values();
159 ///
160 /// assert_eq!(boxed_map.get("one"), Some(&Box::from("uno")));
161 /// ```
162 #[cfg(feature = "alloc")]
163 pub fn to_boxed_keys_values<KB: ?Sized, VB: ?Sized, SB>(&self) -> LiteMap<Box<KB>, Box<VB>, SB>
164 where
165 SB: StoreMut<Box<KB>, Box<VB>>,
166 K: Borrow<KB>,
167 V: Borrow<VB>,
168 Box<KB>: for<'a> From<&'a KB>,
169 Box<VB>: for<'a> From<&'a VB>,
170 {
171 let mut values = SB::lm_with_capacity(self.len());
172 for i in 0..self.len() {
173 #[allow(clippy::unwrap_used)] // iterating over our own length
174 let (k, v) = self.values.lm_get(i).unwrap();
175 values.lm_push(Box::from(k.borrow()), Box::from(v.borrow()))
176 }
177 LiteMap {
178 values,
179 _key_type: PhantomData,
180 _value_type: PhantomData,
181 }
182 }
183
184 /// Returns a new [`LiteMap`] with owned keys and cloned values.
185 ///
186 /// The trait bounds allow transforming most slice and string types.
187 ///
188 /// # Examples
189 ///
190 /// ```
191 /// use litemap::LiteMap;
192 ///
193 /// let mut map: LiteMap<&str, usize> = LiteMap::new_vec();
194 /// map.insert("one", 11);
195 /// map.insert("two", 22);
196 ///
197 /// let boxed_map: LiteMap<Box<str>, usize> = map.to_boxed_keys();
198 ///
199 /// assert_eq!(boxed_map.get("one"), Some(&11));
200 /// ```
201 #[cfg(feature = "alloc")]
202 pub fn to_boxed_keys<KB: ?Sized, SB>(&self) -> LiteMap<Box<KB>, V, SB>
203 where
204 V: Clone,
205 SB: StoreMut<Box<KB>, V>,
206 K: Borrow<KB>,
207 Box<KB>: for<'a> From<&'a KB>,
208 {
209 let mut values = SB::lm_with_capacity(self.len());
210 for i in 0..self.len() {
211 #[allow(clippy::unwrap_used)] // iterating over our own length
212 let (k, v) = self.values.lm_get(i).unwrap();
213 values.lm_push(Box::from(k.borrow()), v.clone())
214 }
215 LiteMap {
216 values,
217 _key_type: PhantomData,
218 _value_type: PhantomData,
219 }
220 }
221
222 /// Returns a new [`LiteMap`] with cloned keys and owned values.
223 ///
224 /// The trait bounds allow transforming most slice and string types.
225 ///
226 /// # Examples
227 ///
228 /// ```
229 /// use litemap::LiteMap;
230 ///
231 /// let mut map: LiteMap<usize, &str> = LiteMap::new_vec();
232 /// map.insert(11, "uno");
233 /// map.insert(22, "dos");
234 ///
235 /// let boxed_map: LiteMap<usize, Box<str>> = map.to_boxed_values();
236 ///
237 /// assert_eq!(boxed_map.get(&11), Some(&Box::from("uno")));
238 /// ```
239 #[cfg(feature = "alloc")]
240 pub fn to_boxed_values<VB: ?Sized, SB>(&self) -> LiteMap<K, Box<VB>, SB>
241 where
242 K: Clone,
243 SB: StoreMut<K, Box<VB>>,
244 V: Borrow<VB>,
245 Box<VB>: for<'a> From<&'a VB>,
246 {
247 let mut values = SB::lm_with_capacity(self.len());
248 for i in 0..self.len() {
249 #[allow(clippy::unwrap_used)] // iterating over our own length
250 let (k, v) = self.values.lm_get(i).unwrap();
251 values.lm_push(k.clone(), Box::from(v.borrow()))
252 }
253 LiteMap {
254 values,
255 _key_type: PhantomData,
256 _value_type: PhantomData,
257 }
258 }
259}
260
261impl<K: ?Sized, V: ?Sized, S> LiteMap<K, V, S>
262where
263 K: Ord,
264 S: Store<K, V>,
265{
266 /// Get the value associated with `key`, if it exists.
267 ///
268 /// ```rust
269 /// use litemap::LiteMap;
270 ///
271 /// let mut map = LiteMap::new_vec();
272 /// map.insert(1, "one");
273 /// map.insert(2, "two");
274 /// assert_eq!(map.get(&1), Some(&"one"));
275 /// assert_eq!(map.get(&3), None);
276 /// ```
277 pub fn get<Q>(&self, key: &Q) -> Option<&V>
278 where
279 K: Borrow<Q>,
280 Q: Ord + ?Sized,
281 {
282 match self.find_index(key) {
283 #[allow(clippy::unwrap_used)] // find_index returns a valid index
284 Ok(found) => Some(self.values.lm_get(found).unwrap().1),
285 Err(_) => None,
286 }
287 }
288
289 /// Binary search the map with `predicate` to find a key, returning the value.
290 pub fn get_by(&self, predicate: impl FnMut(&K) -> Ordering) -> Option<&V> {
291 let index = self.values.lm_binary_search_by(predicate).ok()?;
292 self.values.lm_get(index).map(|(_, v)| v)
293 }
294
295 /// Returns whether `key` is contained in this map
296 ///
297 /// ```rust
298 /// use litemap::LiteMap;
299 ///
300 /// let mut map = LiteMap::new_vec();
301 /// map.insert(1, "one");
302 /// map.insert(2, "two");
303 /// assert!(map.contains_key(&1));
304 /// assert!(!map.contains_key(&3));
305 /// ```
306 pub fn contains_key<Q>(&self, key: &Q) -> bool
307 where
308 K: Borrow<Q>,
309 Q: Ord + ?Sized,
310 {
311 self.find_index(key).is_ok()
312 }
313
314 /// Obtain the index for a given key, or if the key is not found, the index
315 /// at which it would be inserted.
316 ///
317 /// (The return value works equivalently to [`slice::binary_search_by()`])
318 ///
319 /// The indices returned can be used with [`Self::get_indexed()`]. Prefer using
320 /// [`Self::get()`] directly where possible.
321 #[inline]
322 pub fn find_index<Q>(&self, key: &Q) -> Result<usize, usize>
323 where
324 K: Borrow<Q>,
325 Q: Ord + ?Sized,
326 {
327 self.values.lm_binary_search_by(|k| k.borrow().cmp(key))
328 }
329}
330
331impl<K: ?Sized, V: ?Sized, S> LiteMap<K, V, S>
332where
333 S: StoreSlice<K, V>,
334{
335 /// Creates a new [`LiteMap`] from a range of the current [`LiteMap`].
336 ///
337 /// # Examples
338 ///
339 /// ```
340 /// use litemap::LiteMap;
341 ///
342 /// let mut map = LiteMap::new_vec();
343 /// map.insert(1, "one");
344 /// map.insert(2, "two");
345 /// map.insert(3, "three");
346 ///
347 /// let mut sub_map = map.get_indexed_range(1..3).expect("valid range");
348 /// assert_eq!(sub_map.get(&1), None);
349 /// assert_eq!(sub_map.get(&2), Some(&"two"));
350 /// assert_eq!(sub_map.get(&3), Some(&"three"));
351 /// ```
352 pub fn get_indexed_range(&self, range: Range<usize>) -> Option<LiteMap<K, V, &S::Slice>> {
353 let subslice = self.values.lm_get_range(range)?;
354 Some(LiteMap {
355 values: subslice,
356 _key_type: PhantomData,
357 _value_type: PhantomData,
358 })
359 }
360
361 /// Borrows this [`LiteMap`] as one of its slice type.
362 ///
363 /// This can be useful in situations where you need a `LiteMap` by value but do not want
364 /// to clone the owned version.
365 ///
366 /// # Examples
367 ///
368 /// ```
369 /// use litemap::LiteMap;
370 ///
371 /// let mut map = LiteMap::new_vec();
372 /// map.insert(1, "one");
373 /// map.insert(2, "two");
374 ///
375 /// let borrowed_map = map.as_sliced();
376 /// assert_eq!(borrowed_map.get(&1), Some(&"one"));
377 /// assert_eq!(borrowed_map.get(&2), Some(&"two"));
378 /// ```
379 pub fn as_sliced(&self) -> LiteMap<K, V, &S::Slice> {
380 // Won't panic: 0..self.len() is within range
381 #[allow(clippy::unwrap_used)]
382 let subslice = self.values.lm_get_range(0..self.len()).unwrap();
383 LiteMap {
384 values: subslice,
385 _key_type: PhantomData,
386 _value_type: PhantomData,
387 }
388 }
389
390 /// Borrows the backing buffer of this [`LiteMap`] as its slice type.
391 ///
392 /// The slice will be sorted.
393 ///
394 /// # Examples
395 ///
396 /// ```
397 /// use litemap::LiteMap;
398 ///
399 /// let mut map = LiteMap::new_vec();
400 /// map.insert(1, "one");
401 /// map.insert(2, "two");
402 ///
403 /// let slice = map.as_slice();
404 /// assert_eq!(slice, &[(1, "one"), (2, "two")]);
405 /// ```
406 pub fn as_slice(&self) -> &S::Slice {
407 // Won't panic: 0..self.len() is within range
408 #[allow(clippy::unwrap_used)]
409 self.values.lm_get_range(0..self.len()).unwrap()
410 }
411}
412
413impl<'a, K: 'a, V: 'a, S> LiteMap<K, V, S>
414where
415 S: Store<K, V>,
416{
417 /// Returns a new [`LiteMap`] with keys and values borrowed from this one.
418 ///
419 /// # Examples
420 ///
421 /// ```
422 /// use litemap::LiteMap;
423 ///
424 /// let mut map: LiteMap<Box<usize>, String> = LiteMap::new_vec();
425 /// map.insert(Box::new(1), "one".to_string());
426 /// map.insert(Box::new(2), "two".to_string());
427 ///
428 /// let borrowed_map: LiteMap<&usize, &str> = map.to_borrowed_keys_values();
429 ///
430 /// assert_eq!(borrowed_map.get(&1), Some(&"one"));
431 /// ```
432 pub fn to_borrowed_keys_values<KB: ?Sized, VB: ?Sized, SB>(
433 &'a self,
434 ) -> LiteMap<&'a KB, &'a VB, SB>
435 where
436 K: Borrow<KB>,
437 V: Borrow<VB>,
438 SB: StoreMut<&'a KB, &'a VB>,
439 {
440 let mut values = SB::lm_with_capacity(self.len());
441 for i in 0..self.len() {
442 #[allow(clippy::unwrap_used)] // iterating over our own length
443 let (k, v) = self.values.lm_get(i).unwrap();
444 values.lm_push(k.borrow(), v.borrow())
445 }
446 LiteMap {
447 values,
448 _key_type: PhantomData,
449 _value_type: PhantomData,
450 }
451 }
452
453 /// Returns a new [`LiteMap`] with keys borrowed from this one and cloned values.
454 ///
455 /// # Examples
456 ///
457 /// ```
458 /// use litemap::LiteMap;
459 ///
460 /// let mut map: LiteMap<Box<usize>, String> = LiteMap::new_vec();
461 /// map.insert(Box::new(1), "one".to_string());
462 /// map.insert(Box::new(2), "two".to_string());
463 ///
464 /// let borrowed_map: LiteMap<&usize, String> = map.to_borrowed_keys();
465 ///
466 /// assert_eq!(borrowed_map.get(&1), Some(&"one".to_string()));
467 /// ```
468 pub fn to_borrowed_keys<KB: ?Sized, SB>(&'a self) -> LiteMap<&'a KB, V, SB>
469 where
470 K: Borrow<KB>,
471 V: Clone,
472 SB: StoreMut<&'a KB, V>,
473 {
474 let mut values = SB::lm_with_capacity(self.len());
475 for i in 0..self.len() {
476 #[allow(clippy::unwrap_used)] // iterating over our own length
477 let (k, v) = self.values.lm_get(i).unwrap();
478 values.lm_push(k.borrow(), v.clone())
479 }
480 LiteMap {
481 values,
482 _key_type: PhantomData,
483 _value_type: PhantomData,
484 }
485 }
486
487 /// Returns a new [`LiteMap`] with values borrowed from this one and cloned keys.
488 ///
489 /// # Examples
490 ///
491 /// ```
492 /// use litemap::LiteMap;
493 ///
494 /// let mut map: LiteMap<Box<usize>, String> = LiteMap::new_vec();
495 /// map.insert(Box::new(1), "one".to_string());
496 /// map.insert(Box::new(2), "two".to_string());
497 ///
498 /// let borrowed_map: LiteMap<Box<usize>, &str> = map.to_borrowed_values();
499 ///
500 /// assert_eq!(borrowed_map.get(&1), Some(&"one"));
501 /// ```
502 pub fn to_borrowed_values<VB: ?Sized, SB>(&'a self) -> LiteMap<K, &'a VB, SB>
503 where
504 K: Clone,
505 V: Borrow<VB>,
506 SB: StoreMut<K, &'a VB>,
507 {
508 let mut values = SB::lm_with_capacity(self.len());
509 for i in 0..self.len() {
510 #[allow(clippy::unwrap_used)] // iterating over our own length
511 let (k, v) = self.values.lm_get(i).unwrap();
512 values.lm_push(k.clone(), v.borrow())
513 }
514 LiteMap {
515 values,
516 _key_type: PhantomData,
517 _value_type: PhantomData,
518 }
519 }
520}
521
522impl<K, V, S> LiteMap<K, V, S>
523where
524 S: StoreMut<K, V>,
525{
526 /// Construct a new [`LiteMap`] with a given capacity
527 pub fn with_capacity(capacity: usize) -> Self {
528 Self {
529 values: S::lm_with_capacity(capacity),
530 _key_type: PhantomData,
531 _value_type: PhantomData,
532 }
533 }
534
535 /// Remove all elements from the [`LiteMap`]
536 pub fn clear(&mut self) {
537 self.values.lm_clear()
538 }
539
540 /// Reserve capacity for `additional` more elements to be inserted into
541 /// the [`LiteMap`] to avoid frequent reallocations.
542 ///
543 /// See [`Vec::reserve()`] for more information.
544 ///
545 /// [`Vec::reserve()`]: alloc::vec::Vec::reserve
546 pub fn reserve(&mut self, additional: usize) {
547 self.values.lm_reserve(additional)
548 }
549}
550
551impl<K, V, S> LiteMap<K, V, S>
552where
553 K: Ord,
554 S: StoreMut<K, V>,
555{
556 /// Get the value associated with `key`, if it exists, as a mutable reference.
557 ///
558 /// ```rust
559 /// use litemap::LiteMap;
560 ///
561 /// let mut map = LiteMap::new_vec();
562 /// map.insert(1, "one");
563 /// map.insert(2, "two");
564 /// if let Some(mut v) = map.get_mut(&1) {
565 /// *v = "uno";
566 /// }
567 /// assert_eq!(map.get(&1), Some(&"uno"));
568 /// ```
569 pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
570 where
571 K: Borrow<Q>,
572 Q: Ord + ?Sized,
573 {
574 match self.find_index(key) {
575 #[allow(clippy::unwrap_used)] // find_index returns a valid index
576 Ok(found) => Some(self.values.lm_get_mut(found).unwrap().1),
577 Err(_) => None,
578 }
579 }
580
581 /// Appends `value` with `key` to the end of the underlying vector, returning
582 /// `key` and `value` _if it failed_. Useful for extending with an existing
583 /// sorted list.
584 /// ```rust
585 /// use litemap::LiteMap;
586 ///
587 /// let mut map = LiteMap::new_vec();
588 /// assert!(map.try_append(1, "uno").is_none());
589 /// assert!(map.try_append(3, "tres").is_none());
590 ///
591 /// assert!(
592 /// matches!(map.try_append(3, "tres-updated"), Some((3, "tres-updated"))),
593 /// "append duplicate of last key",
594 /// );
595 ///
596 /// assert!(
597 /// matches!(map.try_append(2, "dos"), Some((2, "dos"))),
598 /// "append out of order"
599 /// );
600 ///
601 /// assert_eq!(map.get(&1), Some(&"uno"));
602 ///
603 /// // contains the original value for the key: 3
604 /// assert_eq!(map.get(&3), Some(&"tres"));
605 ///
606 /// // not appended since it wasn't in order
607 /// assert_eq!(map.get(&2), None);
608 /// ```
609 #[must_use]
610 pub fn try_append(&mut self, key: K, value: V) -> Option<(K, V)> {
611 if let Some(last) = self.values.lm_last() {
612 if last.0 >= &key {
613 return Some((key, value));
614 }
615 }
616
617 self.values.lm_push(key, value);
618 None
619 }
620
621 /// Insert `value` with `key`, returning the existing value if it exists.
622 ///
623 /// ```rust
624 /// use litemap::LiteMap;
625 ///
626 /// let mut map = LiteMap::new_vec();
627 /// map.insert(1, "one");
628 /// map.insert(2, "two");
629 /// assert_eq!(map.get(&1), Some(&"one"));
630 /// assert_eq!(map.get(&3), None);
631 /// ```
632 pub fn insert(&mut self, key: K, value: V) -> Option<V> {
633 self.insert_save_key(key, value).map(|(_, v)| v)
634 }
635
636 /// Version of [`Self::insert()`] that returns both the key and the old value.
637 fn insert_save_key(&mut self, key: K, value: V) -> Option<(K, V)> {
638 match self.values.lm_binary_search_by(|k| k.cmp(&key)) {
639 #[allow(clippy::unwrap_used)] // Index came from binary_search
640 Ok(found) => Some((
641 key,
642 mem::replace(self.values.lm_get_mut(found).unwrap().1, value),
643 )),
644 Err(ins) => {
645 self.values.lm_insert(ins, key, value);
646 None
647 }
648 }
649 }
650
651 /// Attempts to insert a unique entry into the map.
652 ///
653 /// If `key` is not already in the map, inserts it with the corresponding `value`
654 /// and returns `None`.
655 ///
656 /// If `key` is already in the map, no change is made to the map, and the key and value
657 /// are returned back to the caller.
658 ///
659 /// ```
660 /// use litemap::LiteMap;
661 ///
662 /// let mut map = LiteMap::new_vec();
663 /// map.insert(1, "one");
664 /// map.insert(3, "three");
665 ///
666 /// // 2 is not yet in the map...
667 /// assert_eq!(map.try_insert(2, "two"), None);
668 /// assert_eq!(map.len(), 3);
669 ///
670 /// // ...but now it is.
671 /// assert_eq!(map.try_insert(2, "TWO"), Some((2, "TWO")));
672 /// assert_eq!(map.len(), 3);
673 /// ```
674 pub fn try_insert(&mut self, key: K, value: V) -> Option<(K, V)> {
675 match self.values.lm_binary_search_by(|k| k.cmp(&key)) {
676 Ok(_) => Some((key, value)),
677 Err(ins) => {
678 self.values.lm_insert(ins, key, value);
679 None
680 }
681 }
682 }
683
684 /// Attempts to insert a unique entry into the map.
685 ///
686 /// If `key` is not already in the map, invokes the closure to compute `value`, inserts
687 /// the pair into the map, and returns a reference to the value. The closure is passed
688 /// a reference to the `key` argument.
689 ///
690 /// If `key` is already in the map, a reference to the existing value is returned.
691 ///
692 /// Additionally, the index of the value in the map is returned. If it is not desirable
693 /// to hold on to the mutable reference's lifetime, the index can be used to access the
694 /// element via [`LiteMap::get_indexed()`].
695 ///
696 /// The closure returns a `Result` to allow for a fallible insertion function. If the
697 /// creation of `value` is infallible, you can use [`core::convert::Infallible`].
698 ///
699 /// ```
700 /// use litemap::LiteMap;
701 ///
702 /// /// Helper function to unwrap an `Infallible` result from the insertion function
703 /// fn unwrap_infallible<T>(result: Result<T, core::convert::Infallible>) -> T {
704 /// result.unwrap_or_else(|never| match never {})
705 /// }
706 ///
707 /// let mut map = LiteMap::new_vec();
708 /// map.insert(1, "one");
709 /// map.insert(3, "three");
710 ///
711 /// // 2 is not yet in the map...
712 /// let result1 = unwrap_infallible(
713 /// map.try_get_or_insert(2, |_| Ok("two"))
714 /// );
715 /// assert_eq!(result1.1, &"two");
716 /// assert_eq!(map.len(), 3);
717 ///
718 /// // ...but now it is.
719 /// let result1 = unwrap_infallible(
720 /// map.try_get_or_insert(2, |_| Ok("TWO"))
721 /// );
722 /// assert_eq!(result1.1, &"two");
723 /// assert_eq!(map.len(), 3);
724 /// ```
725 pub fn try_get_or_insert<E>(
726 &mut self,
727 key: K,
728 value: impl FnOnce(&K) -> Result<V, E>,
729 ) -> Result<(usize, &V), E> {
730 let idx = match self.values.lm_binary_search_by(|k| k.cmp(&key)) {
731 Ok(idx) => idx,
732 Err(idx) => {
733 let value = value(&key)?;
734 self.values.lm_insert(idx, key, value);
735 idx
736 }
737 };
738 #[allow(clippy::unwrap_used)] // item at idx found or inserted above
739 Ok((idx, self.values.lm_get(idx).unwrap().1))
740 }
741
742 /// Remove the value at `key`, returning it if it exists.
743 ///
744 /// ```rust
745 /// use litemap::LiteMap;
746 ///
747 /// let mut map = LiteMap::new_vec();
748 /// map.insert(1, "one");
749 /// map.insert(2, "two");
750 /// assert_eq!(map.remove(&1), Some("one"));
751 /// assert_eq!(map.get(&1), None);
752 /// ```
753 pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
754 where
755 K: Borrow<Q>,
756 Q: Ord + ?Sized,
757 {
758 match self.values.lm_binary_search_by(|k| k.borrow().cmp(key)) {
759 Ok(found) => Some(self.values.lm_remove(found).1),
760 Err(_) => None,
761 }
762 }
763}
764
765impl<K, V, S> LiteMap<K, V, S>
766where
767 K: Ord,
768 S: StoreIntoIterator<K, V> + StoreFromIterator<K, V>,
769{
770 /// Insert all elements from `other` into this `LiteMap`.
771 ///
772 /// If `other` contains keys that already exist in `self`, the values in `other` replace the
773 /// corresponding ones in `self`, and the rejected items from `self` are returned as a new
774 /// `LiteMap`. Otherwise, `None` is returned.
775 ///
776 /// The implementation of this function is optimized if `self` and `other` have no overlap.
777 ///
778 /// # Examples
779 ///
780 /// ```
781 /// use litemap::LiteMap;
782 ///
783 /// let mut map1 = LiteMap::new_vec();
784 /// map1.insert(1, "one");
785 /// map1.insert(2, "two");
786 ///
787 /// let mut map2 = LiteMap::new_vec();
788 /// map2.insert(2, "TWO");
789 /// map2.insert(4, "FOUR");
790 ///
791 /// let leftovers = map1.extend_from_litemap(map2);
792 ///
793 /// assert_eq!(map1.len(), 3);
794 /// assert_eq!(map1.get(&1), Some("one").as_ref());
795 /// assert_eq!(map1.get(&2), Some("TWO").as_ref());
796 /// assert_eq!(map1.get(&4), Some("FOUR").as_ref());
797 ///
798 /// let map3 = leftovers.expect("Duplicate keys");
799 /// assert_eq!(map3.len(), 1);
800 /// assert_eq!(map3.get(&2), Some("two").as_ref());
801 /// ```
802 pub fn extend_from_litemap(&mut self, other: Self) -> Option<Self> {
803 if self.is_empty() {
804 self.values = other.values;
805 return None;
806 }
807 if other.is_empty() {
808 return None;
809 }
810 if self.last().map(|(k, _)| k) < other.first().map(|(k, _)| k) {
811 // append other to self
812 self.values.lm_extend_end(other.values);
813 None
814 } else if self.first().map(|(k, _)| k) > other.last().map(|(k, _)| k) {
815 // prepend other to self
816 self.values.lm_extend_start(other.values);
817 None
818 } else {
819 // insert every element
820 let leftover_tuples = other
821 .values
822 .lm_into_iter()
823 .filter_map(|(k, v)| self.insert_save_key(k, v))
824 .collect();
825 let ret = LiteMap {
826 values: leftover_tuples,
827 _key_type: PhantomData,
828 _value_type: PhantomData,
829 };
830 if ret.is_empty() {
831 None
832 } else {
833 Some(ret)
834 }
835 }
836 }
837}
838
839impl<K, V, S> Default for LiteMap<K, V, S>
840where
841 S: Store<K, V> + Default,
842{
843 fn default() -> Self {
844 Self {
845 values: S::default(),
846 _key_type: PhantomData,
847 _value_type: PhantomData,
848 }
849 }
850}
851impl<K, V, S> Index<&'_ K> for LiteMap<K, V, S>
852where
853 K: Ord,
854 S: Store<K, V>,
855{
856 type Output = V;
857 fn index(&self, key: &K) -> &V {
858 #[allow(clippy::panic)] // documented
859 match self.get(key) {
860 Some(v) => v,
861 None => panic!("no entry found for key"),
862 }
863 }
864}
865impl<K, V, S> IndexMut<&'_ K> for LiteMap<K, V, S>
866where
867 K: Ord,
868 S: StoreMut<K, V>,
869{
870 fn index_mut(&mut self, key: &K) -> &mut V {
871 #[allow(clippy::panic)] // documented
872 match self.get_mut(key) {
873 Some(v) => v,
874 None => panic!("no entry found for key"),
875 }
876 }
877}
878impl<K, V, S> FromIterator<(K, V)> for LiteMap<K, V, S>
879where
880 K: Ord,
881 S: StoreFromIterable<K, V>,
882{
883 fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
884 let values = S::lm_sort_from_iter(iter);
885 Self::from_sorted_store_unchecked(values)
886 }
887}
888
889impl<'a, K: 'a, V: 'a, S> LiteMap<K, V, S>
890where
891 S: StoreIterable<'a, K, V>,
892{
893 /// Produce an ordered iterator over key-value pairs
894 pub fn iter(&'a self) -> impl DoubleEndedIterator<Item = (&'a K, &'a V)> {
895 self.values.lm_iter()
896 }
897
898 /// Produce an ordered iterator over keys
899 #[deprecated = "use keys() instead"]
900 pub fn iter_keys(&'a self) -> impl DoubleEndedIterator<Item = &'a K> {
901 self.values.lm_iter().map(|val| val.0)
902 }
903
904 /// Produce an iterator over values, ordered by their keys
905 #[deprecated = "use values() instead"]
906 pub fn iter_values(&'a self) -> impl DoubleEndedIterator<Item = &'a V> {
907 self.values.lm_iter().map(|val| val.1)
908 }
909
910 /// Produce an ordered iterator over keys
911 pub fn keys(&'a self) -> impl DoubleEndedIterator<Item = &'a K> {
912 self.values.lm_iter().map(|val| val.0)
913 }
914
915 /// Produce an iterator over values, ordered by their keys
916 pub fn values(&'a self) -> impl DoubleEndedIterator<Item = &'a V> {
917 self.values.lm_iter().map(|val| val.1)
918 }
919}
920
921impl<'a, K: 'a, V: 'a, S> LiteMap<K, V, S>
922where
923 S: StoreIterableMut<'a, K, V>,
924{
925 /// Produce an ordered mutable iterator over key-value pairs
926 pub fn iter_mut(&'a mut self) -> impl DoubleEndedIterator<Item = (&'a K, &'a mut V)> {
927 self.values.lm_iter_mut()
928 }
929}
930
931impl<K, V, S> IntoIterator for LiteMap<K, V, S>
932where
933 S: StoreIntoIterator<K, V>,
934{
935 type Item = (K, V);
936 type IntoIter = S::KeyValueIntoIter;
937
938 fn into_iter(self) -> Self::IntoIter {
939 self.values.lm_into_iter()
940 }
941}
942
943impl<'a, K, V, S> IntoIterator for &'a LiteMap<K, V, S>
944where
945 S: StoreIterable<'a, K, V>,
946{
947 type Item = (&'a K, &'a V);
948 type IntoIter = S::KeyValueIter;
949
950 fn into_iter(self) -> Self::IntoIter {
951 self.values.lm_iter()
952 }
953}
954
955impl<'a, K, V, S> IntoIterator for &'a mut LiteMap<K, V, S>
956where
957 S: StoreIterableMut<'a, K, V>,
958{
959 type Item = (&'a K, &'a mut V);
960 type IntoIter = S::KeyValueIterMut;
961
962 fn into_iter(self) -> Self::IntoIter {
963 self.values.lm_iter_mut()
964 }
965}
966
967impl<K, V, S> LiteMap<K, V, S>
968where
969 S: StoreMut<K, V>,
970{
971 /// Retains only the elements specified by the predicate.
972 ///
973 /// In other words, remove all elements such that `f((&k, &v))` returns `false`.
974 ///
975 /// # Example
976 ///
977 /// ```rust
978 /// use litemap::LiteMap;
979 ///
980 /// let mut map = LiteMap::new_vec();
981 /// map.insert(1, "one");
982 /// map.insert(2, "two");
983 /// map.insert(3, "three");
984 ///
985 /// // Retain elements with odd keys
986 /// map.retain(|k, _| k % 2 == 1);
987 ///
988 /// assert_eq!(map.get(&1), Some(&"one"));
989 /// assert_eq!(map.get(&2), None);
990 /// ```
991 #[inline]
992 pub fn retain<F>(&mut self, predicate: F)
993 where
994 F: FnMut(&K, &V) -> bool,
995 {
996 self.values.lm_retain(predicate)
997 }
998}
999
1000impl<'a, K, V> LiteMap<K, V, &'a [(K, V)]> {
1001 /// Const version of [`LiteMap::len()`] for a slice store.
1002 ///
1003 /// Note: This function will no longer be needed if const trait behavior is stabilized.
1004 ///
1005 /// # Examples
1006 ///
1007 /// ```rust
1008 /// use litemap::LiteMap;
1009 ///
1010 /// static map: LiteMap<&str, usize, &[(&str, usize)]> =
1011 /// LiteMap::from_sorted_store_unchecked(&[("a", 11), ("b", 22)]);
1012 /// static len: usize = map.const_len();
1013 /// assert_eq!(len, 2);
1014 /// ```
1015 #[inline]
1016 pub const fn const_len(&self) -> usize {
1017 self.values.len()
1018 }
1019
1020 /// Const version of [`LiteMap::is_empty()`] for a slice store.
1021 ///
1022 /// Note: This function will no longer be needed if const trait behavior is stabilized.
1023 ///
1024 /// # Examples
1025 ///
1026 /// ```rust
1027 /// use litemap::LiteMap;
1028 ///
1029 /// static map: LiteMap<&str, usize, &[(&str, usize)]> =
1030 /// LiteMap::from_sorted_store_unchecked(&[]);
1031 /// static is_empty: bool = map.const_is_empty();
1032 /// assert!(is_empty);
1033 /// ```
1034 #[inline]
1035 pub const fn const_is_empty(&self) -> bool {
1036 self.values.is_empty()
1037 }
1038
1039 /// Const version of [`LiteMap::get_indexed()`] for a slice store.
1040 ///
1041 /// Note: This function will no longer be needed if const trait behavior is stabilized.
1042 ///
1043 /// # Panics
1044 ///
1045 /// Panics if the index is out of bounds.
1046 ///
1047 /// # Examples
1048 ///
1049 /// ```rust
1050 /// use litemap::LiteMap;
1051 ///
1052 /// static map: LiteMap<&str, usize, &[(&str, usize)]> =
1053 /// LiteMap::from_sorted_store_unchecked(&[("a", 11), ("b", 22)]);
1054 /// static t: &(&str, usize) = map.const_get_indexed_or_panic(0);
1055 /// assert_eq!(t.0, "a");
1056 /// assert_eq!(t.1, 11);
1057 /// ```
1058 #[inline]
1059 #[allow(clippy::indexing_slicing)] // documented
1060 pub const fn const_get_indexed_or_panic(&self, index: usize) -> &'a (K, V) {
1061 &self.values[index]
1062 }
1063}
1064
1065const fn const_cmp_bytes(a: &[u8], b: &[u8]) -> Ordering {
1066 let (max, default) = if a.len() == b.len() {
1067 (a.len(), Ordering::Equal)
1068 } else if a.len() < b.len() {
1069 (a.len(), Ordering::Less)
1070 } else {
1071 (b.len(), Ordering::Greater)
1072 };
1073 let mut i = 0;
1074 #[allow(clippy::indexing_slicing)] // indexes in range by above checks
1075 while i < max {
1076 if a[i] == b[i] {
1077 i += 1;
1078 continue;
1079 } else if a[i] < b[i] {
1080 return Ordering::Less;
1081 } else {
1082 return Ordering::Greater;
1083 }
1084 }
1085 default
1086}
1087
1088impl<'a, V> LiteMap<&'a str, V, &'a [(&'a str, V)]> {
1089 /// Const function to get the value associated with a `&str` key, if it exists.
1090 ///
1091 /// Also returns the index of the value.
1092 ///
1093 /// Note: This function will no longer be needed if const trait behavior is stabilized.
1094 ///
1095 /// # Examples
1096 ///
1097 /// ```rust
1098 /// use litemap::LiteMap;
1099 ///
1100 /// static map: LiteMap<&str, usize, &[(&str, usize)]> =
1101 /// LiteMap::from_sorted_store_unchecked(&[
1102 /// ("abc", 11),
1103 /// ("bcd", 22),
1104 /// ("cde", 33),
1105 /// ("def", 44),
1106 /// ("efg", 55),
1107 /// ]);
1108 ///
1109 /// static d: Option<(usize, &usize)> = map.const_get_with_index("def");
1110 /// assert_eq!(d, Some((3, &44)));
1111 ///
1112 /// static n: Option<(usize, &usize)> = map.const_get_with_index("dng");
1113 /// assert_eq!(n, None);
1114 /// ```
1115 pub const fn const_get_with_index(&self, key: &str) -> Option<(usize, &'a V)> {
1116 let mut i = 0;
1117 let mut j = self.const_len();
1118 while i < j {
1119 let mid = (i + j) / 2;
1120 #[allow(clippy::indexing_slicing)] // in range
1121 let x = &self.values[mid];
1122 match const_cmp_bytes(key.as_bytes(), x.0.as_bytes()) {
1123 Ordering::Equal => return Some((mid, &x.1)),
1124 Ordering::Greater => i = mid + 1,
1125 Ordering::Less => j = mid,
1126 };
1127 }
1128 None
1129 }
1130}
1131
1132impl<'a, V> LiteMap<&'a [u8], V, &'a [(&'a [u8], V)]> {
1133 /// Const function to get the value associated with a `&[u8]` key, if it exists.
1134 ///
1135 /// Also returns the index of the value.
1136 ///
1137 /// Note: This function will no longer be needed if const trait behavior is stabilized.
1138 ///
1139 /// # Examples
1140 ///
1141 /// ```rust
1142 /// use litemap::LiteMap;
1143 ///
1144 /// static map: LiteMap<&[u8], usize, &[(&[u8], usize)]> =
1145 /// LiteMap::from_sorted_store_unchecked(&[
1146 /// (b"abc", 11),
1147 /// (b"bcd", 22),
1148 /// (b"cde", 33),
1149 /// (b"def", 44),
1150 /// (b"efg", 55),
1151 /// ]);
1152 ///
1153 /// static d: Option<(usize, &usize)> = map.const_get_with_index(b"def");
1154 /// assert_eq!(d, Some((3, &44)));
1155 ///
1156 /// static n: Option<(usize, &usize)> = map.const_get_with_index(b"dng");
1157 /// assert_eq!(n, None);
1158 /// ```
1159 pub const fn const_get_with_index(&self, key: &[u8]) -> Option<(usize, &'a V)> {
1160 let mut i = 0;
1161 let mut j = self.const_len();
1162 while i < j {
1163 let mid = (i + j) / 2;
1164 #[allow(clippy::indexing_slicing)] // in range
1165 let x = &self.values[mid];
1166 match const_cmp_bytes(key, x.0) {
1167 Ordering::Equal => return Some((mid, &x.1)),
1168 Ordering::Greater => i = mid + 1,
1169 Ordering::Less => j = mid,
1170 };
1171 }
1172 None
1173 }
1174}
1175
1176macro_rules! impl_const_get_with_index_for_integer {
1177 ($integer:ty) => {
1178 impl<'a, V> LiteMap<$integer, V, &'a [($integer, V)]> {
1179 /// Const function to get the value associated with an integer key, if it exists.
1180 ///
1181 /// Note: This function will no longer be needed if const trait behavior is stabilized.
1182 ///
1183 /// Also returns the index of the value.
1184 pub const fn const_get_with_index(&self, key: $integer) -> Option<(usize, &'a V)> {
1185 let mut i = 0;
1186 let mut j = self.const_len();
1187 while i < j {
1188 let mid = (i + j) / 2;
1189 #[allow(clippy::indexing_slicing)] // in range
1190 let x = &self.values[mid];
1191 if key == x.0 {
1192 return Some((mid, &x.1));
1193 } else if key > x.0 {
1194 i = mid + 1;
1195 } else {
1196 j = mid;
1197 }
1198 }
1199 return None;
1200 }
1201 }
1202 };
1203}
1204
1205impl_const_get_with_index_for_integer!(u8);
1206impl_const_get_with_index_for_integer!(u16);
1207impl_const_get_with_index_for_integer!(u32);
1208impl_const_get_with_index_for_integer!(u64);
1209impl_const_get_with_index_for_integer!(u128);
1210impl_const_get_with_index_for_integer!(usize);
1211impl_const_get_with_index_for_integer!(i8);
1212impl_const_get_with_index_for_integer!(i16);
1213impl_const_get_with_index_for_integer!(i32);
1214impl_const_get_with_index_for_integer!(i64);
1215impl_const_get_with_index_for_integer!(i128);
1216impl_const_get_with_index_for_integer!(isize);
1217
1218/// An entry in a `LiteMap`, which may be either occupied or vacant.
1219#[allow(clippy::exhaustive_enums)]
1220pub enum Entry<'a, K, V, S>
1221where
1222 K: Ord,
1223 S: StoreMut<K, V>,
1224{
1225 Occupied(OccupiedEntry<'a, K, V, S>),
1226 Vacant(VacantEntry<'a, K, V, S>),
1227}
1228
1229impl<K, V, S> Debug for Entry<'_, K, V, S>
1230where
1231 K: Ord,
1232 S: StoreMut<K, V>,
1233{
1234 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1235 match self {
1236 Self::Occupied(arg0) => f.debug_tuple("Occupied").field(arg0).finish(),
1237 Self::Vacant(arg0) => f.debug_tuple("Vacant").field(arg0).finish(),
1238 }
1239 }
1240}
1241
1242/// A view into an occupied entry in a `LiteMap`.
1243pub struct OccupiedEntry<'a, K, V, S>
1244where
1245 K: Ord,
1246 S: StoreMut<K, V>,
1247{
1248 map: &'a mut LiteMap<K, V, S>,
1249 index: usize,
1250}
1251
1252impl<K, V, S> Debug for OccupiedEntry<'_, K, V, S>
1253where
1254 K: Ord,
1255 S: StoreMut<K, V>,
1256{
1257 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1258 f.debug_struct("OccupiedEntry")
1259 .field("index", &self.index)
1260 .finish()
1261 }
1262}
1263
1264/// A view into a vacant entry in a `LiteMap`.
1265pub struct VacantEntry<'a, K, V, S>
1266where
1267 K: Ord,
1268 S: StoreMut<K, V>,
1269{
1270 map: &'a mut LiteMap<K, V, S>,
1271 key: K,
1272 index: usize,
1273}
1274
1275impl<K, V, S> Debug for VacantEntry<'_, K, V, S>
1276where
1277 K: Ord,
1278 S: StoreMut<K, V>,
1279{
1280 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1281 f.debug_struct("VacantEntry")
1282 .field("index", &self.index)
1283 .finish()
1284 }
1285}
1286
1287impl<'a, K, V, S> Entry<'a, K, V, S>
1288where
1289 K: Ord,
1290 S: StoreMut<K, V>,
1291{
1292 /// Ensures a value is in the entry by inserting the default value if empty,
1293 /// and returns a mutable reference to the value in the entry.
1294 pub fn or_insert(self, default: V) -> &'a mut V {
1295 match self {
1296 Entry::Occupied(entry) => entry.into_mut(),
1297 Entry::Vacant(entry) => entry.insert(default),
1298 }
1299 }
1300
1301 /// Ensures a value is in the entry by inserting the result of the default function if empty,
1302 /// and returns a mutable reference to the value in the entry.
1303 pub fn or_default(self) -> &'a mut V
1304 where
1305 V: Default,
1306 {
1307 self.or_insert(V::default())
1308 }
1309
1310 /// Ensures a value is in the entry by inserting the result of the default function if empty,
1311 /// and returns a mutable reference to the value in the entry.
1312 pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
1313 match self {
1314 Entry::Occupied(entry) => entry.into_mut(),
1315 Entry::Vacant(entry) => entry.insert(default()),
1316 }
1317 }
1318
1319 /// Provides in-place mutable access to an occupied entry before any
1320 /// potential inserts into the map.
1321 pub fn and_modify<F>(self, f: F) -> Self
1322 where
1323 F: FnOnce(&mut V),
1324 {
1325 match self {
1326 Entry::Occupied(mut entry) => {
1327 f(entry.get_mut());
1328 Entry::Occupied(entry)
1329 }
1330 Entry::Vacant(entry) => Entry::Vacant(entry),
1331 }
1332 }
1333}
1334
1335impl<'a, K, V, S> OccupiedEntry<'a, K, V, S>
1336where
1337 K: Ord,
1338 S: StoreMut<K, V>,
1339{
1340 /// Gets a reference to the key in the entry.
1341 pub fn key(&self) -> &K {
1342 #[allow(clippy::unwrap_used)] // index is valid while we have a reference to the map
1343 self.map.values.lm_get(self.index).unwrap().0
1344 }
1345
1346 /// Gets a reference to the value in the entry.
1347 pub fn get(&self) -> &V {
1348 #[allow(clippy::unwrap_used)] // index is valid while we have a reference to the map
1349 self.map.values.lm_get(self.index).unwrap().1
1350 }
1351
1352 /// Gets a mutable reference to the value in the entry.
1353 pub fn get_mut(&mut self) -> &mut V {
1354 #[allow(clippy::unwrap_used)] // index is valid while we have a reference to the map
1355 self.map.values.lm_get_mut(self.index).unwrap().1
1356 }
1357
1358 /// Converts the entry into a mutable reference to the value in the entry with a lifetime bound to the map.
1359 pub fn into_mut(self) -> &'a mut V {
1360 #[allow(clippy::unwrap_used)] // index is valid while we have a reference to the map
1361 self.map.values.lm_get_mut(self.index).unwrap().1
1362 }
1363
1364 /// Sets the value of the entry, and returns the entry's old value.
1365 pub fn insert(&mut self, value: V) -> V {
1366 mem::replace(self.get_mut(), value)
1367 }
1368
1369 /// Takes the value out of the entry, and returns it.
1370 pub fn remove(self) -> V {
1371 self.map.values.lm_remove(self.index).1
1372 }
1373}
1374
1375impl<'a, K, V, S> VacantEntry<'a, K, V, S>
1376where
1377 K: Ord,
1378 S: StoreMut<K, V>,
1379{
1380 /// Gets a reference to the key that would be used when inserting a value through the `VacantEntry`.
1381 pub fn key(&self) -> &K {
1382 &self.key
1383 }
1384
1385 /// Sets the value of the entry with the `VacantEntry`'s key, and returns a mutable reference to it.
1386 pub fn insert(self, value: V) -> &'a mut V {
1387 // index is valid insert index that was found via binary search
1388 // it's valid while we have a reference to the map
1389 self.map.values.lm_insert(self.index, self.key, value);
1390 #[allow(clippy::unwrap_used)] // we inserted at self.index above
1391 self.map.values.lm_get_mut(self.index).unwrap().1
1392 }
1393}
1394
1395impl<K, V, S> LiteMap<K, V, S>
1396where
1397 K: Ord,
1398 S: StoreMut<K, V>,
1399{
1400 /// Gets the entry for the given key in the map for in-place manipulation.
1401 pub fn entry(&mut self, key: K) -> Entry<K, V, S> {
1402 match self.values.lm_binary_search_by(|k| k.cmp(&key)) {
1403 Ok(index) => Entry::Occupied(OccupiedEntry { map: self, index }),
1404 Err(index) => Entry::Vacant(VacantEntry {
1405 map: self,
1406 key,
1407 index,
1408 }),
1409 }
1410 }
1411}
1412
1413#[cfg(test)]
1414mod test {
1415 use super::*;
1416
1417 #[test]
1418 fn from_iterator() {
1419 let mut expected = LiteMap::with_capacity(4);
1420 expected.insert(1, "updated-one");
1421 expected.insert(2, "original-two");
1422 expected.insert(3, "original-three");
1423 expected.insert(4, "updated-four");
1424
1425 let actual = [
1426 (1, "original-one"),
1427 (2, "original-two"),
1428 (4, "original-four"),
1429 (4, "updated-four"),
1430 (1, "updated-one"),
1431 (3, "original-three"),
1432 ]
1433 .into_iter()
1434 .collect::<LiteMap<_, _>>();
1435
1436 assert_eq!(expected, actual);
1437 }
1438
1439 fn make_13() -> LiteMap<usize, &'static str> {
1440 let mut result = LiteMap::new();
1441 result.insert(1, "one");
1442 result.insert(3, "three");
1443 result
1444 }
1445
1446 fn make_24() -> LiteMap<usize, &'static str> {
1447 let mut result = LiteMap::new();
1448 result.insert(2, "TWO");
1449 result.insert(4, "FOUR");
1450 result
1451 }
1452
1453 fn make_46() -> LiteMap<usize, &'static str> {
1454 let mut result = LiteMap::new();
1455 result.insert(4, "four");
1456 result.insert(6, "six");
1457 result
1458 }
1459
1460 #[test]
1461 fn extend_from_litemap_append() {
1462 let mut map = LiteMap::new();
1463 map.extend_from_litemap(make_13())
1464 .ok_or(())
1465 .expect_err("Append to empty map");
1466 map.extend_from_litemap(make_46())
1467 .ok_or(())
1468 .expect_err("Append to lesser map");
1469 assert_eq!(map.len(), 4);
1470 }
1471
1472 #[test]
1473 fn extend_from_litemap_prepend() {
1474 let mut map = LiteMap::new();
1475 map.extend_from_litemap(make_46())
1476 .ok_or(())
1477 .expect_err("Prepend to empty map");
1478 map.extend_from_litemap(make_13())
1479 .ok_or(())
1480 .expect_err("Prepend to lesser map");
1481 assert_eq!(map.len(), 4);
1482 }
1483
1484 #[test]
1485 fn extend_from_litemap_insert() {
1486 let mut map = LiteMap::new();
1487 map.extend_from_litemap(make_13())
1488 .ok_or(())
1489 .expect_err("Append to empty map");
1490 map.extend_from_litemap(make_24())
1491 .ok_or(())
1492 .expect_err("Insert with no conflict");
1493 map.extend_from_litemap(make_46())
1494 .ok_or(())
1495 .expect("Insert with conflict");
1496 assert_eq!(map.len(), 5);
1497 }
1498
1499 #[test]
1500 fn test_const_cmp_bytes() {
1501 let strs = &["a", "aa", "abc", "abde", "bcd", "bcde"];
1502 for i in 0..strs.len() {
1503 for j in 0..strs.len() {
1504 let a = strs[i].as_bytes();
1505 let b = strs[j].as_bytes();
1506 assert_eq!(a.cmp(b), const_cmp_bytes(a, b));
1507 }
1508 }
1509 }
1510
1511 #[test]
1512 fn into_iterator() {
1513 let mut map = LiteMap::<_, _, Vec<(_, _)>>::new();
1514 map.insert(4, "four");
1515 map.insert(6, "six");
1516 let mut reference = vec![(6, "six"), (4, "four")];
1517
1518 for i in map {
1519 let r = reference.pop().unwrap();
1520 assert_eq!(r, i);
1521 }
1522 assert!(reference.is_empty());
1523 }
1524
1525 #[test]
1526 fn entry_insert() {
1527 let mut map: LiteMap<i32, &str> = LiteMap::new();
1528 assert!(matches!(map.entry(1), Entry::Vacant(_)));
1529 map.entry(1).or_insert("one");
1530 assert!(matches!(map.entry(1), Entry::Occupied(_)));
1531 assert_eq!(map.get(&1), Some(&"one"));
1532 }
1533
1534 #[test]
1535 fn entry_insert_with() {
1536 let mut map: LiteMap<i32, &str> = LiteMap::new();
1537 assert!(matches!(map.entry(1), Entry::Vacant(_)));
1538 map.entry(1).or_insert_with(|| "one");
1539 assert!(matches!(map.entry(1), Entry::Occupied(_)));
1540 assert_eq!(map.get(&1), Some(&"one"));
1541 }
1542
1543 #[test]
1544 fn entry_vacant_insert() {
1545 let mut map: LiteMap<i32, &str> = LiteMap::new();
1546 if let Entry::Vacant(entry) = map.entry(1) {
1547 entry.insert("one");
1548 }
1549 assert_eq!(map.get(&1), Some(&"one"));
1550 }
1551
1552 #[test]
1553 fn entry_occupied_get_mut() {
1554 let mut map: LiteMap<i32, &str> = LiteMap::new();
1555 map.insert(1, "one");
1556 if let Entry::Occupied(mut entry) = map.entry(1) {
1557 *entry.get_mut() = "uno";
1558 }
1559 assert_eq!(map.get(&1), Some(&"uno"));
1560 }
1561
1562 #[test]
1563 fn entry_occupied_remove() {
1564 let mut map: LiteMap<i32, &str> = LiteMap::new();
1565 map.insert(1, "one");
1566 if let Entry::Occupied(entry) = map.entry(1) {
1567 entry.remove();
1568 }
1569 assert_eq!(map.get(&1), None);
1570 }
1571
1572 #[test]
1573 fn entry_occupied_key() {
1574 let mut map: LiteMap<i32, &str> = LiteMap::new();
1575 map.insert(1, "one");
1576 if let Entry::Occupied(entry) = map.entry(1) {
1577 assert_eq!(entry.key(), &1);
1578 }
1579 }
1580
1581 #[test]
1582 fn entry_occupied_get() {
1583 let mut map: LiteMap<i32, &str> = LiteMap::new();
1584 map.insert(1, "one");
1585 if let Entry::Occupied(entry) = map.entry(1) {
1586 assert_eq!(entry.get(), &"one");
1587 }
1588 }
1589
1590 #[test]
1591 fn entry_occupied_insert() {
1592 let mut map: LiteMap<i32, &str> = LiteMap::new();
1593 map.insert(1, "one");
1594 if let Entry::Occupied(mut entry) = map.entry(1) {
1595 assert_eq!(entry.insert("uno"), "one");
1596 }
1597 assert_eq!(map.get(&1), Some(&"uno"));
1598 }
1599
1600 #[test]
1601 fn entry_vacant_key() {
1602 let mut map: LiteMap<i32, &str> = LiteMap::new();
1603 if let Entry::Vacant(entry) = map.entry(1) {
1604 assert_eq!(entry.key(), &1);
1605 }
1606 }
1607
1608 #[test]
1609 fn entry_or_insert() {
1610 let mut map: LiteMap<i32, &str> = LiteMap::new();
1611 map.entry(1).or_insert("one");
1612 assert_eq!(map.get(&1), Some(&"one"));
1613 map.entry(1).or_insert("uno");
1614 assert_eq!(map.get(&1), Some(&"one"));
1615 }
1616
1617 #[test]
1618 fn entry_or_insert_with() {
1619 let mut map: LiteMap<i32, &str> = LiteMap::new();
1620 map.entry(1).or_insert_with(|| "one");
1621 assert_eq!(map.get(&1), Some(&"one"));
1622 map.entry(1).or_insert_with(|| "uno");
1623 assert_eq!(map.get(&1), Some(&"one"));
1624 }
1625
1626 #[test]
1627 fn entry_or_default() {
1628 let mut map: LiteMap<i32, String> = LiteMap::new();
1629 map.entry(1).or_default();
1630 assert_eq!(map.get(&1), Some(&String::new()));
1631 }
1632
1633 #[test]
1634 fn entry_and_modify() {
1635 let mut map: LiteMap<i32, i32> = LiteMap::new();
1636 map.entry(1).or_insert(10);
1637 map.entry(1).and_modify(|v| *v += 5);
1638 assert_eq!(map.get(&1), Some(&15));
1639 map.entry(2).and_modify(|v| *v += 5).or_insert(20);
1640 assert_eq!(map.get(&2), Some(&20));
1641 }
1642}