common_traits/
castable.rs

1/// `CastableInto : CastableFrom = Into : From`, It's easier to use to
2/// specify bounds on generic variables
3pub trait CastableInto<W>: Sized {
4    /// Call `W::cast_from(self)`
5    fn cast(self) -> W;
6}
7
8/// Trait for primitive integers, this is the combination of
9/// [`DowncastableFrom`](`crate::downcastable::DowncastableFrom`) and [`UpcastableFrom`](`crate::upcastable::UpcastableFrom`). Prefer using the other two
10/// traits, as casting without knowing which value will be bigger might result
11/// in hard to find bugs.
12///
13/// This is equivalent to calling `as` between two types
14pub trait CastableFrom<W>: Sized {
15    /// Call `Self as W`
16    fn cast_from(value: W) -> Self;
17}
18
19/// Riflexivity
20impl<T> CastableFrom<T> for T {
21    #[inline(always)]
22    fn cast_from(value: T) -> Self {
23        value
24    }
25}
26
27/// UpcastableFrom implies UpcastableInto
28impl<T, U> CastableInto<U> for T
29where
30    U: CastableFrom<T>,
31{
32    #[inline(always)]
33    fn cast(self) -> U {
34        U::cast_from(self)
35    }
36}
37
38macro_rules! impl_casts {
39    ($base_type:ty, $($ty:ty,)*) => {$(
40impl CastableFrom<$base_type> for $ty {
41    #[inline(always)]
42    fn cast_from(value: $base_type) -> Self {
43        value as $ty
44    }
45}
46impl CastableFrom<$ty> for $base_type {
47    #[inline(always)]
48    fn cast_from(value: $ty) -> $base_type {
49        value as $base_type
50    }
51}
52    )*
53    impl_casts!($($ty,)*);
54};
55    () => {};
56}
57
58impl_casts!(u8, u16, u32, u64, u128, usize,);
59impl_casts!(i8, i16, i32, i64, i128, isize,);
60
61impl_casts!(f32, f64,);
62
63#[cfg(feature = "half")]
64mod half_impl {
65    use super::*;
66    impl CastableFrom<f32> for half::f16 {
67        #[inline(always)]
68        fn cast_from(value: f32) -> Self {
69            Self::from_f32(value)
70        }
71    }
72    impl CastableFrom<f64> for half::f16 {
73        #[inline(always)]
74        fn cast_from(value: f64) -> Self {
75            Self::from_f64(value)
76        }
77    }
78    impl CastableFrom<f32> for half::bf16 {
79        #[inline(always)]
80        fn cast_from(value: f32) -> Self {
81            Self::from_f32(value)
82        }
83    }
84    impl CastableFrom<f64> for half::bf16 {
85        #[inline(always)]
86        fn cast_from(value: f64) -> Self {
87            Self::from_f64(value)
88        }
89    }
90    impl CastableFrom<half::f16> for f32 {
91        #[inline(always)]
92        fn cast_from(value: half::f16) -> Self {
93            value.to_f32()
94        }
95    }
96    impl CastableFrom<half::bf16> for f32 {
97        #[inline(always)]
98        fn cast_from(value: half::bf16) -> Self {
99            value.to_f32()
100        }
101    }
102    impl CastableFrom<half::f16> for f64 {
103        #[inline(always)]
104        fn cast_from(value: half::f16) -> Self {
105            value.to_f64()
106        }
107    }
108    impl CastableFrom<half::bf16> for f64 {
109        #[inline(always)]
110        fn cast_from(value: half::bf16) -> Self {
111            value.to_f64()
112        }
113    }
114}