1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Parity Bridges Common.
34// Parity Bridges Common is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
89// Parity Bridges Common is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
1314// You should have received a copy of the GNU General Public License
15// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
1617//! Wrapper for a runtime storage value that checks if value exceeds given maximum
18//! during conversion.
1920use codec::{Decode, Encode, MaxEncodedLen};
21use frame_support::traits::Get;
22use scale_info::{Type, TypeInfo};
23use sp_runtime::RuntimeDebug;
24use sp_std::{marker::PhantomData, ops::Deref};
2526/// Error that is returned when the value size exceeds maximal configured size.
27#[derive(RuntimeDebug)]
28pub struct MaximalSizeExceededError {
29/// Size of the value.
30pub value_size: usize,
31/// Maximal configured size.
32pub maximal_size: usize,
33}
3435/// A bounded runtime storage value.
36#[derive(Clone, Decode, Encode, Eq, PartialEq)]
37pub struct BoundedStorageValue<B, V> {
38 value: V,
39 _phantom: PhantomData<B>,
40}
4142impl<B, V: sp_std::fmt::Debug> sp_std::fmt::Debug for BoundedStorageValue<B, V> {
43fn fmt(&self, fmt: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
44self.value.fmt(fmt)
45 }
46}
4748impl<B: Get<u32>, V: Encode> BoundedStorageValue<B, V> {
49/// Construct `BoundedStorageValue` from the underlying `value` with all required checks.
50 ///
51 /// Returns error if value size exceeds given bounds.
52pub fn try_from_inner(value: V) -> Result<Self, MaximalSizeExceededError> {
53// this conversion is heavy (since we do encoding here), so we may want to optimize it later
54 // (e.g. by introducing custom Encode implementation, and turning `BoundedStorageValue` into
55 // `enum BoundedStorageValue { Decoded(V), Encoded(Vec<u8>) }`)
56let value_size = value.encoded_size();
57let maximal_size = B::get() as usize;
58if value_size > maximal_size {
59Err(MaximalSizeExceededError { value_size, maximal_size })
60 } else {
61Ok(BoundedStorageValue { value, _phantom: Default::default() })
62 }
63 }
6465/// Convert into the inner type
66pub fn into_inner(self) -> V {
67self.value
68 }
69}
7071impl<B, V> Deref for BoundedStorageValue<B, V> {
72type Target = V;
7374fn deref(&self) -> &Self::Target {
75&self.value
76 }
77}
7879impl<B: 'static, V: TypeInfo + 'static> TypeInfo for BoundedStorageValue<B, V> {
80type Identity = Self;
8182fn type_info() -> Type {
83 V::type_info()
84 }
85}
8687impl<B: Get<u32>, V: Encode> MaxEncodedLen for BoundedStorageValue<B, V> {
88fn max_encoded_len() -> usize {
89 B::get() as usize
90 }
91}