1use core::fmt::{Debug, Display};
4use core::num::ParseIntError;
5use core::ops::{
6 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, Mul, MulAssign,
7 Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
8};
9
10pub trait WordBase: Debug + Display + Copy + Eq + Ord + Default {}
13
14impl<T> WordBase for T where T: Debug + Display + Copy + Eq + Ord + Default {}
15
16pub trait WordConvert: TryFrom<usize> + Into<usize> + From<i32> {}
19
20impl<T> WordConvert for T where T: TryFrom<usize> + Into<usize> + From<i32> {}
21
22pub trait WordOps:
25 Sized
26 + Add<Output = Self>
27 + Sub<Output = Self>
28 + Mul<Output = Self>
29 + Div<Output = Self>
30 + AddAssign
31 + SubAssign
32 + MulAssign
33 + DivAssign
34 + Neg
35 + Rem
36 + RemAssign
37{
38}
39
40impl<T> WordOps for T where
41 T: Add<Output = Self>
42 + Sub<Output = Self>
43 + Mul<Output = Self>
44 + Div<Output = Self>
45 + Rem<Output = Self>
46 + AddAssign
47 + SubAssign
48 + MulAssign
49 + DivAssign
50 + RemAssign
51 + Neg
52{
53}
54
55pub trait WordBitOps:
58 Sized
59 + BitAnd<Self, Output = Self>
60 + BitOr<Self, Output = Self>
61 + BitXor<Self, Output = Self>
62 + Not<Output = Self>
63 + Shl<Self, Output = Self>
64 + Shr<Self, Output = Self>
65 + BitAndAssign
66 + BitOrAssign
67 + BitXorAssign
68 + ShlAssign
69 + ShrAssign
70{
71}
72
73impl<T> WordBitOps for T where
74 T: BitAnd<Self, Output = Self>
75 + BitOr<Self, Output = Self>
76 + BitXor<Self, Output = Self>
77 + Not<Output = Self>
78 + Shl<Self, Output = Self>
79 + Shr<Self, Output = Self>
80 + BitAndAssign
81 + BitOrAssign
82 + BitXorAssign
83 + ShlAssign
84 + ShrAssign
85{
86}
87
88pub trait Word: WordBase + WordConvert + WordOps + WordBitOps {
102 fn from_str_radix(s: &str, radix: u32) -> Result<Self, ParseIntError>;
107
108 #[must_use]
110 fn check_carry_add(&self, rhs: Self) -> bool;
111
112 #[must_use]
114 fn check_carry_sub(&self, rhs: Self) -> bool;
115
116 #[must_use]
118 fn check_carry_mul(&self, rhs: Self) -> bool;
119
120 #[must_use]
124 fn check_carry_div(&self, rhs: Self) -> bool;
125
126 #[must_use]
128 fn overflowing_add(&self, rhs: Self) -> (Self, bool);
129 #[must_use]
131 fn overflowing_sub(&self, rhs: Self) -> (Self, bool);
132 #[must_use]
134 fn overflowing_mul(&self, rhs: Self) -> (Self, bool);
135 #[must_use]
137 fn overflowing_div(&self, rhs: Self) -> (Self, bool);
138
139 #[must_use]
141 fn rotate_left(&self, val: u32) -> Self;
142 #[must_use]
144 fn rotate_right(&self, val: u32) -> Self;
145}
146
147macro_rules! from_i32 {
151 ($name: ident, $type: ty $(,)? ) => {
152 impl ::core::convert::From<i32> for $name {
153 fn from(value: i32) -> Self {
154 #[allow(clippy::cast_possible_truncation)]
155 #[allow(clippy::cast_lossless)]
156 #[allow(clippy::cast_sign_loss)]
157 $name(value as $type)
158 }
159 }
160 };
161}
162
163macro_rules! impl_word {
165 ($name: ident, $type: ty $(,)? ) => {
166 #[doc = concat!("Wrapper struct around ", stringify!($type), ".")]
167 #[doc = concat!("Represents a ", stringify!($type), "-bit processor architecture.")]
168 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
169 #[repr(transparent)]
170 pub struct $name($type);
171
172 impl Word for $name {
173 fn from_str_radix(s: &str, radix: u32) -> Result<Self, ParseIntError> {
174 <$type>::from_str_radix(s, radix).map($name)
175 }
176
177 fn check_carry_add(&self, rhs: Self) -> bool {
178 #[allow(clippy::cast_sign_loss)]
179 let (lhs, rhs) = (self.0 as u128, rhs.0 as u128);
180 lhs + rhs > <$type>::MAX as u128
181 }
182
183 fn check_carry_sub(&self, rhs: Self) -> bool {
184 #[allow(clippy::cast_sign_loss)]
185 let (lhs, rhs) = (self.0 as u128, rhs.0 as u128);
186 lhs < rhs
187 }
188
189 fn check_carry_mul(&self, rhs: Self) -> bool {
190 #[allow(clippy::cast_sign_loss)]
191 let (lhs, rhs) = (self.0 as u128, rhs.0 as u128);
192 lhs * rhs > <$type>::MAX as u128
193 }
194
195 fn check_carry_div(&self, rhs: Self) -> bool {
196 self.0.overflowing_div(rhs.0).1
197 }
198
199 fn overflowing_add(&self, rhs: Self) -> (Self, bool) {
200 let (res, overflow) = self.0.overflowing_add(rhs.0);
201 (Self(res), overflow)
202 }
203
204 fn overflowing_sub(&self, rhs: Self) -> (Self, bool) {
205 let (res, overflow) = self.0.overflowing_sub(rhs.0);
206 (Self(res), overflow)
207 }
208
209 fn overflowing_mul(&self, rhs: Self) -> (Self, bool) {
210 let (res, overflow) = self.0.overflowing_mul(rhs.0);
211 (Self(res), overflow)
212 }
213
214 fn overflowing_div(&self, rhs: Self) -> (Self, bool) {
215 let (res, overflow) = self.0.overflowing_div(rhs.0);
216 (Self(res), overflow)
217 }
218
219 fn rotate_left(&self, val: u32) -> Self {
220 Self(self.0.rotate_left(val))
221 }
222
223 fn rotate_right(&self, val: u32) -> Self {
224 Self(self.0.rotate_right(val))
225 }
226 }
227
228 impl ::core::fmt::Display for $name {
229 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> Result<(), ::core::fmt::Error> {
230 write!(f, "{}", self.0)
231 }
232 }
233
234 impl ::core::convert::From<$name> for usize {
235 #[allow(clippy::cast_sign_loss)]
236 #[allow(clippy::cast_possible_truncation)]
237 fn from(value: $name) -> usize {
238 value.0 as usize
239 }
240 }
241
242 impl ::core::convert::TryFrom<usize> for $name {
243 type Error = ::core::num::TryFromIntError;
244
245 fn try_from(value: usize) -> Result<Self, Self::Error> {
246 Ok(Self(<$type>::try_from(value)?))
247 }
248 }
249
250 impl ::core::convert::From<$type> for $name {
251 fn from(value: $type) -> Self {
252 Self(value)
253 }
254 }
255
256 impl ::core::ops::Add for $name {
257 type Output = Self;
258
259 fn add(self, rhs: Self) -> Self {
260 Self(self.0.wrapping_add(rhs.0))
261 }
262 }
263
264 impl ::core::ops::AddAssign for $name {
265 fn add_assign(&mut self, other: Self) {
266 *self = *self + other;
267 }
268 }
269
270 impl ::core::ops::Sub for $name {
271 type Output = Self;
272
273 fn sub(self, rhs: Self) -> Self {
274 Self(self.0.wrapping_sub(rhs.0))
275 }
276 }
277
278 impl ::core::ops::SubAssign for $name {
279 fn sub_assign(&mut self, other: Self) {
280 *self = *self - other;
281 }
282 }
283
284 impl ::core::ops::Mul for $name {
285 type Output = Self;
286
287 fn mul(self, rhs: Self) -> Self {
288 Self(self.0.wrapping_mul(rhs.0))
289 }
290 }
291
292 impl ::core::ops::MulAssign for $name {
293 fn mul_assign(&mut self, other: Self) {
294 *self = *self * other;
295 }
296 }
297
298 impl ::core::ops::Div for $name {
299 type Output = Self;
300
301 fn div(self, rhs: Self) -> Self {
302 Self(self.0.wrapping_div(rhs.0))
303 }
304 }
305
306 impl ::core::ops::DivAssign for $name {
307 fn div_assign(&mut self, other: Self) {
308 *self = *self / other;
309 }
310 }
311
312 impl ::core::ops::Neg for $name {
313 type Output = Self;
314
315 fn neg(self) -> Self {
316 Self(self.0.wrapping_neg())
317 }
318 }
319
320 impl ::core::ops::Rem for $name {
321 type Output = Self;
322
323 fn rem(self, rhs: Self) -> Self {
324 Self(self.0.wrapping_rem(rhs.0))
325 }
326 }
327
328 impl ::core::ops::RemAssign for $name {
329 fn rem_assign(&mut self, rhs: Self) {
330 *self = *self % rhs
331 }
332 }
333
334 impl ::core::ops::BitAnd for $name {
335 type Output = Self;
336
337 fn bitand(self, rhs: Self) -> Self {
338 Self(self.0 & rhs.0)
339 }
340 }
341
342 impl ::core::ops::BitOr for $name {
343 type Output = Self;
344
345 fn bitor(self, rhs: Self) -> Self {
346 Self(self.0 | rhs.0)
347 }
348 }
349
350 impl ::core::ops::BitXor for $name {
351 type Output = Self;
352
353 fn bitxor(self, rhs: Self) -> Self {
354 Self(self.0 ^ rhs.0)
355 }
356 }
357
358 impl ::core::ops::Not for $name {
359 type Output = Self;
360
361 fn not(self) -> Self {
362 Self(!self.0)
363 }
364 }
365
366 impl ::core::ops::Shl for $name {
367 type Output = Self;
368
369 fn shl(self, rhs: Self) -> Self {
370 Self(self.0 << rhs.0)
371 }
372 }
373
374 impl ::core::ops::Shr for $name {
375 type Output = Self;
376
377 fn shr(self, rhs: Self) -> Self {
378 Self(self.0 >> rhs.0)
379 }
380 }
381
382 impl ::core::ops::BitAndAssign for $name {
383 fn bitand_assign(&mut self, rhs: Self) {
384 self.0 &= rhs.0;
385 }
386 }
387
388 impl ::core::ops::BitOrAssign for $name {
389 fn bitor_assign(&mut self, rhs: Self) {
390 self.0 |= rhs.0;
391 }
392 }
393
394 impl ::core::ops::BitXorAssign for $name {
395 fn bitxor_assign(&mut self, rhs: Self) {
396 self.0 ^= rhs.0;
397 }
398 }
399
400 impl ::core::ops::ShlAssign for $name {
401 fn shl_assign(&mut self, rhs: Self) {
402 self.0 <<= rhs.0;
403 }
404 }
405
406 impl ::core::ops::ShrAssign for $name {
407 fn shr_assign(&mut self, rhs: Self) {
408 self.0 >>= rhs.0;
409 }
410 }
411 };
412}
413
414impl_word!(I8, i8);
415impl_word!(I16, i16);
416impl_word!(I32, i32);
417impl_word!(I64, i64);
418impl_word!(I128, i128);
419impl_word!(ISize, isize);
420
421from_i32!(I8, i8);
422from_i32!(I16, i16);
423from_i32!(I64, i64);
424from_i32!(I128, i128);
425from_i32!(ISize, isize);