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