frame_support/storage/generator/
value.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18use crate::{
19	storage::{self, unhashed, StorageAppend},
20	Never,
21};
22use codec::{Decode, Encode, EncodeLike, FullCodec};
23
24/// Generator for `StorageValue` used by `decl_storage`.
25///
26/// By default value is stored at:
27/// ```nocompile
28/// Twox128(pallet_prefix) ++ Twox128(storage_prefix)
29/// ```
30pub trait StorageValue<T: FullCodec> {
31	/// The type that get/take returns.
32	type Query;
33
34	/// Pallet prefix. Used for generating final key.
35	fn pallet_prefix() -> &'static [u8];
36
37	/// Storage prefix. Used for generating final key.
38	fn storage_prefix() -> &'static [u8];
39
40	/// Convert an optional value retrieved from storage to the type queried.
41	fn from_optional_value_to_query(v: Option<T>) -> Self::Query;
42
43	/// Convert a query to an optional value into storage.
44	fn from_query_to_optional_value(v: Self::Query) -> Option<T>;
45
46	/// Generate the full key used in top storage.
47	fn storage_value_final_key() -> [u8; 32];
48}
49
50impl<T: FullCodec, G: StorageValue<T>> storage::StorageValue<T> for G {
51	type Query = G::Query;
52
53	fn hashed_key() -> [u8; 32] {
54		Self::storage_value_final_key()
55	}
56
57	fn exists() -> bool {
58		unhashed::exists(&Self::storage_value_final_key())
59	}
60
61	fn get() -> Self::Query {
62		let value = unhashed::get(&Self::storage_value_final_key());
63		G::from_optional_value_to_query(value)
64	}
65
66	fn try_get() -> Result<T, ()> {
67		unhashed::get(&Self::storage_value_final_key()).ok_or(())
68	}
69
70	fn translate<O: Decode, F: FnOnce(Option<O>) -> Option<T>>(f: F) -> Result<Option<T>, ()> {
71		let key = Self::storage_value_final_key();
72
73		// attempt to get the length directly.
74		let maybe_old = unhashed::get_raw(&key)
75			.map(|old_data| O::decode(&mut &old_data[..]).map_err(|_| ()))
76			.transpose()?;
77		let maybe_new = f(maybe_old);
78		if let Some(new) = maybe_new.as_ref() {
79			new.using_encoded(|d| unhashed::put_raw(&key, d));
80		} else {
81			unhashed::kill(&key);
82		}
83		Ok(maybe_new)
84	}
85
86	fn put<Arg: EncodeLike<T>>(val: Arg) {
87		unhashed::put(&Self::storage_value_final_key(), &val)
88	}
89
90	fn set(maybe_val: Self::Query) {
91		if let Some(val) = G::from_query_to_optional_value(maybe_val) {
92			unhashed::put(&Self::storage_value_final_key(), &val)
93		} else {
94			unhashed::kill(&Self::storage_value_final_key())
95		}
96	}
97
98	fn mutate<R, F: FnOnce(&mut G::Query) -> R>(f: F) -> R {
99		Self::try_mutate(|v| Ok::<R, Never>(f(v))).expect("`Never` can not be constructed; qed")
100	}
101
102	fn try_mutate<R, E, F: FnOnce(&mut G::Query) -> Result<R, E>>(f: F) -> Result<R, E> {
103		let mut val = G::get();
104
105		let ret = f(&mut val);
106		if ret.is_ok() {
107			match G::from_query_to_optional_value(val) {
108				Some(ref val) => G::put(val),
109				None => G::kill(),
110			}
111		}
112		ret
113	}
114
115	fn mutate_exists<R, F>(f: F) -> R
116	where
117		F: FnOnce(&mut Option<T>) -> R,
118	{
119		Self::try_mutate_exists(|v| Ok::<R, Never>(f(v)))
120			.expect("`Never` can not be constructed; qed")
121	}
122
123	fn try_mutate_exists<R, E, F>(f: F) -> Result<R, E>
124	where
125		F: FnOnce(&mut Option<T>) -> Result<R, E>,
126	{
127		let mut val = G::from_query_to_optional_value(Self::get());
128
129		let ret = f(&mut val);
130		if ret.is_ok() {
131			match val {
132				Some(ref val) => Self::put(val),
133				None => Self::kill(),
134			}
135		}
136		ret
137	}
138
139	fn kill() {
140		unhashed::kill(&Self::storage_value_final_key())
141	}
142
143	fn take() -> G::Query {
144		let key = Self::storage_value_final_key();
145		let value = unhashed::get(&key);
146		if value.is_some() {
147			unhashed::kill(&key)
148		}
149		G::from_optional_value_to_query(value)
150	}
151
152	fn append<Item, EncodeLikeItem>(item: EncodeLikeItem)
153	where
154		Item: Encode,
155		EncodeLikeItem: EncodeLike<Item>,
156		T: StorageAppend<Item>,
157	{
158		let key = Self::storage_value_final_key();
159		sp_io::storage::append(&key, item.encode());
160	}
161}