gear_common/storage/primitives/
triple_map.rs

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