bnum/cast/
mod.rs

1//! Panic-free casting between numeric types.
2
3/// Backend implementation trait for panic-free casting between numeric types.
4pub trait CastFrom<T> {
5    fn cast_from(from: T) -> Self;
6}
7
8#[cfg(test)]
9pub(crate) trait CastTo<U> {
10    fn cast_to(self) -> U;
11}
12
13macro_rules! as_trait_doc {
14    () => {
15"Trait which allows panic-free casting between numeric types.
16
17The behavior matches the behavior of the `as` conversion operator between primitive integers. This trait can be used to convert between bnum's integer types, as well as between bnum's integer types and Rust's primitive integers. Conversions between Rust's primitive integers themselves are also defined for consistency."
18    };
19}
20
21macro_rules! as_method_doc {
22    () => {
23"Casts `self` to type `T`. The [semantics of numeric casting](https://doc.rust-lang.org/reference/expressions/operator-expr.html#semantics) with the `as` operator are followed, so `<T as As>::as_::<U>` can be used in the same way as `T as U` for numeric conversions.
24
25# Examples
26 
27```
28use bnum::types::{U256, I512, I256, U1024};
29use bnum::cast::As;
30 
31// Cast `u64` to `U256`:
32let a = 399872465243u64;
33let b: U256 = a.as_();
34assert_eq!(a.as_::<u16>(), b.as_());
35
36// Cast `i128` to `I512`:
37let c = -2098409234529234584094i128;
38let d = c.as_::<I512>();
39//assert_eq!(c.as::<I256>(), d.as_());
40
41// Cast `I512` to `U1024` (result will be sign-extended with leading ones):
42let e: U1024 = d.as_();
43assert_eq!(d, e.as_());
44
45// Cast `U256` to `f64` and back:
46let f: f64 = b.as_();
47assert_eq!(b, f.as_());
48```"
49    };
50}
51
52#[cfg(feature = "nightly")]
53macro_rules! as_trait {
54    () => {
55        // impl<T, U> const CastTo<U> for T
56        #[cfg(test)]
57        impl<T, U> CastTo<U> for T
58        where
59            // U: ~const CastFrom<T>,
60            U: CastFrom<T>,
61        {
62            fn cast_to(self) -> U {
63                U::cast_from(self)
64            }
65        }
66
67        #[doc = as_trait_doc!()]
68        // #[const_trait]
69        pub trait As {
70            #[doc = as_method_doc!()]
71            fn as_<T>(self) -> T
72            where
73                T: CastFrom<Self>,
74                Self: Sized;
75        }
76
77        // impl<U> const As for U {
78        impl<U> As for U {
79            #[inline]
80            fn as_<T>(self) -> T
81            where
82                // T: ~const CastFrom<Self>,
83                T: CastFrom<Self>,
84                Self: Sized,
85            {
86                T::cast_from(self)
87            }
88        }
89    };
90}
91
92#[cfg(not(feature = "nightly"))]
93macro_rules! as_trait {
94    () => {
95        #[cfg(test)]
96        impl<T, U> CastTo<U> for T
97        where
98            U: CastFrom<T>,
99        {
100            fn cast_to(self) -> U {
101                U::cast_from(self)
102            }
103        }
104
105        #[doc = as_trait_doc!()]
106        pub trait As {
107            #[doc = as_method_doc!()]
108            fn as_<T>(self) -> T
109            where
110                T: CastFrom<Self>,
111                Self: Sized;
112        }
113
114        impl<U> As for U {
115            #[inline]
116            fn as_<T>(self) -> T
117            where
118                T: CastFrom<Self>,
119                Self: Sized,
120            {
121                T::cast_from(self)
122            }
123        }
124    };
125}
126
127as_trait!();
128
129macro_rules! primitive_cast_impl {
130    ($from: ty as [$($ty: ty), *]) => {
131        $(
132            impl CastFrom<$from> for $ty {
133                #[inline]
134                fn cast_from(from: $from) -> Self {
135                    from as Self
136                }
137            }
138        )*
139    };
140}
141
142macro_rules! multiple_impls {
143    ($($from: ty), *) => {
144        $(
145            primitive_cast_impl!($from as [u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64]);
146        )*
147    };
148}
149
150primitive_cast_impl!(bool as [u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, bool]);
151primitive_cast_impl!(char as [u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, char]);
152primitive_cast_impl!(u8 as [u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64, char]);
153multiple_impls!(u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64);
154
155pub(crate) mod float;