bounded_integer/
prim_int.rs1#![expect(clippy::must_use_candidate)]
2
3use core::fmt::{self, Display, Formatter};
4use core::num::NonZero;
5
6#[derive(Debug, Clone, Copy)]
8#[non_exhaustive]
9pub struct TryFromError;
10
11impl Display for TryFromError {
12 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
13 f.write_str("out of range conversion to bounded integer attempted")
14 }
15}
16
17#[cfg(feature = "std")]
18impl std::error::Error for TryFromError {}
19
20#[must_use]
21pub fn try_from_error() -> TryFromError {
22 TryFromError
23}
24
25pub trait PrimInt {
26 type Signed;
27 type Unsigned;
28}
29
30pub type Signed<T> = <T as PrimInt>::Signed;
31pub type Unsigned<T> = <T as PrimInt>::Unsigned;
32
33generate! {
34 u8 i8,
35 u16 i16,
36 u32 i32,
37 u64 i64,
38 u128 i128,
39 usize isize,
40}
41
42macro_rules! generate {
43 ($($unsigned:ident $signed:ident,)*) => { $(
44 impl PrimInt for $unsigned {
45 type Signed = $signed;
46 type Unsigned = $unsigned;
47 }
48 impl PrimInt for $signed {
49 type Signed = $signed;
50 type Unsigned = $unsigned;
51 }
52
53 impl crate::__private::Dispatch<$unsigned> {
54 pub const fn checked_add_unsigned(lhs: $unsigned, rhs: $unsigned) -> Option<$unsigned> {
55 lhs.checked_add(rhs)
56 }
57 pub const fn checked_sub_unsigned(lhs: $unsigned, rhs: $unsigned) -> Option<$unsigned> {
58 lhs.checked_sub(rhs)
59 }
60 pub const fn rem_euclid_unsigned(lhs: $unsigned, rhs: NonZero<$unsigned>) -> $unsigned {
61 lhs.rem_euclid(rhs.get())
62 }
63 }
64 impl crate::__private::Dispatch<$signed> {
65 pub const fn checked_add_unsigned(lhs: $signed, rhs: $unsigned) -> Option<$signed> {
66 lhs.checked_add_unsigned(rhs)
67 }
68 pub const fn checked_sub_unsigned(lhs: $signed, rhs: $unsigned) -> Option<$signed> {
69 lhs.checked_sub_unsigned(rhs)
70 }
71 pub const fn rem_euclid_unsigned(lhs: $signed, rhs: NonZero<$unsigned>) -> $unsigned {
72 #[expect(clippy::cast_possible_wrap)]
74 #[expect(clippy::cast_sign_loss)]
75 if 0 <= lhs {
76 (lhs as $unsigned).rem_euclid(rhs.get())
78 } else if 0 <= rhs.get() as $signed {
79 lhs.rem_euclid(rhs.get() as $signed) as $unsigned
82 } else {
83 rhs.get().checked_add_signed(lhs).unwrap().rem_euclid(rhs.get())
87 }
88 }
89 }
90 )* };
91}
92use generate;
93
94pub trait HasWide {
97 type Wide;
98}
99
100pub type Wide<T> = <T as HasWide>::Wide;
101
102impl HasWide for u8 {
103 type Wide = u16;
104}
105impl HasWide for u16 {
106 type Wide = u32;
107}
108impl HasWide for u32 {
109 type Wide = u64;
110}
111impl HasWide for u64 {
112 type Wide = u128;
113}
114impl HasWide for i8 {
115 type Wide = i16;
116}
117impl HasWide for i16 {
118 type Wide = i32;
119}
120impl HasWide for i32 {
121 type Wide = i64;
122}
123impl HasWide for i64 {
124 type Wide = i128;
125}