bounded_integer/
types.rs

1define_bounded_integers! {
2    BoundedU8(u8, unaligned, unsigned),
3    BoundedU16(u16, unsigned),
4    BoundedU32(u32, unsigned),
5    BoundedU64(u64, unsigned),
6    BoundedU128(u128, unsigned),
7    BoundedUsize(usize, unsigned),
8    BoundedI8(i8, unaligned, unsigned),
9    BoundedI16(i16),
10    BoundedI32(i32),
11    BoundedI64(i64),
12    BoundedI128(i128),
13    BoundedIsize(isize),
14}
15
16macro_rules! define_bounded_integers {
17    ($($name:ident(
18        $inner:ident
19        $(, unaligned $([$unaligned:ident])?)?
20        $(, unsigned $([$unsigned:ident])?)?
21    ),)*) => { $(
22        #[doc = "An"]
23        #[doc = concat!("[`", stringify!($inner), "`]")]
24        #[doc = "constrained to be in the range `MIN..=MAX`."]
25        #[repr(transparent)]
26        #[cfg_attr(feature = "zerocopy", derive(zerocopy::IntoBytes, zerocopy::Immutable))]
27        #[cfg_attr(
28            all(feature = "zerocopy", any($($(if $unaligned)? true)?)),
29            derive(zerocopy::Unaligned),
30        )]
31        pub struct $name<const MIN: $inner, const MAX: $inner>($inner);
32
33        $crate::unsafe_api! {
34            [const MIN: $inner, const MAX: $inner] for $name<MIN, MAX>,
35            unsafe repr: $inner,
36            min: MIN,
37            max: MAX,
38        }
39
40        #[cfg(any($($(if $unsigned)? true)?))]
41        impl<const MAX: $inner> Default for $name<0, MAX> {
42            fn default() -> Self {
43                Self::const_new::<0>()
44            }
45        }
46
47        #[cfg(feature = "bytemuck1")]
48        #[cfg(any($($($unsigned)? true)?))]
49        unsafe impl<const MAX: $inner> bytemuck1::Zeroable for $name<0, MAX> {}
50    )* }
51}
52use define_bounded_integers;
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    #[test]
59    fn range() {
60        type Bounded = BoundedI8<3, 10>;
61        assert_eq!(Bounded::MIN_VALUE, 3);
62        assert_eq!(Bounded::MAX_VALUE, 10);
63        assert_eq!(Bounded::MIN.get(), Bounded::MIN_VALUE);
64        assert_eq!(Bounded::MAX.get(), Bounded::MAX_VALUE);
65
66        assert!(Bounded::in_range(3));
67        assert!(!Bounded::in_range(2));
68        assert!(Bounded::in_range(10));
69        assert!(!Bounded::in_range(11));
70    }
71
72    #[test]
73    fn new_saturating() {
74        type Bounded = BoundedI8<3, 10>;
75        assert_eq!(Bounded::new_saturating(i8::MIN), Bounded::MIN);
76        assert_eq!(Bounded::new_saturating(i8::MAX), Bounded::MAX);
77        assert_eq!(Bounded::new_saturating(11).get(), 10);
78        assert_eq!(Bounded::new_saturating(10).get(), 10);
79        assert_eq!(Bounded::new_saturating(3).get(), 3);
80        assert_eq!(Bounded::new_saturating(2).get(), 3);
81    }
82
83    #[test]
84    fn wrapping_unwiden() {
85        type Bounded = BoundedU8<2, 20>;
86
87        assert_eq!(Bounded::new_wrapping(0_u8), 19);
88        assert_eq!(Bounded::new_wrapping(2_u8), 2);
89        assert_eq!(Bounded::new_wrapping(20_u8), 20);
90        assert_eq!(Bounded::new_wrapping(21_u8), 2);
91        assert_eq!(Bounded::new_wrapping(255_u8), 8);
92
93        assert_eq!(Bounded::new_wrapping(12_u16), 12);
94        assert_eq!(Bounded::new_wrapping(21_u16), 2);
95        assert_eq!(Bounded::new_wrapping(12_i16), 12);
96        assert_eq!(Bounded::new_wrapping(21_i16), 2);
97
98        assert_eq!(Bounded::new_wrapping(0_u16), 19);
99        assert_eq!(Bounded::new_wrapping(65535_u16), 4);
100        assert_eq!(Bounded::new_wrapping(65533_u16), 2);
101        assert_eq!(Bounded::new_wrapping(65532_u16), 20);
102
103        assert_eq!(Bounded::new_wrapping(-32768_i16), 7);
104        assert_eq!(Bounded::new_wrapping(-32755_i16), 20);
105        assert_eq!(Bounded::new_wrapping(-32754_i16), 2);
106        assert_eq!(Bounded::new_wrapping(32767_i16), 11);
107    }
108
109    #[test]
110    fn wrapping_full() {
111        type Bounded = BoundedI8<{ i8::MIN }, { i8::MAX }>;
112        assert_eq!(Bounded::new_wrapping(37_i8), 37);
113        assert_eq!(Bounded::new_wrapping(-128_i8), -128);
114        assert_eq!(Bounded::new_wrapping(127_i8), 127);
115        assert_eq!(Bounded::new_wrapping(128_i16), -128);
116        assert_eq!(Bounded::new_wrapping(-200_i16), 56);
117        assert_eq!(Bounded::new(25).unwrap().wrapping_pow(20), 97);
118    }
119
120    #[test]
121    fn wrapping_signed() {
122        type Bounded = BoundedI8<-5, 2>;
123        assert_eq!(Bounded::new_wrapping(0_i8).get(), 0);
124        assert_eq!(Bounded::new_wrapping(-5_i8).get(), -5);
125        assert_eq!(Bounded::new_wrapping(2_i8).get(), 2);
126        assert_eq!(Bounded::new_wrapping(-128_i8).get(), 0);
127    }
128
129    #[test]
130    fn arithmetic() {
131        #![expect(clippy::modulo_one)]
132        type Bounded = BoundedI8<-5, 20>;
133        assert_eq!(Bounded::new(2).unwrap() + 3, 5);
134        assert_eq!(Bounded::new(2).unwrap() - 5, -3);
135        assert_eq!(Bounded::new(3).unwrap() * 5, 15);
136        assert_eq!(Bounded::new(11).unwrap() / 3, 3);
137        assert_eq!(Bounded::new(11).unwrap() % 3, 2);
138        assert_eq!(Bounded::new(-3).unwrap() / 2, -1);
139        assert_eq!(Bounded::new(-3).unwrap() % 2, -1);
140        assert_eq!(-Bounded::new(-3).unwrap(), 3);
141        assert_eq!(!Bounded::new(-3).unwrap(), 2);
142        assert_eq!(-&Bounded::new(-3).unwrap(), 3);
143        assert_eq!(!&Bounded::new(-3).unwrap(), 2);
144        assert_eq!(Bounded::new(3).unwrap() << 1, 6);
145        assert_eq!(Bounded::new(3).unwrap() >> 1, 1);
146        variations!(Bounded, i8, + += - -= * *= / /= % %=);
147
148        assert_eq!(Bounded::new(2).unwrap().pow(3).get(), 8);
149        assert_eq!(Bounded::new(-3).unwrap().div_euclid(2).get(), -2);
150        assert_eq!(Bounded::new(-3).unwrap().rem_euclid(2).get(), 1);
151        assert_eq!(Bounded::new(-3).unwrap().abs().get(), 3);
152        assert_eq!(Bounded::new(4).unwrap().abs().get(), 4);
153
154        macro_rules! variations {
155            ($ty:ty, $inner:ty, $($op:tt $op_assign:tt)*) => {
156                $(
157                    let _: $ty = <$ty>::new(0).unwrap() $op 1;
158                    let _: $ty = &<$ty>::new(0).unwrap() $op 1;
159                    let _: $ty = <$ty>::new(0).unwrap() $op &1;
160                    let _: $ty = &<$ty>::new(0).unwrap() $op &1;
161                    let _: $inner = 0 $op <$ty>::new(1).unwrap();
162                    let _: $inner = 0 $op &<$ty>::new(1).unwrap();
163                    let _: $inner = &0 $op <$ty>::new(1).unwrap();
164                    let _: $inner = &0 $op &<$ty>::new(1).unwrap();
165                    let _: $ty = <$ty>::new(0).unwrap() $op <$ty>::new(1).unwrap();
166                    let _: $ty = &<$ty>::new(0).unwrap() $op <$ty>::new(1).unwrap();
167                    let _: $ty = <$ty>::new(0).unwrap() $op &<$ty>::new(1).unwrap();
168                    let _: $ty = &<$ty>::new(0).unwrap() $op &<$ty>::new(1).unwrap();
169                    *&mut <$ty>::new(0).unwrap() $op_assign 1;
170                    *&mut <$ty>::new(0).unwrap() $op_assign &1;
171                    *&mut <$ty>::new(0).unwrap() $op_assign <$ty>::new(1).unwrap();
172                    *&mut <$ty>::new(0).unwrap() $op_assign &<$ty>::new(1).unwrap();
173                    *&mut 0 $op_assign <$ty>::new(1).unwrap();
174                    *&mut 0 $op_assign &<$ty>::new(1).unwrap();
175                )*
176            };
177        }
178        use variations;
179    }
180
181    #[test]
182    fn saturating() {
183        type Bounded = BoundedI8<-5, 20>;
184        assert_eq!(Bounded::new(13).unwrap().saturating_add(1).get(), 14);
185        assert_eq!(Bounded::new(14).unwrap().saturating_add(7).get(), 20);
186        assert_eq!(Bounded::new(-2).unwrap().saturating_sub(-1).get(), -1);
187        assert_eq!(Bounded::new(-2).unwrap().saturating_sub(127).get(), -5);
188        assert_eq!(Bounded::new(2).unwrap().saturating_mul(3).get(), 6);
189        assert_eq!(Bounded::new(15).unwrap().saturating_mul(-1).get(), -5);
190        assert_eq!(Bounded::new(3).unwrap().saturating_pow(2).get(), 9);
191        assert_eq!(Bounded::new(3).unwrap().saturating_pow(3).get(), 20);
192        assert_eq!(Bounded::new(-4).unwrap().saturating_neg().get(), 4);
193        assert_eq!(Bounded::new(8).unwrap().saturating_neg().get(), -5);
194        assert_eq!(Bounded::new(8).unwrap().saturating_abs().get(), 8);
195        assert_eq!(<BoundedI8<-20, 5>>::new(-6).unwrap().saturating_abs(), 5);
196    }
197
198    #[test]
199    fn checked() {
200        type Bounded = BoundedI8<-5, 20>;
201        assert_eq!(Bounded::new(13).unwrap().checked_add(2).unwrap().get(), 15);
202        assert_eq!(Bounded::new(14).unwrap().checked_add(7), None);
203        assert_eq!(Bounded::new(-2).unwrap().checked_sub(-1).unwrap().get(), -1);
204        assert_eq!(Bounded::new(-2).unwrap().checked_sub(127), None);
205        assert_eq!(Bounded::new(2).unwrap().checked_mul(3).unwrap().get(), 6);
206        assert_eq!(Bounded::new(15).unwrap().checked_mul(-1), None);
207        assert_eq!(Bounded::new(3).unwrap().checked_pow(2).unwrap().get(), 9);
208        assert_eq!(Bounded::new(3).unwrap().checked_pow(3), None);
209        assert_eq!(Bounded::new(2).unwrap().checked_shl(3).unwrap().get(), 16);
210        assert_eq!(Bounded::new(3).unwrap().checked_shl(3), None);
211        assert_eq!(Bounded::new(9).unwrap().checked_shr(2).unwrap().get(), 2);
212        assert_eq!(<BoundedI8<4, 8>>::new(8).unwrap().checked_shr(2), None);
213        assert_eq!(Bounded::new(11).unwrap().checked_div(3).unwrap().get(), 3);
214        assert_eq!(Bounded::new(11).unwrap().checked_rem(3).unwrap().get(), 2);
215        assert_eq!(<BoundedI8<4, 11>>::new(11).unwrap().checked_div(3), None);
216        assert_eq!(<BoundedI8<4, 11>>::new(11).unwrap().checked_rem(3), None);
217        assert_eq!(Bounded::new(11).unwrap().checked_div_euclid(3).unwrap(), 3);
218        assert_eq!(Bounded::new(11).unwrap().checked_rem_euclid(3).unwrap(), 2);
219        assert_eq!(
220            <BoundedI8<4, 11>>::new(11).unwrap().checked_div_euclid(3),
221            None
222        );
223        assert_eq!(
224            <BoundedI8<4, 11>>::new(11).unwrap().checked_rem_euclid(3),
225            None
226        );
227        assert_eq!(Bounded::new(-3).unwrap().checked_neg().unwrap().get(), 3);
228        assert_eq!(Bounded::new(6).unwrap().checked_neg(), None);
229        assert_eq!(Bounded::new(-3).unwrap().checked_abs().unwrap().get(), 3);
230        assert_eq!(Bounded::new(6).unwrap().checked_abs().unwrap().get(), 6);
231        assert_eq!(<BoundedI8<-20, 5>>::new(-6).unwrap().checked_abs(), None);
232    }
233
234    #[test]
235    fn wrapping() {
236        type Bounded = BoundedI8<-5, 20>;
237        assert_eq!(Bounded::new(0).unwrap().wrapping_add(0).get(), 0);
238        assert_eq!(Bounded::new(-5).unwrap().wrapping_add(-128), -3);
239        assert_eq!(Bounded::new(-5).unwrap().wrapping_sub(127), -2);
240        assert_eq!(Bounded::new(20).unwrap().wrapping_add(127), 17);
241        assert_eq!(Bounded::new(15).unwrap().wrapping_mul(17), -5);
242        assert_eq!(Bounded::new(-5).unwrap().wrapping_div(2), -2);
243        assert_eq!(Bounded::new(-5).unwrap().wrapping_rem(2), -1);
244        assert_eq!(Bounded::new(-5).unwrap().wrapping_div_euclid(2), -3);
245        assert_eq!(Bounded::new(-5).unwrap().wrapping_rem_euclid(2), 1);
246        assert_eq!(Bounded::new(-5).unwrap().wrapping_neg(), 5);
247        assert_eq!(Bounded::new(6).unwrap().wrapping_neg(), 20);
248        assert_eq!(Bounded::new(-5).unwrap().wrapping_abs(), 5);
249        assert_eq!(Bounded::new(6).unwrap().wrapping_abs(), 6);
250        assert_eq!(<BoundedI8<-20, 5>>::new(-6).unwrap().wrapping_abs(), -20);
251        assert_eq!(Bounded::new(5).unwrap().wrapping_pow(607), -5);
252    }
253
254    #[test]
255    fn wrapping_div() {
256        type Bounded = BoundedI32<{ i32::MIN }, -1>;
257        assert_eq!(Bounded::new(i32::MIN).unwrap().wrapping_div(-1), i32::MIN);
258    }
259
260    #[test]
261    fn iter() {
262        type Bounded = BoundedI8<-8, 8>;
263        #[expect(clippy::trivially_copy_pass_by_ref)]
264        fn b(&n: &i8) -> Bounded {
265            Bounded::new(n).unwrap()
266        }
267        assert_eq!([3, 2, 1].iter().map(b).sum::<Bounded>().get(), 6);
268        assert_eq!([-8, 3, 7, 5, -2].iter().map(b).sum::<Bounded>().get(), 5);
269        assert_eq!([7, 6, 4].iter().map(b).sum::<i8>(), 17);
270        assert_eq!([-8, 3, 7, 5, -2].iter().map(b).sum::<i8>(), 5);
271
272        assert_eq!([1, 3, 2, 1].iter().map(b).product::<Bounded>().get(), 6);
273        assert_eq!([1, 3, 2, 1, 0].iter().map(b).product::<Bounded>().get(), 0);
274        assert_eq!([-2, -3, -1].iter().map(b).product::<Bounded>().get(), -6);
275        assert_eq!([3, 3].iter().map(b).product::<i8>(), 9);
276    }
277
278    #[test]
279    fn parse() {
280        use crate::ParseErrorKind::*;
281
282        type Bounded = BoundedI8<3, 11>;
283
284        assert_eq!("3".parse::<Bounded>().unwrap().get(), 3);
285        assert_eq!("10".parse::<Bounded>().unwrap().get(), 10);
286        assert_eq!("+11".parse::<Bounded>().unwrap().get(), 11);
287        assert_eq!(Bounded::from_str_radix("1010", 2).unwrap().get(), 10);
288        assert_eq!(Bounded::from_str_radix("B", 0xC).unwrap().get(), 11);
289        assert_eq!(Bounded::from_str_radix("11", 7).unwrap().get(), 8);
290        assert_eq!(Bounded::from_str_radix("7", 36).unwrap().get(), 7);
291
292        assert_eq!("".parse::<Bounded>().unwrap_err().kind(), NoDigits);
293        assert_eq!("+".parse::<Bounded>().unwrap_err().kind(), NoDigits);
294        assert_eq!("-".parse::<Bounded>().unwrap_err().kind(), NoDigits);
295        assert_eq!("2".parse::<Bounded>().unwrap_err().kind(), BelowMin);
296        assert_eq!("12".parse::<Bounded>().unwrap_err().kind(), AboveMax);
297        assert_eq!("-5".parse::<Bounded>().unwrap_err().kind(), BelowMin);
298        assert_eq!("128".parse::<Bounded>().unwrap_err().kind(), AboveMax);
299        assert_eq!("-129".parse::<Bounded>().unwrap_err().kind(), BelowMin);
300
301        assert_eq!("++0".parse::<Bounded>().unwrap_err().kind(), InvalidDigit);
302        assert_eq!("--0".parse::<Bounded>().unwrap_err().kind(), InvalidDigit);
303        assert_eq!("O".parse::<Bounded>().unwrap_err().kind(), InvalidDigit);
304        assert_eq!("C".parse::<Bounded>().unwrap_err().kind(), InvalidDigit);
305        assert_eq!(
306            Bounded::from_str_radix("3", 2).unwrap_err().kind(),
307            InvalidDigit
308        );
309    }
310
311    #[test]
312    #[cfg(feature = "alloc")]
313    fn fmt() {
314        use alloc::format;
315        use alloc::string::ToString;
316        type Bounded = BoundedU8<3, 210>;
317        assert_eq!(Bounded::new(3).unwrap().to_string(), "3");
318        assert_eq!(format!("{:b}", Bounded::new(5).unwrap()), "101");
319        assert_eq!(format!("{:x}", Bounded::new(200).unwrap()), "c8");
320        assert_eq!(format!("{:X}", Bounded::new(200).unwrap()), "C8");
321        assert_eq!(format!("{:o}", Bounded::new(200).unwrap()), "310");
322    }
323
324    #[test]
325    fn default() {
326        assert_eq!(<BoundedU8<0, 5>>::default().get(), 0);
327    }
328
329    #[test]
330    fn conversions() {
331        assert_eq!(i8::from(<BoundedI8<1, 5>>::new(3).unwrap()), 3);
332        assert_eq!(i16::from(<BoundedI8<1, 5>>::new(3).unwrap()), 3);
333        assert_eq!(i32::from(<BoundedI8<1, 5>>::new(3).unwrap()), 3);
334        assert_eq!(u32::from(<BoundedU32<1, 5>>::new(3).unwrap()), 3);
335        assert_eq!(i64::from(<BoundedU32<1, 5>>::new(3).unwrap()), 3);
336        assert_eq!(usize::from(<BoundedU16<1, 5>>::new(3).unwrap()), 3);
337        assert_eq!(
338            u8::try_from(<BoundedI8<-5, 5>>::new(3).unwrap()).unwrap(),
339            3
340        );
341        u8::try_from(<BoundedI8<-5, 5>>::new(-1).unwrap()).unwrap_err();
342        assert_eq!(<BoundedI8<2, 5>>::try_from(3_u16).unwrap(), 3);
343        <BoundedI8<2, 5>>::try_from(8_u16).unwrap_err();
344    }
345
346    #[test]
347    #[cfg(feature = "num-traits02")]
348    #[expect(clippy::too_many_lines)]
349    fn num() {
350        use num_traits02::{
351            AsPrimitive, Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem,
352            CheckedShl, CheckedShr, CheckedSub, FromPrimitive, NumCast, ToPrimitive,
353        };
354
355        type B = BoundedI8<2, 8>;
356        type BNeg = BoundedI8<-4, 8>;
357
358        fn b(n: i8) -> B {
359            B::new(n).unwrap()
360        }
361
362        fn bneg(n: i8) -> BNeg {
363            BNeg::new(n).unwrap()
364        }
365
366        assert_eq!(B::min_value(), 2);
367        assert_eq!(B::max_value(), 8);
368
369        assert_eq!(BNeg::min_value(), -4);
370        assert_eq!(BNeg::max_value(), 8);
371
372        assert_eq!(<B as AsPrimitive<u8>>::as_(b(4)), 4u8);
373        assert_eq!(<B as AsPrimitive<u16>>::as_(b(4)), 4u16);
374        assert_eq!(<B as AsPrimitive<u32>>::as_(b(4)), 4u32);
375        assert_eq!(<B as AsPrimitive<u64>>::as_(b(4)), 4u64);
376        assert_eq!(<B as AsPrimitive<u128>>::as_(b(4)), 4u128);
377        assert_eq!(<B as AsPrimitive<usize>>::as_(b(4)), 4usize);
378        assert_eq!(<B as AsPrimitive<i8>>::as_(b(4)), 4i8);
379        assert_eq!(<B as AsPrimitive<i16>>::as_(b(4)), 4i16);
380        assert_eq!(<B as AsPrimitive<i32>>::as_(b(4)), 4i32);
381        assert_eq!(<B as AsPrimitive<i64>>::as_(b(4)), 4i64);
382        assert_eq!(<B as AsPrimitive<i128>>::as_(b(4)), 4i128);
383        assert_eq!(<B as AsPrimitive<isize>>::as_(b(4)), 4isize);
384        #[expect(clippy::float_cmp)]
385        let () = assert_eq!(<B as AsPrimitive<f32>>::as_(b(4)), 4f32);
386        #[expect(clippy::float_cmp)]
387        let () = assert_eq!(<B as AsPrimitive<f64>>::as_(b(4)), 4f64);
388
389        assert_eq!(B::from_u8(4u8), Some(b(4)));
390        assert_eq!(B::from_u16(4u16), Some(b(4)));
391        assert_eq!(B::from_u32(4u32), Some(b(4)));
392        assert_eq!(B::from_u64(4u64), Some(b(4)));
393        assert_eq!(B::from_u128(4u128), Some(b(4)));
394        assert_eq!(B::from_usize(4usize), Some(b(4)));
395        assert_eq!(B::from_i8(4i8), Some(b(4)));
396        assert_eq!(B::from_i16(4i16), Some(b(4)));
397        assert_eq!(B::from_i32(4i32), Some(b(4)));
398        assert_eq!(B::from_i64(4i64), Some(b(4)));
399        assert_eq!(B::from_i128(4i128), Some(b(4)));
400        assert_eq!(B::from_isize(4isize), Some(b(4)));
401        assert_eq!(B::from_f32(4f32), Some(b(4)));
402        assert_eq!(B::from_f64(4f64), Some(b(4)));
403
404        assert_eq!(B::from_u8(16u8), None);
405        assert_eq!(B::from_u16(16u16), None);
406        assert_eq!(B::from_u32(16u32), None);
407        assert_eq!(B::from_u64(16u64), None);
408        assert_eq!(B::from_u128(16u128), None);
409        assert_eq!(B::from_usize(16usize), None);
410        assert_eq!(B::from_i8(16i8), None);
411        assert_eq!(B::from_i16(16i16), None);
412        assert_eq!(B::from_i32(16i32), None);
413        assert_eq!(B::from_i64(16i64), None);
414        assert_eq!(B::from_i128(16i128), None);
415        assert_eq!(B::from_isize(16isize), None);
416        assert_eq!(B::from_f32(16f32), None);
417        assert_eq!(B::from_f64(16f64), None);
418
419        assert_eq!(<B as NumCast>::from(4u8), Some(b(4)));
420        assert_eq!(<B as NumCast>::from(4u16), Some(b(4)));
421        assert_eq!(<B as NumCast>::from(4u32), Some(b(4)));
422        assert_eq!(<B as NumCast>::from(4u64), Some(b(4)));
423        assert_eq!(<B as NumCast>::from(4u128), Some(b(4)));
424        assert_eq!(<B as NumCast>::from(4usize), Some(b(4)));
425        assert_eq!(<B as NumCast>::from(4i8), Some(b(4)));
426        assert_eq!(<B as NumCast>::from(4i16), Some(b(4)));
427        assert_eq!(<B as NumCast>::from(4i32), Some(b(4)));
428        assert_eq!(<B as NumCast>::from(4i64), Some(b(4)));
429        assert_eq!(<B as NumCast>::from(4i128), Some(b(4)));
430        assert_eq!(<B as NumCast>::from(4isize), Some(b(4)));
431        assert_eq!(<B as NumCast>::from(4f32), Some(b(4)));
432        assert_eq!(<B as NumCast>::from(4f64), Some(b(4)));
433
434        assert_eq!(<B as NumCast>::from(16u8), None);
435        assert_eq!(<B as NumCast>::from(16u16), None);
436        assert_eq!(<B as NumCast>::from(16u32), None);
437        assert_eq!(<B as NumCast>::from(16u64), None);
438        assert_eq!(<B as NumCast>::from(16u128), None);
439        assert_eq!(<B as NumCast>::from(16usize), None);
440        assert_eq!(<B as NumCast>::from(16i8), None);
441        assert_eq!(<B as NumCast>::from(16i16), None);
442        assert_eq!(<B as NumCast>::from(16i32), None);
443        assert_eq!(<B as NumCast>::from(16i64), None);
444        assert_eq!(<B as NumCast>::from(16i128), None);
445        assert_eq!(<B as NumCast>::from(16isize), None);
446        assert_eq!(<B as NumCast>::from(16f32), None);
447        assert_eq!(<B as NumCast>::from(16f64), None);
448
449        assert_eq!(b(4).to_u8(), Some(4u8));
450        assert_eq!(b(4).to_u16(), Some(4u16));
451        assert_eq!(b(4).to_u32(), Some(4u32));
452        assert_eq!(b(4).to_u64(), Some(4u64));
453        assert_eq!(b(4).to_u128(), Some(4u128));
454        assert_eq!(b(4).to_usize(), Some(4usize));
455        assert_eq!(b(4).to_i8(), Some(4i8));
456        assert_eq!(b(4).to_i16(), Some(4i16));
457        assert_eq!(b(4).to_i32(), Some(4i32));
458        assert_eq!(b(4).to_i64(), Some(4i64));
459        assert_eq!(b(4).to_i128(), Some(4i128));
460        assert_eq!(b(4).to_isize(), Some(4isize));
461        assert_eq!(b(4).to_f32(), Some(4f32));
462        assert_eq!(b(4).to_f64(), Some(4f64));
463
464        assert_eq!(<B as CheckedAdd>::checked_add(&b(4), &b(4)), Some(b(8)));
465        assert_eq!(<B as CheckedAdd>::checked_add(&b(4), &b(8)), None);
466
467        assert_eq!(<B as CheckedDiv>::checked_div(&b(8), &b(2)), Some(b(4)));
468        assert_eq!(<B as CheckedDiv>::checked_div(&b(4), &b(4)), None);
469
470        assert_eq!(<B as CheckedMul>::checked_mul(&b(2), &b(2)), Some(b(4)));
471        assert_eq!(<B as CheckedMul>::checked_mul(&b(2), &b(8)), None);
472
473        assert_eq!(<BNeg as CheckedNeg>::checked_neg(&bneg(2)), Some(bneg(-2)));
474
475        assert_eq!(<BNeg as CheckedNeg>::checked_neg(&bneg(8)), None);
476
477        assert_eq!(<B as CheckedRem>::checked_rem(&b(8), &b(6)), Some(b(2)));
478        assert_eq!(<B as CheckedRem>::checked_rem(&b(8), &b(7)), None);
479
480        assert_eq!(<B as CheckedSub>::checked_sub(&b(4), &b(2)), Some(b(2)));
481        assert_eq!(<B as CheckedSub>::checked_sub(&b(4), &b(4)), None);
482
483        assert_eq!(<B as CheckedShl>::checked_shl(&b(4), 1u32), Some(b(8)));
484        assert_eq!(<B as CheckedShl>::checked_shl(&b(4), 2u32), None);
485
486        assert_eq!(<B as CheckedShr>::checked_shr(&b(4), 1u32), Some(b(2)));
487        assert_eq!(<B as CheckedShr>::checked_shr(&b(4), 2u32), None);
488    }
489}