parity_scale_codec/
const_encoded_len.rs

1// Copyright (C) 2023 Parity Technologies (UK) Ltd.
2// SPDX-License-Identifier: Apache-2.0
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// 	http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16//! Contains the [`ConstEncodedLen`] trait. 
17
18use crate::MaxEncodedLen;
19use core::{
20	marker::PhantomData,
21	num::*,
22	ops::{Range, RangeInclusive},
23	time::Duration,
24};
25use crate::alloc::boxed::Box;
26use impl_trait_for_tuples::impl_for_tuples;
27
28/// Types that have a constant encoded length. This implies [`MaxEncodedLen`].
29///
30/// No derive macros is provided; instead use an empty implementation like for a marker trait.
31pub trait ConstEncodedLen: MaxEncodedLen {}
32
33#[impl_for_tuples(18)]
34impl ConstEncodedLen for Tuple { }
35
36impl<T: ConstEncodedLen, const N: usize> ConstEncodedLen for [T; N] { }
37
38/// Mark `T` or `T<S>` as `CEL`.
39macro_rules! mark_cel {
40	( $($n:ident <$t:ident>),+ ) => {
41		$(
42			impl<$t: ConstEncodedLen> ConstEncodedLen for $n<$t> { }
43		)+
44	};
45	( $($t:ty),+ ) => {
46		$(
47			impl ConstEncodedLen for $t { }
48		)+
49	};
50}
51
52mark_cel!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, bool);
53mark_cel!(NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128);
54
55mark_cel!(Duration);
56mark_cel!(PhantomData<T>);
57mark_cel!(Box<T>);
58mark_cel!(Range<T>, RangeInclusive<T>);
59
60// `Option`, `Result` and `Compact` are sum types, therefore not `CEL`.
61
62#[cfg(test)]
63mod tests {
64	use super::*;
65	use crate::Encode;
66	use proptest::prelude::*;
67
68	/// Test that some random instances of `T` have encoded len `T::max_encoded_len()`.
69	macro_rules! test_cel_compliance {
70		( $( $t:ty ),+ ) => {
71			$(
72				paste::paste! {
73					proptest::proptest! {
74						#[test]
75						fn [< cel_compliance_ $t:snake >](x: $t) {
76							prop_assert_eq!(x.encode().len(), $t::max_encoded_len());
77						}
78					}
79				}
80			)*
81		};
82	}
83
84	type Void = ();
85	test_cel_compliance!(Void);
86
87	test_cel_compliance!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, bool);
88	
89	type TupleArithmetic = (u8, u16, u32, u64, u128, i8, i16, i32, i64, i128);
90	test_cel_compliance!(TupleArithmetic);
91
92	test_cel_compliance!(
93		NonZeroU8,
94		NonZeroU16,
95		NonZeroU32,
96		NonZeroU64,
97		NonZeroU128,
98		NonZeroI8,
99		NonZeroI16,
100		NonZeroI32,
101		NonZeroI64,
102		NonZeroI128
103	);
104
105	type TupleNonZero = (
106		NonZeroU8,
107		NonZeroU16,
108		NonZeroU32,
109		NonZeroU64,
110		NonZeroU128,
111		NonZeroI8,
112		NonZeroI16,
113		NonZeroI32,
114		NonZeroI64,
115		NonZeroI128,
116	);
117	test_cel_compliance!(TupleNonZero);
118
119	type ArrayArithmetic = [(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128); 10];
120	test_cel_compliance!(ArrayArithmetic);
121
122	test_cel_compliance!(Duration);
123
124	type BoxedArithmetic = Box<(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128)>;
125	test_cel_compliance!(BoxedArithmetic);
126
127	type PhantomArithmetic = PhantomData<(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128)>;
128	test_cel_compliance!(PhantomArithmetic);
129
130	type Ranges = (Range<u8>, Range<u16>, Range<u32>, Range<u64>, Range<u128>);
131	test_cel_compliance!(Ranges);
132
133	type Ranges2D = (
134		Range<(u8, u8)>,
135		Range<(u16, u16)>,
136		Range<(u32, u32)>,
137		Range<(u64, u64)>,
138		Range<(u128, u128)>,
139	);
140	test_cel_compliance!(Ranges2D);
141
142	type RangesInc = (
143		RangeInclusive<u8>,
144		RangeInclusive<u16>,
145		RangeInclusive<u32>,
146		RangeInclusive<u64>,
147		RangeInclusive<u128>,
148	);
149	test_cel_compliance!(RangesInc);
150
151	type RangesInc2D = (
152		RangeInclusive<(u8, u8)>,
153		RangeInclusive<(u16, u16)>,
154		RangeInclusive<(u32, u32)>,
155		RangeInclusive<(u64, u64)>,
156		RangeInclusive<(u128, u128)>,
157	);
158	test_cel_compliance!(RangesInc2D);
159}