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