gear_common/storage/primitives/
double_map.rs

1// This file is part of Gear.
2
3// Copyright (C) 2022-2025 Gear Technologies Inc.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19//! Module for double map storing primitive.
20//!
21//! This primitive defines interface of interaction
22//! with globally stored double-key map (Key1 -> Key2 -> Value).
23
24/// Represents logic of managing globally stored
25/// double-key map for more complicated logic.
26///
27/// In fact, represents custom implementation/wrapper
28/// around of Substrate's `StorageDoubleMap` with `OptionQuery`.
29pub trait DoubleMapStorage {
30    /// Map's first key type.
31    type Key1;
32    /// Map's second key type.
33    type Key2;
34    /// Map's stored value type.
35    type Value;
36
37    /// Returns bool, defining does map contain value under given keys.
38    fn contains_keys(key1: &Self::Key1, key2: &Self::Key2) -> bool;
39
40    /// Gets value stored under given keys, if present.
41    fn get(key1: &Self::Key1, key2: &Self::Key2) -> Option<Self::Value>;
42
43    /// Inserts value with given keys.
44    fn insert(key1: Self::Key1, key2: Self::Key2, value: Self::Value);
45
46    /// Mutates value by `Option` reference, which stored (or not
47    /// in `None` case) under given keys with given function.
48    ///
49    /// May return generic type value.
50    fn mutate<R, F: FnOnce(&mut Option<Self::Value>) -> R>(
51        key1: Self::Key1,
52        key2: Self::Key2,
53        f: F,
54    ) -> R;
55
56    /// Works the same as `Self::mutate`, but triggers if value present.
57    fn mutate_exists<R, F: FnOnce(&mut Self::Value) -> R>(
58        key1: Self::Key1,
59        key2: Self::Key2,
60        f: F,
61    ) -> Option<R> {
62        Self::mutate(key1, key2, |opt_val| opt_val.as_mut().map(f))
63    }
64
65    /// Mutates all stored values with given convert function.
66    fn mutate_values<F: FnMut(Self::Value) -> Self::Value>(f: F);
67
68    /// Removes value stored under the given keys.
69    fn remove(key1: Self::Key1, key2: Self::Key2);
70
71    /// Removes all values.
72    fn clear();
73
74    /// Gets value stored under given keys, if present,
75    /// and removes it from storage.
76    fn take(key1: Self::Key1, key2: Self::Key2) -> Option<Self::Value>;
77
78    /// Remove items from the map matching a `first_key` prefix.
79    fn clear_prefix(first_key: Self::Key1);
80}
81
82/// Creates new type with specified name and key1-key2-value types and
83/// implements `DoubleMapStorage` for it based on specified storage,
84/// which is a `Substrate`'s `StorageDoubleMap`.
85///
86/// This macro main purpose is to follow newtype pattern
87/// and avoid `Substrate` dependencies in `gear_common`.
88///
89/// Requires `PhantomData` be in scope: from `std`, `core` or `sp_std`.
90///
91/// Requires `Config` be in scope of the crate root where it called.
92#[allow(clippy::crate_in_macro_def)]
93#[macro_export]
94macro_rules! wrap_storage_double_map {
95    (storage: $storage: ident, name: $name: ident, key1: $key1: ty,
96        key2: $key2: ty, value: $val: ty) => {
97        pub struct $name<T>(PhantomData<T>);
98
99        impl<T: crate::Config> DoubleMapStorage for $name<T> {
100            type Key1 = $key1;
101            type Key2 = $key2;
102            type Value = $val;
103
104            fn contains_keys(key1: &Self::Key1, key2: &Self::Key2) -> bool {
105                $storage::<T>::contains_key(key1, key2)
106            }
107
108            fn get(key1: &Self::Key1, key2: &Self::Key2) -> Option<Self::Value> {
109                $storage::<T>::get(key1, key2)
110            }
111
112            fn insert(key1: Self::Key1, key2: Self::Key2, value: Self::Value) {
113                $storage::<T>::insert(key1, key2, value)
114            }
115
116            fn mutate<R, F: FnOnce(&mut Option<Self::Value>) -> R>(
117                key1: Self::Key1,
118                key2: Self::Key2,
119                f: F,
120            ) -> R {
121                $storage::<T>::mutate(key1, key2, f)
122            }
123
124            fn mutate_values<F: FnMut(Self::Value) -> Self::Value>(mut f: F) {
125                let f = |v| Some(f(v));
126                $storage::<T>::translate_values(f)
127            }
128
129            fn remove(key1: Self::Key1, key2: Self::Key2) {
130                $storage::<T>::remove(key1, key2)
131            }
132
133            fn clear() {
134                let _ = $storage::<T>::clear(u32::MAX, None);
135            }
136
137            fn take(key1: Self::Key1, key2: Self::Key2) -> Option<Self::Value> {
138                $storage::<T>::take(key1, key2)
139            }
140
141            fn clear_prefix(first_key: Self::Key1) {
142                let _ = $storage::<T>::clear_prefix(first_key, u32::MAX, None);
143            }
144        }
145    };
146}
147
148/// Same as `wrap_storage_double_map!`, but with extra implementations
149/// of `CountedByKey`, `IterableMap` and `IterableByKeyMap`
150/// over double map values.
151///
152/// `PrefixIterator` from `frame_support` and `KeyValueIteratorWrap` from
153/// this crate should be in scope.
154#[allow(clippy::crate_in_macro_def)]
155#[macro_export]
156macro_rules! wrap_extended_storage_double_map {
157    (storage: $storage: ident, name: $name: ident, key1: $key1: ty,
158        key2: $key2: ty, value: $val: ty, length: $len: ty) => {
159        $crate::wrap_storage_double_map!(
160            storage: $storage,
161            name: $name,
162            key1: $key1,
163            key2: $key2,
164            value: $val
165        );
166
167        impl<T: crate::Config> CountedByKey for $name<T> {
168            type Key = $key1;
169            type Length = $len;
170
171            fn len(key: &Self::Key) -> Self::Length {
172                $storage::<T>::iter_prefix(key).count()
173            }
174        }
175
176        impl<T: crate::Config> IterableByKeyMap<$val> for $name<T> {
177            type Key = $key1;
178            type DrainIter = IteratorWrap<PrefixIterator<($key2, $val)>, $val, GetSecondPos>;
179            type Iter = IteratorWrap<PrefixIterator<($key2, $val)>, $val, GetSecondPos>;
180
181            fn drain_key(key: Self::Key) -> Self::DrainIter {
182                $storage::<T>::drain_prefix(key).into()
183            }
184
185            fn iter_key(key: Self::Key) -> Self::Iter {
186                $storage::<T>::iter_prefix(key).into()
187            }
188        }
189
190        impl<T: crate::Config> IterableMap<$val> for $name<T> {
191            type DrainIter = IteratorWrap<PrefixIterator<($key1, $key2, $val)>, $val, GetThirdPos>;
192            type Iter = IteratorWrap<PrefixIterator<($key1, $key2, $val)>, $val, GetThirdPos>;
193
194            fn drain() -> Self::DrainIter {
195                $storage::<T>::drain().into()
196            }
197
198            fn iter() -> Self::Iter {
199                $storage::<T>::iter().into()
200            }
201        }
202
203        impl<T: crate::Config> KeyIterableByKeyMap for $name<T> {
204            type Key1 = $key1;
205            type Key2 = $key2;
206            type DrainIter = IteratorWrap<PrefixIterator<($key2, $val)>, $key2, GetFirstPos>;
207            type Iter = IteratorWrap<PrefixIterator<($key2, $val)>, $key2, GetFirstPos>;
208
209            fn drain_prefix_keys(key: Self::Key1) -> Self::DrainIter {
210                $storage::<T>::drain_prefix(key).into()
211            }
212
213            fn iter_prefix_keys(key: Self::Key1) -> Self::Iter {
214                $storage::<T>::iter_prefix(key).into()
215            }
216        }
217    };
218}
219
220#[cfg(feature = "std")]
221pub mod auxiliary_double_map {
222    use crate::storage::{
223        Counted, CountedByKey, DoubleMapStorage, GetFirstPos, GetSecondPos, IterableByKeyMap,
224        IteratorWrap, KeyIterableByKeyMap, MapStorage,
225    };
226    use std::collections::btree_map::{BTreeMap, Entry, IntoIter};
227
228    /// Double key `BTreeMap`.
229    ///
230    /// Basically is just a map of the map.
231    #[derive(Clone)]
232    pub struct DoubleBTreeMap<K1, K2, V> {
233        inner: BTreeMap<K1, BTreeMap<K2, V>>,
234    }
235
236    impl<K1, K2, V> DoubleBTreeMap<K1, K2, V> {
237        /// Instantiate new empty double key map.
238        pub const fn new() -> Self {
239            Self {
240                inner: BTreeMap::new(),
241            }
242        }
243
244        /// Returns `true` if the map contains a value for the specified keys.
245        pub fn contains_keys(&self, key1: &K1, key2: &K2) -> bool
246        where
247            K1: Ord,
248            K2: Ord,
249        {
250            self.inner
251                .get(key1)
252                .map(|map| map.contains_key(key2))
253                .unwrap_or_default()
254        }
255
256        pub fn count_key(&self, key1: &K1) -> usize
257        where
258            K1: Ord,
259        {
260            self.inner
261                .get(key1)
262                .map(|key2_map| key2_map.len())
263                .unwrap_or_default()
264        }
265
266        /// Returns a reference to the value corresponding to the keys.
267        pub fn get(&self, key1: &K1, key2: &K2) -> Option<&V>
268        where
269            K1: Ord,
270            K2: Ord,
271        {
272            self.inner.get(key1).and_then(|map| map.get(key2))
273        }
274
275        /// Inserts a value under provided keys in the map.
276        pub fn insert(&mut self, key1: K1, key2: K2, value: V) -> Option<V>
277        where
278            K1: Ord,
279            K2: Ord,
280        {
281            match self.inner.entry(key1) {
282                Entry::Vacant(vacant) => {
283                    let mut map = BTreeMap::new();
284                    map.insert(key2, value);
285                    vacant.insert(map);
286
287                    None
288                }
289                Entry::Occupied(mut occupied) => occupied.get_mut().insert(key2, value),
290            }
291        }
292
293        /// Removes keys from the map, returning the value at the keys if the keys
294        /// were previously in the map.
295        pub fn remove(&mut self, key1: K1, key2: K2) -> Option<V>
296        where
297            K1: Ord,
298            K2: Ord,
299        {
300            self.inner.get_mut(&key1).and_then(|map| map.remove(&key2))
301        }
302
303        /// Clears the map, removing all elements.
304        pub fn clear(&mut self) {
305            self.inner.clear()
306        }
307    }
308
309    // Iterator related impl
310    impl<K1, K2, V> DoubleBTreeMap<K1, K2, V> {
311        pub fn iter_key(&self, key1: &K1) -> IntoIter<K2, V>
312        where
313            K1: Ord,
314            K2: Clone,
315            V: Clone,
316        {
317            self.inner
318                .get(key1)
319                .cloned()
320                .map(|key2_map| key2_map.into_iter())
321                .unwrap_or_default()
322        }
323
324        pub fn drain_key(&mut self, key1: &K1) -> IntoIter<K2, V>
325        where
326            K1: Ord,
327        {
328            self.inner
329                .remove(key1)
330                .map(|key2_map| key2_map.into_iter())
331                .unwrap_or_default()
332        }
333    }
334
335    impl<K1, K2, V> Default for DoubleBTreeMap<K1, K2, V> {
336        fn default() -> Self {
337            Self::new()
338        }
339    }
340
341    /// An auxiliary storage wrapper type.
342    ///
343    /// Implements DoubleMapStorage and traits like [`IterableByKeyMap`] for such type automatically.
344    pub trait AuxiliaryDoubleStorageWrap {
345        type Key1: Ord + Clone;
346        type Key2: Ord + Clone;
347        type Value: Clone;
348        fn with_storage<F, R>(f: F) -> R
349        where
350            F: FnOnce(&DoubleBTreeMap<Self::Key1, Self::Key2, Self::Value>) -> R;
351
352        fn with_storage_mut<F, R>(f: F) -> R
353        where
354            F: FnOnce(&mut DoubleBTreeMap<Self::Key1, Self::Key2, Self::Value>) -> R;
355    }
356
357    impl<T: AuxiliaryDoubleStorageWrap> DoubleMapStorage for T {
358        type Key1 = T::Key1;
359        type Key2 = T::Key2;
360        type Value = T::Value;
361
362        fn get(key1: &Self::Key1, key2: &Self::Key2) -> Option<Self::Value> {
363            T::with_storage(|map| map.get(key1, key2).cloned())
364        }
365
366        fn insert(key1: Self::Key1, key2: Self::Key2, value: Self::Value) {
367            T::with_storage_mut(|map| map.insert(key1, key2, value));
368        }
369
370        fn clear() {
371            T::with_storage_mut(|map| map.clear());
372        }
373
374        fn clear_prefix(first_key: Self::Key1) {
375            T::with_storage_mut(|map| {
376                let keys = map.iter_key(&first_key).map(|(k, _)| k.clone());
377                for key in keys {
378                    map.remove(first_key.clone(), key);
379                }
380            });
381        }
382
383        fn contains_keys(key1: &Self::Key1, key2: &Self::Key2) -> bool {
384            T::with_storage_mut(|map| map.contains_keys(key1, key2))
385        }
386
387        fn mutate<R, F: FnOnce(&mut Option<Self::Value>) -> R>(
388            key1: Self::Key1,
389            key2: Self::Key2,
390            f: F,
391        ) -> R {
392            T::with_storage_mut(|map| {
393                let inner_map = map.inner.entry(key1).or_default();
394                match inner_map.entry(key2) {
395                    Entry::Occupied(mut occupied) => {
396                        let mut value = Some(occupied.get().clone());
397                        let result = f(&mut value);
398                        if let Some(value) = value {
399                            *occupied.get_mut() = value;
400                        } else {
401                            occupied.remove();
402                        }
403
404                        result
405                    }
406
407                    Entry::Vacant(vacant) => {
408                        let mut value = None;
409                        let result = f(&mut value);
410                        if let Some(value) = value {
411                            vacant.insert(value);
412                        }
413                        result
414                    }
415                }
416            })
417        }
418
419        fn mutate_exists<R, F: FnOnce(&mut Self::Value) -> R>(
420            key1: Self::Key1,
421            key2: Self::Key2,
422            f: F,
423        ) -> Option<R> {
424            T::with_storage_mut(|map| {
425                if let Some(inner_map) = map.inner.get_mut(&key1)
426                    && let Some(value) = inner_map.get_mut(&key2)
427                {
428                    return Some(f(value));
429                }
430
431                None
432            })
433        }
434
435        fn mutate_values<F: FnMut(Self::Value) -> Self::Value>(mut f: F) {
436            T::with_storage_mut(|map| {
437                for (_, inner_map) in map.inner.iter_mut() {
438                    for (_, value) in inner_map.iter_mut() {
439                        *value = f(value.clone());
440                    }
441                }
442            });
443        }
444
445        fn remove(key1: Self::Key1, key2: Self::Key2) {
446            Self::take(key1, key2);
447        }
448
449        fn take(key1: Self::Key1, key2: Self::Key2) -> Option<Self::Value> {
450            T::with_storage_mut(|map| map.remove(key1, key2))
451        }
452    }
453
454    impl<T: AuxiliaryDoubleStorageWrap> IterableByKeyMap<T::Value> for T {
455        type Key = T::Key1;
456
457        type DrainIter = IteratorWrap<IntoIter<T::Key2, T::Value>, T::Value, GetSecondPos>;
458
459        type Iter = IteratorWrap<IntoIter<T::Key2, T::Value>, T::Value, GetSecondPos>;
460
461        fn drain_key(key: Self::Key) -> Self::DrainIter {
462            T::with_storage_mut(|map| map.drain_key(&key)).into()
463        }
464
465        fn iter_key(key: Self::Key) -> Self::Iter {
466            T::with_storage(|map| map.iter_key(&key)).into()
467        }
468    }
469
470    impl<T: AuxiliaryDoubleStorageWrap> KeyIterableByKeyMap for T {
471        type Key1 = T::Key1;
472        type Key2 = T::Key2;
473        type DrainIter = IteratorWrap<IntoIter<T::Key2, T::Value>, T::Key2, GetFirstPos>;
474        type Iter = IteratorWrap<IntoIter<T::Key2, T::Value>, T::Key2, GetFirstPos>;
475
476        fn drain_prefix_keys(key: Self::Key1) -> Self::DrainIter {
477            T::with_storage_mut(|map| map.drain_key(&key).into())
478        }
479
480        fn iter_prefix_keys(key: Self::Key1) -> Self::Iter {
481            T::with_storage(|map| map.iter_key(&key)).into()
482        }
483    }
484
485    impl<T: AuxiliaryDoubleStorageWrap> CountedByKey for T {
486        type Key = T::Key1;
487        type Length = usize;
488
489        fn len(key: &Self::Key) -> Self::Length {
490            T::with_storage(|map| map.count_key(key))
491        }
492    }
493
494    pub trait AuxiliaryStorageWrap {
495        type Key: Clone + Ord;
496        type Value: Clone;
497
498        fn with_storage<F, R>(f: F) -> R
499        where
500            F: FnOnce(&BTreeMap<Self::Key, Self::Value>) -> R;
501
502        fn with_storage_mut<F, R>(f: F) -> R
503        where
504            F: FnOnce(&mut BTreeMap<Self::Key, Self::Value>) -> R;
505    }
506
507    impl<T: AuxiliaryStorageWrap> MapStorage for T {
508        type Key = T::Key;
509        type Value = T::Value;
510
511        fn clear() {
512            T::with_storage_mut(|map| map.clear());
513        }
514
515        fn contains_key(key: &Self::Key) -> bool {
516            T::with_storage(|map| map.contains_key(key))
517        }
518
519        fn get(key: &Self::Key) -> Option<Self::Value> {
520            T::with_storage(|map| map.get(key).cloned())
521        }
522
523        fn insert(key: Self::Key, value: Self::Value) {
524            T::with_storage_mut(|map| map.insert(key, value));
525        }
526
527        fn mutate<R, F: FnOnce(&mut Option<Self::Value>) -> R>(key: Self::Key, f: F) -> R {
528            T::with_storage_mut(|map| match map.entry(key) {
529                Entry::Occupied(mut occupied) => {
530                    let mut value = Some(occupied.get().clone());
531
532                    let result = f(&mut value);
533                    if let Some(value) = value.take() {
534                        *occupied.get_mut() = value;
535                    } else {
536                        occupied.remove();
537                    }
538
539                    result
540                }
541
542                Entry::Vacant(vacant) => {
543                    let mut value = None;
544
545                    let result = f(&mut value);
546
547                    if let Some(value) = value.take() {
548                        vacant.insert(value);
549                    }
550
551                    result
552                }
553            })
554        }
555
556        fn mutate_exists<R, F: FnOnce(&mut Self::Value) -> R>(key: Self::Key, f: F) -> Option<R> {
557            T::with_storage_mut(|map| map.get_mut(&key).map(f))
558        }
559
560        fn mutate_values<F: FnMut(Self::Value) -> Self::Value>(mut f: F) {
561            T::with_storage_mut(|map| {
562                map.iter_mut()
563                    .for_each(|(_, value)| *value = f(value.clone()))
564            });
565        }
566
567        fn remove(key: Self::Key) {
568            Self::take(key);
569        }
570
571        fn take(key: Self::Key) -> Option<Self::Value> {
572            T::with_storage_mut(|map| map.remove(&key))
573        }
574    }
575
576    impl<T: AuxiliaryStorageWrap> Counted for T {
577        type Length = usize;
578        fn len() -> Self::Length {
579            T::with_storage(|map| map.len())
580        }
581    }
582}