osom_lib_primitives/
length.rs1#![allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_sign_loss)]
2
3#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
11#[repr(transparent)]
12#[must_use]
13pub struct Length {
14 value: i32,
15}
16
17impl core::fmt::Debug for Length {
18 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
19 write!(f, "{}", self.value())
20 }
21}
22
23#[derive(Debug, Clone, PartialEq, Eq, Hash)]
25#[repr(u8)]
26pub enum LengthError {
27 TooLarge,
29
30 Negative,
32}
33
34impl Length {
35 pub const MAX: usize = (i32::MAX - 1024) as usize;
36 pub const ZERO: Self = unsafe { Self::new_unchecked(0) };
37
38 #[inline]
44 pub const fn try_from_usize(len: usize) -> Result<Self, LengthError> {
45 if len > Self::MAX {
46 return Err(LengthError::TooLarge);
47 }
48
49 Ok(unsafe { Self::new_unchecked(len as i32) })
50 }
51
52 #[inline]
58 pub const fn try_from_i32(len: i32) -> Result<Self, LengthError> {
59 if len < 0 {
60 return Err(LengthError::Negative);
61 }
62
63 if len as usize > Self::MAX {
64 return Err(LengthError::TooLarge);
65 }
66
67 Ok(unsafe { Self::new_unchecked(len) })
68 }
69
70 #[inline(always)]
76 pub const unsafe fn new_unchecked(len: i32) -> Self {
77 Self { value: len }
78 }
79
80 #[inline(always)]
82 #[must_use]
83 pub const fn value(&self) -> i32 {
84 unsafe { core::hint::assert_unchecked(self.value >= 0) };
85 self.value
86 }
87
88 #[inline]
94 pub const fn add(&mut self, value: i32) -> Result<(), LengthError> {
95 let new_value = self.value + value;
96 if new_value < 0 {
97 return Err(LengthError::Negative);
98 }
99
100 if new_value > Self::MAX as i32 {
101 return Err(LengthError::TooLarge);
102 }
103
104 self.value = new_value;
105 Ok(())
106 }
107
108 #[inline]
114 pub const fn mul(&mut self, value: i32) -> Result<(), LengthError> {
115 let new_value = self.value * value;
116 if new_value < 0 {
117 return Err(LengthError::Negative);
118 }
119
120 if new_value > Self::MAX as i32 {
121 return Err(LengthError::TooLarge);
122 }
123
124 self.value = new_value;
125 Ok(())
126 }
127}
128
129impl TryFrom<usize> for Length {
130 type Error = LengthError;
131
132 fn try_from(value: usize) -> Result<Self, Self::Error> {
133 Self::try_from_usize(value)
134 }
135}
136
137impl TryFrom<i32> for Length {
138 type Error = LengthError;
139
140 fn try_from(value: i32) -> Result<Self, Self::Error> {
141 Self::try_from_i32(value)
142 }
143}
144
145impl From<Length> for usize {
146 fn from(value: Length) -> Self {
147 value.value() as usize
148 }
149}
150
151impl From<Length> for i32 {
152 fn from(value: Length) -> Self {
153 value.value()
154 }
155}
156
157impl From<Length> for u32 {
158 fn from(value: Length) -> Self {
159 value.value() as u32
160 }
161}
162
163impl core::ops::Add<i32> for Length {
164 type Output = Self;
165
166 fn add(mut self, rhs: i32) -> Self::Output {
167 Self::add(&mut self, rhs).unwrap();
168 self
169 }
170}
171
172impl core::ops::AddAssign<i32> for Length {
173 fn add_assign(&mut self, rhs: i32) {
174 Self::add(self, rhs).unwrap();
175 }
176}
177
178impl core::ops::Add<Length> for Length {
179 type Output = Self;
180
181 fn add(self, rhs: Length) -> Self::Output {
182 self.add(rhs.value())
183 }
184}
185
186impl core::ops::AddAssign<Length> for Length {
187 fn add_assign(&mut self, rhs: Length) {
188 self.add(rhs.value()).unwrap();
189 }
190}
191
192impl core::ops::Sub<i32> for Length {
193 type Output = Self;
194
195 fn sub(mut self, rhs: i32) -> Self::Output {
196 self.value -= rhs;
197 self
198 }
199}
200
201impl core::ops::SubAssign<i32> for Length {
202 fn sub_assign(&mut self, rhs: i32) {
203 self.value -= rhs;
204 }
205}
206
207impl core::ops::Sub<Length> for Length {
208 type Output = Self;
209
210 fn sub(self, rhs: Length) -> Self::Output {
211 self + (-rhs.value())
212 }
213}
214
215impl core::ops::SubAssign<Length> for Length {
216 fn sub_assign(&mut self, rhs: Length) {
217 self.add(-rhs.value()).unwrap();
218 }
219}
220
221impl core::ops::Mul<i32> for Length {
222 type Output = Self;
223
224 fn mul(mut self, rhs: i32) -> Self::Output {
225 Self::mul(&mut self, rhs).unwrap();
226 self
227 }
228}
229
230impl core::ops::MulAssign<i32> for Length {
231 fn mul_assign(&mut self, rhs: i32) {
232 Self::mul(self, rhs).unwrap();
233 }
234}
235
236impl AsRef<i32> for Length {
237 fn as_ref(&self) -> &i32 {
238 &self.value
239 }
240}
241
242impl AsMut<i32> for Length {
243 fn as_mut(&mut self) -> &mut i32 {
244 &mut self.value
245 }
246}