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}