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