1#![allow(trivial_numeric_casts)]
19
20pub trait CastFrom<T> {
37 fn cast_from(from: T) -> Self;
39}
40
41pub trait CastInto<T> {
44 fn cast_into(self) -> T;
46}
47
48impl<T, U> CastInto<U> for T
49where
50 U: CastFrom<T>,
51{
52 fn cast_into(self) -> U {
53 U::cast_from(self)
54 }
55}
56
57macro_rules! cast_from {
58 ($from:ty, $to:ty) => {
59 paste::paste! {
60 impl crate::cast::CastFrom<$from> for $to {
61 #[allow(clippy::as_conversions)]
62 fn cast_from(from: $from) -> $to {
63 from as $to
64 }
65 }
66
67 #[allow(clippy::as_conversions)]
72 pub const fn [< $from _to_ $to >](from: $from) -> $to {
73 from as $to
74 }
75
76 impl crate::cast::CastFrom<std::num::NonZero<$from>> for $to {
77 #[allow(clippy::as_conversions)]
78 fn cast_from(from: std::num::NonZero<$from>) -> $to {
79 from.get() as $to
80 }
81 }
82 }
83 };
84}
85
86#[cfg(target_pointer_width = "32")]
87mod target32 {
89 cast_from!(u8, usize);
91 cast_from!(u16, usize);
92 cast_from!(u8, isize);
93 cast_from!(i8, isize);
94 cast_from!(u16, isize);
95 cast_from!(i16, isize);
96
97 cast_from!(usize, u64);
98 cast_from!(usize, i64);
99 cast_from!(usize, u128);
100 cast_from!(usize, i128);
101 cast_from!(isize, i64);
102 cast_from!(isize, i128);
103
104 cast_from!(usize, u32);
106 cast_from!(isize, i32);
107 cast_from!(u32, usize);
108 cast_from!(i32, isize);
109}
110#[cfg(target_pointer_width = "32")]
111pub use target32::*;
112
113#[cfg(target_pointer_width = "64")]
114pub mod target64 {
116 cast_from!(u8, usize);
118 cast_from!(u16, usize);
119 cast_from!(u32, usize);
120 cast_from!(u8, isize);
121 cast_from!(i8, isize);
122 cast_from!(u16, isize);
123 cast_from!(i16, isize);
124 cast_from!(u32, isize);
125 cast_from!(i32, isize);
126
127 cast_from!(usize, u128);
128 cast_from!(usize, i128);
129 cast_from!(isize, i128);
130
131 cast_from!(usize, u64);
133 cast_from!(isize, i64);
134 cast_from!(u64, usize);
135 cast_from!(i64, isize);
136}
137#[cfg(target_pointer_width = "64")]
138pub use target64::*;
139
140cast_from!(u8, u8);
142cast_from!(u8, u16);
143cast_from!(u8, i16);
144cast_from!(u8, u32);
145cast_from!(u8, i32);
146cast_from!(u8, u64);
147cast_from!(u8, i64);
148cast_from!(u8, u128);
149cast_from!(u8, i128);
150cast_from!(u16, u16);
151cast_from!(u16, u32);
152cast_from!(u16, i32);
153cast_from!(u16, u64);
154cast_from!(u16, i64);
155cast_from!(u16, u128);
156cast_from!(u16, i128);
157cast_from!(u32, u32);
158cast_from!(u32, u64);
159cast_from!(u32, i64);
160cast_from!(u32, u128);
161cast_from!(u32, i128);
162cast_from!(u64, u64);
163cast_from!(u64, u128);
164cast_from!(u64, i128);
165cast_from!(i8, i8);
166cast_from!(i8, i16);
167cast_from!(i8, i32);
168cast_from!(i8, i64);
169cast_from!(i8, i128);
170cast_from!(i16, i16);
171cast_from!(i16, i32);
172cast_from!(i16, i64);
173cast_from!(i16, i128);
174cast_from!(i32, i32);
175cast_from!(i32, i64);
176cast_from!(i32, i128);
177cast_from!(i64, i64);
178cast_from!(i64, i128);
179
180pub trait ReinterpretCast<T> {
191 fn reinterpret_cast(from: T) -> Self;
193}
194
195macro_rules! reinterpret_cast {
196 ($from:ty, $to:ty) => {
197 impl ReinterpretCast<$from> for $to {
198 #[allow(clippy::as_conversions)]
199 fn reinterpret_cast(from: $from) -> $to {
200 from as $to
201 }
202 }
203 };
204}
205
206reinterpret_cast!(u8, i8);
207reinterpret_cast!(i8, u8);
208reinterpret_cast!(u16, i16);
209reinterpret_cast!(i16, u16);
210reinterpret_cast!(u32, i32);
211reinterpret_cast!(i32, u32);
212reinterpret_cast!(u64, i64);
213reinterpret_cast!(i64, u64);
214
215pub trait TryCastFrom<T>: Sized {
225 fn try_cast_from(from: T) -> Option<Self>;
227}
228
229macro_rules! try_cast_from {
233 ($from:ty, $to:ty) => {
234 impl crate::cast::TryCastFrom<$from> for $to {
235 #[allow(clippy::as_conversions)]
236 fn try_cast_from(from: $from) -> Option<$to> {
237 let to = from as $to;
238 let inverse = to as $from;
239 if from == inverse { Some(to) } else { None }
240 }
241 }
242 };
243}
244
245try_cast_from!(f64, i64);
246try_cast_from!(i64, f64);
247try_cast_from!(f64, u64);
248try_cast_from!(u64, f64);
249
250pub trait CastLossy<T> {
254 fn cast_lossy(from: T) -> Self;
256}
257
258macro_rules! cast_lossy {
260 ($from:ty, $to:ty) => {
261 impl crate::cast::CastLossy<$from> for $to {
262 #[allow(clippy::as_conversions)]
263 fn cast_lossy(from: $from) -> $to {
264 from as $to
265 }
266 }
267 };
268}
269
270cast_lossy!(usize, f32);
271cast_lossy!(isize, f32);
272cast_lossy!(f32, usize);
273cast_lossy!(i64, f32);
274cast_lossy!(f32, i64);
275cast_lossy!(u64, f32);
276cast_lossy!(f32, u64);
277cast_lossy!(f32, u32);
278cast_lossy!(usize, f64);
279cast_lossy!(isize, f64);
280cast_lossy!(f64, usize);
281cast_lossy!(i64, f64);
282cast_lossy!(f64, i64);
283cast_lossy!(u64, f64);
284cast_lossy!(f64, u64);
285cast_lossy!(f64, u32);
286
287#[crate::test]
288fn test_try_cast_from() {
289 let f64_i64_cases = vec![
290 (0.0, Some(0)),
291 (1.0, Some(1)),
292 (1.5, None),
293 (f64::INFINITY, None),
294 (f64::NAN, None),
295 (f64::EPSILON, None),
296 (f64::MAX, None),
297 (f64::MIN, None),
298 (9223372036854775807f64, Some(i64::MAX)),
299 (-9223372036854775808f64, Some(i64::MIN)),
300 (9223372036854775807f64 + 10_000f64, None),
301 (-9223372036854775808f64 - 10_000f64, None),
302 ];
303 let i64_f64_cases = vec![
304 (0, Some(0.0)),
305 (1, Some(1.0)),
306 (-1, Some(-1.0)),
307 (i64::MAX, Some(9223372036854775807f64)),
308 (i64::MIN, Some(-9223372036854775808f64)),
309 (i64::MAX - 1, None),
310 (i64::MIN + 1, None),
311 ];
312 let f64_u64_cases = vec![
313 (0.0, Some(0)),
314 (1.0, Some(1)),
315 (1.5, None),
316 (f64::INFINITY, None),
317 (f64::NAN, None),
318 (f64::EPSILON, None),
319 (f64::MAX, None),
320 (f64::MIN, None),
321 (-1.0, None),
322 (18446744073709551615f64, Some(u64::MAX)),
323 (18446744073709551615f64 + 10_000f64, None),
324 (9007199254740992f64, Some(9007199254740992)),
326 (9007199254740991f64, Some(9007199254740991)),
328 ];
329 let u64_f64_cases = vec![
330 (0, Some(0.0)),
331 (1, Some(1.0)),
332 (u64::MAX, Some(18446744073709551615f64)),
333 (u64::MAX - 1, None),
334 (9007199254740992, Some(9007199254740992f64)),
336 (9007199254740991, Some(9007199254740991f64)),
338 (9007199254740993, None),
340 ];
341 for (f, expect) in f64_i64_cases {
342 let r = i64::try_cast_from(f);
343 assert_eq!(r, expect, "input: {f}");
344 }
345 for (i, expect) in i64_f64_cases {
346 let r = f64::try_cast_from(i);
347 assert_eq!(r, expect, "input: {i}");
348 }
349 for (f, expect) in f64_u64_cases {
350 let r = u64::try_cast_from(f);
351 assert_eq!(r, expect, "input: {f}");
352 }
353 for (u, expect) in u64_f64_cases {
354 let r = f64::try_cast_from(u);
355 assert_eq!(r, expect, "input: {u}");
356 }
357}