1#![no_std]
49
50use core::convert::TryFrom;
51use core::fmt::{self, Binary, Display, LowerHex, Octal, UpperHex};
52use core::hash::Hash;
53use core::marker::PhantomData;
54use core::num::NonZero;
55use core::ops::{
56 Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Rem, RemAssign, Sub, SubAssign,
57};
58
59#[cfg(feature = "alloc")]
60extern crate alloc;
61
62#[macro_export]
88macro_rules! non_max {
89 ($val:expr) => {{
90 const _: () = const {
91 if $val == <_ as $crate::NonMaxItem>::MAX {
92 panic!("provided value is the maximum value for this type");
93 }
94 };
95 unsafe { <_ as $crate::NonMaxItem>::create_nonmax_unchecked($val) }
96 }};
97}
98
99#[derive(Debug, Clone, Copy, PartialEq, Eq)]
101pub struct MaxValueError;
102
103impl Display for MaxValueError {
104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105 write!(f, "provided value is the maximum value for this type")
106 }
107}
108
109impl core::error::Error for MaxValueError {}
110
111#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
124pub struct NonMax<T: NonMaxItem>(T::NonZero);
125
126impl<T: NonMaxItem + Copy> NonMax<T> {
127 pub fn new(value: T) -> Option<Self> {
136 Value::new(value).to_inner_repr().to_nonmax()
137 }
138
139 fn to_real_repr(self) -> Value<T, Real> {
140 T::from_nonzero(self.0).to_real_repr()
141 }
142
143 pub fn get(&self) -> T {
152 self.to_real_repr().value()
153 }
154}
155
156impl<T: NonMaxItem + Copy + PartialEq> NonMax<T> {
157 pub fn is_min(&self) -> bool {
159 self.to_real_repr() == Value::new(T::MIN_VALUE)
160 }
161
162 pub fn is_max(&self) -> bool {
164 self.to_real_repr() == Value::new(T::MAX_SAFE)
165 }
166
167 pub fn is_zero(&self) -> bool {
169 self.to_real_repr() == Value::new(T::ZERO_VALUE)
170 }
171}
172
173impl<T: NonMaxItem + Copy> NonMax<T> {
174 pub fn checked_add(self, rhs: Self) -> Option<Self> {
177 self.to_real_repr()
178 .checked_add(rhs.to_real_repr())?
179 .to_inner_repr()
180 .to_nonmax()
181 }
182
183 pub fn checked_sub(self, rhs: Self) -> Option<Self> {
186 self.to_real_repr()
187 .checked_sub(rhs.to_real_repr())?
188 .to_inner_repr()
189 .to_nonmax()
190 }
191
192 pub fn checked_mul(self, rhs: Self) -> Option<Self> {
195 self.to_real_repr()
196 .checked_mul(rhs.to_real_repr())?
197 .to_inner_repr()
198 .to_nonmax()
199 }
200
201 pub fn checked_div(self, rhs: Self) -> Option<Self> {
204 self.to_real_repr()
205 .checked_div(rhs.to_real_repr())?
206 .to_inner_repr()
207 .to_nonmax()
208 }
209
210 pub fn checked_rem(self, rhs: Self) -> Option<Self> {
213 self.to_real_repr()
214 .checked_rem(rhs.to_real_repr())?
215 .to_inner_repr()
216 .to_nonmax()
217 }
218
219 pub fn checked_add_val(self, rhs: T) -> Option<Self> {
229 self.to_real_repr()
230 .checked_add(Value::new(rhs))?
231 .to_inner_repr()
232 .to_nonmax()
233 }
234
235 pub fn checked_sub_val(self, rhs: T) -> Option<Self> {
237 self.to_real_repr()
238 .checked_sub(Value::new(rhs))?
239 .to_inner_repr()
240 .to_nonmax()
241 }
242
243 pub fn checked_mul_val(self, rhs: T) -> Option<Self> {
245 self.to_real_repr()
246 .checked_mul(Value::new(rhs))?
247 .to_inner_repr()
248 .to_nonmax()
249 }
250
251 pub fn checked_div_val(self, rhs: T) -> Option<Self> {
253 self.to_real_repr()
254 .checked_div(Value::new(rhs))?
255 .to_inner_repr()
256 .to_nonmax()
257 }
258
259 pub fn checked_rem_val(self, rhs: T) -> Option<Self> {
261 self.to_real_repr()
262 .checked_rem(Value::new(rhs))?
263 .to_inner_repr()
264 .to_nonmax()
265 }
266}
267
268impl<T: NonMaxItem + Copy + Add<Output = T>> Add for NonMax<T> {
269 type Output = Self;
270 fn add(self, rhs: Self) -> Self::Output {
271 self.checked_add(rhs)
272 .expect("attempt to add with overflow or to maximum value")
273 }
274}
275
276impl<T: NonMaxItem + Copy + Add<Output = T>> Add<T> for NonMax<T> {
277 type Output = Self;
278 fn add(self, rhs: T) -> Self::Output {
279 self.checked_add_val(rhs)
280 .expect("attempt to add with overflow or to maximum value")
281 }
282}
283
284impl<T: NonMaxItem + Copy + Add<Output = T>> AddAssign for NonMax<T> {
285 fn add_assign(&mut self, rhs: Self) {
286 *self = *self + rhs;
287 }
288}
289
290impl<T: NonMaxItem + Copy + Add<Output = T>> AddAssign<T> for NonMax<T> {
291 fn add_assign(&mut self, rhs: T) {
292 *self = *self + rhs;
293 }
294}
295
296impl<T: NonMaxItem + Copy + Sub<Output = T>> Sub for NonMax<T> {
297 type Output = Self;
298 fn sub(self, rhs: Self) -> Self::Output {
299 self.checked_sub(rhs)
300 .expect("attempt to subtract with overflow or to maximum value")
301 }
302}
303
304impl<T: NonMaxItem + Copy + Sub<Output = T>> Sub<T> for NonMax<T> {
305 type Output = Self;
306 fn sub(self, rhs: T) -> Self::Output {
307 self.checked_sub_val(rhs)
308 .expect("attempt to subtract with overflow or to maximum value")
309 }
310}
311
312impl<T: NonMaxItem + Copy + Sub<Output = T>> SubAssign for NonMax<T> {
313 fn sub_assign(&mut self, rhs: Self) {
314 *self = *self - rhs;
315 }
316}
317
318impl<T: NonMaxItem + Copy + Sub<Output = T>> SubAssign<T> for NonMax<T> {
319 fn sub_assign(&mut self, rhs: T) {
320 *self = *self - rhs;
321 }
322}
323
324impl<T: NonMaxItem + Copy + Mul<Output = T>> Mul for NonMax<T> {
325 type Output = Self;
326 fn mul(self, rhs: Self) -> Self::Output {
327 self.checked_mul(rhs)
328 .expect("attempt to multiply with overflow or to maximum value")
329 }
330}
331
332impl<T: NonMaxItem + Copy + Mul<Output = T>> Mul<T> for NonMax<T> {
333 type Output = Self;
334 fn mul(self, rhs: T) -> Self::Output {
335 self.checked_mul_val(rhs)
336 .expect("attempt to multiply with overflow or to maximum value")
337 }
338}
339
340impl<T: NonMaxItem + Copy + Mul<Output = T>> MulAssign for NonMax<T> {
341 fn mul_assign(&mut self, rhs: Self) {
342 *self = *self * rhs;
343 }
344}
345
346impl<T: NonMaxItem + Copy + Mul<Output = T>> MulAssign<T> for NonMax<T> {
347 fn mul_assign(&mut self, rhs: T) {
348 *self = *self * rhs;
349 }
350}
351
352impl<T: NonMaxItem + Copy + Div<Output = T>> Div for NonMax<T> {
353 type Output = Self;
354 fn div(self, rhs: Self) -> Self::Output {
355 self.checked_div(rhs)
356 .expect("attempt to divide by zero or to maximum value")
357 }
358}
359
360impl<T: NonMaxItem + Copy + Div<T, Output = T>> Div<T> for NonMax<T> {
361 type Output = Self;
362 fn div(self, rhs: T) -> Self::Output {
363 self.checked_div_val(rhs)
364 .expect("attempt to divide by zero or to maximum value")
365 }
366}
367
368impl<T: NonMaxItem + Copy + Div<Output = T>> DivAssign for NonMax<T> {
369 fn div_assign(&mut self, rhs: Self) {
370 *self = *self / rhs;
371 }
372}
373
374impl<T: NonMaxItem + Copy + Div<T, Output = T>> DivAssign<T> for NonMax<T> {
375 fn div_assign(&mut self, rhs: T) {
376 *self = *self / rhs;
377 }
378}
379
380impl<T: NonMaxItem + Copy + Rem<Output = T>> Rem for NonMax<T> {
381 type Output = Self;
382 fn rem(self, rhs: Self) -> Self::Output {
383 self.checked_rem(rhs)
384 .expect("attempt to calculate remainder by zero or to maximum value")
385 }
386}
387
388impl<T: NonMaxItem + Copy + Rem<T, Output = T>> Rem<T> for NonMax<T> {
389 type Output = Self;
390 fn rem(self, rhs: T) -> Self::Output {
391 self.checked_rem_val(rhs)
392 .expect("attempt to calculate remainder by zero or to maximum value")
393 }
394}
395
396impl<T: NonMaxItem + Copy + Rem<Output = T>> RemAssign for NonMax<T> {
397 fn rem_assign(&mut self, rhs: Self) {
398 *self = *self % rhs;
399 }
400}
401
402impl<T: NonMaxItem + Copy + Rem<T, Output = T>> RemAssign<T> for NonMax<T> {
403 fn rem_assign(&mut self, rhs: T) {
404 *self = *self % rhs;
405 }
406}
407
408impl<T: NonMaxItem + Copy + PartialOrd> PartialOrd for NonMax<T> {
409 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
410 self.to_real_repr().partial_cmp(&other.to_real_repr())
411 }
412}
413
414impl<T: NonMaxItem + Copy + Ord> Ord for NonMax<T> {
415 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
416 self.to_real_repr().cmp(&other.to_real_repr())
417 }
418}
419
420impl<T: NonMaxItem + Copy + Display> Display for NonMax<T> {
421 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
422 Display::fmt(&self.to_real_repr(), f)
423 }
424}
425
426impl<T: NonMaxItem + Copy + Binary> Binary for NonMax<T> {
427 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
428 Binary::fmt(&self.to_real_repr(), f)
429 }
430}
431
432impl<T: NonMaxItem + Copy + Octal> Octal for NonMax<T> {
433 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
434 Octal::fmt(&self.to_real_repr(), f)
435 }
436}
437
438impl<T: NonMaxItem + Copy + LowerHex> LowerHex for NonMax<T> {
439 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
440 LowerHex::fmt(&self.to_real_repr(), f)
441 }
442}
443
444impl<T: NonMaxItem + Copy + UpperHex> UpperHex for NonMax<T> {
445 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
446 UpperHex::fmt(&self.to_real_repr(), f)
447 }
448}
449
450impl<T: NonMaxItem + Copy> Default for NonMax<T> {
451 fn default() -> Self {
452 Self::new(T::ZERO_VALUE).unwrap()
453 }
454}
455
456use core::iter::{Product, Sum};
457
458impl<T: NonMaxItem + Copy + Add<Output = T>> Sum for NonMax<T> {
459 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
460 iter.fold(Self::new(T::ZERO_VALUE).unwrap(), |a, b| a + b)
461 }
462}
463
464impl<'a, T: NonMaxItem + Copy + Add<Output = T>> Sum<&'a NonMax<T>> for NonMax<T> {
465 fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
466 iter.fold(Self::new(T::ZERO_VALUE).unwrap(), |a, b| a + *b)
467 }
468}
469
470impl<T: NonMaxItem + Copy + Mul<Output = T>> Product for NonMax<T> {
471 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
472 iter.fold(Self::new(T::ONE_VALUE).unwrap(), |a, b| a * b)
473 }
474}
475
476impl<'a, T: NonMaxItem + Copy + Mul<Output = T>> Product<&'a NonMax<T>> for NonMax<T> {
477 fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
478 iter.fold(Self::new(T::ONE_VALUE).unwrap(), |a, b| a * *b)
479 }
480}
481
482#[doc(hidden)]
483pub trait NonMaxItem: Sized {
484 type NonZero: Copy + PartialEq + Eq + PartialOrd + Ord + Hash;
485 const MIN_VALUE: Self;
486 const MAX: Self;
487 const MAX_SAFE: Self;
488 const ZERO_VALUE: Self;
489 const ONE_VALUE: Self;
490 fn transform(self) -> Self;
491 fn to_nonzero(value: Value<Self, Inner>) -> Option<Self::NonZero>;
492 unsafe fn to_nonzero_unchecked(value: Value<Self, Inner>) -> Self::NonZero;
493 fn from_nonzero(value: Self::NonZero) -> Value<Self, Inner>;
494
495 fn checked_add(self, rhs: Self) -> Option<Self>;
496 fn checked_sub(self, rhs: Self) -> Option<Self>;
497 fn checked_mul(self, rhs: Self) -> Option<Self>;
498 fn checked_div(self, rhs: Self) -> Option<Self>;
499 fn checked_rem(self, rhs: Self) -> Option<Self>;
500
501 unsafe fn create_nonmax_unchecked(self) -> NonMax<Self>;
506}
507
508macro_rules! impl_non_max_item {
509 ($($t:ty, $name:ident, $doc:expr),*) => {
510 $(
511 impl NonMaxItem for $t {
512 type NonZero = NonZero<$t>;
513 const MIN_VALUE: Self = <$t>::MIN;
514 const MAX: Self = <$t>::MAX;
515 const MAX_SAFE: Self = <$t>::MAX - 1;
516 const ZERO_VALUE: Self = 0;
517 const ONE_VALUE: Self = 1;
518 fn transform(self) -> Self {
519 self ^ <$t>::MAX
520 }
521 fn to_nonzero(value: Value<Self, Inner>) -> Option<Self::NonZero> {
522 Self::NonZero::new(value.value())
523 }
524 unsafe fn to_nonzero_unchecked(value: Value<Self, Inner>) -> Self::NonZero {
525 unsafe { Self::NonZero::new_unchecked(value.value()) }
526 }
527 fn from_nonzero(value: Self::NonZero) -> Value<Self, Inner> {
528 Value::new(value.get())
529 }
530
531 fn checked_add(self, rhs: Self) -> Option<Self> { self.checked_add(rhs) }
532 fn checked_sub(self, rhs: Self) -> Option<Self> { self.checked_sub(rhs) }
533 fn checked_mul(self, rhs: Self) -> Option<Self> { self.checked_mul(rhs) }
534 fn checked_div(self, rhs: Self) -> Option<Self> { self.checked_div(rhs) }
535 fn checked_rem(self, rhs: Self) -> Option<Self> { self.checked_rem(rhs) }
536
537 unsafe fn create_nonmax_unchecked(self) -> NonMax<Self> {
538 unsafe { NonMax::<$t>::new_unchecked(self) }
539 }
540 }
541
542 impl From<NonMax<$t>> for $t {
543 fn from(value: NonMax<$t>) -> Self {
544 value.get()
545 }
546 }
547
548 impl TryFrom<$t> for NonMax<$t> {
549 type Error = MaxValueError;
550
551 fn try_from(value: $t) -> Result<Self, Self::Error> {
552 Self::new(value).ok_or(MaxValueError)
553 }
554 }
555
556 #[doc = $doc]
557 pub type $name = NonMax<$t>;
558
559 impl $name {
560 pub const MIN: Self = unsafe { Self(NonZero::new_unchecked(<$t>::MIN ^ <$t>::MAX)) };
562 pub const MAX: Self = unsafe { Self(NonZero::new_unchecked((<$t>::MAX - 1) ^ <$t>::MAX)) };
564 pub const ZERO: Self = unsafe { Self(NonZero::new_unchecked(0 ^ <$t>::MAX)) };
566
567 pub const unsafe fn new_unchecked(value: $t) -> Self {
572 Self(unsafe { NonZero::new_unchecked(value ^ <$t>::MAX) })
573 }
574 }
575 )*
576 };
577}
578
579impl_non_max_item!(
580 u8,
581 NonMaxU8,
582 "An unsigned 8-bit integer that cannot be `u8::MAX`.",
583 u16,
584 NonMaxU16,
585 "An unsigned 16-bit integer that cannot be `u16::MAX`.",
586 u32,
587 NonMaxU32,
588 "An unsigned 32-bit integer that cannot be `u32::MAX`.",
589 u64,
590 NonMaxU64,
591 "An unsigned 64-bit integer that cannot be `u64::MAX`.",
592 u128,
593 NonMaxU128,
594 "An unsigned 128-bit integer that cannot be `u128::MAX`.",
595 usize,
596 NonMaxUsize,
597 "An unsigned pointer-sized integer that cannot be `usize::MAX`.",
598 i8,
599 NonMaxI8,
600 "A signed 8-bit integer that cannot be `i8::MAX`.",
601 i16,
602 NonMaxI16,
603 "A signed 16-bit integer that cannot be `i16::MAX`.",
604 i32,
605 NonMaxI32,
606 "A signed 32-bit integer that cannot be `i32::MAX`.",
607 i64,
608 NonMaxI64,
609 "A signed 64-bit integer that cannot be `i64::MAX`.",
610 i128,
611 NonMaxI128,
612 "A signed 128-bit integer that cannot be `i128::MAX`.",
613 isize,
614 NonMaxIsize,
615 "A signed pointer-sized integer that cannot be `isize::MAX`."
616);
617
618#[doc(hidden)]
619#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
620pub struct Real;
621#[doc(hidden)]
622#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
623pub struct Inner;
624
625#[doc(hidden)]
626#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
627pub struct Value<T, M> {
628 value: T,
629 _marker: PhantomData<M>,
630}
631
632impl<T: NonMaxItem + Copy, M> Value<T, M> {
633 fn new(value: T) -> Self {
634 Self {
635 value,
636 _marker: PhantomData,
637 }
638 }
639
640 fn value(&self) -> T {
641 self.value
642 }
643}
644
645impl<T: NonMaxItem + Copy> Value<T, Real> {
646 fn to_inner_repr(self) -> Value<T, Inner> {
647 Value::new(T::transform(self.value))
648 }
649
650 fn checked_add(self, rhs: Self) -> Option<Self> {
651 self.value().checked_add(rhs.value()).map(Self::new)
652 }
653
654 fn checked_sub(self, rhs: Self) -> Option<Self> {
655 self.value().checked_sub(rhs.value()).map(Self::new)
656 }
657
658 fn checked_mul(self, rhs: Self) -> Option<Self> {
659 self.value().checked_mul(rhs.value()).map(Self::new)
660 }
661
662 fn checked_div(self, rhs: Self) -> Option<Self> {
663 self.value().checked_div(rhs.value()).map(Self::new)
664 }
665
666 fn checked_rem(self, rhs: Self) -> Option<Self> {
667 self.value().checked_rem(rhs.value()).map(Self::new)
668 }
669}
670
671impl<T: NonMaxItem + Copy + Add<Output = T>> Add for Value<T, Real> {
672 type Output = Self;
673 fn add(self, rhs: Self) -> Self::Output {
674 Self::new(self.value() + rhs.value())
675 }
676}
677
678impl<T: NonMaxItem + Copy + Sub<Output = T>> Sub for Value<T, Real> {
679 type Output = Self;
680 fn sub(self, rhs: Self) -> Self::Output {
681 Self::new(self.value() - rhs.value())
682 }
683}
684
685impl<T: NonMaxItem + Copy + Mul<Output = T>> Mul for Value<T, Real> {
686 type Output = Self;
687 fn mul(self, rhs: Self) -> Self::Output {
688 Self::new(self.value() * rhs.value())
689 }
690}
691
692impl<T: NonMaxItem + Copy + Div<Output = T>> Div for Value<T, Real> {
693 type Output = Self;
694 fn div(self, rhs: Self) -> Self::Output {
695 Self::new(self.value() / rhs.value())
696 }
697}
698
699impl<T: NonMaxItem + Copy + Rem<Output = T>> Rem for Value<T, Real> {
700 type Output = Self;
701 fn rem(self, rhs: Self) -> Self::Output {
702 Self::new(self.value() % rhs.value())
703 }
704}
705
706impl<T: NonMaxItem + Copy> Value<T, Inner> {
707 fn to_real_repr(self) -> Value<T, Real> {
708 Value::new(T::transform(self.value))
709 }
710
711 fn to_nonmax(self) -> Option<NonMax<T>> {
712 T::to_nonzero(self).map(NonMax)
713 }
714}
715
716impl<T: NonMaxItem + Copy + PartialOrd> PartialOrd for Value<T, Real> {
717 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
718 self.value().partial_cmp(&other.value())
719 }
720}
721
722impl<T: NonMaxItem + Copy + Ord> Ord for Value<T, Real> {
723 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
724 self.value().cmp(&other.value())
725 }
726}
727
728impl<T: NonMaxItem + Copy + Display> Display for Value<T, Real> {
729 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
730 write!(f, "{}", self.value())
731 }
732}
733
734impl<T: NonMaxItem + Copy + Binary> Binary for Value<T, Real> {
735 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
736 Binary::fmt(&self.value(), f)
737 }
738}
739
740impl<T: NonMaxItem + Copy + Octal> Octal for Value<T, Real> {
741 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
742 Octal::fmt(&self.value(), f)
743 }
744}
745
746impl<T: NonMaxItem + Copy + LowerHex> LowerHex for Value<T, Real> {
747 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
748 LowerHex::fmt(&self.value(), f)
749 }
750}
751
752impl<T: NonMaxItem + Copy + UpperHex> UpperHex for Value<T, Real> {
753 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
754 UpperHex::fmt(&self.value(), f)
755 }
756}
757
758impl<T> Index<NonMaxUsize> for [T] {
759 type Output = T;
760 #[inline]
761 fn index(&self, index: NonMaxUsize) -> &Self::Output {
762 &self[index.get()]
763 }
764}
765
766impl<T> IndexMut<NonMaxUsize> for [T] {
767 #[inline]
768 fn index_mut(&mut self, index: NonMaxUsize) -> &mut Self::Output {
769 &mut self[index.get()]
770 }
771}
772
773#[cfg(feature = "alloc")]
774impl<T> Index<NonMaxUsize> for alloc::vec::Vec<T> {
775 type Output = T;
776 #[inline]
777 fn index(&self, index: NonMaxUsize) -> &Self::Output {
778 &self[index.get()]
779 }
780}
781
782#[cfg(feature = "alloc")]
783impl<T> IndexMut<NonMaxUsize> for alloc::vec::Vec<T> {
784 #[inline]
785 fn index_mut(&mut self, index: NonMaxUsize) -> &mut Self::Output {
786 &mut self[index.get()]
787 }
788}
789
790#[cfg(test)]
791mod tests {
792 extern crate std;
793 use super::*;
794 use core::mem::size_of;
795 use std::collections::HashSet;
796
797 #[test]
798 fn test_hash() {
799 let mut set = HashSet::new();
800 set.insert(NonMaxU32::new(1).unwrap());
801 set.insert(NonMaxU32::new(2).unwrap());
802 set.insert(NonMaxU32::new(1).unwrap());
803
804 assert_eq!(set.len(), 2);
805 assert!(set.contains(&NonMaxU32::new(1).unwrap()));
806 }
807
808 #[test]
809 fn test_sizes() {
810 assert_eq!(size_of::<NonMaxU32>(), 4);
811 assert_eq!(size_of::<Option<NonMaxU32>>(), 4);
812
813 assert_eq!(size_of::<NonMaxI32>(), 4);
814 assert_eq!(size_of::<Option<NonMaxI32>>(), 4);
815
816 assert_eq!(size_of::<NonMaxU8>(), 1);
817 assert_eq!(size_of::<Option<NonMaxU8>>(), 1);
818 }
819
820 #[test]
821 fn test_conversions() {
822 let x = NonMaxU8::try_from(100).unwrap();
823 assert_eq!(u8::from(x), 100);
824
825 let max_val = u8::MAX;
826 assert!(NonMaxU8::try_from(max_val).is_err());
827 }
828
829 #[test]
830 fn test_arithmetic_with_val() {
831 let x = NonMaxU8::new(100).unwrap();
832 let y = x + 50;
833 assert_eq!(u8::from(y), 150);
834
835 let mut z = NonMaxU8::new(10).unwrap();
836 z += 20;
837 assert_eq!(u8::from(z), 30);
838
839 let a = NonMaxU8::new(10).unwrap();
840 let b = a * 5;
841 assert_eq!(u8::from(b), 50);
842
843 let c = NonMaxU8::new(100).unwrap();
844 let d = c / 3;
845 assert_eq!(u8::from(d), 33);
846 }
847
848 #[test]
849 fn test_add_overflow() {
850 let x = NonMaxU8::try_from(250).unwrap();
851 assert!(x.checked_add_val(10).is_none());
853 }
854
855 #[test]
856 fn test_add_to_max() {
857 let x = NonMaxU8::try_from(250).unwrap();
858 assert!(x.checked_add_val(5).is_none());
860 }
861
862 #[test]
863 fn test_signed_integer() {
864 let x = NonMaxI8::try_from(100).unwrap();
866 let y = x + 20;
867 assert_eq!(i8::from(y), 120);
868
869 let z = NonMaxI8::try_from(-50).unwrap();
870 let w = z + 10;
871 assert_eq!(i8::from(w), -40);
872
873 let min_val = NonMaxI8::try_from(i8::MIN).unwrap();
875 assert_eq!(i8::from(min_val), -128);
876 }
877
878 #[test]
879 fn test_signed_overflow() {
880 let x = NonMaxI8::try_from(120).unwrap();
881 assert!(x.checked_add_val(10).is_none());
883 }
884
885 #[test]
886 fn test_signed_to_max() {
887 let x = NonMaxI8::try_from(120).unwrap();
888 assert!(x.checked_add_val(7).is_none());
890 }
891
892 #[test]
893 fn test_formatting() {
894 let x = NonMaxU8::new(254).unwrap();
895 assert_eq!(std::format!("{}", x), "254");
896 assert_eq!(std::format!("{:b}", x), "11111110");
897 assert_eq!(std::format!("{:o}", x), "376");
898 assert_eq!(std::format!("{:x}", x), "fe");
899 assert_eq!(std::format!("{:X}", x), "FE");
900 }
901
902 #[test]
903 fn test_min_max_constants() {
904 assert_eq!(NonMaxU8::MIN.get(), 0);
905 assert_eq!(NonMaxU8::MAX.get(), 254);
906 assert!(NonMaxU8::MIN.is_min());
907 assert!(NonMaxU8::MAX.is_max());
908 assert!(!NonMaxU8::MIN.is_max());
909 assert!(!NonMaxU8::MAX.is_min());
910
911 assert_eq!(NonMaxI8::MIN.get(), -128);
912 assert_eq!(NonMaxI8::MAX.get(), 126);
913 }
914
915 #[test]
916 fn test_zero_constant() {
917 assert_eq!(NonMaxU8::ZERO.get(), 0);
918 assert!(NonMaxU8::ZERO.is_zero());
919 assert_eq!(NonMaxI32::ZERO.get(), 0);
920 assert!(NonMaxI32::ZERO.is_zero());
921 }
922
923 #[test]
924 fn test_non_max_macro() {
925 let x = non_max!(123u8);
926 assert_eq!(x.get(), 123);
927
928 let y = non_max!(456u32);
929 assert_eq!(y.get(), 456);
930
931 let z = non_max!(-10i32);
932 assert_eq!(z.get(), -10);
933 }
934
935 #[test]
936 fn test_indexing() {
937 let v = [1, 2, 3];
938 let idx = NonMaxUsize::new(1).unwrap();
939 assert_eq!(v[idx], 2);
940
941 let mut v_mut = [1, 2, 3];
942 v_mut[idx] = 10;
943 assert_eq!(v_mut[1], 10);
944
945 #[cfg(feature = "alloc")]
946 {
947 let v_vec = std::vec![1, 2, 3];
948 assert_eq!(v_vec[idx], 2);
949
950 let mut v_vec_mut = std::vec![1, 2, 3];
951 v_vec_mut[idx] = 20;
952 assert_eq!(v_vec_mut[1], 20);
953 }
954 }
955
956 #[test]
957 fn test_sum_product() {
958 let v = [
959 NonMaxU32::new(1).unwrap(),
960 NonMaxU32::new(2).unwrap(),
961 NonMaxU32::new(3).unwrap(),
962 ];
963
964 let sum: NonMaxU32 = v.iter().copied().sum();
965 assert_eq!(sum.get(), 6);
966
967 let sum_ref: NonMaxU32 = v.iter().sum();
968 assert_eq!(sum_ref.get(), 6);
969
970 let prod: NonMaxU32 = v.iter().copied().product();
971 assert_eq!(prod.get(), 6);
972
973 let prod_ref: NonMaxU32 = v.iter().product();
974 assert_eq!(prod_ref.get(), 6);
975
976 let empty: [NonMaxU32; 0] = [];
978 let sum_empty: NonMaxU32 = empty.iter().sum();
979 assert_eq!(sum_empty.get(), 0);
980
981 let prod_empty: NonMaxU32 = empty.iter().product();
982 assert_eq!(prod_empty.get(), 1);
983 }
984}