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}