1macro_rules! bin_op_variations {
2 ([$($generics:tt)*] $lhs:ty, $rhs:ty, $op:ident::$method:ident/$op_assign:ident::$method_assign:ident) => {
3 impl<$($generics)*> $op<$rhs> for &$lhs {
4 type Output = $lhs;
5 #[inline]
6 fn $method(self, rhs: $rhs) -> Self::Output {
7 <$lhs as $op<$rhs>>::$method(*self, rhs)
8 }
9 }
10 impl<$($generics)*> $op<&$rhs> for $lhs {
11 type Output = $lhs;
12 #[inline]
13 fn $method(self, rhs: &$rhs) -> Self::Output {
14 <$lhs as $op<$rhs>>::$method(self, *rhs)
15 }
16 }
17 impl<$($generics)*> $op<&$rhs> for &$lhs {
18 type Output = $lhs;
19 #[inline]
20 fn $method(self, rhs: &$rhs) -> Self::Output {
21 <$lhs as $op<$rhs>>::$method(*self, *rhs)
22 }
23 }
24
25 impl<$($generics)*> $op_assign<$rhs> for $lhs {
26 #[inline]
27 fn $method_assign(&mut self, rhs: $rhs) {
28 *self = <Self as $op<$rhs>>::$method(*self, rhs);
29 }
30 }
31 impl<$($generics)*> $op_assign<&$rhs> for $lhs {
32 #[inline]
33 fn $method_assign(&mut self, rhs: &$rhs) {
34 *self = <Self as $op<$rhs>>::$method(*self, *rhs);
35 }
36 }
37 }
38}
39
40macro_rules! impl_bin_op {
41 ($op:ident::$method:ident/$op_assign:ident::$method_assign:ident, $desc:literal) => {
42 use core::ops::{$op, $op_assign};
43
44 impl<const MIN: Inner, const MAX: Inner> $op<Inner> for Bounded<MIN, MAX> {
45 type Output = Self;
46 #[inline]
47 fn $method(self, rhs: Inner) -> Self::Output {
48 Self::new(self.get().$method(rhs))
49 .expect(concat!("Attempted to ", $desc, " out of range"))
50 }
51 }
52 bin_op_variations!(
53 [const MIN: Inner, const MAX: Inner]
54 Bounded<MIN, MAX>, Inner, $op::$method/$op_assign::$method_assign
55 );
56
57 impl<const MIN: Inner, const MAX: Inner> $op<Bounded<MIN, MAX>> for Inner {
58 type Output = Self;
59 #[inline]
60 fn $method(self, rhs: Bounded<MIN, MAX>) -> Self::Output {
61 self.$method(rhs.get())
62 }
63 }
64 bin_op_variations! {
65 [const MIN: Inner, const MAX: Inner]
66 Inner, Bounded<MIN, MAX>, $op::$method/$op_assign::$method_assign
67 }
68
69 impl<const L_MIN: Inner, const L_MAX: Inner, const R_MIN: Inner, const R_MAX: Inner>
70 $op<Bounded<R_MIN, R_MAX>> for Bounded<L_MIN, L_MAX>
71 {
72 type Output = Self;
73 #[inline]
74 fn $method(self, rhs: Bounded<R_MIN, R_MAX>) -> Self::Output {
75 Self::new(self.get().$method(rhs))
76 .expect(concat!("Attempted to ", $desc, " out of range"))
77 }
78 }
79 bin_op_variations! {
80 [const L_MIN: Inner, const L_MAX: Inner, const R_MIN: Inner, const R_MAX: Inner]
81 Bounded<L_MIN, L_MAX>, Bounded<R_MIN, R_MAX>, $op::$method/$op_assign::$method_assign
82 }
83 };
84}
85
86macro_rules! impl_shift_bin_op {
87 (u32, $op:ident::$method:ident/$op_assign:ident::$method_assign:ident, $desc:literal) => {
88 impl_bin_op!($op::$method/$op_assign::$method_assign, $desc);
89 };
90 ($inner:ident, $op:ident::$method:ident/$op_assign:ident::$method_assign:ident, $desc:literal) => {
91 impl_bin_op!($op::$method/$op_assign::$method_assign, $desc);
92
93 impl<const MIN: Inner, const MAX: Inner> $op<u32> for Bounded<MIN, MAX> {
95 type Output = Self;
96 #[inline]
97 fn $method(self, rhs: u32) -> Self::Output {
98 Self::new(self.get().$method(rhs))
99 .expect(concat!("Attempted to ", $desc, " out of range"))
100 }
101 }
102 bin_op_variations!(
103 [const MIN: Inner, const MAX: Inner]
104 Bounded<MIN, MAX>, u32, $op::$method/$op_assign::$method_assign
105 );
106 };
107}
108
109#[cfg(test)]
110macro_rules! test_arithmetic {
111 (ops($($op:tt $op_assign:tt)*) infallibles($($infallible:ident)*) fallibles($($fallible:ident)*)) => {
112 $( #[allow(const_item_mutation)] {
113 let _: Bounded = Bounded::MIN $op 0;
114 let _: Bounded = &Bounded::MIN $op 0;
115 let _: Bounded = Bounded::MIN $op &0;
116 let _: Bounded = &Bounded::MIN $op &0;
117 let _: Inner = 0 $op Bounded::MIN;
118 let _: Inner = 0 $op &Bounded::MIN;
119 let _: Inner = &0 $op Bounded::MIN;
120 let _: Inner = &0 $op &Bounded::MIN;
121 let _: Bounded = Bounded::MIN $op Bounded::MIN;
122 let _: Bounded = &Bounded::MIN $op Bounded::MIN;
123 let _: Bounded = Bounded::MIN $op &Bounded::MIN;
124 let _: Bounded = &Bounded::MIN $op &Bounded::MIN;
125 *&mut Bounded::MIN $op_assign 0;
126 *&mut Bounded::MIN $op_assign &0;
127 *&mut Bounded::MIN $op_assign Bounded::MIN;
128 *&mut Bounded::MIN $op_assign &Bounded::MIN;
129 *&mut 0 $op_assign Bounded::MIN;
130 *&mut 0 $op_assign &Bounded::MIN;
131 } )*
132 $(let _: Bounded = Bounded::MIN.$infallible(0);)*
133 $(let _: Option<Bounded> = Bounded::MIN.$fallible(0);)*
134 let _: Option<Bounded> = Bounded::MIN.checked_neg();
135 };
136 (signed $($tt:tt)*) => {
137 test_arithmetic!($($tt)*);
138
139 let _: Bounded = Bounded::MIN.abs();
140 let _: Option<Bounded> = Bounded::MIN.checked_abs();
141
142 let _: Bounded = -Bounded::MIN;
143 let _: Bounded = -&Bounded::MIN;
144 let _: Bounded = Bounded::MIN.saturating_neg();
145 };
146}
147
148macro_rules! impl_fmt_traits {
149 ($($trait:ident),*) => { $(
150 impl<const MIN: Inner, const MAX: Inner> fmt::$trait for Bounded<MIN, MAX> {
151 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
152 fmt::$trait::fmt(&self.get(), f)
153 }
154 }
155 )* }
156}
157
158macro_rules! define_bounded_integers {
159 ($(
160 $name:ident $inner:ident $(signed $([$signed:ident])?)? -> $($into:ident)*,
161 )*) => { $( mod $inner {
162 use core::borrow::Borrow;
163 use core::cmp;
164 use core::fmt;
165 use core::iter;
166 use core::str::FromStr;
167
168 use crate::parse::{ParseError, FromStrRadix};
169
170 type Inner = core::primitive::$inner;
171
172 #[doc = "An"]
173 #[doc = concat!("[`", stringify!($inner), "`]")]
174 #[doc = "constrained to be in the range `MIN..=MAX`."]
175 #[cfg_attr(doc_cfg, doc(cfg(feature = "types")))]
176 #[repr(transparent)]
177 #[derive(Debug, Hash, Clone, Copy, Eq, Ord)]
178 #[cfg_attr(feature = "zerocopy", derive(zerocopy::IntoBytes))]
179 pub struct Bounded<const MIN: Inner, const MAX: Inner>(Inner);
180
181 impl<const MIN: Inner, const MAX: Inner> Bounded<MIN, MAX> {
182 pub const MIN_VALUE: Inner = MIN;
184 pub const MAX_VALUE: Inner = MAX;
186
187 pub const MIN: Self = Self(MIN);
189 pub const MAX: Self = Self(MAX);
191
192 #[must_use]
199 pub const unsafe fn new_unchecked(n: Inner) -> Self {
200 Self(n)
203 }
204
205 #[must_use]
213 pub unsafe fn new_ref_unchecked(n: &Inner) -> &Self {
214 debug_assert!(Self::in_range(*n));
215 &*<*const _>::cast(n)
216 }
217
218 #[must_use]
226 pub unsafe fn new_mut_unchecked(n: &mut Inner) -> &mut Self {
227 debug_assert!(Self::in_range(*n));
228 &mut *<*mut _>::cast(n)
229 }
230
231 #[must_use]
233 #[inline]
234 pub const fn in_range(n: Inner) -> bool {
235 n >= Self::MIN_VALUE && n <= Self::MAX_VALUE
236 }
237
238 #[must_use]
241 #[inline]
242 pub const fn new(n: Inner) -> Option<Self> {
243 if Self::in_range(n) {
244 Some(Self(n))
245 } else {
246 None
247 }
248 }
249
250 #[must_use]
253 #[inline]
254 pub fn new_ref(n: &Inner) -> Option<&Self> {
255 Self::in_range(*n).then(|| {
256 unsafe { Self::new_ref_unchecked(n) }
258 })
259 }
260
261 #[must_use]
265 #[inline]
266 pub fn new_mut(n: &mut Inner) -> Option<&mut Self> {
267 Self::in_range(*n).then(move || {
268 unsafe { Self::new_mut_unchecked(n) }
270 })
271 }
272
273 #[must_use]
276 #[inline]
277 pub const fn new_saturating(n: Inner) -> Self {
278 if n < Self::MIN_VALUE {
279 Self::MIN
280 } else if n > Self::MAX_VALUE {
281 Self::MAX
282 } else {
283 Self(n)
284 }
285 }
286
287 pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseError> {
293 let value = <Inner as FromStrRadix>::from_str_radix(src, radix)?;
294 if value < Self::MIN_VALUE {
295 Err(crate::parse::error_below_min())
296 } else if value > Self::MAX_VALUE {
297 Err(crate::parse::error_above_max())
298 } else {
299 Ok(unsafe { Self::new_unchecked(value) })
300 }
301 }
302
303 #[must_use]
305 #[inline]
306 pub const fn get(self) -> Inner {
307 self.0
308 }
309
310 #[must_use]
312 #[inline]
313 pub const fn get_ref(&self) -> &Inner {
314 &self.0
315 }
316
317 #[must_use]
323 #[inline]
324 pub unsafe fn get_mut(&mut self) -> &mut Inner {
325 &mut *<*mut _>::cast(self)
326 }
327
328 $($(if $signed)?
329 #[must_use]
331 #[inline]
332 pub fn abs(self) -> Self {
333 Self::new(self.get().abs()).expect("Absolute value out of range")
334 }
335 )*
336
337 #[must_use]
340 #[inline]
341 pub fn pow(self, exp: u32) -> Self {
342 Self::new(self.get().pow(exp)).expect("Value raised to power out of range")
343 }
344
345 #[must_use]
348 #[inline]
349 pub fn div_euclid(self, rhs: Inner) -> Self {
350 Self::new(self.get().div_euclid(rhs)).expect("Attempted to divide out of range")
351 }
352
353 #[must_use]
356 #[inline]
357 pub fn rem_euclid(self, rhs: Inner) -> Self {
358 Self::new(self.get().rem_euclid(rhs))
359 .expect("Attempted to divide with remainder out of range")
360 }
361
362 #[must_use]
364 #[inline]
365 pub const fn checked_add(self, rhs: Inner) -> Option<Self> {
366 match self.get().checked_add(rhs) {
367 Some(val) => Self::new(val),
368 None => None,
369 }
370 }
371
372 #[must_use]
374 #[inline]
375 pub const fn saturating_add(self, rhs: Inner) -> Self {
376 Self::new_saturating(self.get().saturating_add(rhs))
377 }
378
379 #[must_use]
381 #[inline]
382 pub const fn checked_sub(self, rhs: Inner) -> Option<Self> {
383 match self.get().checked_sub(rhs) {
384 Some(val) => Self::new(val),
385 None => None,
386 }
387 }
388
389 #[must_use]
391 #[inline]
392 pub const fn saturating_sub(self, rhs: Inner) -> Self {
393 Self::new_saturating(self.get().saturating_sub(rhs))
394 }
395
396 #[must_use]
398 #[inline]
399 pub const fn checked_mul(self, rhs: Inner) -> Option<Self> {
400 match self.get().checked_mul(rhs) {
401 Some(val) => Self::new(val),
402 None => None,
403 }
404 }
405
406 #[must_use]
408 #[inline]
409 pub const fn saturating_mul(self, rhs: Inner) -> Self {
410 Self::new_saturating(self.get().saturating_mul(rhs))
411 }
412
413 #[must_use]
415 #[inline]
416 pub const fn checked_div(self, rhs: Inner) -> Option<Self> {
417 match self.get().checked_div(rhs) {
418 Some(val) => Self::new(val),
419 None => None,
420 }
421 }
422
423 #[must_use]
425 #[inline]
426 pub const fn checked_div_euclid(self, rhs: Inner) -> Option<Self> {
427 match self.get().checked_div_euclid(rhs) {
428 Some(val) => Self::new(val),
429 None => None,
430 }
431 }
432
433 #[must_use]
435 #[inline]
436 pub const fn checked_rem(self, rhs: Inner) -> Option<Self> {
437 match self.get().checked_rem(rhs) {
438 Some(val) => Self::new(val),
439 None => None,
440 }
441 }
442
443 #[must_use]
445 #[inline]
446 pub const fn checked_rem_euclid(self, rhs: Inner) -> Option<Self> {
447 match self.get().checked_rem_euclid(rhs) {
448 Some(val) => Self::new(val),
449 None => None,
450 }
451 }
452
453 #[must_use]
455 #[inline]
456 pub const fn checked_neg(self) -> Option<Self> {
457 match self.get().checked_neg() {
458 Some(val) => Self::new(val),
459 None => None,
460 }
461 }
462
463 $($(if $signed)?
464 #[must_use]
466 #[inline]
467 pub const fn saturating_neg(self) -> Self {
468 Self::new_saturating(self.get().saturating_neg())
469 }
470
471 #[must_use]
473 #[inline]
474 pub const fn checked_abs(self) -> Option<Self> {
475 match self.get().checked_abs() {
476 Some(val) => Self::new(val),
477 None => None,
478 }
479 }
480
481 #[must_use]
483 #[inline]
484 pub const fn saturating_abs(self) -> Self {
485 Self::new_saturating(self.get().saturating_abs())
486 }
487 )*
488
489 #[must_use]
491 #[inline]
492 pub const fn checked_pow(self, rhs: u32) -> Option<Self> {
493 match self.get().checked_pow(rhs) {
494 Some(val) => Self::new(val),
495 None => None,
496 }
497 }
498
499 #[must_use]
501 #[inline]
502 pub const fn saturating_pow(self, rhs: u32) -> Self {
503 Self::new_saturating(self.get().saturating_pow(rhs))
504 }
505
506 #[must_use]
508 #[inline]
509 pub const fn checked_shl(self, rhs: u32) -> Option<Self> {
510 match self.get().checked_shl(rhs) {
511 Some(val) => Self::new(val),
512 None => None,
513 }
514 }
515
516 #[must_use]
518 #[inline]
519 pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
520 match self.get().checked_shr(rhs) {
521 Some(val) => Self::new(val),
522 None => None,
523 }
524 }
525 }
526
527 impl_bin_op!(Add::add/AddAssign::add_assign, "add");
530 impl_bin_op!(Sub::sub/SubAssign::sub_assign, "subtract");
531 impl_bin_op!(Mul::mul/MulAssign::mul_assign, "multiply");
532 impl_bin_op!(Div::div/DivAssign::div_assign, "divide");
533 impl_bin_op!(Rem::rem/RemAssign::rem_assign, "take remainder");
534 impl_bin_op!(BitAnd::bitand/BitAndAssign::bitand_assign, "binary and");
535 impl_bin_op!(BitOr::bitor/BitOrAssign::bitor_assign, "binary or");
536 impl_bin_op!(BitXor::bitxor/BitXorAssign::bitxor_assign, "binary xor");
537 impl_shift_bin_op!($inner, Shl::shl/ShlAssign::shl_assign, "shift left");
538 impl_shift_bin_op!($inner, Shr::shr/ShrAssign::shr_assign, "shift right");
539
540 $($(if $signed)?
541 use core::ops::Neg;
542
543 impl<const MIN: Inner, const MAX: Inner> Neg for Bounded<MIN, MAX> {
544 type Output = Self;
545 #[inline]
546 fn neg(self) -> Self::Output {
547 Self::new(-self.get())
548 .expect("Attempted to negate out of range")
549 }
550 }
551 impl<const MIN: Inner, const MAX: Inner> Neg for &Bounded<MIN, MAX> {
552 type Output = Bounded<MIN, MAX>;
553 #[inline]
554 fn neg(self) -> Self::Output {
555 -*self
556 }
557 }
558 )?
559
560 use core::ops::Not;
561
562 impl<const MIN: Inner, const MAX: Inner> Not for Bounded<MIN, MAX> {
563 type Output = Self;
564 #[inline]
565 fn not(self) -> Self::Output {
566 Self::new(!self.get())
567 .expect("Attempted to negate out of range")
568 }
569 }
570 impl<const MIN: Inner, const MAX: Inner> Not for &Bounded<MIN, MAX> {
571 type Output = Bounded<MIN, MAX>;
572 #[inline]
573 fn not(self) -> Self::Output {
574 !*self
575 }
576 }
577
578 impl<const MIN: Inner, const MAX: Inner> PartialEq<Inner> for Bounded<MIN, MAX> {
581 #[inline]
582 fn eq(&self, other: &Inner) -> bool {
583 self.get() == *other
584 }
585 }
586 impl<const MIN: Inner, const MAX: Inner> PartialEq<Bounded<MIN, MAX>> for Inner {
587 #[inline]
588 fn eq(&self, other: &Bounded<MIN, MAX>) -> bool {
589 *self == other.get()
590 }
591 }
592 impl<const A_MIN: Inner, const A_MAX: Inner, const B_MIN: Inner, const B_MAX: Inner>
593 PartialEq<Bounded<B_MIN, B_MAX>> for Bounded<A_MIN, A_MAX>
594 {
595 #[inline]
596 fn eq(&self, other: &Bounded<B_MIN, B_MAX>) -> bool {
597 self.get() == other.get()
598 }
599 }
600
601 impl<const MIN: Inner, const MAX: Inner> PartialOrd<Inner> for Bounded<MIN, MAX> {
602 #[inline]
603 fn partial_cmp(&self, other: &Inner) -> Option<cmp::Ordering> {
604 self.get().partial_cmp(other)
605 }
606 }
607 impl<const MIN: Inner, const MAX: Inner> PartialOrd<Bounded<MIN, MAX>> for Inner {
608 #[inline]
609 fn partial_cmp(&self, other: &Bounded<MIN, MAX>) -> Option<cmp::Ordering> {
610 self.partial_cmp(&other.get())
611 }
612 }
613 impl<const A_MIN: Inner, const A_MAX: Inner, const B_MIN: Inner, const B_MAX: Inner>
614 PartialOrd<Bounded<B_MIN, B_MAX>> for Bounded<A_MIN, A_MAX>
615 {
616 #[inline]
617 fn partial_cmp(&self, other: &Bounded<B_MIN, B_MAX>) -> Option<cmp::Ordering> {
618 self.get().partial_cmp(&other.get())
619 }
620 }
621
622 impl<const MIN: Inner, const MAX: Inner> AsRef<Inner> for Bounded<MIN, MAX> {
625 #[inline]
626 fn as_ref(&self) -> &Inner {
627 self.get_ref()
628 }
629 }
630 impl<const MIN: Inner, const MAX: Inner> Borrow<Inner> for Bounded<MIN, MAX> {
631 #[inline]
632 fn borrow(&self) -> &Inner {
633 self.get_ref()
634 }
635 }
636
637 impl<const MIN: Inner, const MAX: Inner> iter::Sum for Bounded<MIN, MAX> {
641 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
642 iter.reduce(Add::add)
643 .unwrap_or_else(|| Self::new(0).expect("Attempted to sum to zero"))
644 }
645 }
646 impl<'a, const MIN: Inner, const MAX: Inner> iter::Sum<&'a Self> for Bounded<MIN, MAX> {
647 fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
648 iter.copied().sum()
649 }
650 }
651
652 impl<const MIN: Inner, const MAX: Inner> iter::Sum<Bounded<MIN, MAX>> for Inner {
654 fn sum<I: Iterator<Item = Bounded<MIN, MAX>>>(iter: I) -> Self {
655 iter.map(Bounded::get).sum()
656 }
657 }
658 impl<'a, const MIN: Inner, const MAX: Inner> iter::Sum<&'a Bounded<MIN, MAX>> for Inner {
659 fn sum<I: Iterator<Item = &'a Bounded<MIN, MAX>>>(iter: I) -> Self {
660 iter.copied().sum()
661 }
662 }
663
664 impl<const MIN: Inner, const MAX: Inner> iter::Product for Bounded<MIN, MAX> {
666 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
667 iter.reduce(Mul::mul)
668 .unwrap_or_else(|| Self::new(1).expect("Attempted to take product to one"))
669 }
670 }
671 impl<'a, const MIN: Inner, const MAX: Inner> iter::Product<&'a Self> for Bounded<MIN, MAX> {
672 fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
673 iter.copied().product()
674 }
675 }
676
677 impl<const MIN: Inner, const MAX: Inner> iter::Product<Bounded<MIN, MAX>> for Inner {
679 fn product<I: Iterator<Item = Bounded<MIN, MAX>>>(iter: I) -> Self {
680 iter.map(Bounded::get).product()
681 }
682 }
683 impl<'a, const MIN: Inner, const MAX: Inner> iter::Product<&'a Bounded<MIN, MAX>> for Inner {
684 fn product<I: Iterator<Item = &'a Bounded<MIN, MAX>>>(iter: I) -> Self {
685 iter.copied().product()
686 }
687 }
688
689 #[cfg(feature = "step_trait")]
690 #[cfg_attr(doc_cfg, doc(cfg(feature = "step_trait")))]
691 impl<const MIN: Inner, const MAX: Inner> iter::Step for Bounded<MIN, MAX> {
692 #[inline]
693 fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
694 iter::Step::steps_between(&start.get(), &end.get())
695 }
696 #[inline]
697 fn forward_checked(start: Self, count: usize) -> Option<Self> {
698 iter::Step::forward_checked(start.get(), count).and_then(Self::new)
699 }
700 #[inline]
701 fn backward_checked(start: Self, count: usize) -> Option<Self> {
702 iter::Step::backward_checked(start.get(), count).and_then(Self::new)
703 }
704 }
705
706 impl<const MIN: Inner, const MAX: Inner> FromStr for Bounded<MIN, MAX> {
709 type Err = ParseError;
710
711 fn from_str(s: &str) -> Result<Self, Self::Err> {
712 Self::from_str_radix(s, 10)
713 }
714 }
715
716 impl_fmt_traits!(Binary, Display, LowerExp, LowerHex, Octal, UpperExp, UpperHex);
719
720 #[cfg(feature = "arbitrary1")]
723 use arbitrary1::{Arbitrary, Unstructured};
724
725 #[cfg(feature = "arbitrary1")]
726 #[cfg_attr(doc_cfg, doc(cfg(feature = "arbitrary1")))]
727 impl<'a, const MIN: Inner, const MAX: Inner> Arbitrary<'a> for Bounded<MIN, MAX> {
728 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary1::Result<Self> {
729 Self::new(u.arbitrary()?).ok_or(arbitrary1::Error::IncorrectFormat)
730 }
731
732 #[inline]
733 fn size_hint(depth: usize) -> (usize, Option<usize>) {
734 <Inner as Arbitrary<'a>>::size_hint(depth)
735 }
736 }
737
738 #[cfg(feature = "bytemuck1")]
741 #[cfg_attr(doc_cfg, doc(cfg(feature = "bytemuck1")))]
742 unsafe impl<const MIN: Inner, const MAX: Inner> bytemuck1::Contiguous for Bounded<MIN, MAX> {
743 type Int = Inner;
744 const MAX_VALUE: Inner = MAX;
745 const MIN_VALUE: Inner = MIN;
746 }
747
748 #[cfg(feature = "num-traits02")]
751 #[cfg_attr(doc_cfg, doc(cfg(feature = "num-traits02")))]
752 impl<const MIN: Inner, const MAX: Inner> num_traits02::Bounded for Bounded<MIN, MAX> {
753 fn min_value() -> Self {
754 Self::MIN
755 }
756
757 fn max_value() -> Self {
758 Self::MAX
759 }
760 }
761
762 #[cfg(feature = "num-traits02")]
763 #[cfg_attr(doc_cfg, doc(cfg(feature = "num-traits02")))]
764 impl<T, const MIN: Inner, const MAX: Inner> num_traits02::AsPrimitive<T>
765 for Bounded<MIN, MAX>
766 where
767 Inner: num_traits02::AsPrimitive<T>,
768 T: 'static + Copy,
769 {
770 fn as_(self) -> T {
771 self.get().as_()
772 }
773 }
774
775 #[cfg(feature = "num-traits02")]
776 #[cfg_attr(doc_cfg, doc(cfg(feature = "num-traits02")))]
777 impl<const MIN: Inner, const MAX: Inner> num_traits02::FromPrimitive for Bounded<MIN, MAX>
778 where
779 Inner: num_traits02::FromPrimitive,
780 {
781 fn from_i64(n: i64) -> Option<Self> {
782 Inner::from_i64(n)
783 .map(Self::new)
784 .flatten()
785 }
786
787 fn from_u64(n: u64) -> Option<Self> {
788 Inner::from_u64(n)
789 .map(Self::new)
790 .flatten()
791 }
792
793 fn from_isize(n: isize) -> Option<Self> {
794 Inner::from_isize(n)
795 .map(Self::new)
796 .flatten()
797 }
798
799 fn from_i8(n: i8) -> Option<Self> {
800 Inner::from_i8(n)
801 .map(Self::new)
802 .flatten()
803 }
804
805 fn from_i16(n: i16) -> Option<Self> {
806 Inner::from_i16(n)
807 .map(Self::new)
808 .flatten()
809 }
810
811 fn from_i32(n: i32) -> Option<Self> {
812 Inner::from_i32(n)
813 .map(Self::new)
814 .flatten()
815 }
816
817 fn from_i128(n: i128) -> Option<Self> {
818 Inner::from_i128(n)
819 .map(Self::new)
820 .flatten()
821 }
822
823 fn from_usize(n: usize) -> Option<Self> {
824 Inner::from_usize(n)
825 .map(Self::new)
826 .flatten()
827 }
828
829 fn from_u8(n: u8) -> Option<Self> {
830 Inner::from_u8(n)
831 .map(Self::new)
832 .flatten()
833 }
834
835 fn from_u16(n: u16) -> Option<Self> {
836 Inner::from_u16(n)
837 .map(Self::new)
838 .flatten()
839 }
840
841 fn from_u32(n: u32) -> Option<Self> {
842 Inner::from_u32(n)
843 .map(Self::new)
844 .flatten()
845 }
846
847 fn from_u128(n: u128) -> Option<Self> {
848 Inner::from_u128(n)
849 .map(Self::new)
850 .flatten()
851 }
852
853 fn from_f32(n: f32) -> Option<Self> {
854 Inner::from_f32(n)
855 .map(Self::new)
856 .flatten()
857 }
858
859 fn from_f64(n: f64) -> Option<Self> {
860 Inner::from_f64(n)
861 .map(Self::new)
862 .flatten()
863 }
864 }
865
866 #[cfg(feature = "num-traits02")]
867 #[cfg_attr(doc_cfg, doc(cfg(feature = "num-traits02")))]
868 impl<const MIN: Inner, const MAX: Inner> num_traits02::NumCast for Bounded<MIN, MAX>
869 where
870 Inner: num_traits02::NumCast,
871 {
872 fn from<T: num_traits02::ToPrimitive>(n: T) -> Option<Self> {
873 <Inner as num_traits02::NumCast>::from(n).map(Self::new).flatten()
874 }
875 }
876
877 #[cfg(feature = "num-traits02")]
878 #[cfg_attr(doc_cfg, doc(cfg(feature = "num-traits02")))]
879 impl<const MIN: Inner, const MAX: Inner> num_traits02::ToPrimitive for Bounded<MIN, MAX>
880 where
881 Inner: num_traits02::ToPrimitive,
882 {
883 fn to_i64(&self) -> Option<i64> {
884 self.get().to_i64()
885 }
886
887 fn to_u64(&self) -> Option<u64> {
888 self.get().to_u64()
889 }
890
891 fn to_isize(&self) -> Option<isize> {
892 self.get().to_isize()
893 }
894
895 fn to_i8(&self) -> Option<i8> {
896 self.get().to_i8()
897 }
898
899 fn to_i16(&self) -> Option<i16> {
900 self.get().to_i16()
901 }
902
903 fn to_i32(&self) -> Option<i32> {
904 self.get().to_i32()
905 }
906
907 fn to_i128(&self) -> Option<i128> {
908 self.get().to_i128()
909 }
910
911 fn to_usize(&self) -> Option<usize> {
912 self.get().to_usize()
913 }
914
915 fn to_u8(&self) -> Option<u8> {
916 self.get().to_u8()
917 }
918
919 fn to_u16(&self) -> Option<u16> {
920 self.get().to_u16()
921 }
922
923 fn to_u32(&self) -> Option<u32> {
924 self.get().to_u32()
925 }
926
927 fn to_u128(&self) -> Option<u128> {
928 self.get().to_u128()
929 }
930
931 fn to_f32(&self) -> Option<f32> {
932 self.get().to_f32()
933 }
934
935 fn to_f64(&self) -> Option<f64> {
936 self.get().to_f64()
937 }
938 }
939
940 #[cfg(feature = "num-traits02")]
941 #[cfg_attr(doc_cfg, doc(cfg(feature = "num-traits02")))]
942 impl<const MIN: Inner, const MAX: Inner> num_traits02::CheckedAdd for Bounded<MIN, MAX> {
943 fn checked_add(&self, v: &Self) -> Option<Self> {
944 Self::checked_add(*self, v.get())
945 }
946 }
947
948 #[cfg(feature = "num-traits02")]
949 #[cfg_attr(doc_cfg, doc(cfg(feature = "num-traits02")))]
950 impl<const MIN: Inner, const MAX: Inner> num_traits02::CheckedDiv for Bounded<MIN, MAX> {
951 fn checked_div(&self, v: &Self) -> Option<Self> {
952 Self::checked_div(*self, v.get())
953 }
954 }
955
956 #[cfg(feature = "num-traits02")]
957 #[cfg_attr(doc_cfg, doc(cfg(feature = "num-traits02")))]
958 impl<const MIN: Inner, const MAX: Inner> num_traits02::CheckedMul for Bounded<MIN, MAX> {
959 fn checked_mul(&self, v: &Self) -> Option<Self> {
960 Self::checked_mul(*self, v.get())
961 }
962 }
963
964 #[cfg(feature = "num-traits02")]
965 #[cfg_attr(doc_cfg, doc(cfg(feature = "num-traits02")))]
966 impl<const MIN: Inner, const MAX: Inner> num_traits02::CheckedNeg for Bounded<MIN, MAX> {
967 fn checked_neg(&self) -> Option<Self> {
968 Self::checked_neg(*self)
969 }
970 }
971
972 #[cfg(feature = "num-traits02")]
973 #[cfg_attr(doc_cfg, doc(cfg(feature = "num-traits02")))]
974 impl<const MIN: Inner, const MAX: Inner> num_traits02::CheckedRem for Bounded<MIN, MAX> {
975 fn checked_rem(&self, v: &Self) -> Option<Self> {
976 Self::checked_rem(*self, v.get())
977 }
978 }
979
980 #[cfg(feature = "num-traits02")]
981 #[cfg_attr(doc_cfg, doc(cfg(feature = "num-traits02")))]
982 impl<const MIN: Inner, const MAX: Inner> num_traits02::CheckedShl for Bounded<MIN, MAX> {
983 fn checked_shl(&self, v: u32) -> Option<Self> {
984 Self::checked_shl(*self, v)
985 }
986 }
987
988 #[cfg(feature = "num-traits02")]
989 #[cfg_attr(doc_cfg, doc(cfg(feature = "num-traits02")))]
990 impl<const MIN: Inner, const MAX: Inner> num_traits02::CheckedShr for Bounded<MIN, MAX> {
991 fn checked_shr(&self, v: u32) -> Option<Self> {
992 Self::checked_shr(*self, v)
993 }
994 }
995
996 #[cfg(feature = "num-traits02")]
997 #[cfg_attr(doc_cfg, doc(cfg(feature = "num-traits02")))]
998 impl<const MIN: Inner, const MAX: Inner> num_traits02::CheckedSub for Bounded<MIN, MAX> {
999 fn checked_sub(&self, v: &Self) -> Option<Self> {
1000 Self::checked_sub(*self, v.get())
1001 }
1002 }
1003
1004 #[cfg(feature = "num-traits02")]
1005 #[cfg_attr(doc_cfg, doc(cfg(feature = "num-traits02")))]
1006 impl<A, B, const MIN: Inner, const MAX: Inner> num_traits02::MulAdd<A, B>
1007 for Bounded<MIN, MAX>
1008 where
1009 Inner: num_traits02::MulAdd<A, B, Output = Inner>,
1010 {
1011 type Output = Inner;
1012
1013 fn mul_add(self, a: A, b: B) -> Self::Output {
1014 self.get().mul_add(a, b)
1015 }
1016 }
1017
1018 #[cfg(feature = "num-traits02")]
1019 #[cfg_attr(doc_cfg, doc(cfg(feature = "num-traits02")))]
1020 impl<const MIN: Inner, const MAX: Inner> num_traits02::SaturatingAdd for Bounded<MIN, MAX> {
1021 fn saturating_add(&self, v: &Self) -> Self {
1022 Self::saturating_add(*self, v.get())
1023 }
1024 }
1025
1026 #[cfg(feature = "num-traits02")]
1027 #[cfg_attr(doc_cfg, doc(cfg(feature = "num-traits02")))]
1028 impl<const MIN: Inner, const MAX: Inner> num_traits02::SaturatingMul for Bounded<MIN, MAX> {
1029 fn saturating_mul(&self, v: &Self) -> Self {
1030 Self::saturating_mul(*self, v.get())
1031 }
1032 }
1033
1034 #[cfg(feature = "num-traits02")]
1035 #[cfg_attr(doc_cfg, doc(cfg(feature = "num-traits02")))]
1036 impl<const MIN: Inner, const MAX: Inner> num_traits02::SaturatingSub for Bounded<MIN, MAX> {
1037 fn saturating_sub(&self, v: &Self) -> Self {
1038 Self::saturating_sub(*self, v.get())
1039 }
1040 }
1041
1042 #[cfg(feature = "serde1")]
1045 use serde1::{de::Error as _, Deserialize, Deserializer, Serialize, Serializer};
1046
1047 #[cfg(feature = "serde1")]
1048 #[cfg_attr(doc_cfg, doc(cfg(feature = "serde1")))]
1049 impl<const MIN: Inner, const MAX: Inner> Serialize for Bounded<MIN, MAX> {
1050 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1051 self.get().serialize(serializer)
1052 }
1053 }
1054
1055 #[cfg(feature = "serde1")]
1056 #[cfg_attr(doc_cfg, doc(cfg(feature = "serde1")))]
1057 impl<'de, const MIN: Inner, const MAX: Inner> Deserialize<'de> for Bounded<MIN, MAX> {
1058 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
1059 Self::new(Inner::deserialize(deserializer)?)
1060 .ok_or_else(|| {
1061 D::Error::custom(format_args!(
1062 "integer out of range, expected it to be between {} and {}",
1063 Self::MIN_VALUE,
1064 Self::MAX_VALUE,
1065 ))
1066 })
1067 }
1068 }
1069
1070 $(impl<const MIN: Inner, const MAX: Inner> From<Bounded<MIN, MAX>> for $into {
1073 fn from(bounded: Bounded<MIN, MAX>) -> Self {
1074 Self::from(bounded.get())
1075 }
1076 })*
1077
1078 #[cfg(test)]
1081 mod tests {
1082 use super::Inner;
1083
1084 #[cfg(feature = "std")]
1085 use std::format;
1086
1087 #[test]
1088 fn range() {
1089 type Bounded = super::Bounded<3, 10>;
1090 assert_eq!(Bounded::MIN_VALUE, 3);
1091 assert_eq!(Bounded::MAX_VALUE, 10);
1092 assert_eq!(Bounded::MIN.get(), Bounded::MIN_VALUE);
1093 assert_eq!(Bounded::MAX.get(), Bounded::MAX_VALUE);
1094
1095 assert!(Bounded::in_range(3));
1096 assert!(!Bounded::in_range(2));
1097 assert!(Bounded::in_range(10));
1098 assert!(!Bounded::in_range(11));
1099 }
1100
1101 #[test]
1102 fn saturating() {
1103 type Bounded = super::Bounded<3, 10>;
1104 assert_eq!(Bounded::new_saturating(Inner::MIN), Bounded::MIN);
1105 assert_eq!(Bounded::new_saturating(Inner::MAX), Bounded::MAX);
1106 assert_eq!(Bounded::new_saturating(11).get(), 10);
1107 assert_eq!(Bounded::new_saturating(10).get(), 10);
1108 assert_eq!(Bounded::new_saturating(3).get(), 3);
1109 assert_eq!(Bounded::new_saturating(2).get(), 3);
1110 }
1111
1112 #[test]
1113 fn arithmetic() {
1114 if false {
1115 type Bounded = super::Bounded<0, 15>;
1116 test_arithmetic! {
1117 $($(if $signed)? signed)?
1118 ops(+ += - -= * *= / /= % %=)
1119 infallibles(
1120 pow
1121 div_euclid
1122 rem_euclid
1123 saturating_add
1124 saturating_sub
1125 saturating_mul
1126 saturating_pow
1127 )
1128 fallibles(
1129 checked_add
1130 checked_sub
1131 checked_mul
1132 checked_div
1133 checked_div_euclid
1134 checked_rem
1135 checked_rem_euclid
1136 checked_pow
1137 checked_shl
1138 checked_shr
1139 )
1140 }
1141 }
1142 }
1143
1144 #[test]
1145 fn iter() {
1146 type Bounded = super::Bounded<{ 0 $($(if $signed)? - 8)? }, 8>;
1147
1148 fn b(&n: &Inner) -> Bounded {
1149 Bounded::new(n).unwrap()
1150 }
1151
1152 assert_eq!([3, 2, 1].iter().map(b).sum::<Bounded>().get(), 6);
1153 $($(if $signed)? assert_eq!([-8, 3, 7, 5, -2].iter().map(b).sum::<Bounded>().get(), 5);)?
1154 assert_eq!([7, 6, 4].iter().map(b).sum::<Inner>(), 17);
1155 $($(if $signed)? assert_eq!([-8, 3, 7, 5, -2].iter().map(b).sum::<Inner>(), 5);)?
1156
1157 assert_eq!([1, 3, 2, 1].iter().map(b).product::<Bounded>().get(), 6);
1158 assert_eq!([1, 3, 2, 1, 0].iter().map(b).product::<Bounded>().get(), 0);
1159 $($(if $signed)? assert_eq!([-2, -3, -1].iter().map(b).product::<Bounded>().get(), -6);)?
1160 assert_eq!([3, 3].iter().map(b).product::<Inner>(), 9);
1161 }
1162
1163 #[test]
1164 fn parse() {
1165 use crate::ParseErrorKind::*;
1166
1167 type Bounded = super::Bounded<3, 11>;
1168
1169 assert_eq!("3".parse::<Bounded>().unwrap().get(), 3);
1170 assert_eq!("10".parse::<Bounded>().unwrap().get(), 10);
1171 assert_eq!("+11".parse::<Bounded>().unwrap().get(), 11);
1172 assert_eq!(Bounded::from_str_radix("1010", 2).unwrap().get(), 10);
1173 assert_eq!(Bounded::from_str_radix("B", 0xC).unwrap().get(), 11);
1174 assert_eq!(Bounded::from_str_radix("11", 7).unwrap().get(), 8);
1175 assert_eq!(Bounded::from_str_radix("7", 36).unwrap().get(), 7);
1176
1177 assert_eq!("".parse::<Bounded>().unwrap_err().kind(), NoDigits);
1178 assert_eq!("+".parse::<Bounded>().unwrap_err().kind(), NoDigits);
1179 assert_eq!("-".parse::<Bounded>().unwrap_err().kind(), NoDigits);
1180 assert_eq!("2".parse::<Bounded>().unwrap_err().kind(), BelowMin);
1181 assert_eq!("12".parse::<Bounded>().unwrap_err().kind(), AboveMax);
1182 assert_eq!("-5".parse::<Bounded>().unwrap_err().kind(), BelowMin);
1183 #[cfg(feature = "std")]
1184 assert_eq!(
1185 format!("{}00", Inner::MAX).parse::<Bounded>().unwrap_err().kind(),
1186 AboveMax
1187 );
1188 #[cfg(feature = "std")]
1189 assert_eq!(
1190 format!("{}00", Inner::MIN).parse::<Bounded>().unwrap_err().kind(),
1191 BelowMin
1192 );
1193
1194 assert_eq!("++0".parse::<Bounded>().unwrap_err().kind(), InvalidDigit);
1195 assert_eq!("--0".parse::<Bounded>().unwrap_err().kind(), InvalidDigit);
1196 assert_eq!("O".parse::<Bounded>().unwrap_err().kind(), InvalidDigit);
1197 assert_eq!("C".parse::<Bounded>().unwrap_err().kind(), InvalidDigit);
1198 assert_eq!(Bounded::from_str_radix("3", 2).unwrap_err().kind(), InvalidDigit);
1199 }
1200
1201 #[test]
1202 #[cfg(feature = "num-traits02")]
1203 fn num() {
1204 use num_traits02::{
1205 Bounded, AsPrimitive, FromPrimitive, NumCast, ToPrimitive, CheckedAdd,
1206 CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedSub, CheckedShl, CheckedShr
1207 };
1208
1209 type B = super::Bounded<2, 8>;
1210 type BNeg = super::Bounded<{0 $($(if $signed)? - 4)?}, 8>;
1211
1212 fn b(n: Inner) -> B {
1213 B::new(n).unwrap()
1214 }
1215
1216 fn bneg(n: Inner) -> BNeg {
1217 BNeg::new(n).unwrap()
1218 }
1219
1220 assert_eq!(B::min_value(), 2);
1221 assert_eq!(B::max_value(), 8);
1222
1223 assert_eq!(BNeg::min_value(), 0 $($(if $signed)? - 4)?);
1224 assert_eq!(BNeg::max_value(), 8);
1225
1226 assert_eq!(<B as AsPrimitive<u8>>::as_(b(4)), 4u8);
1227 assert_eq!(<B as AsPrimitive<u16>>::as_(b(4)), 4u16);
1228 assert_eq!(<B as AsPrimitive<u32>>::as_(b(4)), 4u32);
1229 assert_eq!(<B as AsPrimitive<u64>>::as_(b(4)), 4u64);
1230 assert_eq!(<B as AsPrimitive<u128>>::as_(b(4)), 4u128);
1231 assert_eq!(<B as AsPrimitive<usize>>::as_(b(4)), 4usize);
1232 assert_eq!(<B as AsPrimitive<i8>>::as_(b(4)), 4i8);
1233 assert_eq!(<B as AsPrimitive<i16>>::as_(b(4)), 4i16);
1234 assert_eq!(<B as AsPrimitive<i32>>::as_(b(4)), 4i32);
1235 assert_eq!(<B as AsPrimitive<i64>>::as_(b(4)), 4i64);
1236 assert_eq!(<B as AsPrimitive<i128>>::as_(b(4)), 4i128);
1237 assert_eq!(<B as AsPrimitive<isize>>::as_(b(4)), 4isize);
1238 assert_eq!(<B as AsPrimitive<f32>>::as_(b(4)), 4f32);
1239 assert_eq!(<B as AsPrimitive<f64>>::as_(b(4)), 4f64);
1240
1241 assert_eq!(B::from_u8(4u8), Some(b(4)));
1242 assert_eq!(B::from_u16(4u16), Some(b(4)));
1243 assert_eq!(B::from_u32(4u32), Some(b(4)));
1244 assert_eq!(B::from_u64(4u64), Some(b(4)));
1245 assert_eq!(B::from_u128(4u128), Some(b(4)));
1246 assert_eq!(B::from_usize(4usize), Some(b(4)));
1247 assert_eq!(B::from_i8(4i8), Some(b(4)));
1248 assert_eq!(B::from_i16(4i16), Some(b(4)));
1249 assert_eq!(B::from_i32(4i32), Some(b(4)));
1250 assert_eq!(B::from_i64(4i64), Some(b(4)));
1251 assert_eq!(B::from_i128(4i128), Some(b(4)));
1252 assert_eq!(B::from_isize(4isize), Some(b(4)));
1253 assert_eq!(B::from_f32(4f32), Some(b(4)));
1254 assert_eq!(B::from_f64(4f64), Some(b(4)));
1255
1256 assert_eq!(B::from_u8(16u8), None);
1257 assert_eq!(B::from_u16(16u16), None);
1258 assert_eq!(B::from_u32(16u32), None);
1259 assert_eq!(B::from_u64(16u64), None);
1260 assert_eq!(B::from_u128(16u128), None);
1261 assert_eq!(B::from_usize(16usize), None);
1262 assert_eq!(B::from_i8(16i8), None);
1263 assert_eq!(B::from_i16(16i16), None);
1264 assert_eq!(B::from_i32(16i32), None);
1265 assert_eq!(B::from_i64(16i64), None);
1266 assert_eq!(B::from_i128(16i128), None);
1267 assert_eq!(B::from_isize(16isize), None);
1268 assert_eq!(B::from_f32(16f32), None);
1269 assert_eq!(B::from_f64(16f64), None);
1270
1271 assert_eq!(<B as NumCast>::from(4u8), Some(b(4)));
1272 assert_eq!(<B as NumCast>::from(4u16), Some(b(4)));
1273 assert_eq!(<B as NumCast>::from(4u32), Some(b(4)));
1274 assert_eq!(<B as NumCast>::from(4u64), Some(b(4)));
1275 assert_eq!(<B as NumCast>::from(4u128), Some(b(4)));
1276 assert_eq!(<B as NumCast>::from(4usize), Some(b(4)));
1277 assert_eq!(<B as NumCast>::from(4i8), Some(b(4)));
1278 assert_eq!(<B as NumCast>::from(4i16), Some(b(4)));
1279 assert_eq!(<B as NumCast>::from(4i32), Some(b(4)));
1280 assert_eq!(<B as NumCast>::from(4i64), Some(b(4)));
1281 assert_eq!(<B as NumCast>::from(4i128), Some(b(4)));
1282 assert_eq!(<B as NumCast>::from(4isize), Some(b(4)));
1283 assert_eq!(<B as NumCast>::from(4f32), Some(b(4)));
1284 assert_eq!(<B as NumCast>::from(4f64), Some(b(4)));
1285
1286 assert_eq!(<B as NumCast>::from(16u8), None);
1287 assert_eq!(<B as NumCast>::from(16u16), None);
1288 assert_eq!(<B as NumCast>::from(16u32), None);
1289 assert_eq!(<B as NumCast>::from(16u64), None);
1290 assert_eq!(<B as NumCast>::from(16u128), None);
1291 assert_eq!(<B as NumCast>::from(16usize), None);
1292 assert_eq!(<B as NumCast>::from(16i8), None);
1293 assert_eq!(<B as NumCast>::from(16i16), None);
1294 assert_eq!(<B as NumCast>::from(16i32), None);
1295 assert_eq!(<B as NumCast>::from(16i64), None);
1296 assert_eq!(<B as NumCast>::from(16i128), None);
1297 assert_eq!(<B as NumCast>::from(16isize), None);
1298 assert_eq!(<B as NumCast>::from(16f32), None);
1299 assert_eq!(<B as NumCast>::from(16f64), None);
1300
1301 assert_eq!(b(4).to_u8(), Some(4u8));
1302 assert_eq!(b(4).to_u16(), Some(4u16));
1303 assert_eq!(b(4).to_u32(), Some(4u32));
1304 assert_eq!(b(4).to_u64(), Some(4u64));
1305 assert_eq!(b(4).to_u128(), Some(4u128));
1306 assert_eq!(b(4).to_usize(), Some(4usize));
1307 assert_eq!(b(4).to_i8(), Some(4i8));
1308 assert_eq!(b(4).to_i16(), Some(4i16));
1309 assert_eq!(b(4).to_i32(), Some(4i32));
1310 assert_eq!(b(4).to_i64(), Some(4i64));
1311 assert_eq!(b(4).to_i128(), Some(4i128));
1312 assert_eq!(b(4).to_isize(), Some(4isize));
1313 assert_eq!(b(4).to_f32(), Some(4f32));
1314 assert_eq!(b(4).to_f64(), Some(4f64));
1315
1316 assert_eq!(<B as CheckedAdd>::checked_add(&b(4), &b(4)), Some(b(8)));
1317 assert_eq!(<B as CheckedAdd>::checked_add(&b(4), &b(8)), None);
1318
1319 assert_eq!(<B as CheckedDiv>::checked_div(&b(8), &b(2)), Some(b(4)));
1320 assert_eq!(<B as CheckedDiv>::checked_div(&b(4), &b(4)), None);
1321
1322 assert_eq!(<B as CheckedMul>::checked_mul(&b(2), &b(2)), Some(b(4)));
1323 assert_eq!(<B as CheckedMul>::checked_mul(&b(2), &b(8)), None);
1324
1325 $($(if $signed)? {
1326 assert_eq!(<BNeg as CheckedNeg>::checked_neg(&bneg(2)), Some(bneg(-2)));
1327 })?
1328
1329 assert_eq!(<BNeg as CheckedNeg>::checked_neg(&bneg(8)), None);
1330
1331 assert_eq!(<B as CheckedRem>::checked_rem(&b(8), &b(6)), Some(b(2)));
1332 assert_eq!(<B as CheckedRem>::checked_rem(&b(8), &b(7)), None);
1333
1334 assert_eq!(<B as CheckedSub>::checked_sub(&b(4), &b(2)), Some(b(2)));
1335 assert_eq!(<B as CheckedSub>::checked_sub(&b(4), &b(4)), None);
1336
1337 assert_eq!(<B as CheckedShl>::checked_shl(&b(4), 1u32), Some(b(8)));
1338 assert_eq!(<B as CheckedShl>::checked_shl(&b(4), 2u32), None);
1339
1340 assert_eq!(<B as CheckedShr>::checked_shr(&b(4), 1u32), Some(b(2)));
1341 assert_eq!(<B as CheckedShr>::checked_shr(&b(4), 2u32), None);
1342 }
1343 }
1344 } pub use self::$inner::Bounded as $name; )* }
1345}
1346
1347define_bounded_integers! {
1348 BoundedU8 u8 -> u8 u16 u32 u64 u128 usize i16 i32 i64 i128 isize,
1349 BoundedU16 u16 -> u16 u32 u64 u128 usize i32 i64 i128,
1350 BoundedU32 u32 -> u32 u64 u128 i64 i128,
1351 BoundedU64 u64 -> u64 u128 i128,
1352 BoundedU128 u128 -> u128,
1353 BoundedUsize usize -> usize,
1354 BoundedI8 i8 signed -> i8 i16 i32 i64 i128 isize,
1355 BoundedI16 i16 signed -> i16 i32 i64 i128 isize,
1356 BoundedI32 i32 signed -> i32 i64 i128,
1357 BoundedI64 i64 signed -> i64 i128,
1358 BoundedI128 i128 signed -> i128,
1359 BoundedIsize isize signed -> isize,
1360}
1361
1362mod indexing;