multiversx_sc/storage/mappers/
map_storage_mapper.rs

1use core::marker::PhantomData;
2
3use super::{
4    set_mapper::{self},
5    source::{CurrentStorage, StorageAddress},
6    SetMapper, StorageClearable, StorageMapper, StorageMapperFromAddress,
7};
8use crate::{
9    api::StorageMapperApi,
10    codec::{NestedDecode, NestedEncode, TopDecode, TopEncode},
11    contract_base::ErrorHelper,
12    storage::{self, StorageKey},
13    types::ManagedAddress,
14};
15
16const MAPPED_STORAGE_VALUE_IDENTIFIER: &[u8] = b".storage";
17type Keys<'a, SA, A, T> = set_mapper::Iter<'a, SA, A, T>;
18
19pub struct MapStorageMapper<SA, K, V, A = CurrentStorage>
20where
21    SA: StorageMapperApi,
22    K: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
23    A: StorageAddress<SA>,
24    V: StorageMapper<SA> + StorageClearable,
25{
26    _phantom_api: PhantomData<SA>,
27    base_key: StorageKey<SA>,
28    keys_set: SetMapper<SA, K, A>,
29    _phantom_value: PhantomData<V>,
30}
31
32impl<SA, K, V> StorageMapper<SA> for MapStorageMapper<SA, K, V, CurrentStorage>
33where
34    SA: StorageMapperApi,
35    K: TopEncode + TopDecode + NestedEncode + NestedDecode,
36    V: StorageMapper<SA> + StorageClearable,
37{
38    fn new(base_key: StorageKey<SA>) -> Self {
39        Self {
40            _phantom_api: PhantomData,
41            base_key: base_key.clone(),
42            keys_set: SetMapper::new(base_key),
43            _phantom_value: PhantomData,
44        }
45    }
46}
47
48impl<SA, K, V> StorageClearable for MapStorageMapper<SA, K, V, CurrentStorage>
49where
50    SA: StorageMapperApi,
51    K: TopEncode + TopDecode + NestedEncode + NestedDecode,
52    V: StorageMapper<SA> + StorageClearable,
53{
54    fn clear(&mut self) {
55        for mut value in self.values() {
56            value.clear();
57        }
58        self.keys_set.clear();
59    }
60}
61
62impl<SA, K, V> MapStorageMapper<SA, K, V, CurrentStorage>
63where
64    SA: StorageMapperApi,
65    K: TopEncode + TopDecode + NestedEncode + NestedDecode,
66    V: StorageMapper<SA> + StorageClearable,
67{
68    /// Adds a default value for the key, if it is not already present.
69    ///
70    /// If the map did not have this key present, `true` is returned.
71    ///
72    /// If the map did have this value present, `false` is returned.
73    pub fn insert_default(&mut self, k: K) -> bool {
74        self.keys_set.insert(k)
75    }
76
77    /// Removes the entry from the map.
78    ///
79    /// If the entry was removed, `true` is returned.
80    ///
81    /// If the map didn't contain an entry with this key, `false` is returned.
82    pub fn remove(&mut self, k: &K) -> bool {
83        if self.keys_set.remove(k) {
84            self.get_mapped_storage_value(k).clear();
85            return true;
86        }
87        false
88    }
89}
90
91impl<SA, K, V> StorageMapperFromAddress<SA> for MapStorageMapper<SA, K, V, ManagedAddress<SA>>
92where
93    SA: StorageMapperApi,
94    K: TopEncode + TopDecode + NestedEncode + NestedDecode,
95    V: StorageMapper<SA> + StorageClearable,
96{
97    fn new_from_address(address: ManagedAddress<SA>, base_key: StorageKey<SA>) -> Self {
98        MapStorageMapper {
99            _phantom_api: PhantomData,
100            base_key: base_key.clone(),
101            keys_set: SetMapper::new_from_address(address, base_key),
102            _phantom_value: PhantomData,
103        }
104    }
105}
106
107impl<SA, A, K, V> MapStorageMapper<SA, K, V, A>
108where
109    SA: StorageMapperApi,
110    A: StorageAddress<SA>,
111    K: TopEncode + TopDecode + NestedEncode + NestedDecode,
112    V: StorageMapper<SA> + StorageClearable,
113{
114    fn build_named_key(&self, name: &[u8], key: &K) -> StorageKey<SA> {
115        let mut named_key = self.base_key.clone();
116        named_key.append_bytes(name);
117        named_key.append_item(key);
118        named_key
119    }
120
121    fn get_mapped_storage_value(&self, key: &K) -> V {
122        let key = self.build_named_key(MAPPED_STORAGE_VALUE_IDENTIFIER, key);
123        <V as storage::mappers::StorageMapper<SA>>::new(key)
124    }
125
126    /// Gets a reference to the value in the entry.
127    pub fn get(&self, k: &K) -> Option<V> {
128        if self.keys_set.contains(k) {
129            return Some(self.get_mapped_storage_value(k));
130        }
131        None
132    }
133
134    pub fn keys(&self) -> Keys<'_, SA, A, K> {
135        self.keys_set.iter()
136    }
137
138    /// Returns `true` if the map contains no elements.
139    pub fn is_empty(&self) -> bool {
140        self.keys_set.is_empty()
141    }
142
143    /// Returns the number of elements in the map.
144    pub fn len(&self) -> usize {
145        self.keys_set.len()
146    }
147
148    /// Returns `true` if the map contains a value for the specified key.
149    pub fn contains_key(&self, k: &K) -> bool {
150        self.keys_set.contains(k)
151    }
152
153    /// Gets the given key's corresponding entry in the map for in-place manipulation.
154    pub fn entry(&mut self, key: K) -> Entry<'_, SA, A, K, V> {
155        if self.contains_key(&key) {
156            Entry::Occupied(OccupiedEntry {
157                key,
158                map: self,
159                _marker: PhantomData,
160            })
161        } else {
162            Entry::Vacant(VacantEntry {
163                key,
164                map: self,
165                _marker: PhantomData,
166            })
167        }
168    }
169
170    /// An iterator visiting all values in arbitrary order.
171    /// The iterator element type is `&'a V`.
172    pub fn values(&self) -> Values<'_, SA, A, K, V> {
173        Values::new(self)
174    }
175
176    /// An iterator visiting all key-value pairs in arbitrary order.
177    /// The iterator element type is `(&'a K, &'a V)`.
178    pub fn iter(&self) -> Iter<'_, SA, A, K, V> {
179        Iter::new(self)
180    }
181}
182
183impl<'a, SA, A, K, V> IntoIterator for &'a MapStorageMapper<SA, K, V, A>
184where
185    SA: StorageMapperApi,
186    A: StorageAddress<SA>,
187    K: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
188    V: StorageMapper<SA> + StorageClearable,
189{
190    type Item = (K, V);
191
192    type IntoIter = Iter<'a, SA, A, K, V>;
193
194    fn into_iter(self) -> Self::IntoIter {
195        self.iter()
196    }
197}
198
199pub struct Iter<'a, SA, A, K, V>
200where
201    SA: StorageMapperApi,
202    K: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
203    A: StorageAddress<SA>,
204    V: StorageMapper<SA> + StorageClearable,
205{
206    key_iter: Keys<'a, SA, A, K>,
207    hash_map: &'a MapStorageMapper<SA, K, V, A>,
208}
209
210impl<'a, SA, A, K, V> Iter<'a, SA, A, K, V>
211where
212    SA: StorageMapperApi,
213    A: StorageAddress<SA>,
214    K: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
215    V: StorageMapper<SA> + StorageClearable,
216{
217    fn new(hash_map: &'a MapStorageMapper<SA, K, V, A>) -> Iter<'a, SA, A, K, V> {
218        Iter {
219            key_iter: hash_map.keys(),
220            hash_map,
221        }
222    }
223}
224
225impl<SA, A, K, V> Iterator for Iter<'_, SA, A, K, V>
226where
227    SA: StorageMapperApi,
228    A: StorageAddress<SA>,
229    K: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
230    V: StorageMapper<SA> + StorageClearable,
231{
232    type Item = (K, V);
233
234    #[inline]
235    fn next(&mut self) -> Option<(K, V)> {
236        if let Some(key) = self.key_iter.next() {
237            let Some(value) = self.hash_map.get(&key) else {
238                ErrorHelper::<SA>::signal_error_with_message("missing key")
239            };
240            return Some((key, value));
241        }
242        None
243    }
244}
245
246pub struct Values<'a, SA, A, K, V>
247where
248    SA: StorageMapperApi,
249    K: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
250    A: StorageAddress<SA>,
251    V: StorageMapper<SA> + StorageClearable,
252{
253    key_iter: Keys<'a, SA, A, K>,
254    hash_map: &'a MapStorageMapper<SA, K, V, A>,
255}
256
257impl<'a, SA, A, K, V> Values<'a, SA, A, K, V>
258where
259    SA: StorageMapperApi,
260    A: StorageAddress<SA>,
261    K: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
262    V: StorageMapper<SA> + StorageClearable,
263{
264    fn new(hash_map: &'a MapStorageMapper<SA, K, V, A>) -> Values<'a, SA, A, K, V> {
265        Values {
266            key_iter: hash_map.keys(),
267            hash_map,
268        }
269    }
270}
271
272impl<SA, A, K, V> Iterator for Values<'_, SA, A, K, V>
273where
274    SA: StorageMapperApi,
275    A: StorageAddress<SA>,
276    K: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
277    V: StorageMapper<SA> + StorageClearable,
278{
279    type Item = V;
280
281    #[inline]
282    fn next(&mut self) -> Option<V> {
283        if let Some(key) = self.key_iter.next() {
284            let value = self.hash_map.get(&key).unwrap();
285            return Some(value);
286        }
287        None
288    }
289}
290
291pub enum Entry<'a, SA, A, K: 'a, V: 'a>
292where
293    SA: StorageMapperApi,
294    K: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
295    A: StorageAddress<SA>,
296    V: StorageMapper<SA> + StorageClearable,
297{
298    /// A vacant entry.
299    Vacant(VacantEntry<'a, SA, A, K, V>),
300
301    /// An occupied entry.
302    Occupied(OccupiedEntry<'a, SA, A, K, V>),
303}
304
305/// A view into a vacant entry in a `MapStorageMapper`.
306/// It is part of the [`Entry`] enum.
307pub struct VacantEntry<'a, SA, A, K: 'a, V: 'a>
308where
309    SA: StorageMapperApi,
310    K: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
311    A: StorageAddress<SA>,
312    V: StorageMapper<SA> + StorageClearable,
313{
314    pub(super) key: K,
315    pub(super) map: &'a mut MapStorageMapper<SA, K, V, A>,
316
317    // Be invariant in `K` and `V`
318    pub(super) _marker: PhantomData<&'a mut (K, V)>,
319}
320
321/// A view into an occupied entry in a `MapStorageMapper`.
322/// It is part of the [`Entry`] enum.
323pub struct OccupiedEntry<'a, SA, A, K: 'a, V: 'a>
324where
325    SA: StorageMapperApi,
326    K: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
327    A: StorageAddress<SA>,
328    V: StorageMapper<SA> + StorageClearable,
329{
330    pub(super) key: K,
331    pub(super) map: &'a mut MapStorageMapper<SA, K, V, A>,
332
333    // Be invariant in `K` and `V`
334    pub(super) _marker: PhantomData<&'a mut (K, V)>,
335}
336
337impl<'a, SA, K, V> Entry<'a, SA, CurrentStorage, K, V>
338where
339    SA: StorageMapperApi,
340    K: TopEncode + TopDecode + NestedEncode + NestedDecode + Clone + 'static,
341    V: StorageMapper<SA> + StorageClearable,
342{
343    /// Ensures a value is in the entry by inserting the default if empty, and returns
344    /// an `OccupiedEntry`.
345    pub fn or_insert_default(self) -> OccupiedEntry<'a, SA, CurrentStorage, K, V> {
346        match self {
347            Entry::Occupied(entry) => entry,
348            Entry::Vacant(entry) => entry.insert_default(),
349        }
350    }
351
352    /// Returns a reference to this entry's key.
353    pub fn key(&self) -> &K {
354        match *self {
355            Entry::Occupied(ref entry) => entry.key(),
356            Entry::Vacant(ref entry) => entry.key(),
357        }
358    }
359
360    /// Provides in-place mutable access to an occupied entry before any
361    /// potential inserts into the map.
362    pub fn and_modify<F>(self, f: F) -> Self
363    where
364        F: FnOnce(&mut V),
365    {
366        match self {
367            Entry::Occupied(mut entry) => {
368                entry.update(f);
369                Entry::Occupied(entry)
370            }
371            Entry::Vacant(entry) => Entry::Vacant(entry),
372        }
373    }
374}
375
376impl<'a, SA, K, V> Entry<'a, SA, CurrentStorage, K, V>
377where
378    SA: StorageMapperApi,
379    K: TopEncode + TopDecode + NestedEncode + NestedDecode + Clone + 'static,
380    V: StorageMapper<SA> + StorageClearable,
381{
382    /// Ensures a value is in the entry by inserting the default value if empty,
383    /// and returns an `OccupiedEntry`.
384    pub fn or_default(self) -> OccupiedEntry<'a, SA, CurrentStorage, K, V> {
385        match self {
386            Entry::Occupied(entry) => entry,
387            Entry::Vacant(entry) => entry.insert_default(),
388        }
389    }
390}
391
392impl<SA, A, K, V> VacantEntry<'_, SA, A, K, V>
393where
394    SA: StorageMapperApi,
395    A: StorageAddress<SA>,
396    K: TopEncode + TopDecode + NestedEncode + NestedDecode + Clone + 'static,
397    V: StorageMapper<SA> + StorageClearable,
398{
399    /// Gets a reference to the key that would be used when inserting a value
400    /// through the VacantEntry.
401    pub fn key(&self) -> &K {
402        &self.key
403    }
404}
405
406impl<'a, SA, K, V> VacantEntry<'a, SA, CurrentStorage, K, V>
407where
408    SA: StorageMapperApi,
409    K: TopEncode + TopDecode + NestedEncode + NestedDecode + Clone + 'static,
410    V: StorageMapper<SA> + StorageClearable,
411{
412    /// Sets the value of the entry with the `VacantEntry`'s key,
413    /// and returns an `OccupiedEntry`.
414    pub fn insert_default(self) -> OccupiedEntry<'a, SA, CurrentStorage, K, V> {
415        self.map.insert_default(self.key.clone());
416        OccupiedEntry {
417            key: self.key,
418            map: self.map,
419            _marker: PhantomData,
420        }
421    }
422}
423
424impl<SA, A, K, V> OccupiedEntry<'_, SA, A, K, V>
425where
426    SA: StorageMapperApi,
427    A: StorageAddress<SA>,
428    K: TopEncode + TopDecode + NestedEncode + NestedDecode + Clone + 'static,
429    V: StorageMapper<SA> + StorageClearable,
430{
431    /// Gets a reference to the key in the entry.
432    pub fn key(&self) -> &K {
433        &self.key
434    }
435
436    /// Gets the value in the entry.
437    pub fn get(&self) -> V {
438        self.map.get(&self.key).unwrap()
439    }
440}
441
442impl<SA, K, V> OccupiedEntry<'_, SA, CurrentStorage, K, V>
443where
444    SA: StorageMapperApi,
445    K: TopEncode + TopDecode + NestedEncode + NestedDecode + Clone + 'static,
446    V: StorageMapper<SA> + StorageClearable,
447{
448    /// Syntactic sugar, to more compactly express a get, update and set in one line.
449    /// Takes whatever lies in storage, apples the given closure and saves the final value back to storage.
450    /// Propagates the return value of the given function.
451    pub fn update<R, F: FnOnce(&mut V) -> R>(&mut self, f: F) -> R {
452        let mut value = self.get();
453        f(&mut value)
454    }
455
456    /// Removes the entry from the map.
457    pub fn remove(self) {
458        self.map.remove(&self.key);
459    }
460}