bounded_collections_next/
const_int.rs1use crate::{Get, TypedGet};
10use core::marker::PhantomData;
11
12trait ConstBounded<T> {
14 const MIN: T;
15 const MAX: T;
16}
17
18macro_rules! impl_const_bounded {
19 ($bound:ty, $t:ty) => {
20 impl ConstBounded<$bound> for $t {
21 const MIN: $bound = <$t>::MIN as $bound;
22 const MAX: $bound = <$t>::MAX as $bound;
23 }
24 };
25}
26
27impl_const_bounded!(u128, u8);
28impl_const_bounded!(u128, u16);
29impl_const_bounded!(u128, u32);
30impl_const_bounded!(u128, u64);
31impl_const_bounded!(u128, u128);
32impl_const_bounded!(u128, usize);
33
34impl_const_bounded!(i128, i8);
35impl_const_bounded!(i128, i16);
36impl_const_bounded!(i128, i32);
37impl_const_bounded!(i128, i64);
38impl_const_bounded!(i128, i128);
39
40struct CheckOverflowU128<T: ConstBounded<u128>, const N: u128>(PhantomData<T>);
42
43impl<T: ConstBounded<u128>, const N: u128> CheckOverflowU128<T, N> {
44 const ASSERTION: () = assert!(N >= T::MIN && N <= T::MAX);
45}
46
47struct CheckOverflowI128<T: ConstBounded<i128>, const N: i128>(PhantomData<T>);
49
50impl<T: ConstBounded<i128>, const N: i128> CheckOverflowI128<T, N> {
51 const ASSERTION: () = assert!(N >= T::MIN && N <= T::MAX);
52}
53
54#[derive(Default, Clone)]
63pub struct ConstUint<const N: u128>;
64
65impl<const N: u128> core::fmt::Debug for ConstUint<N> {
66 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
67 fmt.write_str(&alloc::format!("ConstUint<{}>", N))
68 }
69}
70
71impl<const N: u128> TypedGet for ConstUint<N> {
72 type Type = u128;
73 fn get() -> u128 {
74 N
75 }
76}
77
78#[derive(Default, Clone)]
80pub struct ConstInt<const N: i128>;
81
82impl<const N: i128> core::fmt::Debug for ConstInt<N> {
83 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
84 fmt.write_str(&alloc::format!("ConstInt<{}>", N))
85 }
86}
87
88impl<const N: i128> TypedGet for ConstInt<N> {
89 type Type = i128;
90 fn get() -> i128 {
91 N
92 }
93}
94
95macro_rules! impl_const_int {
96 ($t:ident, $check:ident, $bound:ty, $target:ty) => {
97 impl<const N: $bound> Get<$target> for $t<N> {
98 fn get() -> $target {
99 let _ = <$check<$target, N>>::ASSERTION;
100 N as $target
101 }
102 }
103 impl<const N: $bound> Get<Option<$target>> for $t<N> {
104 fn get() -> Option<$target> {
105 let _ = <$check<$target, N>>::ASSERTION;
106 Some(N as $target)
107 }
108 }
109 };
110}
111
112impl_const_int!(ConstUint, CheckOverflowU128, u128, u8);
113impl_const_int!(ConstUint, CheckOverflowU128, u128, u16);
114impl_const_int!(ConstUint, CheckOverflowU128, u128, u32);
115impl_const_int!(ConstUint, CheckOverflowU128, u128, u64);
116impl_const_int!(ConstUint, CheckOverflowU128, u128, u128);
117impl_const_int!(ConstUint, CheckOverflowU128, u128, usize);
118
119impl_const_int!(ConstInt, CheckOverflowI128, i128, i8);
120impl_const_int!(ConstInt, CheckOverflowI128, i128, i16);
121impl_const_int!(ConstInt, CheckOverflowI128, i128, i32);
122impl_const_int!(ConstInt, CheckOverflowI128, i128, i64);
123impl_const_int!(ConstInt, CheckOverflowI128, i128, i128);
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128
129 #[test]
130 fn const_uint_works() {
131 assert_eq!(<ConstUint<42> as Get<u8>>::get(), 42);
132 assert_eq!(<ConstUint<42> as Get<Option<u8>>>::get(), Some(42));
133 assert_eq!(<ConstUint<42> as Get<u16>>::get(), 42);
134 assert_eq!(<ConstUint<42> as Get<u32>>::get(), 42);
135 assert_eq!(<ConstUint<42> as Get<u64>>::get(), 42);
136 assert_eq!(<ConstUint<42> as Get<u128>>::get(), 42);
137 assert_eq!(<ConstUint<42> as Get<usize>>::get(), 42);
138 assert_eq!(<ConstUint<42> as TypedGet>::get(), 42);
139 }
142
143 #[test]
144 fn const_int_works() {
145 assert_eq!(<ConstInt<-42> as Get<i8>>::get(), -42);
146 assert_eq!(<ConstInt<-42> as Get<Option<i8>>>::get(), Some(-42));
147 assert_eq!(<ConstInt<-42> as Get<i16>>::get(), -42);
148 assert_eq!(<ConstInt<-42> as Get<i32>>::get(), -42);
149 assert_eq!(<ConstInt<-42> as Get<i64>>::get(), -42);
150 assert_eq!(<ConstInt<-42> as Get<i128>>::get(), -42);
151 assert_eq!(<ConstInt<-42> as TypedGet>::get(), -42);
152 }
153}