Skip to main content

gear_common/storage/primitives/
triple_map.rs

1// Copyright (C) Gear Technologies Inc.
2// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
3
4//! Module for map with three keys storing primitive.
5//!
6//! This primitive defines interface of interaction
7//! with globally stored triple-key map (Key1 -> Key2 -> Key3 -> Value).
8
9/// Represents logic of managing globally stored
10/// triple-key map for more complicated logic.
11///
12/// In fact, represents custom implementation/wrapper
13/// around of Substrate's `StorageNMap` with `OptionQuery`.
14pub trait TripleMapStorage {
15    /// Map's first key type.
16    type Key1;
17    /// Map's second key type.
18    type Key2;
19    /// Map's third key type.
20    type Key3;
21    /// Map's stored value type.
22    type Value;
23
24    /// Returns bool, defining does map contain value under given keys.
25    fn contains_keys(key1: &Self::Key1, key2: &Self::Key2, key3: &Self::Key3) -> bool;
26
27    /// Gets value stored under given keys, if present.
28    fn get(key1: &Self::Key1, key2: &Self::Key2, key3: &Self::Key3) -> Option<Self::Value>;
29
30    /// Inserts value with given keys.
31    fn insert(key1: Self::Key1, key2: Self::Key2, key3: Self::Key3, value: Self::Value);
32
33    /// Mutates value by `Option` reference, which stored (or not
34    /// in `None` case) under given keys with given function.
35    ///
36    /// May return generic type value.
37    fn mutate<R, F: FnOnce(&mut Option<Self::Value>) -> R>(
38        key1: Self::Key1,
39        key2: Self::Key2,
40        key3: Self::Key3,
41        f: F,
42    ) -> R;
43
44    /// Works the same as `Self::mutate`, but triggers if value present.
45    fn mutate_exists<R, F: FnOnce(&mut Self::Value) -> R>(
46        key1: Self::Key1,
47        key2: Self::Key2,
48        key3: Self::Key3,
49        f: F,
50    ) -> Option<R> {
51        Self::mutate(key1, key2, key3, |opt_val| opt_val.as_mut().map(f))
52    }
53
54    /// Mutates all stored values with given convert function.
55    fn mutate_values<F: FnMut(Self::Value) -> Self::Value>(f: F);
56
57    /// Removes value stored under the given keys.
58    fn remove(key1: Self::Key1, key2: Self::Key2, key3: Self::Key3);
59
60    /// Removes all values.
61    fn clear();
62
63    /// Gets value stored under given keys, if present,
64    /// and removes it from storage.
65    fn take(key1: Self::Key1, key2: Self::Key2, key3: Self::Key3) -> Option<Self::Value>;
66
67    /// Remove items from the map matching a `key1`/`key2` prefix.
68    fn clear_prefix(key1: Self::Key1, key2: Self::Key2);
69
70    fn iter_prefix(
71        key1: &Self::Key1,
72        key2: &Self::Key2,
73    ) -> impl Iterator<Item = (Self::Key3, Self::Value)>;
74}
75
76/// Creates new type with specified name and key1-key2-key3-value types and
77/// implements `TripleMapStorage` for it based on specified storage,
78/// which is a `Substrate`'s `StorageNMap`.
79///
80/// The macro main purpose is to follow newtype pattern
81/// and avoid `Substrate` dependencies in `gear_common`.
82///
83/// Requires `PhantomData` be in scope: from `std`, `core` or `sp_std`.
84///
85/// Requires `Config` be in scope of the crate root where it called.
86#[allow(clippy::crate_in_macro_def)]
87#[macro_export]
88macro_rules! wrap_storage_triple_map {
89    (storage: $storage: ident, name: $name: ident,
90        key1: $key1: ty,
91        key2: $key2: ty,
92        key3: $key3: ty,
93        value: $val: ty) => {
94        pub struct $name<T>(PhantomData<T>);
95
96        impl<T: crate::Config> TripleMapStorage for $name<T> {
97            type Key1 = $key1;
98            type Key2 = $key2;
99            type Key3 = $key3;
100            type Value = $val;
101
102            fn contains_keys(key1: &Self::Key1, key2: &Self::Key2, key3: &Self::Key3) -> bool {
103                $storage::<T>::contains_key((key1, key2, key3))
104            }
105
106            fn get(key1: &Self::Key1, key2: &Self::Key2, key3: &Self::Key3) -> Option<Self::Value> {
107                $storage::<T>::get((key1, key2, key3))
108            }
109
110            fn insert(key1: Self::Key1, key2: Self::Key2, key3: Self::Key3, value: Self::Value) {
111                $storage::<T>::insert((key1, key2, key3), value)
112            }
113
114            fn mutate<R, F: FnOnce(&mut Option<Self::Value>) -> R>(
115                key1: Self::Key1,
116                key2: Self::Key2,
117                key3: Self::Key3,
118                f: F,
119            ) -> R {
120                $storage::<T>::mutate((key1, key2, key3), f)
121            }
122
123            fn mutate_values<F: FnMut(Self::Value) -> Self::Value>(mut f: F) {
124                let f = |v| Some(f(v));
125                $storage::<T>::translate_values(f)
126            }
127
128            fn remove(key1: Self::Key1, key2: Self::Key2, key3: Self::Key3) {
129                $storage::<T>::remove((key1, key2, key3))
130            }
131
132            fn clear() {
133                let _ = $storage::<T>::clear(u32::MAX, None);
134            }
135
136            fn take(key1: Self::Key1, key2: Self::Key2, key3: Self::Key3) -> Option<Self::Value> {
137                $storage::<T>::take((key1, key2, key3))
138            }
139
140            fn clear_prefix(key1: Self::Key1, key2: Self::Key2) {
141                let _ = $storage::<T>::clear_prefix((key1, key2), u32::MAX, None);
142            }
143
144            fn iter_prefix(
145                key1: &Self::Key1,
146                key2: &Self::Key2,
147            ) -> impl Iterator<Item = (Self::Key3, Self::Value)> {
148                $storage::<T>::iter_prefix((key1, key2))
149            }
150        }
151    };
152}