unc_sdk/store/unordered_map/mod.rs
1// This suppresses the depreciation warnings for uses of UnorderedSet in this module
2#![allow(deprecated)]
3
4mod entry;
5mod impls;
6mod iter;
7
8use std::borrow::Borrow;
9use std::{fmt, mem};
10
11use borsh::{BorshDeserialize, BorshSerialize};
12
13use unc_sdk_macros::unc;
14
15use crate::store::key::{Sha256, ToKey};
16use crate::{env, IntoStorageKey};
17
18pub use entry::{Entry, OccupiedEntry, VacantEntry};
19
20pub use self::iter::{Drain, Iter, IterMut, Keys, Values, ValuesMut};
21use super::free_list::FreeListIndex;
22use super::{FreeList, LookupMap, ERR_INCONSISTENT_STATE, ERR_NOT_EXIST};
23
24/// A lazily loaded storage map that stores its content directly on the storage trie.
25/// This structure is similar to [`unc_sdk::store::LookupMap`](crate::store::LookupMap), except
26/// that it stores the keys so that [`UnorderedMap`] can be iterable.
27///
28/// This map stores the values under a hash of the map's `prefix` and [`BorshSerialize`] of the key
29/// using the map's [`ToKey`] implementation.
30///
31/// The default hash function for [`UnorderedMap`] is [`Sha256`] which uses a syscall
32/// (or host function) built into the UNC runtime to hash the key. To use a custom function,
33/// use [`with_hasher`]. Alternative builtin hash functions can be found at
34/// [`unc_sdk::store::key`](crate::store::key).
35///
36/// # Performance considerations
37/// Note that this collection is optimized for fast removes at the expense of key management.
38/// If the amount of removes is significantly higher than the amount of inserts the iteration
39/// becomes more costly. See [`remove`](UnorderedMap::remove) for details.
40/// If this is the use-case - see ['IterableMap`](crate::store::IterableMap).
41///
42/// # Examples
43/// ```
44/// use unc_sdk::store::UnorderedMap;
45///
46/// // Initializes a map, the generic types can be inferred to `UnorderedMap<String, u8, Sha256>`
47/// // The `b"a"` parameter is a prefix for the storage keys of this data structure.
48/// let mut map = UnorderedMap::new(b"a");
49///
50/// map.insert("test".to_string(), 7u8);
51/// assert!(map.contains_key("test"));
52/// assert_eq!(map.get("test"), Some(&7u8));
53///
54/// let prev = std::mem::replace(map.get_mut("test").unwrap(), 5u8);
55/// assert_eq!(prev, 7u8);
56/// assert_eq!(map["test"], 5u8);
57/// ```
58///
59/// [`UnorderedMap`] also implements an [`Entry API`](Self::entry), which allows
60/// for more complex methods of getting, setting, updating and removing keys and
61/// their values:
62///
63/// ```
64/// use unc_sdk::store::UnorderedMap;
65///
66/// // type inference lets us omit an explicit type signature (which
67/// // would be `UnorderedMap<String, u8>` in this example).
68/// let mut player_stats = UnorderedMap::new(b"m");
69///
70/// fn random_stat_buff() -> u8 {
71/// // could actually return some random value here - let's just return
72/// // some fixed value for now
73/// 42
74/// }
75///
76/// // insert a key only if it doesn't already exist
77/// player_stats.entry("health".to_string()).or_insert(100);
78///
79/// // insert a key using a function that provides a new value only if it
80/// // doesn't already exist
81/// player_stats.entry("defence".to_string()).or_insert_with(random_stat_buff);
82///
83/// // update a key, guarding against the key possibly not being set
84/// let stat = player_stats.entry("attack".to_string()).or_insert(100);
85/// *stat += random_stat_buff();
86/// ```
87///
88/// [`with_hasher`]: Self::with_hasher
89#[deprecated(
90 since = "2.0.0",
91 note = "Suboptimal iteration performance. See performance considerations doc for details."
92)]
93#[derive(BorshDeserialize, BorshSerialize)]
94pub struct UnorderedMap<K, V, H = Sha256>
95where
96 K: BorshSerialize + Ord,
97 V: BorshSerialize,
98 H: ToKey,
99{
100 // ser/de is independent of `K` ser/de, `BorshSerialize`/`BorshDeserialize` bounds removed
101 #[borsh(bound(serialize = "", deserialize = ""))]
102 keys: FreeList<K>,
103 // ser/de is independent of `K`, `V`, `H` ser/de, `BorshSerialize`/`BorshDeserialize` bounds removed
104 #[borsh(bound(serialize = "", deserialize = ""))]
105 values: LookupMap<K, ValueAndIndex<V>, H>,
106}
107
108#[unc(inside_uncsdk)]
109struct ValueAndIndex<V> {
110 value: V,
111 key_index: FreeListIndex,
112}
113
114impl<K, V, H> Drop for UnorderedMap<K, V, H>
115where
116 K: BorshSerialize + Ord,
117 V: BorshSerialize,
118 H: ToKey,
119{
120 fn drop(&mut self) {
121 self.flush()
122 }
123}
124
125impl<K, V, H> fmt::Debug for UnorderedMap<K, V, H>
126where
127 K: BorshSerialize + Ord + BorshDeserialize + fmt::Debug,
128 V: BorshSerialize,
129 H: ToKey,
130{
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 f.debug_struct("UnorderedMap")
133 .field("keys", &self.keys)
134 .field("values", &self.values)
135 .finish()
136 }
137}
138
139impl<K, V> UnorderedMap<K, V, Sha256>
140where
141 K: BorshSerialize + Ord,
142 V: BorshSerialize,
143{
144 /// Create a new iterable map. Use `prefix` as a unique prefix for keys.
145 ///
146 /// This prefix can be anything that implements [`IntoStorageKey`]. The prefix is used when
147 /// storing and looking up values in storage to ensure no collisions with other collections.
148 ///
149 /// # Examples
150 ///
151 /// ```
152 /// use unc_sdk::store::UnorderedMap;
153 ///
154 /// let mut map: UnorderedMap<String, u8> = UnorderedMap::new(b"b");
155 /// ```
156 #[inline]
157 pub fn new<S>(prefix: S) -> Self
158 where
159 S: IntoStorageKey,
160 {
161 Self::with_hasher(prefix)
162 }
163}
164
165impl<K, V, H> UnorderedMap<K, V, H>
166where
167 K: BorshSerialize + Ord,
168 V: BorshSerialize,
169 H: ToKey,
170{
171 /// Initialize a [`UnorderedMap`] with a custom hash function.
172 ///
173 /// # Example
174 /// ```
175 /// use unc_sdk::store::{UnorderedMap, key::Keccak256};
176 ///
177 /// let map = UnorderedMap::<String, String, Keccak256>::with_hasher(b"m");
178 /// ```
179 pub fn with_hasher<S>(prefix: S) -> Self
180 where
181 S: IntoStorageKey,
182 {
183 let mut vec_key = prefix.into_storage_key();
184 let map_key = [vec_key.as_slice(), b"m"].concat();
185 vec_key.push(b'v');
186 Self { keys: FreeList::new(vec_key), values: LookupMap::with_hasher(map_key) }
187 }
188
189 /// Return the amount of elements inside of the map.
190 ///
191 /// # Example
192 /// ```
193 /// use unc_sdk::store::UnorderedMap;
194 ///
195 /// let mut map: UnorderedMap<String, u8> = UnorderedMap::new(b"b");
196 /// assert_eq!(map.len(), 0);
197 /// map.insert("a".to_string(), 1);
198 /// map.insert("b".to_string(), 2);
199 /// assert_eq!(map.len(), 2);
200 /// ```
201 pub fn len(&self) -> u32 {
202 self.keys.len()
203 }
204
205 /// Returns true if there are no elements inside of the map.
206 ///
207 /// # Example
208 /// ```
209 /// use unc_sdk::store::UnorderedMap;
210 ///
211 /// let mut map: UnorderedMap<String, u8> = UnorderedMap::new(b"b");
212 /// assert!(map.is_empty());
213 /// map.insert("a".to_string(), 1);
214 /// assert!(!map.is_empty());
215 /// ```
216 pub fn is_empty(&self) -> bool {
217 self.keys.is_empty()
218 }
219
220 /// Clears the map, removing all key-value pairs. Keeps the allocated memory
221 /// for reuse.
222 ///
223 /// # Examples
224 ///
225 /// ```
226 /// use unc_sdk::store::UnorderedMap;
227 ///
228 /// let mut map: UnorderedMap<String, u8> = UnorderedMap::new(b"b");
229 /// map.insert("a".to_string(), 1);
230 ///
231 /// map.clear();
232 ///
233 /// assert!(map.is_empty());
234 /// ```
235 pub fn clear(&mut self)
236 where
237 K: BorshDeserialize + Clone,
238 V: BorshDeserialize,
239 {
240 for k in self.keys.drain() {
241 // Set instead of remove to avoid loading the value from storage.
242 self.values.set(k, None);
243 }
244 }
245
246 /// An iterator visiting all key-value pairs in arbitrary order.
247 /// The iterator element type is `(&'a K, &'a V)`.
248 ///
249 /// # Examples
250 ///
251 /// ```
252 /// use unc_sdk::store::UnorderedMap;
253 ///
254 /// let mut map = UnorderedMap::new(b"m");
255 /// map.insert("a".to_string(), 1);
256 /// map.insert("b".to_string(), 2);
257 /// map.insert("c".to_string(), 3);
258 ///
259 /// for (key, val) in map.iter() {
260 /// println!("key: {} val: {}", key, val);
261 /// }
262 /// ```
263 pub fn iter(&self) -> Iter<K, V, H>
264 where
265 K: BorshDeserialize,
266 {
267 Iter::new(self)
268 }
269
270 /// An iterator visiting all key-value pairs in arbitrary order,
271 /// with exclusive references to the values.
272 /// The iterator element type is `(&'a K, &'a mut V)`.
273 ///
274 /// # Examples
275 ///
276 /// ```
277 /// use unc_sdk::store::UnorderedMap;
278 ///
279 /// let mut map = UnorderedMap::new(b"m");
280 /// map.insert("a".to_string(), 1);
281 /// map.insert("b".to_string(), 2);
282 /// map.insert("c".to_string(), 3);
283 ///
284 /// // Update all values
285 /// for (_, val) in map.iter_mut() {
286 /// *val *= 2;
287 /// }
288 ///
289 /// for (key, val) in &map {
290 /// println!("key: {} val: {}", key, val);
291 /// }
292 /// ```
293 pub fn iter_mut(&mut self) -> IterMut<K, V, H>
294 where
295 K: BorshDeserialize,
296 {
297 IterMut::new(self)
298 }
299
300 /// An iterator visiting all keys in arbitrary order.
301 /// The iterator element type is `&'a K`.
302 ///
303 /// # Examples
304 ///
305 /// ```
306 /// use unc_sdk::store::UnorderedMap;
307 ///
308 /// let mut map = UnorderedMap::new(b"m");
309 /// map.insert("a".to_string(), 1);
310 /// map.insert("b".to_string(), 2);
311 /// map.insert("c".to_string(), 3);
312 ///
313 /// for key in map.keys() {
314 /// println!("{}", key);
315 /// }
316 /// ```
317 pub fn keys(&self) -> Keys<K>
318 where
319 K: BorshDeserialize,
320 {
321 Keys::new(self)
322 }
323
324 /// An iterator visiting all values in arbitrary order.
325 /// The iterator element type is `&'a V`.
326 ///
327 /// # Examples
328 ///
329 /// ```
330 /// use unc_sdk::store::UnorderedMap;
331 ///
332 /// let mut map = UnorderedMap::new(b"m");
333 /// map.insert("a".to_string(), 1);
334 /// map.insert("b".to_string(), 2);
335 /// map.insert("c".to_string(), 3);
336 ///
337 /// for val in map.values() {
338 /// println!("{}", val);
339 /// }
340 /// ```
341 pub fn values(&self) -> Values<K, V, H>
342 where
343 K: BorshDeserialize,
344 {
345 Values::new(self)
346 }
347
348 /// A mutable iterator visiting all values in arbitrary order.
349 /// The iterator element type is `&'a mut V`.
350 ///
351 /// # Examples
352 ///
353 /// ```
354 /// use unc_sdk::store::UnorderedMap;
355 ///
356 /// let mut map = UnorderedMap::new(b"m");
357 /// map.insert("a".to_string(), 1);
358 /// map.insert("b".to_string(), 2);
359 /// map.insert("c".to_string(), 3);
360 ///
361 /// for val in map.values_mut() {
362 /// *val = *val + 10;
363 /// }
364 ///
365 /// for val in map.values() {
366 /// println!("{}", val);
367 /// }
368 /// ```
369 pub fn values_mut(&mut self) -> ValuesMut<K, V, H>
370 where
371 K: BorshDeserialize,
372 {
373 ValuesMut::new(self)
374 }
375
376 /// Clears the map, returning all key-value pairs as an iterator.
377 ///
378 /// This will clear all values, even if only some key/value pairs are yielded.
379 ///
380 /// # Examples
381 ///
382 /// ```
383 /// use unc_sdk::store::UnorderedMap;
384 ///
385 /// let mut a = UnorderedMap::new(b"m");
386 /// a.insert(1, "a".to_string());
387 /// a.insert(2, "b".to_string());
388 ///
389 /// for (k, v) in a.drain().take(1) {
390 /// assert!(k == 1 || k == 2);
391 /// assert!(&v == "a" || &v == "b");
392 /// }
393 ///
394 /// assert!(a.is_empty());
395 /// ```
396 pub fn drain(&mut self) -> Drain<K, V, H>
397 where
398 K: BorshDeserialize,
399 {
400 Drain::new(self)
401 }
402}
403
404impl<K, V, H> UnorderedMap<K, V, H>
405where
406 K: BorshSerialize + Ord,
407 V: BorshSerialize + BorshDeserialize,
408 H: ToKey,
409{
410 /// Returns a reference to the value corresponding to the key.
411 ///
412 /// The key may be any borrowed form of the map's key type, but
413 /// [`BorshSerialize`] and [`ToOwned<Owned = K>`](ToOwned) on the borrowed form *must* match
414 /// those for the key type.
415 ///
416 /// # Examples
417 ///
418 /// ```
419 /// use unc_sdk::store::UnorderedMap;
420 ///
421 /// let mut map: UnorderedMap<String, u8> = UnorderedMap::new(b"b");
422 /// assert!(map.insert("test".to_string(), 5u8).is_none());
423 /// assert_eq!(map.get("test"), Some(&5));
424 /// ```
425 pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
426 where
427 K: Borrow<Q>,
428 Q: BorshSerialize + ToOwned<Owned = K>,
429 {
430 self.values.get(k).map(|v| &v.value)
431 }
432
433 /// Returns a mutable reference to the value corresponding to the key.
434 ///
435 /// The key may be any borrowed form of the map's key type, but
436 /// [`BorshSerialize`] and [`ToOwned<Owned = K>`](ToOwned) on the borrowed form *must* match
437 /// those for the key type.
438 ///
439 /// # Examples
440 ///
441 /// ```
442 /// use unc_sdk::store::UnorderedMap;
443 ///
444 /// let mut map: UnorderedMap<String, u8> = UnorderedMap::new(b"b");
445 /// assert!(map.insert("test".to_string(), 5u8).is_none());
446 ///
447 /// *map.get_mut("test").unwrap() = 6;
448 /// assert_eq!(map["test"], 6);
449 /// ```
450 pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
451 where
452 K: Borrow<Q>,
453 Q: BorshSerialize + ToOwned<Owned = K>,
454 {
455 self.values.get_mut(k).map(|v| &mut v.value)
456 }
457
458 /// Inserts a key-value pair into the map.
459 ///
460 /// If the map did not have this key present, [`None`] is returned.
461 ///
462 /// If the map did have this key present, the value is updated, and the old
463 /// value is returned. The key is not updated, though; this matters for
464 /// types that can be `==` without being identical.
465 ///
466 /// # Examples
467 ///
468 /// ```
469 /// use unc_sdk::store::UnorderedMap;
470 ///
471 /// let mut map: UnorderedMap<String, u8> = UnorderedMap::new(b"b");
472 /// assert!(map.is_empty());
473 ///
474 /// map.insert("a".to_string(), 1);
475 ///
476 /// assert!(!map.is_empty());
477 /// assert_eq!(map.values().collect::<Vec<_>>(), [&1]);
478 /// ```
479 pub fn insert(&mut self, k: K, value: V) -> Option<V>
480 where
481 K: Clone + BorshDeserialize,
482 {
483 // Check if value is in map to replace first
484 let entry = self.values.get_mut_inner(&k);
485 if let Some(existing) = entry.value_mut() {
486 return Some(mem::replace(&mut existing.value, value));
487 }
488
489 // At this point, we know that the key-value doesn't exist in the map, add key to bucket.
490 let key_index = self.keys.insert(k);
491 entry.replace(Some(ValueAndIndex { value, key_index }));
492 None
493 }
494
495 /// Returns `true` if the map contains a value for the specified key.
496 ///
497 /// The key may be any borrowed form of the map's key type, but
498 /// [`BorshSerialize`] and [`ToOwned<Owned = K>`](ToOwned) on the borrowed form *must* match
499 /// those for the key type.
500 ///
501 /// # Examples
502 ///
503 /// ```
504 /// use unc_sdk::store::UnorderedMap;
505 ///
506 /// let mut map: UnorderedMap<String, u8> = UnorderedMap::new(b"b");
507 /// map.insert("test".to_string(), 7u8);
508 ///
509 /// assert!(map.contains_key("test"));
510 /// ```
511 pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
512 where
513 K: Borrow<Q>,
514 Q: BorshSerialize + ToOwned<Owned = K> + Ord,
515 {
516 self.values.contains_key(k)
517 }
518
519 /// Removes a key from the map, returning the value at the key if the key
520 /// was previously in the map.
521 ///
522 /// The key may be any borrowed form of the map's key type, but
523 /// [`BorshSerialize`] and [`ToOwned<Owned = K>`](ToOwned) on the borrowed form *must* match
524 /// those for the key type.
525 ///
526 /// # Performance
527 ///
528 /// When elements are removed, the underlying vector of keys isn't
529 /// rearranged; instead, the removed key is replaced with a placeholder value. These
530 /// empty slots are reused on subsequent [`insert`](Self::insert) operations.
531 ///
532 /// In cases where there are a lot of removals and not a lot of insertions, these leftover
533 /// placeholders might make iteration more costly, driving higher gas costs. If you need to
534 /// remedy this, take a look at [`defrag`](Self::defrag).
535 ///
536 /// # Examples
537 ///
538 /// ```
539 /// use unc_sdk::store::UnorderedMap;
540 ///
541 /// let mut map: UnorderedMap<String, u8> = UnorderedMap::new(b"b");
542 /// map.insert("test".to_string(), 7u8);
543 /// assert_eq!(map.len(), 1);
544 ///
545 /// map.remove("test");
546 ///
547 /// assert_eq!(map.len(), 0);
548 /// ```
549 pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
550 where
551 K: Borrow<Q> + BorshDeserialize,
552 Q: BorshSerialize + ToOwned<Owned = K>,
553 {
554 self.remove_entry(k).map(|(_, v)| v)
555 }
556
557 /// Removes a key from the map, returning the stored key and value if the
558 /// key was previously in the map.
559 ///
560 /// The key may be any borrowed form of the map's key type, but
561 /// [`BorshSerialize`] and [`ToOwned<Owned = K>`](ToOwned) on the borrowed form *must* match
562 /// those for the key type.
563 ///
564 /// # Performance
565 ///
566 /// When elements are removed, the underlying vector of keys isn't
567 /// rearranged; instead, the removed key is replaced with a placeholder value. These
568 /// empty slots are reused on subsequent [`insert`](Self::insert) operations.
569 ///
570 /// In cases where there are a lot of removals and not a lot of insertions, these leftover
571 /// placeholders might make iteration more costly, driving higher gas costs. If you need to
572 /// remedy this, take a look at [`defrag`](Self::defrag).
573 ///
574 /// # Examples
575 ///
576 /// ```
577 /// use unc_sdk::store::UnorderedMap;
578 ///
579 /// let mut map = UnorderedMap::new(b"m");
580 /// map.insert(1, "a".to_string());
581 /// assert_eq!(map.remove(&1), Some("a".to_string()));
582 /// assert_eq!(map.remove(&1), None);
583 /// ```
584 pub fn remove_entry<Q: ?Sized>(&mut self, k: &Q) -> Option<(K, V)>
585 where
586 K: Borrow<Q> + BorshDeserialize,
587 Q: BorshSerialize + ToOwned<Owned = K>,
588 {
589 // Remove value
590 let old_value = self.values.remove(k)?;
591
592 // Remove key with index if value exists
593 let key = self
594 .keys
595 .remove(old_value.key_index)
596 .unwrap_or_else(|| env::panic_str(ERR_INCONSISTENT_STATE));
597
598 // Return removed value
599 Some((key, old_value.value))
600 }
601
602 /// Gets the given key's corresponding entry in the map for in-place manipulation.
603 /// ```
604 /// use unc_sdk::store::UnorderedMap;
605 ///
606 /// let mut count = UnorderedMap::new(b"m");
607 ///
608 /// for ch in [7, 2, 4, 7, 4, 1, 7] {
609 /// let counter = count.entry(ch).or_insert(0);
610 /// *counter += 1;
611 /// }
612 ///
613 /// assert_eq!(count[&4], 2);
614 /// assert_eq!(count[&7], 3);
615 /// assert_eq!(count[&1], 1);
616 /// assert_eq!(count.get(&8), None);
617 /// ```
618 pub fn entry(&mut self, key: K) -> Entry<K, V>
619 where
620 K: Clone,
621 {
622 Entry::new(self.values.entry(key), &mut self.keys)
623 }
624}
625
626impl<K, V, H> UnorderedMap<K, V, H>
627where
628 K: BorshSerialize + Ord,
629 V: BorshSerialize,
630 H: ToKey,
631{
632 /// Flushes the intermediate values of the map before this is called when the structure is
633 /// [`Drop`]ed. This will write all modified values to storage but keep all cached values
634 /// in memory.
635 pub fn flush(&mut self) {
636 self.keys.flush();
637 self.values.flush();
638 }
639}
640
641impl<K, V, H> UnorderedMap<K, V, H>
642where
643 K: BorshSerialize + BorshDeserialize + Ord + Clone,
644 V: BorshSerialize + BorshDeserialize,
645 H: ToKey,
646{
647 /// Remove empty placeholders leftover from calling [`remove`](Self::remove).
648 ///
649 /// When elements are removed using [`remove`](Self::remove), the underlying vector isn't
650 /// rearranged; instead, the removed element is replaced with a placeholder value. These
651 /// empty slots are reused on subsequent [`insert`](Self::insert) operations.
652 ///
653 /// In cases where there are a lot of removals and not a lot of insertions, these leftover
654 /// placeholders might make iteration more costly, driving higher gas costs. This method is meant
655 /// to remedy that by removing all empty slots from the underlying vector and compacting it.
656 ///
657 /// Note that this might exceed the available gas amount depending on the amount of free slots,
658 /// therefore has to be used with caution.
659 ///
660 /// # Examples
661 ///
662 /// ```
663 /// use unc_sdk::store::UnorderedMap;
664 ///
665 /// let mut map = UnorderedMap::new(b"b");
666 ///
667 /// for i in 0..4 {
668 /// map.insert(i, i);
669 /// }
670 ///
671 /// map.remove(&1);
672 /// map.remove(&3);
673 ///
674 /// map.defrag();
675 /// ```
676 pub fn defrag(&mut self) {
677 self.keys.defrag(|key, new_index| {
678 if let Some(existing) = self.values.get_mut(key) {
679 existing.key_index = FreeListIndex(new_index);
680 }
681 });
682 }
683}
684
685#[cfg(not(target_arch = "wasm32"))]
686#[cfg(test)]
687mod tests {
688 use super::UnorderedMap;
689 use crate::test_utils::test_env::setup_free;
690 use arbitrary::{Arbitrary, Unstructured};
691 use borsh::{to_vec, BorshDeserialize};
692 use rand::RngCore;
693 use rand::SeedableRng;
694 use std::collections::HashMap;
695
696 #[test]
697 fn basic_functionality() {
698 let mut map = UnorderedMap::new(b"b");
699 assert!(map.is_empty());
700 assert!(map.insert("test".to_string(), 5u8).is_none());
701 assert_eq!(map.get("test"), Some(&5));
702 assert_eq!(map.len(), 1);
703
704 *map.get_mut("test").unwrap() = 6;
705 assert_eq!(map["test"], 6);
706
707 assert_eq!(map.remove("test"), Some(6));
708 assert_eq!(map.len(), 0);
709 }
710
711 #[test]
712 fn entry_api() {
713 let mut map = UnorderedMap::new(b"b");
714 {
715 let test_entry = map.entry("test".to_string());
716 assert_eq!(test_entry.key(), "test");
717 let entry_ref = test_entry.or_insert(8u8);
718 *entry_ref += 1;
719 }
720 assert_eq!(map["test"], 9);
721
722 // Try getting entry of filled value
723 let value = map.entry("test".to_string()).and_modify(|v| *v += 3).or_default();
724 assert_eq!(*value, 12);
725 }
726
727 #[test]
728 fn map_iterator() {
729 let mut map = UnorderedMap::new(b"b");
730
731 map.insert(0u8, 0u8);
732 map.insert(1, 1);
733 map.insert(2, 2);
734 map.insert(3, 3);
735 map.remove(&1);
736 let iter = map.iter();
737 assert_eq!(iter.len(), 3);
738 assert_eq!(iter.collect::<Vec<_>>(), [(&0, &0), (&2, &2), (&3, &3)]);
739
740 let iter = map.iter_mut().rev();
741 assert_eq!(iter.collect::<Vec<_>>(), [(&3, &mut 3), (&2, &mut 2), (&0, &mut 0)]);
742
743 let mut iter = map.iter();
744 assert_eq!(iter.nth(2), Some((&3, &3)));
745 // Check fused iterator assumption that each following one will be None
746 assert_eq!(iter.next(), None);
747
748 // Double all values
749 map.values_mut().for_each(|v| {
750 *v *= 2;
751 });
752 assert_eq!(map.values().collect::<Vec<_>>(), [&0, &4, &6]);
753
754 // Collect all keys
755 assert_eq!(map.keys().collect::<Vec<_>>(), [&0, &2, &3]);
756 }
757
758 #[derive(Arbitrary, Debug)]
759 enum Op {
760 Insert(u8, u8),
761 Remove(u8),
762 Flush,
763 Restore,
764 Get(u8),
765 }
766
767 #[test]
768 fn arbitrary() {
769 setup_free();
770
771 let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(0);
772 let mut buf = vec![0; 4096];
773 for _ in 0..512 {
774 // Clear storage in-between runs
775 crate::mock::with_mocked_blockchain(|b| b.take_storage());
776 rng.fill_bytes(&mut buf);
777
778 let mut um = UnorderedMap::new(b"l");
779 let mut hm = HashMap::new();
780 let u = Unstructured::new(&buf);
781 if let Ok(ops) = Vec::<Op>::arbitrary_take_rest(u) {
782 for op in ops {
783 match op {
784 Op::Insert(k, v) => {
785 let r1 = um.insert(k, v);
786 let r2 = hm.insert(k, v);
787 assert_eq!(r1, r2)
788 }
789 Op::Remove(k) => {
790 let r1 = um.remove(&k);
791 let r2 = hm.remove(&k);
792 assert_eq!(r1, r2)
793 }
794 Op::Flush => {
795 um.flush();
796 }
797 Op::Restore => {
798 let serialized = to_vec(&um).unwrap();
799 um = UnorderedMap::deserialize(&mut serialized.as_slice()).unwrap();
800 }
801 Op::Get(k) => {
802 let r1 = um.get(&k);
803 let r2 = hm.get(&k);
804 assert_eq!(r1, r2)
805 }
806 }
807 }
808 }
809 }
810 }
811
812 #[test]
813 fn defrag() {
814 let mut map = UnorderedMap::new(b"b");
815
816 let all_indices = 0..=8;
817
818 for i in all_indices {
819 map.insert(i, i);
820 }
821
822 let removed = [2, 4, 6];
823 let existing = [0, 1, 3, 5, 7, 8];
824
825 for id in removed {
826 map.remove(&id);
827 }
828
829 map.defrag();
830
831 for i in removed {
832 assert_eq!(map.get(&i), None);
833 }
834 for i in existing {
835 assert_eq!(map.get(&i), Some(&i));
836 }
837
838 //Check the elements moved during defragmentation
839 assert_eq!(map.remove_entry(&7).unwrap(), (7, 7));
840 assert_eq!(map.remove_entry(&8).unwrap(), (8, 8));
841 assert_eq!(map.remove_entry(&1).unwrap(), (1, 1));
842 assert_eq!(map.remove_entry(&3).unwrap(), (3, 3));
843 }
844}