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::{alloc::boxed::Box, MaxEncodedLen};
19use core::{
20	marker::PhantomData,
21	num::*,
22	ops::{Range, RangeInclusive},
23	time::Duration,
24};
25use impl_trait_for_tuples::impl_for_tuples;
26
27/// Types that have a constant encoded length. This implies [`MaxEncodedLen`].
28///
29/// No derive macros is provided; instead use an empty implementation like for a marker trait.
30pub trait ConstEncodedLen: MaxEncodedLen {}
31
32#[impl_for_tuples(18)]
33impl ConstEncodedLen for Tuple {}
34
35impl<T: ConstEncodedLen, const N: usize> ConstEncodedLen for [T; N] {}
36
37/// Mark `T` or `T<S>` as `CEL`.
38macro_rules! mark_cel {
39	( $($n:ident <$t:ident>),+ ) => {
40		$(
41			impl<$t: ConstEncodedLen> ConstEncodedLen for $n<$t> { }
42		)+
43	};
44	( $($t:ty),+ ) => {
45		$(
46			impl ConstEncodedLen for $t { }
47		)+
48	};
49}
50
51mark_cel!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, bool);
52mark_cel!(
53	NonZeroU8,
54	NonZeroU16,
55	NonZeroU32,
56	NonZeroU64,
57	NonZeroU128,
58	NonZeroI8,
59	NonZeroI16,
60	NonZeroI32,
61	NonZeroI64,
62	NonZeroI128
63);
64
65mark_cel!(Duration);
66mark_cel!(PhantomData<T>);
67mark_cel!(Box<T>);
68mark_cel!(Range<T>, RangeInclusive<T>);
69
70// `Option`, `Result` and `Compact` are sum types, therefore not `CEL`.
71
72#[cfg(test)]
73mod tests {
74	use super::*;
75	use crate::Encode;
76	use proptest::prelude::*;
77
78	/// Test that some random instances of `T` have encoded len `T::max_encoded_len()`.
79	macro_rules! test_cel_compliance {
80		( $( $t:ty ),+ ) => {
81			$(
82				paste::paste! {
83					proptest::proptest! {
84						#[test]
85						fn [< cel_compliance_ $t:snake >](x: $t) {
86							prop_assert_eq!(x.encode().len(), $t::max_encoded_len());
87						}
88					}
89				}
90			)*
91		};
92	}
93
94	type Void = ();
95	test_cel_compliance!(Void);
96
97	test_cel_compliance!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, bool);
98
99	type TupleArithmetic = (u8, u16, u32, u64, u128, i8, i16, i32, i64, i128);
100	test_cel_compliance!(TupleArithmetic);
101
102	test_cel_compliance!(
103		NonZeroU8,
104		NonZeroU16,
105		NonZeroU32,
106		NonZeroU64,
107		NonZeroU128,
108		NonZeroI8,
109		NonZeroI16,
110		NonZeroI32,
111		NonZeroI64,
112		NonZeroI128
113	);
114
115	type TupleNonZero = (
116		NonZeroU8,
117		NonZeroU16,
118		NonZeroU32,
119		NonZeroU64,
120		NonZeroU128,
121		NonZeroI8,
122		NonZeroI16,
123		NonZeroI32,
124		NonZeroI64,
125		NonZeroI128,
126	);
127	test_cel_compliance!(TupleNonZero);
128
129	type ArrayArithmetic = [(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128); 10];
130	test_cel_compliance!(ArrayArithmetic);
131
132	test_cel_compliance!(Duration);
133
134	type BoxedArithmetic = Box<(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128)>;
135	test_cel_compliance!(BoxedArithmetic);
136
137	type PhantomArithmetic = PhantomData<(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128)>;
138	test_cel_compliance!(PhantomArithmetic);
139
140	type Ranges = (Range<u8>, Range<u16>, Range<u32>, Range<u64>, Range<u128>);
141	test_cel_compliance!(Ranges);
142
143	type Ranges2D = (
144		Range<(u8, u8)>,
145		Range<(u16, u16)>,
146		Range<(u32, u32)>,
147		Range<(u64, u64)>,
148		Range<(u128, u128)>,
149	);
150	test_cel_compliance!(Ranges2D);
151
152	type RangesInc = (
153		RangeInclusive<u8>,
154		RangeInclusive<u16>,
155		RangeInclusive<u32>,
156		RangeInclusive<u64>,
157		RangeInclusive<u128>,
158	);
159	test_cel_compliance!(RangesInc);
160
161	type RangesInc2D = (
162		RangeInclusive<(u8, u8)>,
163		RangeInclusive<(u16, u16)>,
164		RangeInclusive<(u32, u32)>,
165		RangeInclusive<(u64, u64)>,
166		RangeInclusive<(u128, u128)>,
167	);
168	test_cel_compliance!(RangesInc2D);
169}