Skip to main content

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