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}