1#![no_std]
16
17use core::convert::TryFrom;
18use core::fmt::{self, Binary, Display, LowerHex, Octal, UpperHex};
19use core::hash::Hash;
20use core::marker::PhantomData;
21use core::num::NonZero;
22use core::ops::{
23 Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Rem, RemAssign, Sub, SubAssign,
24};
25
26#[cfg(feature = "alloc")]
27extern crate alloc;
28
29#[macro_export]
55macro_rules! non_max {
56 ($val:expr) => {{
57 const _: () = const {
58 if $val == <_ as $crate::NonMaxItem>::MAX {
59 panic!("provided value is the maximum value for this type");
60 }
61 };
62 unsafe { <_ as $crate::NonMaxItem>::create_nonmax_unchecked($val) }
63 }};
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub struct MaxValueError;
69
70impl Display for MaxValueError {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 write!(f, "provided value is the maximum value for this type")
73 }
74}
75
76impl core::error::Error for MaxValueError {}
77
78#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
91pub struct NonMax<T: NonMaxItem>(T::NonZero);
92
93impl<T: NonMaxItem + Copy> NonMax<T> {
94 pub fn new(value: T) -> Option<Self> {
103 Value::new(value).to_inner_repr().to_nonmax()
104 }
105
106 fn to_real_repr(self) -> Value<T, Real> {
107 T::from_nonzero(self.0).to_real_repr()
108 }
109
110 pub fn get(&self) -> T {
119 self.to_real_repr().value()
120 }
121}
122
123impl<T: NonMaxItem + Copy + PartialEq> NonMax<T> {
124 pub fn is_min(&self) -> bool {
126 self.get() == T::MIN_VALUE
127 }
128
129 pub fn is_max(&self) -> bool {
131 self.get() == T::MAX_SAFE
132 }
133
134 pub fn is_zero(&self) -> bool {
136 self.get() == T::ZERO_VALUE
137 }
138}
139
140impl<T: NonMaxItem + Copy> NonMax<T> {
141 pub fn checked_add(self, rhs: Self) -> Option<Self> {
144 self.get().checked_add(rhs.get()).and_then(Self::new)
145 }
146
147 pub fn checked_sub(self, rhs: Self) -> Option<Self> {
150 self.get().checked_sub(rhs.get()).and_then(Self::new)
151 }
152
153 pub fn checked_mul(self, rhs: Self) -> Option<Self> {
156 self.get().checked_mul(rhs.get()).and_then(Self::new)
157 }
158
159 pub fn checked_div(self, rhs: Self) -> Option<Self> {
162 self.get().checked_div(rhs.get()).and_then(Self::new)
163 }
164
165 pub fn checked_rem(self, rhs: Self) -> Option<Self> {
168 self.get().checked_rem(rhs.get()).and_then(Self::new)
169 }
170
171 pub fn checked_add_val(self, rhs: T) -> Option<Self> {
181 self.get().checked_add(rhs).and_then(Self::new)
182 }
183
184 pub fn checked_sub_val(self, rhs: T) -> Option<Self> {
186 self.get().checked_sub(rhs).and_then(Self::new)
187 }
188
189 pub fn checked_mul_val(self, rhs: T) -> Option<Self> {
191 self.get().checked_mul(rhs).and_then(Self::new)
192 }
193
194 pub fn checked_div_val(self, rhs: T) -> Option<Self> {
196 self.get().checked_div(rhs).and_then(Self::new)
197 }
198
199 pub fn checked_rem_val(self, rhs: T) -> Option<Self> {
201 self.get().checked_rem(rhs).and_then(Self::new)
202 }
203}
204
205impl<T: NonMaxItem + Copy + Add<Output = T>> Add for NonMax<T> {
206 type Output = Self;
207 fn add(self, rhs: Self) -> Self::Output {
208 self.checked_add(rhs)
209 .expect("attempt to add with overflow or to maximum value")
210 }
211}
212
213impl<T: NonMaxItem + Copy + Add<Output = T>> Add<T> for NonMax<T> {
214 type Output = Self;
215 fn add(self, rhs: T) -> Self::Output {
216 self.checked_add_val(rhs)
217 .expect("attempt to add with overflow or to maximum value")
218 }
219}
220
221impl<T: NonMaxItem + Copy + Add<Output = T>> AddAssign for NonMax<T> {
222 fn add_assign(&mut self, rhs: Self) {
223 *self = *self + rhs;
224 }
225}
226
227impl<T: NonMaxItem + Copy + Add<Output = T>> AddAssign<T> for NonMax<T> {
228 fn add_assign(&mut self, rhs: T) {
229 *self = *self + rhs;
230 }
231}
232
233impl<T: NonMaxItem + Copy + Sub<Output = T>> Sub for NonMax<T> {
234 type Output = Self;
235 fn sub(self, rhs: Self) -> Self::Output {
236 self.checked_sub(rhs)
237 .expect("attempt to subtract with overflow or to maximum value")
238 }
239}
240
241impl<T: NonMaxItem + Copy + Sub<Output = T>> Sub<T> for NonMax<T> {
242 type Output = Self;
243 fn sub(self, rhs: T) -> Self::Output {
244 self.checked_sub_val(rhs)
245 .expect("attempt to subtract with overflow or to maximum value")
246 }
247}
248
249impl<T: NonMaxItem + Copy + Sub<Output = T>> SubAssign for NonMax<T> {
250 fn sub_assign(&mut self, rhs: Self) {
251 *self = *self - rhs;
252 }
253}
254
255impl<T: NonMaxItem + Copy + Sub<Output = T>> SubAssign<T> for NonMax<T> {
256 fn sub_assign(&mut self, rhs: T) {
257 *self = *self - rhs;
258 }
259}
260
261impl<T: NonMaxItem + Copy + Mul<Output = T>> Mul for NonMax<T> {
262 type Output = Self;
263 fn mul(self, rhs: Self) -> Self::Output {
264 self.checked_mul(rhs)
265 .expect("attempt to multiply with overflow or to maximum value")
266 }
267}
268
269impl<T: NonMaxItem + Copy + Mul<Output = T>> Mul<T> for NonMax<T> {
270 type Output = Self;
271 fn mul(self, rhs: T) -> Self::Output {
272 self.checked_mul_val(rhs)
273 .expect("attempt to multiply with overflow or to maximum value")
274 }
275}
276
277impl<T: NonMaxItem + Copy + Mul<Output = T>> MulAssign for NonMax<T> {
278 fn mul_assign(&mut self, rhs: Self) {
279 *self = *self * rhs;
280 }
281}
282
283impl<T: NonMaxItem + Copy + Mul<Output = T>> MulAssign<T> for NonMax<T> {
284 fn mul_assign(&mut self, rhs: T) {
285 *self = *self * rhs;
286 }
287}
288
289impl<T: NonMaxItem + Copy + Div<Output = T>> Div for NonMax<T> {
290 type Output = Self;
291 fn div(self, rhs: Self) -> Self::Output {
292 self.checked_div(rhs)
293 .expect("attempt to divide by zero or to maximum value")
294 }
295}
296
297impl<T: NonMaxItem + Copy + Div<T, Output = T>> Div<T> for NonMax<T> {
298 type Output = Self;
299 fn div(self, rhs: T) -> Self::Output {
300 self.checked_div_val(rhs)
301 .expect("attempt to divide by zero or to maximum value")
302 }
303}
304
305impl<T: NonMaxItem + Copy + Div<Output = T>> DivAssign for NonMax<T> {
306 fn div_assign(&mut self, rhs: Self) {
307 *self = *self / rhs;
308 }
309}
310
311impl<T: NonMaxItem + Copy + Div<T, Output = T>> DivAssign<T> for NonMax<T> {
312 fn div_assign(&mut self, rhs: T) {
313 *self = *self / rhs;
314 }
315}
316
317impl<T: NonMaxItem + Copy + Rem<Output = T>> Rem for NonMax<T> {
318 type Output = Self;
319 fn rem(self, rhs: Self) -> Self::Output {
320 self.checked_rem(rhs)
321 .expect("attempt to calculate remainder by zero or to maximum value")
322 }
323}
324
325impl<T: NonMaxItem + Copy + Rem<T, Output = T>> Rem<T> for NonMax<T> {
326 type Output = Self;
327 fn rem(self, rhs: T) -> Self::Output {
328 self.checked_rem_val(rhs)
329 .expect("attempt to calculate remainder by zero or to maximum value")
330 }
331}
332
333impl<T: NonMaxItem + Copy + Rem<Output = T>> RemAssign for NonMax<T> {
334 fn rem_assign(&mut self, rhs: Self) {
335 *self = *self % rhs;
336 }
337}
338
339impl<T: NonMaxItem + Copy + Rem<T, Output = T>> RemAssign<T> for NonMax<T> {
340 fn rem_assign(&mut self, rhs: T) {
341 *self = *self % rhs;
342 }
343}
344
345impl<T: NonMaxItem + Copy + PartialOrd> PartialOrd for NonMax<T> {
346 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
347 self.to_real_repr().partial_cmp(&other.to_real_repr())
348 }
349}
350
351impl<T: NonMaxItem + Copy + Ord> Ord for NonMax<T> {
352 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
353 self.to_real_repr().cmp(&other.to_real_repr())
354 }
355}
356
357impl<T: NonMaxItem + Copy + Display> Display for NonMax<T> {
358 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
359 Display::fmt(&self.get(), f)
360 }
361}
362
363impl<T: NonMaxItem + Copy + Binary> Binary for NonMax<T> {
364 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
365 Binary::fmt(&self.get(), f)
366 }
367}
368
369impl<T: NonMaxItem + Copy + Octal> Octal for NonMax<T> {
370 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
371 Octal::fmt(&self.get(), f)
372 }
373}
374
375impl<T: NonMaxItem + Copy + LowerHex> LowerHex for NonMax<T> {
376 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
377 LowerHex::fmt(&self.get(), f)
378 }
379}
380
381impl<T: NonMaxItem + Copy + UpperHex> UpperHex for NonMax<T> {
382 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
383 UpperHex::fmt(&self.get(), f)
384 }
385}
386
387impl<T: NonMaxItem + Copy> Default for NonMax<T> {
388 fn default() -> Self {
389 Self::new(T::ZERO_VALUE).unwrap()
390 }
391}
392
393#[doc(hidden)]
394pub trait NonMaxItem: Sized {
395 type NonZero: Copy + PartialEq + Eq + PartialOrd + Ord + Hash;
396 const MIN_VALUE: Self;
397 const MAX: Self;
398 const MAX_SAFE: Self;
399 const ZERO_VALUE: Self;
400 fn transform(self) -> Self;
401 fn to_nonzero(value: Value<Self, Inner>) -> Option<Self::NonZero>;
402 unsafe fn to_nonzero_unchecked(value: Value<Self, Inner>) -> Self::NonZero;
403 fn from_nonzero(value: Self::NonZero) -> Value<Self, Inner>;
404
405 fn checked_add(self, rhs: Self) -> Option<Self>;
406 fn checked_sub(self, rhs: Self) -> Option<Self>;
407 fn checked_mul(self, rhs: Self) -> Option<Self>;
408 fn checked_div(self, rhs: Self) -> Option<Self>;
409 fn checked_rem(self, rhs: Self) -> Option<Self>;
410
411 unsafe fn create_nonmax_unchecked(self) -> NonMax<Self>;
416}
417
418macro_rules! impl_non_max_item {
419 ($($t:ty, $name:ident, $doc:expr),*) => {
420 $(
421 impl NonMaxItem for $t {
422 type NonZero = NonZero<$t>;
423 const MIN_VALUE: Self = <$t>::MIN;
424 const MAX: Self = <$t>::MAX;
425 const MAX_SAFE: Self = <$t>::MAX - 1;
426 const ZERO_VALUE: Self = 0;
427 fn transform(self) -> Self {
428 self ^ <$t>::MAX
429 }
430 fn to_nonzero(value: Value<Self, Inner>) -> Option<Self::NonZero> {
431 Self::NonZero::new(value.value())
432 }
433 unsafe fn to_nonzero_unchecked(value: Value<Self, Inner>) -> Self::NonZero {
434 unsafe { Self::NonZero::new_unchecked(value.value()) }
435 }
436 fn from_nonzero(value: Self::NonZero) -> Value<Self, Inner> {
437 Value::new(value.get())
438 }
439
440 fn checked_add(self, rhs: Self) -> Option<Self> { self.checked_add(rhs) }
441 fn checked_sub(self, rhs: Self) -> Option<Self> { self.checked_sub(rhs) }
442 fn checked_mul(self, rhs: Self) -> Option<Self> { self.checked_mul(rhs) }
443 fn checked_div(self, rhs: Self) -> Option<Self> { self.checked_div(rhs) }
444 fn checked_rem(self, rhs: Self) -> Option<Self> { self.checked_rem(rhs) }
445
446 unsafe fn create_nonmax_unchecked(self) -> NonMax<Self> {
447 unsafe { NonMax::<$t>::new_unchecked(self) }
448 }
449 }
450
451 impl From<NonMax<$t>> for $t {
452 fn from(value: NonMax<$t>) -> Self {
453 value.get()
454 }
455 }
456
457 impl TryFrom<$t> for NonMax<$t> {
458 type Error = MaxValueError;
459
460 fn try_from(value: $t) -> Result<Self, Self::Error> {
461 Self::new(value).ok_or(MaxValueError)
462 }
463 }
464
465 #[doc = $doc]
466 pub type $name = NonMax<$t>;
467
468 impl $name {
469 pub const MIN: Self = unsafe { Self(NonZero::new_unchecked(<$t>::MIN ^ <$t>::MAX)) };
471 pub const MAX: Self = unsafe { Self(NonZero::new_unchecked((<$t>::MAX - 1) ^ <$t>::MAX)) };
473 pub const ZERO: Self = unsafe { Self(NonZero::new_unchecked(0 ^ <$t>::MAX)) };
475
476 pub const unsafe fn new_unchecked(value: $t) -> Self {
481 Self(unsafe { NonZero::new_unchecked(value ^ <$t>::MAX) })
482 }
483 }
484 )*
485 };
486}
487
488impl_non_max_item!(
489 u8,
490 NonMaxU8,
491 "An unsigned 8-bit integer that cannot be `u8::MAX`.",
492 u16,
493 NonMaxU16,
494 "An unsigned 16-bit integer that cannot be `u16::MAX`.",
495 u32,
496 NonMaxU32,
497 "An unsigned 32-bit integer that cannot be `u32::MAX`.",
498 u64,
499 NonMaxU64,
500 "An unsigned 64-bit integer that cannot be `u64::MAX`.",
501 u128,
502 NonMaxU128,
503 "An unsigned 128-bit integer that cannot be `u128::MAX`.",
504 usize,
505 NonMaxUsize,
506 "An unsigned pointer-sized integer that cannot be `usize::MAX`.",
507 i8,
508 NonMaxI8,
509 "A signed 8-bit integer that cannot be `i8::MAX`.",
510 i16,
511 NonMaxI16,
512 "A signed 16-bit integer that cannot be `i16::MAX`.",
513 i32,
514 NonMaxI32,
515 "A signed 32-bit integer that cannot be `i32::MAX`.",
516 i64,
517 NonMaxI64,
518 "A signed 64-bit integer that cannot be `i64::MAX`.",
519 i128,
520 NonMaxI128,
521 "A signed 128-bit integer that cannot be `i128::MAX`.",
522 isize,
523 NonMaxIsize,
524 "A signed pointer-sized integer that cannot be `isize::MAX`."
525);
526
527#[doc(hidden)]
528#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
529pub struct Real;
530#[doc(hidden)]
531#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
532pub struct Inner;
533
534#[doc(hidden)]
535#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
536pub struct Value<T, M> {
537 value: T,
538 _marker: PhantomData<M>,
539}
540
541impl<T: NonMaxItem + Copy, M> Value<T, M> {
542 fn new(value: T) -> Self {
543 Self {
544 value,
545 _marker: PhantomData,
546 }
547 }
548
549 fn value(&self) -> T {
550 self.value
551 }
552}
553
554impl<T: NonMaxItem + Copy> Value<T, Real> {
555 fn to_inner_repr(self) -> Value<T, Inner> {
556 Value::new(T::transform(self.value))
557 }
558}
559
560impl<T: NonMaxItem + Copy + Add<Output = T>> Add for Value<T, Real> {
561 type Output = Self;
562 fn add(self, rhs: Self) -> Self::Output {
563 Self::new(self.value() + rhs.value())
564 }
565}
566
567impl<T: NonMaxItem + Copy + Sub<Output = T>> Sub for Value<T, Real> {
568 type Output = Self;
569 fn sub(self, rhs: Self) -> Self::Output {
570 Self::new(self.value() - rhs.value())
571 }
572}
573
574impl<T: NonMaxItem + Copy + Mul<Output = T>> Mul for Value<T, Real> {
575 type Output = Self;
576 fn mul(self, rhs: Self) -> Self::Output {
577 Self::new(self.value() * rhs.value())
578 }
579}
580
581impl<T: NonMaxItem + Copy + Div<Output = T>> Div for Value<T, Real> {
582 type Output = Self;
583 fn div(self, rhs: Self) -> Self::Output {
584 Self::new(self.value() / rhs.value())
585 }
586}
587
588impl<T: NonMaxItem + Copy + Rem<Output = T>> Rem for Value<T, Real> {
589 type Output = Self;
590 fn rem(self, rhs: Self) -> Self::Output {
591 Self::new(self.value() % rhs.value())
592 }
593}
594
595impl<T: NonMaxItem + Copy> Value<T, Inner> {
596 fn to_real_repr(self) -> Value<T, Real> {
597 Value::new(T::transform(self.value))
598 }
599
600 fn to_nonmax(self) -> Option<NonMax<T>> {
601 T::to_nonzero(self).map(NonMax)
602 }
603}
604
605impl<T: NonMaxItem + Copy + PartialOrd> PartialOrd for Value<T, Real> {
606 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
607 self.value().partial_cmp(&other.value())
608 }
609}
610
611impl<T: NonMaxItem + Copy + Ord> Ord for Value<T, Real> {
612 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
613 self.value().cmp(&other.value())
614 }
615}
616
617impl<T: NonMaxItem + Copy + Display> Display for Value<T, Real> {
618 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
619 write!(f, "{}", self.value())
620 }
621}
622
623impl<T> Index<NonMaxUsize> for [T] {
624 type Output = T;
625 #[inline]
626 fn index(&self, index: NonMaxUsize) -> &Self::Output {
627 &self[index.get()]
628 }
629}
630
631impl<T> IndexMut<NonMaxUsize> for [T] {
632 #[inline]
633 fn index_mut(&mut self, index: NonMaxUsize) -> &mut Self::Output {
634 &mut self[index.get()]
635 }
636}
637
638#[cfg(feature = "alloc")]
639impl<T> Index<NonMaxUsize> for alloc::vec::Vec<T> {
640 type Output = T;
641 #[inline]
642 fn index(&self, index: NonMaxUsize) -> &Self::Output {
643 &self[index.get()]
644 }
645}
646
647#[cfg(feature = "alloc")]
648impl<T> IndexMut<NonMaxUsize> for alloc::vec::Vec<T> {
649 #[inline]
650 fn index_mut(&mut self, index: NonMaxUsize) -> &mut Self::Output {
651 &mut self[index.get()]
652 }
653}
654
655#[cfg(test)]
656mod tests {
657 extern crate std;
658 use super::*;
659 use core::mem::size_of;
660 use std::collections::HashSet;
661
662 #[test]
663 fn test_hash() {
664 let mut set = HashSet::new();
665 set.insert(NonMaxU32::new(1).unwrap());
666 set.insert(NonMaxU32::new(2).unwrap());
667 set.insert(NonMaxU32::new(1).unwrap());
668
669 assert_eq!(set.len(), 2);
670 assert!(set.contains(&NonMaxU32::new(1).unwrap()));
671 }
672
673 #[test]
674 fn test_sizes() {
675 assert_eq!(size_of::<NonMaxU32>(), 4);
676 assert_eq!(size_of::<Option<NonMaxU32>>(), 4);
677
678 assert_eq!(size_of::<NonMaxI32>(), 4);
679 assert_eq!(size_of::<Option<NonMaxI32>>(), 4);
680
681 assert_eq!(size_of::<NonMaxU8>(), 1);
682 assert_eq!(size_of::<Option<NonMaxU8>>(), 1);
683 }
684
685 #[test]
686 fn test_conversions() {
687 let x = NonMaxU8::try_from(100).unwrap();
688 assert_eq!(u8::from(x), 100);
689
690 let max_val = u8::MAX;
691 assert!(NonMaxU8::try_from(max_val).is_err());
692 }
693
694 #[test]
695 fn test_arithmetic_with_val() {
696 let x = NonMaxU8::new(100).unwrap();
697 let y = x + 50;
698 assert_eq!(u8::from(y), 150);
699
700 let mut z = NonMaxU8::new(10).unwrap();
701 z += 20;
702 assert_eq!(u8::from(z), 30);
703
704 let a = NonMaxU8::new(10).unwrap();
705 let b = a * 5;
706 assert_eq!(u8::from(b), 50);
707
708 let c = NonMaxU8::new(100).unwrap();
709 let d = c / 3;
710 assert_eq!(u8::from(d), 33);
711 }
712
713 #[test]
714 fn test_add_overflow() {
715 let x = NonMaxU8::try_from(250).unwrap();
716 assert!(x.checked_add_val(10).is_none());
718 }
719
720 #[test]
721 fn test_add_to_max() {
722 let x = NonMaxU8::try_from(250).unwrap();
723 assert!(x.checked_add_val(5).is_none());
725 }
726
727 #[test]
728 fn test_signed_integer() {
729 let x = NonMaxI8::try_from(100).unwrap();
731 let y = x + 20;
732 assert_eq!(i8::from(y), 120);
733
734 let z = NonMaxI8::try_from(-50).unwrap();
735 let w = z + 10;
736 assert_eq!(i8::from(w), -40);
737
738 let min_val = NonMaxI8::try_from(i8::MIN).unwrap();
740 assert_eq!(i8::from(min_val), -128);
741 }
742
743 #[test]
744 fn test_signed_overflow() {
745 let x = NonMaxI8::try_from(120).unwrap();
746 assert!(x.checked_add_val(10).is_none());
748 }
749
750 #[test]
751 fn test_signed_to_max() {
752 let x = NonMaxI8::try_from(120).unwrap();
753 assert!(x.checked_add_val(7).is_none());
755 }
756
757 #[test]
758 fn test_formatting() {
759 let x = NonMaxU8::new(254).unwrap();
760 assert_eq!(std::format!("{}", x), "254");
761 assert_eq!(std::format!("{:b}", x), "11111110");
762 assert_eq!(std::format!("{:o}", x), "376");
763 assert_eq!(std::format!("{:x}", x), "fe");
764 assert_eq!(std::format!("{:X}", x), "FE");
765 }
766
767 #[test]
768 fn test_min_max_constants() {
769 assert_eq!(NonMaxU8::MIN.get(), 0);
770 assert_eq!(NonMaxU8::MAX.get(), 254);
771 assert!(NonMaxU8::MIN.is_min());
772 assert!(NonMaxU8::MAX.is_max());
773 assert!(!NonMaxU8::MIN.is_max());
774 assert!(!NonMaxU8::MAX.is_min());
775
776 assert_eq!(NonMaxI8::MIN.get(), -128);
777 assert_eq!(NonMaxI8::MAX.get(), 126);
778 }
779
780 #[test]
781 fn test_zero_constant() {
782 assert_eq!(NonMaxU8::ZERO.get(), 0);
783 assert!(NonMaxU8::ZERO.is_zero());
784 assert_eq!(NonMaxI32::ZERO.get(), 0);
785 assert!(NonMaxI32::ZERO.is_zero());
786 }
787
788 #[test]
789 fn test_non_max_macro() {
790 let x = non_max!(123u8);
791 assert_eq!(x.get(), 123);
792
793 let y = non_max!(456u32);
794 assert_eq!(y.get(), 456);
795
796 let z = non_max!(-10i32);
797 assert_eq!(z.get(), -10);
798 }
799
800 #[test]
801 fn test_indexing() {
802 let v = [1, 2, 3];
803 let idx = NonMaxUsize::new(1).unwrap();
804 assert_eq!(v[idx], 2);
805
806 let mut v_mut = [1, 2, 3];
807 v_mut[idx] = 10;
808 assert_eq!(v_mut[1], 10);
809
810 #[cfg(feature = "alloc")]
811 {
812 let v_vec = std::vec![1, 2, 3];
813 assert_eq!(v_vec[idx], 2);
814
815 let mut v_vec_mut = std::vec![1, 2, 3];
816 v_vec_mut[idx] = 20;
817 assert_eq!(v_vec_mut[1], 20);
818 }
819 }
820}