sp_runtime/
type_with_default.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
18//! Provides a type that wraps another type and provides a default value.
19
20use crate::traits::{Bounded, One, Zero};
21use codec::{Compact, CompactAs, Decode, DecodeWithMemTracking, Encode, HasCompact, MaxEncodedLen};
22use core::{
23	fmt::Display,
24	marker::PhantomData,
25	ops::{
26		Add, AddAssign, BitAnd, BitOr, BitXor, Deref, Div, DivAssign, Mul, MulAssign, Not, Rem,
27		RemAssign, Shl, Shr, Sub, SubAssign,
28	},
29};
30use num_traits::{
31	CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr, CheckedSub,
32	Num, NumCast, PrimInt, Saturating, ToPrimitive,
33};
34use scale_info::{StaticTypeInfo, TypeInfo};
35use sp_core::Get;
36
37#[cfg(feature = "serde")]
38use serde::{Deserialize, Serialize};
39
40/// A type that wraps another type and provides a default value.
41///
42/// Passes through arithmetical and many other operations to the inner value.
43/// Type information for metadata is the same as the inner value's type.
44#[derive(Encode, Decode, DecodeWithMemTracking, Debug, MaxEncodedLen)]
45#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
46pub struct TypeWithDefault<T, D: Get<T>>(T, PhantomData<D>);
47
48impl<T, D: Get<T>> TypeWithDefault<T, D> {
49	fn new(value: T) -> Self {
50		Self(value, PhantomData)
51	}
52}
53
54// Hides implementation details from the outside (for metadata type information).
55//
56// The type info showed in metadata is the one of the inner value's type.
57impl<T: StaticTypeInfo, D: Get<T> + 'static> TypeInfo for TypeWithDefault<T, D> {
58	type Identity = Self;
59
60	fn type_info() -> scale_info::Type {
61		T::type_info()
62	}
63}
64
65impl<T: Clone, D: Get<T>> Clone for TypeWithDefault<T, D> {
66	fn clone(&self) -> Self {
67		Self(self.0.clone(), PhantomData)
68	}
69}
70
71impl<T: Copy, D: Get<T>> Copy for TypeWithDefault<T, D> {}
72
73impl<T: PartialEq, D: Get<T>> PartialEq for TypeWithDefault<T, D> {
74	fn eq(&self, other: &Self) -> bool {
75		self.0 == other.0
76	}
77}
78
79impl<T: Eq, D: Get<T>> Eq for TypeWithDefault<T, D> {}
80
81impl<T: PartialOrd, D: Get<T>> PartialOrd for TypeWithDefault<T, D> {
82	fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
83		self.0.partial_cmp(&other.0)
84	}
85}
86
87impl<T: Ord, D: Get<T>> Ord for TypeWithDefault<T, D> {
88	fn cmp(&self, other: &Self) -> core::cmp::Ordering {
89		self.0.cmp(&other.0)
90	}
91}
92
93impl<T, D: Get<T>> Deref for TypeWithDefault<T, D> {
94	type Target = T;
95	fn deref(&self) -> &Self::Target {
96		&self.0
97	}
98}
99
100impl<T, D: Get<T>> Default for TypeWithDefault<T, D> {
101	fn default() -> Self {
102		Self::new(D::get())
103	}
104}
105
106impl<T: CheckedNeg, D: Get<T>> CheckedNeg for TypeWithDefault<T, D> {
107	fn checked_neg(&self) -> Option<Self> {
108		self.0.checked_neg().map(Self::new)
109	}
110}
111
112impl<T: CheckedRem, D: Get<T>> CheckedRem for TypeWithDefault<T, D> {
113	fn checked_rem(&self, rhs: &Self) -> Option<Self> {
114		self.0.checked_rem(&rhs.0).map(Self::new)
115	}
116}
117
118impl<T: CheckedShr, D: Get<T>> CheckedShr for TypeWithDefault<T, D> {
119	fn checked_shr(&self, n: u32) -> Option<Self> {
120		self.0.checked_shr(n).map(Self::new)
121	}
122}
123
124impl<T: CheckedShl, D: Get<T>> CheckedShl for TypeWithDefault<T, D> {
125	fn checked_shl(&self, n: u32) -> Option<Self> {
126		self.0.checked_shl(n).map(Self::new)
127	}
128}
129
130impl<T: Rem<Output = T>, D: Get<T>> Rem for TypeWithDefault<T, D> {
131	type Output = Self;
132	fn rem(self, rhs: Self) -> Self {
133		Self::new(self.0 % rhs.0)
134	}
135}
136
137impl<T: Rem<u32, Output = T>, D: Get<T>> Rem<u32> for TypeWithDefault<T, D> {
138	type Output = Self;
139	fn rem(self, rhs: u32) -> Self {
140		Self::new(self.0 % (rhs.into()))
141	}
142}
143
144impl<T: Shr<u32, Output = T>, D: Get<T>> Shr<u32> for TypeWithDefault<T, D> {
145	type Output = Self;
146	fn shr(self, rhs: u32) -> Self {
147		Self::new(self.0 >> rhs)
148	}
149}
150
151impl<T: Shr<usize, Output = T>, D: Get<T>> Shr<usize> for TypeWithDefault<T, D> {
152	type Output = Self;
153	fn shr(self, rhs: usize) -> Self {
154		Self::new(self.0 >> rhs)
155	}
156}
157
158impl<T: Shl<u32, Output = T>, D: Get<T>> Shl<u32> for TypeWithDefault<T, D> {
159	type Output = Self;
160	fn shl(self, rhs: u32) -> Self {
161		Self::new(self.0 << rhs)
162	}
163}
164
165impl<T: Shl<usize, Output = T>, D: Get<T>> Shl<usize> for TypeWithDefault<T, D> {
166	type Output = Self;
167	fn shl(self, rhs: usize) -> Self {
168		Self::new(self.0 << rhs)
169	}
170}
171
172impl<T: RemAssign, D: Get<T>> RemAssign for TypeWithDefault<T, D> {
173	fn rem_assign(&mut self, rhs: Self) {
174		self.0 %= rhs.0
175	}
176}
177
178impl<T: DivAssign, D: Get<T>> DivAssign for TypeWithDefault<T, D> {
179	fn div_assign(&mut self, rhs: Self) {
180		self.0 /= rhs.0
181	}
182}
183
184impl<T: MulAssign, D: Get<T>> MulAssign for TypeWithDefault<T, D> {
185	fn mul_assign(&mut self, rhs: Self) {
186		self.0 *= rhs.0
187	}
188}
189
190impl<T: SubAssign, D: Get<T>> SubAssign for TypeWithDefault<T, D> {
191	fn sub_assign(&mut self, rhs: Self) {
192		self.0 -= rhs.0
193	}
194}
195
196impl<T: AddAssign, D: Get<T>> AddAssign for TypeWithDefault<T, D> {
197	fn add_assign(&mut self, rhs: Self) {
198		self.0 += rhs.0
199	}
200}
201
202impl<T: Display, D: Get<T>> Display for TypeWithDefault<T, D> {
203	fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
204		write!(f, "{}", self.0)
205	}
206}
207
208macro_rules! impl_from {
209    ($for_type:ty $(, $from_type:ty)*) => {
210		$(
211			impl<D: Get<$for_type>> From<$from_type> for TypeWithDefault<$for_type, D> {
212				fn from(value: $from_type) -> Self {
213					Self::new(value.into())
214				}
215			}
216		)*
217    }
218}
219impl_from!(u128, u128, u64, u32, u16, u8);
220impl_from!(u64, u64, u32, u16, u8);
221impl_from!(u32, u32, u16, u8);
222impl_from!(u16, u16, u8);
223impl_from!(u8, u8);
224
225macro_rules! impl_try_from {
226    ($for_type:ty $(, $try_from_type:ty)*) => {
227		$(
228			impl<D: Get<$for_type>> TryFrom<$try_from_type> for TypeWithDefault<$for_type, D> {
229				type Error = <$for_type as TryFrom<$try_from_type>>::Error;
230				fn try_from(n: $try_from_type) -> Result<TypeWithDefault<$for_type, D>, Self::Error> {
231					<$for_type as TryFrom<$try_from_type>>::try_from(n).map(Self::new)
232				}
233			}
234		)*
235    }
236}
237impl_try_from!(u8, u16, u32, u64, u128);
238impl_try_from!(u16, u32, u64, u128);
239impl_try_from!(u32, u64, u128);
240impl_try_from!(u64, u128);
241
242impl<T: TryFrom<usize>, D: Get<T>> TryFrom<usize> for TypeWithDefault<T, D> {
243	type Error = <T as TryFrom<usize>>::Error;
244	fn try_from(n: usize) -> Result<TypeWithDefault<T, D>, Self::Error> {
245		T::try_from(n).map(Self::new)
246	}
247}
248
249impl<T: TryInto<u8>, D: Get<T>> TryFrom<TypeWithDefault<T, D>> for u8 {
250	type Error = <T as TryInto<u8>>::Error;
251	fn try_from(value: TypeWithDefault<T, D>) -> Result<Self, Self::Error> {
252		value.0.try_into()
253	}
254}
255
256impl<T: TryInto<u16>, D: Get<T>> TryFrom<TypeWithDefault<T, D>> for u16 {
257	type Error = <T as TryInto<u16>>::Error;
258	fn try_from(value: TypeWithDefault<T, D>) -> Result<Self, Self::Error> {
259		value.0.try_into()
260	}
261}
262
263impl<T: TryInto<u32>, D: Get<T>> TryFrom<TypeWithDefault<T, D>> for u32 {
264	type Error = <T as TryInto<u32>>::Error;
265	fn try_from(value: TypeWithDefault<T, D>) -> Result<Self, Self::Error> {
266		value.0.try_into()
267	}
268}
269
270impl<T: TryInto<u64>, D: Get<T>> TryFrom<TypeWithDefault<T, D>> for u64 {
271	type Error = <T as TryInto<u64>>::Error;
272	fn try_from(value: TypeWithDefault<T, D>) -> Result<Self, Self::Error> {
273		value.0.try_into()
274	}
275}
276
277impl<T: TryInto<u128>, D: Get<T>> TryFrom<TypeWithDefault<T, D>> for u128 {
278	type Error = <T as TryInto<u128>>::Error;
279	fn try_from(value: TypeWithDefault<T, D>) -> Result<Self, Self::Error> {
280		value.0.try_into()
281	}
282}
283
284impl<T: TryInto<usize>, D: Get<T>> TryFrom<TypeWithDefault<T, D>> for usize {
285	type Error = <T as TryInto<usize>>::Error;
286	fn try_from(value: TypeWithDefault<T, D>) -> Result<Self, Self::Error> {
287		value.0.try_into()
288	}
289}
290
291impl<T: Zero + PartialEq, D: Get<T>> Zero for TypeWithDefault<T, D> {
292	fn zero() -> Self {
293		Self::new(T::zero())
294	}
295
296	fn is_zero(&self) -> bool {
297		self.0 == T::zero()
298	}
299}
300
301impl<T: Bounded, D: Get<T>> Bounded for TypeWithDefault<T, D> {
302	fn min_value() -> Self {
303		Self::new(T::min_value())
304	}
305
306	fn max_value() -> Self {
307		Self::new(T::max_value())
308	}
309}
310
311impl<T: PrimInt, D: Get<T>> PrimInt for TypeWithDefault<T, D> {
312	fn count_ones(self) -> u32 {
313		self.0.count_ones()
314	}
315
316	fn leading_zeros(self) -> u32 {
317		self.0.leading_zeros()
318	}
319
320	fn trailing_zeros(self) -> u32 {
321		self.0.trailing_zeros()
322	}
323
324	fn rotate_left(self, n: u32) -> Self {
325		Self::new(self.0.rotate_left(n))
326	}
327
328	fn rotate_right(self, n: u32) -> Self {
329		Self::new(self.0.rotate_right(n))
330	}
331
332	fn swap_bytes(self) -> Self {
333		Self::new(self.0.swap_bytes())
334	}
335
336	fn from_be(x: Self) -> Self {
337		Self::new(T::from_be(x.0))
338	}
339
340	fn from_le(x: Self) -> Self {
341		Self::new(T::from_le(x.0))
342	}
343
344	fn to_be(self) -> Self {
345		Self::new(self.0.to_be())
346	}
347
348	fn to_le(self) -> Self {
349		Self::new(self.0.to_le())
350	}
351
352	fn count_zeros(self) -> u32 {
353		self.0.count_zeros()
354	}
355
356	fn signed_shl(self, n: u32) -> Self {
357		Self::new(self.0.signed_shl(n))
358	}
359
360	fn signed_shr(self, n: u32) -> Self {
361		Self::new(self.0.signed_shr(n))
362	}
363
364	fn unsigned_shl(self, n: u32) -> Self {
365		Self::new(self.0.unsigned_shl(n))
366	}
367
368	fn unsigned_shr(self, n: u32) -> Self {
369		Self::new(self.0.unsigned_shr(n))
370	}
371
372	fn pow(self, exp: u32) -> Self {
373		Self::new(self.0.pow(exp))
374	}
375}
376
377impl<T: Saturating, D: Get<T>> Saturating for TypeWithDefault<T, D> {
378	fn saturating_add(self, rhs: Self) -> Self {
379		Self::new(self.0.saturating_add(rhs.0))
380	}
381
382	fn saturating_sub(self, rhs: Self) -> Self {
383		Self::new(self.0.saturating_sub(rhs.0))
384	}
385}
386
387impl<T: Div<Output = T>, D: Get<T>> Div for TypeWithDefault<T, D> {
388	type Output = Self;
389	fn div(self, rhs: Self) -> Self {
390		Self::new(self.0 / rhs.0)
391	}
392}
393
394impl<T: Mul<Output = T>, D: Get<T>> Mul for TypeWithDefault<T, D> {
395	type Output = Self;
396	fn mul(self, rhs: Self) -> Self {
397		Self::new(self.0 * rhs.0)
398	}
399}
400
401impl<T: CheckedDiv, D: Get<T>> CheckedDiv for TypeWithDefault<T, D> {
402	fn checked_div(&self, rhs: &Self) -> Option<Self> {
403		self.0.checked_div(&rhs.0).map(Self::new)
404	}
405}
406
407impl<T: CheckedMul, D: Get<T>> CheckedMul for TypeWithDefault<T, D> {
408	fn checked_mul(&self, rhs: &Self) -> Option<Self> {
409		self.0.checked_mul(&rhs.0).map(Self::new)
410	}
411}
412
413impl<T: Sub<Output = T>, D: Get<T>> Sub for TypeWithDefault<T, D> {
414	type Output = Self;
415	fn sub(self, rhs: Self) -> Self {
416		Self::new(self.0 - rhs.0)
417	}
418}
419
420impl<T: CheckedSub, D: Get<T>> CheckedSub for TypeWithDefault<T, D> {
421	fn checked_sub(&self, rhs: &Self) -> Option<Self> {
422		self.0.checked_sub(&rhs.0).map(Self::new)
423	}
424}
425
426impl<T: Add<Output = T>, D: Get<T>> Add for TypeWithDefault<T, D> {
427	type Output = Self;
428	fn add(self, rhs: Self) -> Self {
429		Self::new(self.0 + rhs.0)
430	}
431}
432
433impl<T: CheckedAdd, D: Get<T>> CheckedAdd for TypeWithDefault<T, D> {
434	fn checked_add(&self, rhs: &Self) -> Option<Self> {
435		self.0.checked_add(&rhs.0).map(Self::new)
436	}
437}
438
439impl<T: BitAnd<Output = T>, D: Get<T>> BitAnd for TypeWithDefault<T, D> {
440	type Output = Self;
441	fn bitand(self, rhs: Self) -> Self {
442		Self::new(self.0 & rhs.0)
443	}
444}
445
446impl<T: BitOr<Output = T>, D: Get<T>> BitOr for TypeWithDefault<T, D> {
447	type Output = Self;
448	fn bitor(self, rhs: Self) -> Self {
449		Self::new(self.0 | rhs.0)
450	}
451}
452
453impl<T: BitXor<Output = T>, D: Get<T>> BitXor for TypeWithDefault<T, D> {
454	type Output = Self;
455	fn bitxor(self, rhs: Self) -> Self {
456		Self::new(self.0 ^ rhs.0)
457	}
458}
459
460impl<T: One, D: Get<T>> One for TypeWithDefault<T, D> {
461	fn one() -> Self {
462		Self::new(T::one())
463	}
464}
465
466impl<T: Not<Output = T>, D: Get<T>> Not for TypeWithDefault<T, D> {
467	type Output = Self;
468	fn not(self) -> Self {
469		Self::new(self.0.not())
470	}
471}
472
473impl<T: NumCast, D: Get<T>> NumCast for TypeWithDefault<T, D> {
474	fn from<P: ToPrimitive>(n: P) -> Option<Self> {
475		<T as NumCast>::from(n).map_or(None, |n| Some(Self::new(n)))
476	}
477}
478
479impl<T: Num, D: Get<T>> Num for TypeWithDefault<T, D> {
480	type FromStrRadixErr = <T as Num>::FromStrRadixErr;
481
482	fn from_str_radix(s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
483		T::from_str_radix(s, radix).map(Self::new)
484	}
485}
486
487impl<T: ToPrimitive, D: Get<T>> ToPrimitive for TypeWithDefault<T, D> {
488	fn to_i64(&self) -> Option<i64> {
489		self.0.to_i64()
490	}
491
492	fn to_u64(&self) -> Option<u64> {
493		self.0.to_u64()
494	}
495
496	fn to_i128(&self) -> Option<i128> {
497		self.0.to_i128()
498	}
499
500	fn to_u128(&self) -> Option<u128> {
501		self.0.to_u128()
502	}
503}
504
505impl<T, D: Get<T>> From<Compact<TypeWithDefault<T, D>>> for TypeWithDefault<T, D> {
506	fn from(c: Compact<TypeWithDefault<T, D>>) -> Self {
507		c.0
508	}
509}
510
511impl<T: HasCompact, D: Get<T>> CompactAs for TypeWithDefault<T, D> {
512	type As = T;
513
514	fn encode_as(&self) -> &Self::As {
515		&self.0
516	}
517
518	fn decode_from(val: Self::As) -> Result<Self, codec::Error> {
519		Ok(Self::new(val))
520	}
521}
522
523#[cfg(test)]
524mod tests {
525	use super::TypeWithDefault;
526	use scale_info::TypeInfo;
527	use sp_arithmetic::traits::{AtLeast16Bit, AtLeast32Bit, AtLeast8Bit};
528	use sp_core::Get;
529
530	#[test]
531	#[allow(dead_code)]
532	fn test_type_with_default_impl_base_arithmetic() {
533		trait WrapAtLeast8Bit: AtLeast8Bit {}
534		trait WrapAtLeast16Bit: AtLeast16Bit {}
535		trait WrapAtLeast32Bit: AtLeast32Bit {}
536
537		struct Getu8;
538		impl Get<u8> for Getu8 {
539			fn get() -> u8 {
540				0
541			}
542		}
543		type U8WithDefault = TypeWithDefault<u8, Getu8>;
544		impl WrapAtLeast8Bit for U8WithDefault {}
545
546		struct Getu16;
547		impl Get<u16> for Getu16 {
548			fn get() -> u16 {
549				0
550			}
551		}
552		type U16WithDefault = TypeWithDefault<u16, Getu16>;
553		impl WrapAtLeast16Bit for U16WithDefault {}
554
555		struct Getu32;
556		impl Get<u32> for Getu32 {
557			fn get() -> u32 {
558				0
559			}
560		}
561		type U32WithDefault = TypeWithDefault<u32, Getu32>;
562		impl WrapAtLeast32Bit for U32WithDefault {}
563
564		struct Getu64;
565		impl Get<u64> for Getu64 {
566			fn get() -> u64 {
567				0
568			}
569		}
570		type U64WithDefault = TypeWithDefault<u64, Getu64>;
571		impl WrapAtLeast32Bit for U64WithDefault {}
572
573		struct Getu128;
574		impl Get<u128> for Getu128 {
575			fn get() -> u128 {
576				0
577			}
578		}
579		type U128WithDefault = TypeWithDefault<u128, Getu128>;
580		impl WrapAtLeast32Bit for U128WithDefault {}
581
582		assert_eq!(U8WithDefault::type_info(), <u8 as TypeInfo>::type_info());
583		assert_eq!(U16WithDefault::type_info(), <u16 as TypeInfo>::type_info());
584		assert_eq!(U32WithDefault::type_info(), <u32 as TypeInfo>::type_info());
585		assert_eq!(U64WithDefault::type_info(), <u64 as TypeInfo>::type_info());
586		assert_eq!(U128WithDefault::type_info(), <u128 as TypeInfo>::type_info());
587	}
588}