frame_support/storage/types/
mod.rs1use alloc::vec::Vec;
22use codec::FullCodec;
23use sp_metadata_ir::{StorageEntryMetadataIR, StorageEntryModifierIR};
24
25mod counted_map;
26mod counted_nmap;
27mod double_map;
28mod key;
29mod map;
30mod nmap;
31mod value;
32
33pub use counted_map::{CountedStorageMap, CountedStorageMapInstance, Counter};
34pub use counted_nmap::{CountedStorageNMap, CountedStorageNMapInstance};
35pub use double_map::StorageDoubleMap;
36pub use key::{
37 EncodeLikeTuple, HasKeyPrefix, HasReversibleKeyPrefix, Key, KeyGenerator,
38 KeyGeneratorMaxEncodedLen, ReversibleKeyGenerator, TupleToEncodedIter,
39};
40pub use map::StorageMap;
41pub use nmap::StorageNMap;
42pub use value::StorageValue;
43
44#[doc = docify::embed!("src/storage/types/mod.rs", value_query_examples)]
57pub trait QueryKindTrait<Value, OnEmpty> {
58 const METADATA: StorageEntryModifierIR;
60
61 type Query: FullCodec + 'static;
63
64 fn from_optional_value_to_query(v: Option<Value>) -> Self::Query;
67
68 fn from_query_to_optional_value(v: Self::Query) -> Option<Value>;
70}
71
72pub struct OptionQuery;
77impl<Value> QueryKindTrait<Value, crate::traits::GetDefault> for OptionQuery
78where
79 Value: FullCodec + 'static,
80{
81 const METADATA: StorageEntryModifierIR = StorageEntryModifierIR::Optional;
82
83 type Query = Option<Value>;
84
85 fn from_optional_value_to_query(v: Option<Value>) -> Self::Query {
86 v
88 }
89
90 fn from_query_to_optional_value(v: Self::Query) -> Option<Value> {
91 v
92 }
93}
94
95pub struct ResultQuery<Error>(core::marker::PhantomData<Error>);
97impl<Value, Error, OnEmpty> QueryKindTrait<Value, OnEmpty> for ResultQuery<Error>
98where
99 Value: FullCodec + 'static,
100 Error: FullCodec + 'static,
101 OnEmpty: crate::traits::Get<Result<Value, Error>>,
102{
103 const METADATA: StorageEntryModifierIR = StorageEntryModifierIR::Optional;
104
105 type Query = Result<Value, Error>;
106
107 fn from_optional_value_to_query(v: Option<Value>) -> Self::Query {
108 match v {
109 Some(v) => Ok(v),
110 None => OnEmpty::get(),
111 }
112 }
113
114 fn from_query_to_optional_value(v: Self::Query) -> Option<Value> {
115 v.ok()
116 }
117}
118
119pub struct ValueQuery;
121impl<Value, OnEmpty> QueryKindTrait<Value, OnEmpty> for ValueQuery
122where
123 Value: FullCodec + 'static,
124 OnEmpty: crate::traits::Get<Value>,
125{
126 const METADATA: StorageEntryModifierIR = StorageEntryModifierIR::Default;
127
128 type Query = Value;
129
130 fn from_optional_value_to_query(v: Option<Value>) -> Self::Query {
131 v.unwrap_or_else(|| OnEmpty::get())
132 }
133
134 fn from_query_to_optional_value(v: Self::Query) -> Option<Value> {
135 Some(v)
136 }
137}
138
139pub trait StorageEntryMetadataBuilder {
143 fn build_metadata(
145 deprecation_status: sp_metadata_ir::ItemDeprecationInfoIR,
146 doc: Vec<&'static str>,
147 entries: &mut Vec<StorageEntryMetadataIR>,
148 );
149}
150
151#[cfg(test)]
152mod test {
153 use super::*;
154 use crate::{
155 storage::types::ValueQuery,
156 traits::{Get, StorageInstance},
157 };
158 use sp_io::TestExternalities;
159
160 struct Prefix;
161 impl StorageInstance for Prefix {
162 fn pallet_prefix() -> &'static str {
163 "test"
164 }
165 const STORAGE_PREFIX: &'static str = "foo";
166 }
167
168 #[docify::export]
169 #[test]
170 pub fn value_query_examples() {
171 struct UniverseSecret;
173 impl Get<u32> for UniverseSecret {
174 fn get() -> u32 {
175 42
176 }
177 }
178
179 struct GetDefaultForResult;
181 impl Get<Result<u32, ()>> for GetDefaultForResult {
182 fn get() -> Result<u32, ()> {
183 Err(())
184 }
185 }
186
187 type A = StorageValue<Prefix, u32, ValueQuery>;
188 type B = StorageValue<Prefix, u32, OptionQuery>;
189 type C = StorageValue<Prefix, u32, ResultQuery<()>, GetDefaultForResult>;
190 type D = StorageValue<Prefix, u32, ValueQuery, UniverseSecret>;
191
192 TestExternalities::default().execute_with(|| {
193 assert_eq!(A::get(), 0);
195
196 assert_eq!(B::get(), None);
198
199 assert_eq!(C::get(), Err(()));
201
202 assert_eq!(D::get(), 42);
204 });
205 }
206}