devela/num/primitive/
cast.rs

1// devela::data::conversion::cast::casts
2//
3//! fns to cast between primitives in a checked manner.
4//
5// TOC
6// - trait definition
7// - trait and wrapper implementation
8// - functions definitions
9
10use crate::{
11    iif, isize_down, isize_up, paste, usize_down, usize_up, Cast,
12    NumError::Overflow,
13    NumResult as Result,
14    Sign::{Negative, Positive},
15};
16
17/// Offers methods for casting between primitives.
18///
19/// See also the [`Cast`] type for the equivalent *const* methods.
20/// # Errors
21/// Checked methods will return [`Overflow`]
22/// if the original value can't fit in the returned type.
23pub trait PrimitiveCast {
24    /* checked */
25
26    /// Casts `self` to `u8` with range check.
27    fn checked_cast_to_u8(self) -> Result<u8>;
28    /// Casts `self` to `u16` with range check.
29    fn checked_cast_to_u16(self) -> Result<u16>;
30    /// Casts `self` to `u32` with range check.
31    fn checked_cast_to_u32(self) -> Result<u32>;
32    /// Casts `self` to `u64` with range check.
33    fn checked_cast_to_u64(self) -> Result<u64>;
34    /// Casts `self` to `u128` with range check.
35    fn checked_cast_to_u128(self) -> Result<u128>;
36    /// Casts `self` to `usize` with range check.
37    fn checked_cast_to_usize(self) -> Result<usize>;
38    /// Casts `self` to `usize_up` with range check.
39    fn checked_cast_to_usize_up(self) -> Result<usize_up>;
40    /// Casts `self` to `usize_down` with range check.
41    fn checked_cast_to_usize_down(self) -> Result<usize_down>;
42
43    /// Casts `self` to `i8` with range check.
44    fn checked_cast_to_i8(self) -> Result<i8>;
45    /// Casts `self` to `i16` with range check.
46    fn checked_cast_to_i16(self) -> Result<i16>;
47    /// Casts `self` to `i32` with range check.
48    fn checked_cast_to_i32(self) -> Result<i32>;
49    /// Casts `self` to `i64` with range check.
50    fn checked_cast_to_i64(self) -> Result<i64>;
51    /// Casts `self` to `i128` with range check.
52    fn checked_cast_to_i128(self) -> Result<i128>;
53    /// Casts `self` to `isize` with range check.
54    fn checked_cast_to_isize(self) -> Result<isize>;
55    /// Casts `self` to `isize_up` with range check.
56    fn checked_cast_to_isize_up(self) -> Result<isize_up>;
57    /// Casts `self` to `isize_down` with range check.
58    fn checked_cast_to_isize_down(self) -> Result<isize_down>;
59
60    /* saturating */
61
62    /// Casts `self` to `u8` clamping at the numeric bounds.
63    #[must_use]
64    fn saturating_cast_to_u8(self) -> u8;
65    /// Casts `self` to `u16` clamping at the numeric bounds.
66    #[must_use]
67    fn saturating_cast_to_u16(self) -> u16;
68    /// Casts `self` to `u32` clamping at the numeric bounds.
69    #[must_use]
70    fn saturating_cast_to_u32(self) -> u32;
71    /// Casts `self` to `u64` clamping at the numeric bounds.
72    #[must_use]
73    fn saturating_cast_to_u64(self) -> u64;
74    /// Casts `self` to `u128` clamping at the numeric bounds.
75    #[must_use]
76    fn saturating_cast_to_u128(self) -> u128;
77    /// Casts `self` to `usize` clamping at the numeric bounds.
78    #[must_use]
79    fn saturating_cast_to_usize(self) -> usize;
80    /// Casts `self` to `usize_up` clamping at the numeric bounds.
81    #[must_use]
82    fn saturating_cast_to_usize_up(self) -> usize_up;
83    /// Casts `self` to `usize_down` clamping at the numeric bounds.
84    #[must_use]
85    fn saturating_cast_to_usize_down(self) -> usize_down;
86
87    /// Casts `self` to `i8` clamping at the numeric bounds.
88    #[must_use]
89    fn saturating_cast_to_i8(self) -> i8;
90    /// Casts `self` to `i16` clamping at the numeric bounds.
91    #[must_use]
92    fn saturating_cast_to_i16(self) -> i16;
93    /// Casts `self` to `i32` clamping at the numeric bounds.
94    #[must_use]
95    fn saturating_cast_to_i32(self) -> i32;
96    /// Casts `self` to `i64` clamping at the numeric bounds.
97    #[must_use]
98    fn saturating_cast_to_i64(self) -> i64;
99    /// Casts `self` to `i128` clamping at the numeric bounds.
100    #[must_use]
101    fn saturating_cast_to_i128(self) -> i128;
102    /// Casts `self` to `isize` clamping at the numeric bounds.
103    #[must_use]
104    fn saturating_cast_to_isize(self) -> isize;
105    /// Casts `self` to `isize_up` clamping at the numeric bounds.
106    #[must_use]
107    fn saturating_cast_to_isize_up(self) -> isize_up;
108    /// Casts `self` to `isize_down` clamping at the numeric bounds.
109    #[must_use]
110    fn saturating_cast_to_isize_down(self) -> isize_down;
111
112    /* wrapping */
113
114    /// Casts `self` to `u8` wrapping at the numeric bounds.
115    #[must_use]
116    fn wrapping_cast_to_u8(self) -> u8;
117    /// Casts `self` to `u16` wrapping at the numeric bounds.
118    #[must_use]
119    fn wrapping_cast_to_u16(self) -> u16;
120    /// Casts `self` to `u32` wrapping at the numeric bounds.
121    #[must_use]
122    fn wrapping_cast_to_u32(self) -> u32;
123    /// Casts `self` to `u64` wrapping at the numeric bounds.
124    #[must_use]
125    fn wrapping_cast_to_u64(self) -> u64;
126    /// Casts `self` to `u128` wrapping at the numeric bounds.
127    #[must_use]
128    fn wrapping_cast_to_u128(self) -> u128;
129    /// Casts `self` to `usize` wrapping at the numeric bounds.
130    #[must_use]
131    fn wrapping_cast_to_usize(self) -> usize;
132    /// Casts `self` to `usize_up` wrapping at the numeric bounds.
133    #[must_use]
134    fn wrapping_cast_to_usize_up(self) -> usize_up;
135    /// Casts `self` to `usize_down` wrapping at the numeric bounds.
136    #[must_use]
137    fn wrapping_cast_to_usize_down(self) -> usize_down;
138
139    /// Casts `self` to `i8` wrapping at the numeric bounds.
140    #[must_use]
141    fn wrapping_cast_to_i8(self) -> i8;
142    /// Casts `self` to `i16` wrapping at the numeric bounds.
143    #[must_use]
144    fn wrapping_cast_to_i16(self) -> i16;
145    /// Casts `self` to `i32` wrapping at the numeric bounds.
146    #[must_use]
147    fn wrapping_cast_to_i32(self) -> i32;
148    /// Casts `self` to `i64` wrapping at the numeric bounds.
149    #[must_use]
150    fn wrapping_cast_to_i64(self) -> i64;
151    /// Casts `self` to `i128` wrapping at the numeric bounds.
152    #[must_use]
153    fn wrapping_cast_to_i128(self) -> i128;
154    /// Casts `self` to `isize` wrapping at the numeric bounds.
155    #[must_use]
156    fn wrapping_cast_to_isize(self) -> isize;
157    /// Casts `self` to `isize_up` wrapping at the numeric bounds.
158    #[must_use]
159    fn wrapping_cast_to_isize_up(self) -> isize_up;
160    /// Casts `self` to `isize_down` wrapping at the numeric bounds.
161    #[must_use]
162    fn wrapping_cast_to_isize_down(self) -> isize_down;
163}
164
165/// Implements the public casting methods for the trait and [`Cast`] wrapper.
166macro_rules! impl_cast_methods {
167    ($($t:ty),+) => { $( impl_cast_methods![@$t]; )+ };
168    (@$t:ty) => { paste! {
169        impl PrimitiveCast for $t {
170            fn checked_cast_to_u8(self) -> Result<u8> { [<checked_cast_ $t _to_u8>](self) }
171            fn checked_cast_to_u16(self) -> Result<u16> { [<checked_cast_ $t _to_u16>](self) }
172            fn checked_cast_to_u32(self) -> Result<u32> { [<checked_cast_ $t _to_u32>](self) }
173            fn checked_cast_to_u64(self) -> Result<u64> { [<checked_cast_ $t _to_u64>](self) }
174            fn checked_cast_to_u128(self) -> Result<u128> { [<checked_cast_ $t _to_u128>](self) }
175            fn checked_cast_to_usize(self) -> Result<usize> { [<checked_cast_ $t _to_usize>](self) }
176            fn checked_cast_to_usize_up(self) -> Result<usize_up> {
177                [<checked_cast_ $t _to_usize_up>](self) }
178            fn checked_cast_to_usize_down(self) -> Result<usize_down> {
179                [<checked_cast_ $t _to_usize_down>](self) }
180
181            fn checked_cast_to_i8(self) -> Result<i8> { [<checked_cast_ $t _to_i8>](self) }
182            fn checked_cast_to_i16(self) -> Result<i16> { [<checked_cast_ $t _to_i16>](self) }
183            fn checked_cast_to_i32(self) -> Result<i32> { [<checked_cast_ $t _to_i32>](self) }
184            fn checked_cast_to_i64(self) -> Result<i64> { [<checked_cast_ $t _to_i64>](self) }
185            fn checked_cast_to_i128(self) -> Result<i128> { [<checked_cast_ $t _to_i128>](self) }
186            fn checked_cast_to_isize(self) -> Result<isize> { [<checked_cast_ $t _to_isize>](self) }
187            fn checked_cast_to_isize_up(self) -> Result<isize_up> {
188                [<checked_cast_ $t _to_isize_up>](self) }
189            fn checked_cast_to_isize_down(self) -> Result<isize_down> {
190                [<checked_cast_ $t _to_isize_down>](self) }
191
192            fn saturating_cast_to_u8(self) -> u8 { [<saturating_cast_ $t _to_u8>](self) }
193            fn saturating_cast_to_u16(self) -> u16 { [<saturating_cast_ $t _to_u16>](self) }
194            fn saturating_cast_to_u32(self) -> u32 { [<saturating_cast_ $t _to_u32>](self) }
195            fn saturating_cast_to_u64(self) -> u64 { [<saturating_cast_ $t _to_u64>](self) }
196            fn saturating_cast_to_u128(self) -> u128 { [<saturating_cast_ $t _to_u128>](self) }
197            fn saturating_cast_to_usize(self) -> usize { [<saturating_cast_ $t _to_usize>](self) }
198            fn saturating_cast_to_usize_up(self) -> usize_up {
199                [<saturating_cast_ $t _to_usize_up>](self) }
200            fn saturating_cast_to_usize_down(self) -> usize_down {
201                [<saturating_cast_ $t _to_usize_down>](self) }
202
203            fn saturating_cast_to_i8(self) -> i8 { [<saturating_cast_ $t _to_i8>](self) }
204            fn saturating_cast_to_i16(self) -> i16 { [<saturating_cast_ $t _to_i16>](self) }
205            fn saturating_cast_to_i32(self) -> i32 { [<saturating_cast_ $t _to_i32>](self) }
206            fn saturating_cast_to_i64(self) -> i64 { [<saturating_cast_ $t _to_i64>](self) }
207            fn saturating_cast_to_i128(self) -> i128 { [<saturating_cast_ $t _to_i128>](self) }
208            fn saturating_cast_to_isize(self) -> isize { [<saturating_cast_ $t _to_isize>](self) }
209            fn saturating_cast_to_isize_up(self) -> isize_up {
210                [<saturating_cast_ $t _to_isize_up>](self) }
211            fn saturating_cast_to_isize_down(self) -> isize_down {
212                [<saturating_cast_ $t _to_isize_down>](self) }
213
214            fn wrapping_cast_to_u8(self) -> u8 { [<wrapping_cast_ $t _to_u8>](self) }
215            fn wrapping_cast_to_u16(self) -> u16 { [<wrapping_cast_ $t _to_u16>](self) }
216            fn wrapping_cast_to_u32(self) -> u32 { [<wrapping_cast_ $t _to_u32>](self) }
217            fn wrapping_cast_to_u64(self) -> u64 { [<wrapping_cast_ $t _to_u64>](self) }
218            fn wrapping_cast_to_u128(self) -> u128 { [<wrapping_cast_ $t _to_u128>](self) }
219            fn wrapping_cast_to_usize(self) -> usize { [<wrapping_cast_ $t _to_usize>](self) }
220            fn wrapping_cast_to_usize_up(self) -> usize_up {
221                [<wrapping_cast_ $t _to_usize_up>](self) }
222            fn wrapping_cast_to_usize_down(self) -> usize_down {
223                [<wrapping_cast_ $t _to_usize_down>](self) }
224
225            fn wrapping_cast_to_i8(self) -> i8 { [<wrapping_cast_ $t _to_i8>](self) }
226            fn wrapping_cast_to_i16(self) -> i16 { [<wrapping_cast_ $t _to_i16>](self) }
227            fn wrapping_cast_to_i32(self) -> i32 { [<wrapping_cast_ $t _to_i32>](self) }
228            fn wrapping_cast_to_i64(self) -> i64 { [<wrapping_cast_ $t _to_i64>](self) }
229            fn wrapping_cast_to_i128(self) -> i128 { [<wrapping_cast_ $t _to_i128>](self) }
230            fn wrapping_cast_to_isize(self) -> isize { [<wrapping_cast_ $t _to_isize>](self) }
231            fn wrapping_cast_to_isize_up(self) -> isize_up {
232                [<wrapping_cast_ $t _to_isize_up>](self) }
233            fn wrapping_cast_to_isize_down(self) -> isize_down {
234                [<wrapping_cast_ $t _to_isize_down>](self) }
235        }
236
237        /// Checked casts and saturating casts.
238        ///
239        /// # Errors
240        /// Checked methods will return [`Overflow`] if `self` can't fit in the returned type.
241        #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "cast")))]
242        impl Cast<$t> {
243            /* checked */
244
245            #[doc = "Casts from `" $t "` to `u8` with range check."]
246            pub const fn checked_cast_to_u8(self) -> Result<u8> {
247                [<checked_cast_ $t _to_u8>](self.0)
248            }
249            #[doc = "Casts from `" $t "` to `u16` with range check."]
250            pub const fn checked_cast_to_u16(self) -> Result<u16> {
251                [<checked_cast_ $t _to_u16>](self.0)
252            }
253            #[doc = "Casts from `" $t "` to `u32` with range check."]
254            pub const fn checked_cast_to_u32(self) -> Result<u32> {
255                [<checked_cast_ $t _to_u32>](self.0)
256            }
257            #[doc = "Casts from `" $t "` to `u64` with range check."]
258            pub const fn checked_cast_to_u64(self) -> Result<u64> {
259                [<checked_cast_ $t _to_u64>](self.0)
260            }
261            #[doc = "Casts from `" $t "` to `u128` with range check."]
262            pub const fn checked_cast_to_u128(self) -> Result<u128> {
263                [<checked_cast_ $t _to_u128>](self.0)
264            }
265            #[doc = "Casts from `" $t "` to `usize` with range check."]
266            pub const fn checked_cast_to_usize(self) -> Result<usize> {
267                [<checked_cast_ $t _to_usize>](self.0)
268            }
269            #[doc = "Casts from `" $t "` to `usize_up` with range check."]
270            pub const fn checked_cast_to_usize_up(self) -> Result<usize_up> {
271                [<checked_cast_ $t _to_usize_up>](self.0)
272            }
273            #[doc = "Casts from `" $t "` to `usize_down` with range check."]
274            pub const fn checked_cast_to_usize_down(self) -> Result<usize_down> {
275                [<checked_cast_ $t _to_usize_down>](self.0)
276            }
277
278            #[doc = "Casts from `" $t "` to `i8` with range check."]
279            pub const fn checked_cast_to_i8(self) -> Result<i8> {
280                [<checked_cast_ $t _to_i8>](self.0)
281            }
282            #[doc = "Casts from `" $t "` to `i16` with range check."]
283            pub const fn checked_cast_to_i16(self) -> Result<i16> {
284                [<checked_cast_ $t _to_i16>](self.0)
285            }
286            #[doc = "Casts from `" $t "` to `i32` with range check."]
287            pub const fn checked_cast_to_i32(self) -> Result<i32> {
288                [<checked_cast_ $t _to_i32>](self.0)
289            }
290            #[doc = "Casts from `" $t "` to `i64` with range check."]
291            pub const fn checked_cast_to_i64(self) -> Result<i64> {
292                [<checked_cast_ $t _to_i64>](self.0)
293            }
294            #[doc = "Casts from `" $t "` to `i128` with range check."]
295            pub const fn checked_cast_to_i128(self) -> Result<i128> {
296                [<checked_cast_ $t _to_i128>](self.0)
297            }
298            #[doc = "Casts from `" $t "` to `isize` with range check."]
299            pub const fn checked_cast_to_isize(self) -> Result<isize> {
300                [<checked_cast_ $t _to_isize>](self.0)
301            }
302            #[doc = "Casts from `" $t "` to `isize_up` with range check."]
303            pub const fn checked_cast_to_isize_up(self) -> Result<isize_up> {
304                [<checked_cast_ $t _to_isize_up>](self.0)
305            }
306            #[doc = "Casts from `" $t "` to `isize_down` with range check."]
307            pub const fn checked_cast_to_isize_down(self) -> Result<isize_down> {
308                [<checked_cast_ $t _to_isize_down>](self.0)
309            }
310
311            /* saturating */
312
313            #[doc = "Casts from `" $t "` to `u8` clamping at the numeric bounds."]
314            #[must_use]
315            pub const fn saturating_cast_to_u8(self) -> u8 {
316                [<saturating_cast_ $t _to_u8>](self.0)
317            }
318            #[doc = "Casts from `" $t "` to `u16` clamping at the numeric bounds."]
319            #[must_use]
320            pub const fn saturating_cast_to_u16(self) -> u16 {
321                [<saturating_cast_ $t _to_u16>](self.0)
322            }
323            #[doc = "Casts from `" $t "` to `u32` clamping at the numeric bounds."]
324            #[must_use]
325            pub const fn saturating_cast_to_u32(self) -> u32 {
326                [<saturating_cast_ $t _to_u32>](self.0)
327            }
328            #[doc = "Casts from `" $t "` to `u64` clamping at the numeric bounds."]
329            #[must_use]
330            pub const fn saturating_cast_to_u64(self) -> u64 {
331                [<saturating_cast_ $t _to_u64>](self.0)
332            }
333            #[doc = "Casts from `" $t "` to `u128` clamping at the numeric bounds."]
334            #[must_use]
335            pub const fn saturating_cast_to_u128(self) -> u128 {
336                [<saturating_cast_ $t _to_u128>](self.0)
337            }
338            #[doc = "Casts from `" $t "` to `usize` clamping at the numeric bounds."]
339            #[must_use]
340            pub const fn saturating_cast_to_usize(self) -> usize {
341                [<saturating_cast_ $t _to_usize>](self.0)
342            }
343            #[doc = "Casts from `" $t "` to `usize_up` clamping at the numeric bounds."]
344            #[must_use]
345            pub const fn saturating_cast_to_usize_up(self) -> usize_up {
346                [<saturating_cast_ $t _to_usize_up>](self.0)
347            }
348            #[doc = "Casts from `" $t "` to `usize_down` clamping at the numeric bounds."]
349            #[must_use]
350            pub const fn saturating_cast_to_usize_down(self) -> usize_down {
351                [<saturating_cast_ $t _to_usize_down>](self.0)
352            }
353
354            #[doc = "Casts from `" $t "` to `i8` clamping at the numeric bounds."]
355            #[must_use]
356            pub const fn saturating_cast_to_i8(self) -> i8 {
357                [<saturating_cast_ $t _to_i8>](self.0)
358            }
359            #[doc = "Casts from `" $t "` to `i16` clamping at the numeric bounds."]
360            #[must_use]
361            pub const fn saturating_cast_to_i16(self) -> i16 {
362                [<saturating_cast_ $t _to_i16>](self.0)
363            }
364            #[doc = "Casts from `" $t "` to `i32` clamping at the numeric bounds."]
365            #[must_use]
366            pub const fn saturating_cast_to_i32(self) -> i32 {
367                [<saturating_cast_ $t _to_i32>](self.0)
368            }
369            #[doc = "Casts from `" $t "` to `i64` clamping at the numeric bounds."]
370            #[must_use]
371            pub const fn saturating_cast_to_i64(self) -> i64 {
372                [<saturating_cast_ $t _to_i64>](self.0)
373            }
374            #[doc = "Casts from `" $t "` to `i128` clamping at the numeric bounds."]
375            #[must_use]
376            pub const fn saturating_cast_to_i128(self) -> i128 {
377                [<saturating_cast_ $t _to_i128>](self.0)
378            }
379            #[doc = "Casts from `" $t "` to `isize` clamping at the numeric bounds."]
380            #[must_use]
381            pub const fn saturating_cast_to_isize(self) -> isize {
382                [<saturating_cast_ $t _to_isize>](self.0)
383            }
384            #[doc = "Casts from `" $t "` to `isize_up` clamping at the numeric bounds."]
385            #[must_use]
386            pub const fn saturating_cast_to_isize_up(self) -> isize_up {
387                [<saturating_cast_ $t _to_isize_up>](self.0)
388            }
389            #[doc = "Casts from `" $t "` to `isize_down` clamping at the numeric bounds."]
390            #[must_use]
391            pub const fn saturating_cast_to_isize_down(self) -> isize_down {
392                [<saturating_cast_ $t _to_isize_down>](self.0)
393            }
394
395            /* wrapping */
396
397            #[doc = "Casts from `" $t "` to `u8` wrapping at the numeric bounds."]
398            #[must_use]
399            pub const fn wrapping_cast_to_u8(self) -> u8 {
400                [<wrapping_cast_ $t _to_u8>](self.0)
401            }
402            #[doc = "Casts from `" $t "` to `u16` wrapping at the numeric bounds."]
403            #[must_use]
404            pub const fn wrapping_cast_to_u16(self) -> u16 {
405                [<wrapping_cast_ $t _to_u16>](self.0)
406            }
407            #[doc = "Casts from `" $t "` to `u32` wrapping at the numeric bounds."]
408            #[must_use]
409            pub const fn wrapping_cast_to_u32(self) -> u32 {
410                [<wrapping_cast_ $t _to_u32>](self.0)
411            }
412            #[doc = "Casts from `" $t "` to `u64` wrapping at the numeric bounds."]
413            #[must_use]
414            pub const fn wrapping_cast_to_u64(self) -> u64 {
415                [<wrapping_cast_ $t _to_u64>](self.0)
416            }
417            #[doc = "Casts from `" $t "` to `u128` wrapping at the numeric bounds."]
418            #[must_use]
419            pub const fn wrapping_cast_to_u128(self) -> u128 {
420                [<wrapping_cast_ $t _to_u128>](self.0)
421            }
422            #[doc = "Casts from `" $t "` to `usize` wrapping at the numeric bounds."]
423            #[must_use]
424            pub const fn wrapping_cast_to_usize(self) -> usize {
425                [<wrapping_cast_ $t _to_usize>](self.0)
426            }
427            #[doc = "Casts from `" $t "` to `usize_up` wrapping at the numeric bounds."]
428            #[must_use]
429            pub const fn wrapping_cast_to_usize_up(self) -> usize_up {
430                [<wrapping_cast_ $t _to_usize_up>](self.0)
431            }
432            #[doc = "Casts from `" $t "` to `usize_down` wrapping at the numeric bounds."]
433            #[must_use]
434            pub const fn wrapping_cast_to_usize_down(self) -> usize_down {
435                [<wrapping_cast_ $t _to_usize_down>](self.0)
436            }
437
438            #[doc = "Casts from `" $t "` to `i8` wrapping at the numeric bounds."]
439            #[must_use]
440            pub const fn wrapping_cast_to_i8(self) -> i8 {
441                [<wrapping_cast_ $t _to_i8>](self.0)
442            }
443            #[doc = "Casts from `" $t "` to `i16` wrapping at the numeric bounds."]
444            #[must_use]
445            pub const fn wrapping_cast_to_i16(self) -> i16 {
446                [<wrapping_cast_ $t _to_i16>](self.0)
447            }
448            #[doc = "Casts from `" $t "` to `i32` wrapping at the numeric bounds."]
449            #[must_use]
450            pub const fn wrapping_cast_to_i32(self) -> i32 {
451                [<wrapping_cast_ $t _to_i32>](self.0)
452            }
453            #[doc = "Casts from `" $t "` to `i64` wrapping at the numeric bounds."]
454            #[must_use]
455            pub const fn wrapping_cast_to_i64(self) -> i64 {
456                [<wrapping_cast_ $t _to_i64>](self.0)
457            }
458            #[doc = "Casts from `" $t "` to `i128` wrapping at the numeric bounds."]
459            #[must_use]
460            pub const fn wrapping_cast_to_i128(self) -> i128 {
461                [<wrapping_cast_ $t _to_i128>](self.0)
462            }
463            #[doc = "Casts from `" $t "` to `isize` wrapping at the numeric bounds."]
464            #[must_use]
465            pub const fn wrapping_cast_to_isize(self) -> isize {
466                [<wrapping_cast_ $t _to_isize>](self.0)
467            }
468            #[doc = "Casts from `" $t "` to `isize_up` wrapping at the numeric bounds."]
469            #[must_use]
470            pub const fn wrapping_cast_to_isize_up(self) -> isize_up {
471                [<wrapping_cast_ $t _to_isize_up>](self.0)
472            }
473            #[doc = "Casts from `" $t "` to `isize_down` wrapping at the numeric bounds."]
474            #[must_use]
475            pub const fn wrapping_cast_to_isize_down(self) -> isize_down {
476                [<wrapping_cast_ $t _to_isize_down>](self.0)
477            }
478        }
479    }};
480}
481impl_cast_methods![u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize];
482
483/// Implements private, standalone casting functions between integer primitives
484///
485/// `$f`:   the type to cast from
486/// `$fun`: the type to cast from (unsigned version, used for can_overunderflow)
487/// `$t`:   the type to cast to
488macro_rules! impl_cast_fns {
489    () => {
490        /* independent of pointer width */
491
492        impl_cast_fns![can_overunderflow
493            // from bigger signed to unsigned
494            i16|u16:u8, i32|u32:u8, i64|u64:u8, i128|u128:u8,
495            i32|u32:u16, i64|u64:u16, i128|u128:u16,
496            i64|u64:u32, i128|u128:u32,
497            i128|u128:u64,
498            // from bigger signed to signed
499            i16|u16:i8, i32|u32:i8, i64|u64:i8, i128|u128:i8,
500            i32|u32:i16, i64|u64:i16, i128|u128:i16,
501            i64|u64:i32, i128|u128:i32,
502            i128|u128:i64
503        ];
504        impl_cast_fns![can_overflow
505            // from bigger unsigned to unsigned
506            u16:u8, u32:u8, u64:u8, u128:u8,
507            u32:u16, u64:u16, u128:u16,
508            u64:u32, u128:u32,
509            u128:u64,
510            // from bigger unsigned to signed
511            u16:i8, u32:i8, u64:i8, u128:i8,
512            u32:i16, u64:i16, u128:i16,
513            u64:i32, u128:i32,
514            u128:i64,
515            // from equalsized unsigned to signed
516            u8:i8, u16:i16, u32:i32, u64:i64, u128:i128, usize:isize
517        ];
518        impl_cast_fns![can_underflow
519            // from smaller signed to unsigned
520            i8:u16, i8:u32, i8:u64, i8:u128,
521            i16:u32, i16:u64, i16:u128,
522            i32:u64, i32:u128,
523            i64:u128,
524            // from equalsized signed to unsigned
525            i8:u8, i16:u16, i32:u32, i64:u64, i128:u128, isize:usize
526        ];
527        impl_cast_fns![cant_fail
528            // from smaller unsigned to unsigned
529            u8:u16, u8:u32, u8:u64, u8:u128,
530            u16:u32, u16:u64, u16:u128,
531            u32:u64, u32:u128,
532            u64:u128,
533            // from smaller unsigned to signed
534            u8:i16, u8:i32, u8:i64, u8:i128,
535            u16:i32, u16:i64, u16:i128,
536            u32:i64, u32:i128,
537            u64:i128,
538            // from smaller signed to signed
539            i8:i16, i8:i32, i8:i64, i8:i128,
540            i16:i32, i16:i64, i16:i128,
541            i32:i64, i32:i128,
542            i64:i128,
543            // from equalsized unsigned to unsigned
544            u8:u8, u16:u16, u32:u32, u64:u64, u128:u128, usize:usize,
545            // from equalsized signed to signed
546            i8:i8, i16:i16, i32:i32, i64:i64, i128:i128, isize:isize
547        ];
548
549        /* dependent on pointer width */
550
551        #[cfg(target_pointer_width = "16")]
552        impl_cast_fns![can_overunderflow
553            // from bigger signed to unsigned
554            isize|usize:u8,
555            i32|u32:usize, i64|u64:usize, i128|u128:usize,
556            // from bigger signed to signed
557            isize|usize:i8,
558            i32|u32:isize, i64|u64:isize, i128|u128:isize
559        ];
560        #[cfg(target_pointer_width = "32")]
561        impl_cast_fns![can_overunderflow
562            // from bigger signed to unsigned
563            isize|usize:u8, isize|usize:u16,
564            i64|u64:usize, i128|u128:usize,
565            // from bigger signed to signed
566            isize|usize:i8, isize|usize:i16,
567            i64|u64:isize, i128|u128:isize
568        ];
569        #[cfg(target_pointer_width = "64")]
570        impl_cast_fns![can_overunderflow
571            // from bigger signed to unsigned
572            isize|usize:u8, isize|usize:u16, isize|usize:u32,
573            i128|u128:usize,
574            // from bigger signed to signed
575            isize|usize:i8, isize|usize:i16, isize|usize:i32,
576            i128|u128:isize
577        ];
578
579        #[cfg(target_pointer_width = "16")]
580        impl_cast_fns![can_overflow
581            // from bigger unsigned to unsigned
582            usize:u8,
583            u32:usize, u64:usize, u128:usize,
584            // from bigger unsigned to signed
585            usize:i8,
586            u32:isize, u64:isize, u128:isize,
587            // from equalsized unsigned to signed
588            u16:isize, usize:i16
589        ];
590        #[cfg(target_pointer_width = "32")]
591        impl_cast_fns![can_overflow
592            // from bigger unsigned to unsigned
593            usize:u8, usize:u16,
594            u64:usize, u128:usize,
595            // from bigger unsigned to signed
596            usize:i8, usize:i16,
597            u64:isize, u128:isize,
598            // from equalsized unsigned to signed
599            u32:isize, usize:i32
600        ];
601        #[cfg(target_pointer_width = "64")]
602        impl_cast_fns![can_overflow
603            // from bigger unsigned to unsigned
604            usize:u8, usize:u16, usize:u32,
605            u128:usize,
606            // from bigger unsigned to signed
607            usize:i8, usize:i16, usize:i32,
608            u128:isize,
609            // from equalsized unsigned to signed
610            u64:isize, usize:i64
611        ];
612
613        #[cfg(target_pointer_width = "16")]
614        impl_cast_fns![can_underflow
615            // from smaller signed to unsigned
616            isize:u32, isize:u64, isize:u128,
617            i8:usize,
618            // from equalsized signed to unsigned
619            i16:usize, isize:u16
620        ];
621        #[cfg(target_pointer_width = "32")]
622        impl_cast_fns![can_underflow
623            // from smaller signed to unsigned
624            isize:u64, isize:u128,
625            i8:usize, i16:usize,
626            // from equalsized signed to unsigned
627            i32:usize, isize:u32
628        ];
629        #[cfg(target_pointer_width = "64")]
630        impl_cast_fns![can_underflow
631            // from smaller signed to unsigned
632            isize:u128,
633            i8:usize, i16:usize, i32:usize,
634            // from equalsized signed to unsigned
635            i64:usize, isize:u64
636        ];
637
638        #[cfg(target_pointer_width = "16")]
639        impl_cast_fns![cant_fail ptr:16
640            // from smaller unsigned to unsigned
641            usize:u32, usize:u64, usize:u128,
642            u8:usize,
643            // from smaller unsigned to signed
644            usize:i32, usize:i64, usize:i128,
645            u8:isize,
646            // from smaller signed to signed
647            isize:i32, isize:i64, isize:i128,
648            i8:isize,
649            // from equalsized unsigned to unsigned
650            usize:u16, u16:usize,
651            // from equalsized signed to signed
652            isize:i16, i16:isize
653        ];
654        #[cfg(target_pointer_width = "32")]
655        impl_cast_fns![cant_fail ptr:32
656            // from smaller unsigned to unsigned
657            usize:u64, usize:u128,
658            u8:usize, u16:usize,
659            // from smaller unsigned to signed
660            usize:i64, usize:i128,
661            u8:isize, u16:isize,
662            // from smaller signed to signed
663            isize:i64, isize:i128,
664            i8:isize, i16:isize,
665            // from equalsized unsigned to unsigned
666            usize:u32, u32:usize,
667            // from equalsized signed to signed
668            isize:i32, i32:isize
669        ];
670        #[cfg(target_pointer_width = "64")]
671        impl_cast_fns![cant_fail ptr:64
672            // from smaller unsigned to unsigned
673            usize:u128,
674            u8:usize, u16:usize, u32:usize,
675            // from smaller unsigned to signed
676            usize:i128,
677            u8:isize, u16:isize, u32:isize,
678            // from smaller signed to signed
679            isize:i128,
680            i8:isize, i16:isize, i32:isize,
681            // from equalsized unsigned to unsigned
682            usize:u64, u64:usize,
683            // from equalsized signed to signed
684            isize:i64, i64:isize
685        ];
686    };
687    (can_overunderflow $( $f:ty | $fun:ty : $t:ty ),+) => {
688        $( impl_cast_fns![@can_overunderflow $f|$fun:$t]; )+
689    };
690    (@can_overunderflow $f:ty | $fun:ty : $t:ty) => { paste! {
691        const fn [<checked_cast_ $f _to_ $t>](p: $f) -> Result<$t> {
692            if p < <$t>::MIN as $f {
693                Err(Overflow(Some(Negative)))
694            } else if p > $t::MAX as $f {
695                Err(Overflow(Some(Positive)))
696            } else {
697                Ok(p as $t)
698            }
699        }
700        const fn [<saturating_cast_ $f _to_ $t>](p: $f) -> $t {
701            if p < <$t>::MIN as $f {
702                <$t>::MIN
703            } else if p > $t::MAX as $f {
704                <$t>::MAX
705            } else {
706                p as $t
707            }
708        }
709        const fn [<wrapping_cast_ $f _to_ $t>](p: $f) -> $t {
710            (p as $fun % (<$t>::MAX as $fun + 1)) as $t
711        }
712    }};
713    (can_overflow $( $f:ty:$t:ty ),+) => { $( impl_cast_fns![@can_overflow $f:$t]; )+ };
714    (@can_overflow $f:ty:$t:ty) => { paste! {
715        const fn [<checked_cast_ $f _to_ $t>](p: $f) -> Result<$t> {
716            iif![p > <$t>::MAX as $f; Err(Overflow(Some(Positive))); Ok(p as $t)]
717        }
718        const fn [<saturating_cast_ $f _to_ $t>](p: $f) -> $t {
719            iif![p > <$t>::MAX as $f; <$t>::MAX; p as $t]
720        }
721        const fn [<wrapping_cast_ $f _to_ $t>](p: $f) -> $t {
722            (p % (<$t>::MAX as $f + 1)) as $t
723        }
724    }};
725    (can_underflow $( $f:ty:$t:ty ),+) => { $( impl_cast_fns![@can_underflow $f:$t]; )+ };
726    (@can_underflow $f:ty:$t:ty) => { paste! {
727        const fn [<checked_cast_ $f _to_ $t>](p: $f) -> Result<$t> {
728            iif![p < 0; Err(Overflow(Some(Negative))); Ok(p as $t)]
729        }
730        const fn [<saturating_cast_ $f _to_ $t>](p: $f) -> $t {
731            iif![p < 0; 0; p as $t]
732        }
733        const fn [<wrapping_cast_ $f _to_ $t>](p: $f) -> $t {
734            p as $t
735        }
736    }};
737    (cant_fail $( $f:ty:$t:ty ),+) => { $( impl_cast_fns![@cant_fail $f:$t]; )+ };
738    (@cant_fail $f:ty:$t:ty) => { paste! {
739        const fn [<checked_cast_ $f _to_ $t>](p: $f) -> Result<$t> {
740            Ok(p as $t)
741        }
742        const fn [<saturating_cast_ $f _to_ $t>](p: $f) -> $t {
743            p as $t
744        }
745        const fn [<wrapping_cast_ $f _to_ $t>](p: $f) -> $t {
746            p as $t
747        }
748    }};
749    (cant_fail ptr:$ptr:literal $( $f:ty:$t:ty ),+) => {
750        $( impl_cast_fns![@cant_fail ptr:$ptr $f:$t]; )+
751    };
752    (@cant_fail ptr:$ptr:literal $f:ty:$t:ty) => { paste! {
753        const fn [<checked_cast_ $f _to_ $t>](p: $f) -> Result<$t> {
754            Ok(p as $t)
755        }
756        const fn [<saturating_cast_ $f _to_ $t>](p: $f) -> $t {
757            p as $t
758        }
759        const fn [<wrapping_cast_ $f _to_ $t>](p: $f) -> $t {
760            p as $t
761        }
762    }};
763}
764impl_cast_fns![];
765
766/// implement the casting functions for the upcasted aliases
767///
768/// `$f`: the type to cast from
769/// `$a`: the type to cast to (name alias)
770/// `$t`: the type to cast to (real type)
771macro_rules! impl_cast_fns_alias {
772    () => {
773        #[cfg(target_pointer_width = "16")] impl_cast_fns_alias![@to isize_up|i32];
774        #[cfg(target_pointer_width = "16")] impl_cast_fns_alias![@to usize_up|u32];
775        #[cfg(target_pointer_width = "16")] impl_cast_fns_alias![@to isize_down|i8];
776        #[cfg(target_pointer_width = "16")] impl_cast_fns_alias![@to usize_down|u8];
777        //
778        #[cfg(target_pointer_width = "32")] impl_cast_fns_alias![@to isize_up|i64];
779        #[cfg(target_pointer_width = "32")] impl_cast_fns_alias![@to usize_up|u64];
780        #[cfg(target_pointer_width = "32")] impl_cast_fns_alias![@to isize_down|i16];
781        #[cfg(target_pointer_width = "32")] impl_cast_fns_alias![@to usize_down|u16];
782        //
783        #[cfg(target_pointer_width = "64")] impl_cast_fns_alias![@to isize_up|i128];
784        #[cfg(target_pointer_width = "64")] impl_cast_fns_alias![@to usize_up|u128];
785        #[cfg(target_pointer_width = "64")] impl_cast_fns_alias![@to isize_down|i32];
786        #[cfg(target_pointer_width = "64")] impl_cast_fns_alias![@to usize_down|u32];
787    };
788    (@to $a:ident|$t:ty) => {
789        impl_cast_fns_alias![@to $a|$t:
790            i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize];
791    };
792    (@to $a:ident|$t:ty : $($f:ty),+) => { $( impl_cast_fns_alias!(@impl $f, $a, $t);)+ };
793    (@impl $f:ty, $a:ty, $t:ty) => { paste! {
794        const fn [<checked_cast_ $f _to_ $a>](p: $f) -> Result<$a> {
795            [<checked_cast_ $f _to_ $t>](p)
796        }
797        const fn [<saturating_cast_ $f _to_ $a>](p: $f) -> $a {
798            [<saturating_cast_ $f _to_ $t>](p)
799        }
800        const fn [<wrapping_cast_ $f _to_ $a>](p: $f) -> $a {
801            [<wrapping_cast_ $f _to_ $t>](p)
802        }
803    }};
804}
805impl_cast_fns_alias![];