gear_common/storage/primitives/value.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 single-value storing primitive.
20//!
21//! This primitive defines interface of interaction
22//! with globally stored single-value.
23
24/// Represents logic of managing globally stored
25/// value for more complicated logic.
26///
27/// In fact, represents custom implementation/wrapper
28/// around of Substrate's `ValueStorage` with `OptionQuery`.
29pub trait ValueStorage {
30 /// Stored value type.
31 type Value;
32
33 /// Returns bool, defining does value present.
34 fn exists() -> bool;
35
36 /// Gets stored value, if present.
37 fn get() -> Option<Self::Value>;
38
39 /// Removes stored value.
40 fn kill();
41
42 /// Mutates stored value by `Option` reference, which stored
43 /// (or not in `None` case) with given function.
44 ///
45 /// May return generic type value.
46 fn mutate<R, F: FnOnce(&mut Option<Self::Value>) -> R>(f: F) -> R;
47
48 /// Works the same as `Self::mutate`, but triggers if value present.
49 fn mutate_exists<R, F: FnOnce(&mut Self::Value) -> R>(f: F) -> Option<R> {
50 Self::mutate(|opt_val| opt_val.as_mut().map(f))
51 }
52
53 /// Stores given value.
54 fn put(value: Self::Value);
55
56 /// Stores given value and returns previous one, if present.
57 fn set(value: Self::Value) -> Option<Self::Value>;
58
59 /// Gets stored value, if present, and removes it from storage.
60 fn take() -> Option<Self::Value>;
61}
62
63/// Creates new type with specified name and value type and implements
64/// `ValueStorage` for it based on specified storage,
65/// which is a `Substrate`'s `StorageValue`.
66///
67/// This macro main purpose is to follow newtype pattern
68/// and avoid `Substrate` dependencies in `gear_common`.
69///
70/// Requires `PhantomData` be in scope: from `std`, `core` or `sp_std`.
71///
72/// Requires `Config` be in scope of the crate root where it called.
73#[allow(clippy::crate_in_macro_def)]
74#[macro_export]
75macro_rules! wrap_storage_value {
76 (storage: $storage: ident, name: $name: ident, value: $val: ty) => {
77 #[derive(Debug, PartialEq, Eq)]
78 pub struct $name<T>(PhantomData<T>);
79
80 impl<T: crate::Config> ValueStorage for $name<T> {
81 type Value = $val;
82
83 fn exists() -> bool {
84 $storage::<T>::exists()
85 }
86
87 fn get() -> Option<Self::Value> {
88 $storage::<T>::get()
89 }
90
91 fn kill() {
92 $storage::<T>::kill()
93 }
94
95 fn mutate<R, F: FnOnce(&mut Option<Self::Value>) -> R>(f: F) -> R {
96 $storage::<T>::mutate(f)
97 }
98
99 fn put(value: Self::Value) {
100 $storage::<T>::put(value)
101 }
102
103 fn set(value: Self::Value) -> Option<Self::Value> {
104 $storage::<T>::mutate(|opt| {
105 let prev = opt.take();
106 *opt = Some(value);
107 prev
108 })
109 }
110
111 fn take() -> Option<Self::Value> {
112 $storage::<T>::take()
113 }
114 }
115 };
116}