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 {
23 Some(Self(value))
24 } else {
25 None
26 }
27 }
28
29 pub const fn new_unsigned(value: usize) -> Option<Self> {
33 match NonZeroUsize::new(value) {
34 Some(v) => Self::new_nonzero_unsigned(v),
35 None => None,
36 }
37 }
38
39 pub const fn new_nonzero_unsigned(value: NonZeroUsize) -> Option<Self> {
43 let value = value.get();
44 if value > (isize::MAX as usize) {
45 None
46 } else {
47 Some(Self(value as isize))
48 }
49 }
50
51 pub const fn get(self) -> isize {
53 let Self(v) = self;
54 v
55 }
56}
57
58impl From<PositiveIsize> for isize {
59 fn from(PositiveIsize(value): PositiveIsize) -> Self {
60 value
61 }
62}
63
64impl From<PositiveIsize> for usize {
65 fn from(PositiveIsize(value): PositiveIsize) -> Self {
66 value as usize
69 }
70}
71
72impl From<PositiveIsize> for NonZeroIsize {
73 fn from(PositiveIsize(value): PositiveIsize) -> Self {
74 unsafe { NonZeroIsize::new_unchecked(value) }
76 }
77}
78
79impl From<PositiveIsize> for NonZeroUsize {
80 fn from(PositiveIsize(value): PositiveIsize) -> Self {
81 let value = value as usize;
83 unsafe { NonZeroUsize::new_unchecked(value) }
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn new_positive_isize() {
94 assert_eq!(PositiveIsize::new(0), None);
95 assert_eq!(PositiveIsize::new(-1), None);
96 assert_eq!(PositiveIsize::new(1), Some(PositiveIsize(1)));
97 assert_eq!(PositiveIsize::new(isize::MIN), None);
98 assert_eq!(PositiveIsize::new(isize::MAX), Some(PositiveIsize(isize::MAX)));
99 }
100
101 #[test]
102 fn new_unsigned_positive_isize() {
103 assert_eq!(PositiveIsize::new_unsigned(0), None);
104 assert_eq!(PositiveIsize::new_unsigned(usize::MAX), None);
105 assert_eq!(PositiveIsize::new_unsigned(1), Some(PositiveIsize(1)));
106 let max = usize::try_from(isize::MAX).unwrap();
107 assert_eq!(PositiveIsize::new_unsigned(max), Some(PositiveIsize(isize::MAX)));
108 assert_eq!(PositiveIsize::new_unsigned(max + 1), None);
109 }
110}