1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Numerical helpers functions and traits. 4 //! 5 //! This is essentially a staging module for code to mature until it can be moved to the `kernel` 6 //! crate. 7 8 use kernel::{ 9 macros::paste, 10 prelude::*, // 11 }; 12 13 /// Implements safe `as` conversion functions from a given type into a series of target types. 14 /// 15 /// These functions can be used in place of `as`, with the guarantee that they will be lossless. 16 macro_rules! impl_safe_as { 17 ($from:ty as { $($into:ty),* }) => { 18 $( 19 paste! { 20 #[doc = ::core::concat!( 21 "Losslessly converts a [`", 22 ::core::stringify!($from), 23 "`] into a [`", 24 ::core::stringify!($into), 25 "`].")] 26 /// 27 /// This conversion is allowed as it is always lossless. Prefer this over the `as` 28 /// keyword to ensure no lossy casts are performed. 29 /// 30 /// This is for use from a `const` context. For non `const` use, prefer the 31 /// [`FromSafeCast`] and [`IntoSafeCast`] traits. 32 /// 33 /// # Examples 34 /// 35 /// ``` 36 /// use crate::num; 37 /// 38 #[doc = ::core::concat!( 39 "assert_eq!(num::", 40 ::core::stringify!($from), 41 "_as_", 42 ::core::stringify!($into), 43 "(1", 44 ::core::stringify!($from), 45 "), 1", 46 ::core::stringify!($into), 47 ");")] 48 /// ``` 49 #[allow(unused)] 50 #[inline(always)] 51 pub(crate) const fn [<$from _as_ $into>](value: $from) -> $into { 52 kernel::static_assert!(size_of::<$into>() >= size_of::<$from>()); 53 54 value as $into 55 } 56 } 57 )* 58 }; 59 } 60 61 impl_safe_as!(u8 as { u16, u32, u64, usize }); 62 impl_safe_as!(u16 as { u32, u64, usize }); 63 impl_safe_as!(u32 as { u64, usize } ); 64 // `u64` and `usize` have the same size on 64-bit platforms. 65 #[cfg(CONFIG_64BIT)] 66 impl_safe_as!(u64 as { usize } ); 67 68 // A `usize` fits into a `u64` on 32 and 64-bit platforms. 69 #[cfg(any(CONFIG_32BIT, CONFIG_64BIT))] 70 impl_safe_as!(usize as { u64 }); 71 72 // A `usize` fits into a `u32` on 32-bit platforms. 73 #[cfg(CONFIG_32BIT)] 74 impl_safe_as!(usize as { u32 }); 75 76 /// Extension trait providing guaranteed lossless cast to `Self` from `T`. 77 /// 78 /// The standard library's `From` implementations do not cover conversions that are not portable or 79 /// future-proof. For instance, even though it is safe today, `From<usize>` is not implemented for 80 /// [`u64`] because of the possibility to support larger-than-64bit architectures in the future. 81 /// 82 /// The workaround is to either deal with the error handling of [`TryFrom`] for an operation that 83 /// technically cannot fail, or to use the `as` keyword, which can silently strip data if the 84 /// destination type is smaller than the source. 85 /// 86 /// Both options are hardly acceptable for the kernel. It is also a much more architecture 87 /// dependent environment, supporting only 32 and 64 bit architectures, with some modules 88 /// explicitly depending on a specific bus width that could greatly benefit from infallible 89 /// conversion operations. 90 /// 91 /// Thus this extension trait that provides, for the architecture the kernel is built for, safe 92 /// conversion between types for which such cast is lossless. 93 /// 94 /// In other words, this trait is implemented if, for the current build target and with `t: T`, the 95 /// `t as Self` operation is completely lossless. 96 /// 97 /// Prefer this over the `as` keyword to ensure no lossy casts are performed. 98 /// 99 /// If you need to perform a conversion in `const` context, use [`u64_as_usize`], [`u32_as_usize`], 100 /// [`usize_as_u64`], etc. 101 /// 102 /// # Examples 103 /// 104 /// ``` 105 /// use crate::num::FromSafeCast; 106 /// 107 /// assert_eq!(usize::from_safe_cast(0xf00u32), 0xf00u32 as usize); 108 /// ``` 109 pub(crate) trait FromSafeCast<T> { 110 /// Create a `Self` from `value`. This operation is guaranteed to be lossless. 111 fn from_safe_cast(value: T) -> Self; 112 } 113 114 impl FromSafeCast<usize> for u64 { 115 fn from_safe_cast(value: usize) -> Self { 116 usize_as_u64(value) 117 } 118 } 119 120 #[cfg(CONFIG_32BIT)] 121 impl FromSafeCast<usize> for u32 { 122 fn from_safe_cast(value: usize) -> Self { 123 usize_as_u32(value) 124 } 125 } 126 127 impl FromSafeCast<u32> for usize { 128 fn from_safe_cast(value: u32) -> Self { 129 u32_as_usize(value) 130 } 131 } 132 133 #[cfg(CONFIG_64BIT)] 134 impl FromSafeCast<u64> for usize { 135 fn from_safe_cast(value: u64) -> Self { 136 u64_as_usize(value) 137 } 138 } 139 140 /// Counterpart to the [`FromSafeCast`] trait, i.e. this trait is to [`FromSafeCast`] what [`Into`] 141 /// is to [`From`]. 142 /// 143 /// See the documentation of [`FromSafeCast`] for the motivation. 144 /// 145 /// # Examples 146 /// 147 /// ``` 148 /// use crate::num::IntoSafeCast; 149 /// 150 /// assert_eq!(0xf00u32.into_safe_cast(), 0xf00u32 as usize); 151 /// ``` 152 pub(crate) trait IntoSafeCast<T> { 153 /// Convert `self` into a `T`. This operation is guaranteed to be lossless. 154 fn into_safe_cast(self) -> T; 155 } 156 157 /// Reverse operation for types implementing [`FromSafeCast`]. 158 impl<S, T> IntoSafeCast<T> for S 159 where 160 T: FromSafeCast<S>, 161 { 162 fn into_safe_cast(self) -> T { 163 T::from_safe_cast(self) 164 } 165 } 166