1pub trait Signed {
12 type Signed;
14
15 type Unsigned;
17
18 fn as_unsigned(self) -> Self::Unsigned;
20
21 fn as_signed(self) -> Self::Signed;
23
24 fn abs_unsigned(self) -> Self::Unsigned;
26
27 }
29
30pub trait IsSigned: Signed<Signed = Self> {}
32impl<T: Signed<Signed = T>> IsSigned for T {}
33
34pub trait IsUnsigned: Signed<Unsigned = Self> {}
36impl<T: Signed<Unsigned = T>> IsUnsigned for T {}
37
38macro_rules! impl_signed {
40 (- $TSigned:ty : + $TUnsigned:ty) => {
41 ::static_assertions::assert_eq_size!($TSigned, $TUnsigned);
43
44 impl Signed for $TSigned {
45 type Signed = $TSigned;
46 type Unsigned = $TUnsigned;
47
48 #[inline]
49 #[allow(clippy::as_conversions)]
50 fn as_unsigned(self) -> Self::Unsigned {
51 self as $TUnsigned
53 }
54
55 #[inline]
56 fn as_signed(self) -> Self::Signed {
57 self
58 }
59
60 #[inline]
61 fn abs_unsigned(self) -> Self::Unsigned {
62 if self < 0 {
64 (!self.as_unsigned()).wrapping_add(1)
66 } else {
67 self.as_unsigned()
68 }
69 }
70 }
71
72 impl Signed for $TUnsigned {
73 type Signed = $TSigned;
74 type Unsigned = $TUnsigned;
75
76 #[inline]
77 fn as_unsigned(self) -> Self::Unsigned {
78 self
79 }
80
81 #[inline]
82 #[allow(clippy::as_conversions)]
83 fn as_signed(self) -> Self::Signed {
84 self as $TSigned
86 }
87
88 #[inline]
89 fn abs_unsigned(self) -> Self::Unsigned {
90 self
92 }
93 }
94 };
95}
96
97impl_signed! { -i8 : +u8 }
98impl_signed! { -i16 : +u16 }
99impl_signed! { -i32 : +u32 }
100impl_signed! { -i64 : +u64 }
101impl_signed! { -i128 : +u128 }
102impl_signed! { -isize : +usize }
103
104static_assertions::assert_impl_all! { i8 : Signed, IsSigned }
106static_assertions::assert_impl_all! { i16 : Signed, IsSigned }
107static_assertions::assert_impl_all! { i32 : Signed, IsSigned }
108static_assertions::assert_impl_all! { i64 : Signed, IsSigned }
109static_assertions::assert_impl_all! { i128 : Signed, IsSigned }
110static_assertions::assert_impl_all! { isize: Signed, IsSigned }
111static_assertions::assert_impl_all! { u8 : Signed, IsUnsigned }
112static_assertions::assert_impl_all! { u16 : Signed, IsUnsigned }
113static_assertions::assert_impl_all! { u32 : Signed, IsUnsigned }
114static_assertions::assert_impl_all! { u64 : Signed, IsUnsigned }
115static_assertions::assert_impl_all! { u128 : Signed, IsUnsigned }
116static_assertions::assert_impl_all! { usize: Signed, IsUnsigned }
117
118static_assertions::assert_type_eq_all! { <i8 as Signed>::Signed, <u8 as Signed>::Signed, i8 }
120static_assertions::assert_type_eq_all! { <i16 as Signed>::Signed, <u16 as Signed>::Signed, i16 }
121static_assertions::assert_type_eq_all! { <i32 as Signed>::Signed, <u32 as Signed>::Signed, i32 }
122static_assertions::assert_type_eq_all! { <i64 as Signed>::Signed, <u64 as Signed>::Signed, i64 }
123static_assertions::assert_type_eq_all! { <i128 as Signed>::Signed, <u128 as Signed>::Signed, i128 }
124static_assertions::assert_type_eq_all! { <isize as Signed>::Signed, <usize as Signed>::Signed, isize }
125static_assertions::assert_type_eq_all! { <i8 as Signed>::Unsigned, <u8 as Signed>::Unsigned, u8 }
126static_assertions::assert_type_eq_all! { <i16 as Signed>::Unsigned, <u16 as Signed>::Unsigned, u16 }
127static_assertions::assert_type_eq_all! { <i32 as Signed>::Unsigned, <u32 as Signed>::Unsigned, u32 }
128static_assertions::assert_type_eq_all! { <i64 as Signed>::Unsigned, <u64 as Signed>::Unsigned, u64 }
129static_assertions::assert_type_eq_all! { <i128 as Signed>::Unsigned, <u128 as Signed>::Unsigned, u128 }
130static_assertions::assert_type_eq_all! { <isize as Signed>::Unsigned, <usize as Signed>::Unsigned, usize }
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135
136 #[test]
137 #[rustfmt::skip]
138 fn as_unsigned_positive() {
139 assert_eq!(u8 ::as_unsigned(1), 1);
140 assert_eq!(u16 ::as_unsigned(1), 1);
141 assert_eq!(u32 ::as_unsigned(1), 1);
142 assert_eq!(u64 ::as_unsigned(1), 1);
143 assert_eq!(u128 ::as_unsigned(1), 1);
144 assert_eq!(usize::as_unsigned(1), 1);
145 }
146
147 #[test]
148 #[rustfmt::skip]
149 fn as_unsigned_negative() {
150 assert_eq!(i8 ::as_unsigned(-1), u8 ::MAX);
151 assert_eq!(i16 ::as_unsigned(-1), u16 ::MAX);
152 assert_eq!(i32 ::as_unsigned(-1), u32 ::MAX);
153 assert_eq!(i64 ::as_unsigned(-1), u64 ::MAX);
154 assert_eq!(i128 ::as_unsigned(-1), u128 ::MAX);
155 assert_eq!(isize::as_unsigned(-1), usize::MAX);
156 }
157
158 #[test]
159 #[rustfmt::skip]
160 fn as_unsigned_negative_big() {
161 assert_eq!(i8 ::as_unsigned(i8 ::MIN), u8 ::MAX / 2 + 1);
162 assert_eq!(i16 ::as_unsigned(i16 ::MIN), u16 ::MAX / 2 + 1);
163 assert_eq!(i32 ::as_unsigned(i32 ::MIN), u32 ::MAX / 2 + 1);
164 assert_eq!(i64 ::as_unsigned(i64 ::MIN), u64 ::MAX / 2 + 1);
165 assert_eq!(i128 ::as_unsigned(i128 ::MIN), u128 ::MAX / 2 + 1);
166 assert_eq!(isize::as_unsigned(isize::MIN), usize::MAX / 2 + 1);
167 }
168
169 #[test]
170 #[rustfmt::skip]
171 fn as_signed_positive() {
172 assert_eq!(u8 ::as_signed(1), 1);
173 assert_eq!(u16 ::as_signed(1), 1);
174 assert_eq!(u32 ::as_signed(1), 1);
175 assert_eq!(u64 ::as_signed(1), 1);
176 assert_eq!(u128 ::as_signed(1), 1);
177 assert_eq!(usize::as_signed(1), 1);
178 }
179
180 #[test]
181 #[rustfmt::skip]
182 fn as_signed_negative() {
183 assert_eq!(i8 ::as_signed(u8 ::MAX.as_signed()), -1);
184 assert_eq!(i16 ::as_signed(u16 ::MAX.as_signed()), -1);
185 assert_eq!(i32 ::as_signed(u32 ::MAX.as_signed()), -1);
186 assert_eq!(i64 ::as_signed(u64 ::MAX.as_signed()), -1);
187 assert_eq!(i128 ::as_signed(u128 ::MAX.as_signed()), -1);
188 assert_eq!(isize::as_signed(usize::MAX.as_signed()), -1);
189 }
190
191 #[test]
192 #[rustfmt::skip]
193 fn abs_unsigned_unsigned() {
194 assert_eq!(u8 ::abs_unsigned(1), 1);
195 assert_eq!(u16 ::abs_unsigned(1), 1);
196 assert_eq!(u32 ::abs_unsigned(1), 1);
197 assert_eq!(u64 ::abs_unsigned(1), 1);
198 assert_eq!(u128 ::abs_unsigned(1), 1);
199 assert_eq!(usize::abs_unsigned(1), 1);
200 }
201
202 #[test]
203 #[rustfmt::skip]
204 fn abs_unsigned_unsigned_big() {
205 assert_eq!(u8 ::abs_unsigned(u8 ::MAX), u8 ::MAX);
206 assert_eq!(u16 ::abs_unsigned(u16 ::MAX), u16 ::MAX);
207 assert_eq!(u32 ::abs_unsigned(u32 ::MAX), u32 ::MAX);
208 assert_eq!(u64 ::abs_unsigned(u64 ::MAX), u64 ::MAX);
209 assert_eq!(u128 ::abs_unsigned(u128 ::MAX), u128 ::MAX);
210 assert_eq!(usize::abs_unsigned(usize::MAX), usize::MAX);
211 }
212
213 #[test]
214 #[rustfmt::skip]
215 fn abs_unsigned_signed_positive() {
216 assert_eq!(i8 ::abs_unsigned(1), 1);
217 assert_eq!(i16 ::abs_unsigned(1), 1);
218 assert_eq!(i32 ::abs_unsigned(1), 1);
219 assert_eq!(i64 ::abs_unsigned(1), 1);
220 assert_eq!(i128 ::abs_unsigned(1), 1);
221 assert_eq!(isize::abs_unsigned(1), 1);
222 }
223
224 #[test]
225 #[rustfmt::skip]
226 fn abs_unsigned_signed_positive_big() {
227 assert_eq!(i8 ::abs_unsigned(i8 ::MAX), u8 ::MAX / 2);
228 assert_eq!(i16 ::abs_unsigned(i16 ::MAX), u16 ::MAX / 2);
229 assert_eq!(i32 ::abs_unsigned(i32 ::MAX), u32 ::MAX / 2);
230 assert_eq!(i64 ::abs_unsigned(i64 ::MAX), u64 ::MAX / 2);
231 assert_eq!(i128 ::abs_unsigned(i128 ::MAX), u128 ::MAX / 2);
232 assert_eq!(isize::abs_unsigned(isize::MAX), usize::MAX / 2);
233 }
234
235 #[test]
236 #[rustfmt::skip]
237 fn abs_unsigned_signed_negative() {
238 assert_eq!(i8 ::abs_unsigned(-1), 1);
239 assert_eq!(i16 ::abs_unsigned(-1), 1);
240 assert_eq!(i32 ::abs_unsigned(-1), 1);
241 assert_eq!(i64 ::abs_unsigned(-1), 1);
242 assert_eq!(i128 ::abs_unsigned(-1), 1);
243 assert_eq!(isize::abs_unsigned(-1), 1);
244 }
245
246 #[test]
247 #[rustfmt::skip]
248 fn abs_unsigned_signed_negative_big() {
249 assert_eq!(i8 ::abs_unsigned(i8 ::MIN), u8 ::MAX / 2 + 1);
250 assert_eq!(i16 ::abs_unsigned(i16 ::MIN), u16 ::MAX / 2 + 1);
251 assert_eq!(i32 ::abs_unsigned(i32 ::MIN), u32 ::MAX / 2 + 1);
252 assert_eq!(i64 ::abs_unsigned(i64 ::MIN), u64 ::MAX / 2 + 1);
253 assert_eq!(i128 ::abs_unsigned(i128 ::MIN), u128 ::MAX / 2 + 1);
254 assert_eq!(isize::abs_unsigned(isize::MIN), usize::MAX / 2 + 1);
255 }
256}