1use core::num::{NonZeroIsize, NonZeroUsize};
8
9#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, Ord, PartialOrd)]
15pub struct PositiveIsize(isize);
16
17impl PositiveIsize {
18 pub const fn new(value: isize) -> Option<Self> {
22 if value > 0 { Some(Self(value)) } else { None }
23 }
24
25 pub const fn new_unsigned(value: usize) -> Option<Self> {
29 match NonZeroUsize::new(value) {
30 Some(v) => Self::new_nonzero_unsigned(v),
31 None => None,
32 }
33 }
34
35 pub const fn new_nonzero_unsigned(value: NonZeroUsize) -> Option<Self> {
39 let value = value.get();
40 if value > (isize::MAX as usize) { None } else { Some(Self(value as isize)) }
41 }
42
43 pub const fn get(self) -> isize {
45 let Self(v) = self;
46 v
47 }
48}
49
50impl From<PositiveIsize> for isize {
51 fn from(PositiveIsize(value): PositiveIsize) -> Self {
52 value
53 }
54}
55
56impl From<PositiveIsize> for usize {
57 fn from(PositiveIsize(value): PositiveIsize) -> Self {
58 value as usize
61 }
62}
63
64impl From<PositiveIsize> for NonZeroIsize {
65 fn from(PositiveIsize(value): PositiveIsize) -> Self {
66 unsafe { NonZeroIsize::new_unchecked(value) }
68 }
69}
70
71impl From<PositiveIsize> for NonZeroUsize {
72 fn from(PositiveIsize(value): PositiveIsize) -> Self {
73 let value = value as usize;
75 unsafe { NonZeroUsize::new_unchecked(value) }
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83
84 #[test]
85 fn new_positive_isize() {
86 assert_eq!(PositiveIsize::new(0), None);
87 assert_eq!(PositiveIsize::new(-1), None);
88 assert_eq!(PositiveIsize::new(1), Some(PositiveIsize(1)));
89 assert_eq!(PositiveIsize::new(isize::MIN), None);
90 assert_eq!(PositiveIsize::new(isize::MAX), Some(PositiveIsize(isize::MAX)));
91 }
92
93 #[test]
94 fn new_unsigned_positive_isize() {
95 assert_eq!(PositiveIsize::new_unsigned(0), None);
96 assert_eq!(PositiveIsize::new_unsigned(usize::MAX), None);
97 assert_eq!(PositiveIsize::new_unsigned(1), Some(PositiveIsize(1)));
98 let max = usize::try_from(isize::MAX).unwrap();
99 assert_eq!(PositiveIsize::new_unsigned(max), Some(PositiveIsize(isize::MAX)));
100 assert_eq!(PositiveIsize::new_unsigned(max + 1), None);
101 }
102}