1#![no_std]
6
7pub mod prelude {
16 pub use crate::{CastSigned as _, CastUnsigned as _, Extend as _, Truncate as _};
17}
18
19mod sealed {
20 pub trait Integer {}
21
22 macro_rules! impl_integer {
23 ($($t:ty)*) => {$(
24 impl Integer for $t {}
25 )*};
26 }
27
28 impl Integer for isize {}impl_integer! {
29 u8 u16 u32 u64 u128 usize
30 i8 i16 i32 i64 i128 isize
31 }
32
33 pub trait ExtendTargetSealed<T> {
34 fn extend(self) -> T;
35 }
36
37 pub trait TruncateTargetSealed<T> {
38 fn truncate(self) -> T;
39 }
40}
41
42pub trait CastSigned: sealed::Integer {
67 type Signed;
69
70 fn cast_signed(self) -> Self::Signed;
72}
73
74pub trait CastUnsigned: sealed::Integer {
99 type Unsigned;
101
102 fn cast_unsigned(self) -> Self::Unsigned;
104}
105
106pub trait ExtendTarget<T>: sealed::ExtendTargetSealed<T> {}
111
112pub trait TruncateTarget<T>: sealed::TruncateTargetSealed<T> {}
117
118pub trait Extend: sealed::Integer {
136 fn extend<T>(self) -> T
138 where
139 Self: ExtendTarget<T>;
140}
141
142impl<T: sealed::Integer> Extend for T {
143 fn extend<U>(self) -> U
144 where
145 T: ExtendTarget<U>,
146 {
147 sealed::ExtendTargetSealed::extend(self)
148 }
149}
150
151pub trait Truncate: sealed::Integer {
169 fn truncate<T>(self) -> T
172 where
173 Self: TruncateTarget<T>;
174}
175
176impl<T: sealed::Integer> Truncate for T {
177 fn truncate<U>(self) -> U
178 where
179 T: TruncateTarget<U>,
180 {
181 sealed::TruncateTargetSealed::truncate(self)
182 }
183}
184
185macro_rules! impl_cast_signed {
186 ($($($from:ty),+ => $to:ty;)*) => {$($(
187 const _: () = assert!(
188 core::mem::size_of::<$from>() == core::mem::size_of::<$to>(),
189 concat!(
190 "cannot cast ",
191 stringify!($from),
192 " to ",
193 stringify!($to),
194 " because they are different sizes"
195 )
196 );
197
198 impl CastSigned for $from {
199 type Signed = $to;
200 fn cast_signed(self) -> Self::Signed {
201 self as _
202 }
203 }
204 )+)*};
205}
206
207macro_rules! impl_cast_unsigned {
208 ($($($from:ty),+ => $to:ty;)*) => {$($(
209 const _: () = assert!(
210 core::mem::size_of::<$from>() == core::mem::size_of::<$to>(),
211 concat!(
212 "cannot cast ",
213 stringify!($from),
214 " to ",
215 stringify!($to),
216 " because they are different sizes"
217 )
218 );
219
220 impl CastUnsigned for $from {
221 type Unsigned = $to;
222 fn cast_unsigned(self) -> Self::Unsigned {
223 self as _
224 }
225 }
226 )+)*};
227}
228
229macro_rules! impl_extend {
230 ($($from:ty => $($to:ty),+;)*) => {$($(
231 const _: () = assert!(
232 core::mem::size_of::<$from>() <= core::mem::size_of::<$to>(),
233 concat!(
234 "cannot extend ",
235 stringify!($from),
236 " to ",
237 stringify!($to),
238 " because ",
239 stringify!($from),
240 " is larger than ",
241 stringify!($to)
242 )
243 );
244
245 impl sealed::ExtendTargetSealed<$to> for $from {
246 fn extend(self) -> $to {
247 self as _
248 }
249 }
250
251 impl ExtendTarget<$to> for $from {}
252 )+)*};
253}
254
255macro_rules! impl_truncate {
256 ($($($from:ty),+ => $to:ty;)*) => {$($(
257 const _: () = assert!(
258 core::mem::size_of::<$from>() >= core::mem::size_of::<$to>(),
259 concat!(
260 "cannot truncate ",
261 stringify!($from),
262 " to ",
263 stringify!($to),
264 " because ",
265 stringify!($from),
266 " is smaller than ",
267 stringify!($to)
268 )
269 );
270
271 impl sealed::TruncateTargetSealed<$to> for $from {
272 fn truncate(self) -> $to {
273 self as _
274 }
275 }
276
277 impl TruncateTarget<$to> for $from {}
278 )+)*};
279}
280
281const _: () =
if !(core::mem::size_of::<isize>() == core::mem::size_of::<isize>()) {
{
::core::panicking::panic_fmt(format_args!("cannot cast isize to isize because they are different sizes"));
}
};
impl CastSigned for isize {
type Signed = isize;
fn cast_signed(self) -> Self::Signed { self as _ }
}impl_cast_signed! {
282 u8, i8 => i8;
283 u16, i16 => i16;
284 u32, i32 => i32;
285 u64, i64 => i64;
286 u128, i128 => i128;
287 usize, isize => isize;
288}
289
290const _: () =
if !(core::mem::size_of::<isize>() == core::mem::size_of::<usize>()) {
{
::core::panicking::panic_fmt(format_args!("cannot cast isize to usize because they are different sizes"));
}
};
impl CastUnsigned for isize {
type Unsigned = usize;
fn cast_unsigned(self) -> Self::Unsigned { self as _ }
}impl_cast_unsigned! {
291 u8, i8 => u8;
292 u16, i16 => u16;
293 u32, i32 => u32;
294 u64, i64 => u64;
295 u128, i128 => u128;
296 usize, isize => usize;
297}
298
299const _: () =
if !(core::mem::size_of::<isize>() <= core::mem::size_of::<isize>()) {
{
::core::panicking::panic_fmt(format_args!("cannot extend isize to isize because isize is larger than isize"));
}
};
impl sealed::ExtendTargetSealed<isize> for isize {
fn extend(self) -> isize { self as _ }
}
impl ExtendTarget<isize> for isize {}impl_extend! {
300 u8 => u8, u16, u32, u64, u128, usize;
301 u16 => u16, u32, u64, u128, usize;
302 u32 => u32, u64, u128;
303 u64 => u64, u128;
304 u128 => u128;
305 usize => usize;
306
307 i8 => i8, i16, i32, i64, i128, isize;
308 i16 => i16, i32, i64, i128, isize;
309 i32 => i32, i64, i128;
310 i64 => i64, i128;
311 i128 => i128;
312 isize => isize;
313}
314
315const _: () =
if !(core::mem::size_of::<isize>() >= core::mem::size_of::<isize>()) {
{
::core::panicking::panic_fmt(format_args!("cannot truncate isize to isize because isize is smaller than isize"));
}
};
impl sealed::TruncateTargetSealed<isize> for isize {
fn truncate(self) -> isize { self as _ }
}
impl TruncateTarget<isize> for isize {}impl_truncate! {
316 u8, u16, u32, u64, u128, usize => u8;
317 u16, u32, u64, u128, usize => u16;
318 u32, u64, u128 => u32;
319 u64, u128 => u64;
320 u128 => u128;
321 usize => usize;
322
323 i8, i16, i32, i64, i128, isize => i8;
324 i16, i32, i64, i128, isize => i16;
325 i32, i64, i128 => i32;
326 i64, i128 => i64;
327 i128 => i128;
328 isize => isize;
329}