1*47f27155SAlexandre Courbot // SPDX-License-Identifier: GPL-2.0 2*47f27155SAlexandre Courbot 3*47f27155SAlexandre Courbot //! Helpers for performing lossless integer casts. 4*47f27155SAlexandre Courbot //! 5*47f27155SAlexandre Courbot //! The `as` keyword can be used to perform casts between integer types, but it unfortunately makes 6*47f27155SAlexandre Courbot //! no distinction between casts that are lossless, and casts from a larger type into a smaller one 7*47f27155SAlexandre Courbot //! that might silently strip data away. Thus, its use in the kernel is discouraged in favor of 8*47f27155SAlexandre Courbot //! [`From`] implementations. 9*47f27155SAlexandre Courbot //! 10*47f27155SAlexandre Courbot //! Conversely, there are casts that are lossless depending on the build architecture (such as 11*47f27155SAlexandre Courbot //! casting [`usize`] to [`u64`] on 32 or 64 bit archs), but not supported by [`From`] 12*47f27155SAlexandre Courbot //! implementations in the standard library because they are not portable. It does however make 13*47f27155SAlexandre Courbot //! sense for the kernel to support these, if only for code that is architecture-specific. 14*47f27155SAlexandre Courbot //! 15*47f27155SAlexandre Courbot //! This module provides ways to perform such conversions safely: 16*47f27155SAlexandre Courbot //! 17*47f27155SAlexandre Courbot //! - A series of const functions (e.g. [`usize_as_u64`]) supporting safe conversions in const 18*47f27155SAlexandre Courbot //! context. Conversions supported by [`From`] implementations in the standard library are also 19*47f27155SAlexandre Courbot //! covered as the [`From`] trait cannot be used in const context. 20*47f27155SAlexandre Courbot //! - Two extension traits, [`FromSafeCast`] and [`IntoSafeCast`], providing conversion methods 21*47f27155SAlexandre Courbot //! similar to [`From`] and [`Into`] for conversions that are safe to perform in the kernel, but 22*47f27155SAlexandre Courbot //! not supported by the standard library. 23*47f27155SAlexandre Courbot //! - Another series of const functions (e.g. [`u64_into_u8`]) supporting the conversion of a const 24*47f27155SAlexandre Courbot //! value from a larger type into a smaller one, provided the value fits into the destination 25*47f27155SAlexandre Courbot //! type. This is useful if a constant is defined as a larger type, but needs to be used as a 26*47f27155SAlexandre Courbot //! smaller one. 27*47f27155SAlexandre Courbot //! - An [`arch`] sub-module, defining more conversion functions that are only guaranteed to be 28*47f27155SAlexandre Courbot //! lossless for a given pointer size. These can only be used in code that is specific to a 29*47f27155SAlexandre Courbot //! given pointer size. 30*47f27155SAlexandre Courbot //! 31*47f27155SAlexandre Courbot //! # Examples 32*47f27155SAlexandre Courbot //! 33*47f27155SAlexandre Courbot //! ``` 34*47f27155SAlexandre Courbot //! use kernel::num::casts::{self, FromSafeCast, IntoSafeCast}; 35*47f27155SAlexandre Courbot //! 36*47f27155SAlexandre Courbot //! // Conversion from const context. 37*47f27155SAlexandre Courbot //! const USIZED_CONST: usize = casts::u8_as_usize(255u8); 38*47f27155SAlexandre Courbot //! 39*47f27155SAlexandre Courbot //! // Non-const conversions. 40*47f27155SAlexandre Courbot //! let a = u64::from_safe_cast(4096usize); 41*47f27155SAlexandre Courbot //! let b: u64 = 4096usize.into_safe_cast(); 42*47f27155SAlexandre Courbot //! ``` 43*47f27155SAlexandre Courbot 44*47f27155SAlexandre Courbot use crate::prelude::*; 45*47f27155SAlexandre Courbot 46*47f27155SAlexandre Courbot /// Implements safe `as` conversion functions from a given type into a series of target types. 47*47f27155SAlexandre Courbot /// 48*47f27155SAlexandre Courbot /// These functions can be used in place of `as`, with the guarantee that they will be lossless. 49*47f27155SAlexandre Courbot macro_rules! impl_safe_as { 50*47f27155SAlexandre Courbot ($from:ty as { $($into:ty),* }) => { 51*47f27155SAlexandre Courbot $( 52*47f27155SAlexandre Courbot $crate::macros::paste! { 53*47f27155SAlexandre Courbot #[doc = ::core::concat!( 54*47f27155SAlexandre Courbot "Losslessly converts a [`", 55*47f27155SAlexandre Courbot ::core::stringify!($from), 56*47f27155SAlexandre Courbot "`] into a [`", 57*47f27155SAlexandre Courbot ::core::stringify!($into), 58*47f27155SAlexandre Courbot "`].")] 59*47f27155SAlexandre Courbot /// 60*47f27155SAlexandre Courbot /// This conversion is allowed as it is always lossless. Prefer this over the `as` 61*47f27155SAlexandre Courbot /// keyword to ensure no lossy casts are performed. 62*47f27155SAlexandre Courbot /// 63*47f27155SAlexandre Courbot /// This is for use from a `const` context. For non `const` use, prefer the 64*47f27155SAlexandre Courbot /// [`FromSafeCast`] and [`IntoSafeCast`] traits. 65*47f27155SAlexandre Courbot /// 66*47f27155SAlexandre Courbot /// # Examples 67*47f27155SAlexandre Courbot /// 68*47f27155SAlexandre Courbot /// ``` 69*47f27155SAlexandre Courbot /// use kernel::num::casts; 70*47f27155SAlexandre Courbot /// 71*47f27155SAlexandre Courbot #[doc = ::core::concat!( 72*47f27155SAlexandre Courbot "assert_eq!(casts::", 73*47f27155SAlexandre Courbot ::core::stringify!($from), 74*47f27155SAlexandre Courbot "_as_", 75*47f27155SAlexandre Courbot ::core::stringify!($into), 76*47f27155SAlexandre Courbot "(1", 77*47f27155SAlexandre Courbot ::core::stringify!($from), 78*47f27155SAlexandre Courbot "), 1", 79*47f27155SAlexandre Courbot ::core::stringify!($into), 80*47f27155SAlexandre Courbot ");")] 81*47f27155SAlexandre Courbot /// ``` 82*47f27155SAlexandre Courbot #[inline] 83*47f27155SAlexandre Courbot pub const fn [<$from _as_ $into>](value: $from) -> $into { 84*47f27155SAlexandre Courbot $crate::static_assert!(size_of::<$into>() >= size_of::<$from>()); 85*47f27155SAlexandre Courbot 86*47f27155SAlexandre Courbot value as $into 87*47f27155SAlexandre Courbot } 88*47f27155SAlexandre Courbot } 89*47f27155SAlexandre Courbot )* 90*47f27155SAlexandre Courbot }; 91*47f27155SAlexandre Courbot } 92*47f27155SAlexandre Courbot 93*47f27155SAlexandre Courbot // Valid `Into` transformations. 94*47f27155SAlexandre Courbot impl_safe_as!(u8 as { u16, u32, u64, usize }); 95*47f27155SAlexandre Courbot impl_safe_as!(u16 as { u32, u64, usize }); 96*47f27155SAlexandre Courbot impl_safe_as!(u32 as { u64 }); 97*47f27155SAlexandre Courbot // A `usize` fits into a `u64` on all supported platforms. 98*47f27155SAlexandre Courbot impl_safe_as!(usize as { u64 }); 99*47f27155SAlexandre Courbot // A `u32` fits into a `usize` on all supported platforms. 100*47f27155SAlexandre Courbot impl_safe_as!(u32 as { usize }); 101*47f27155SAlexandre Courbot 102*47f27155SAlexandre Courbot /// Extension trait providing guaranteed lossless cast to [`Self`] from `T`. 103*47f27155SAlexandre Courbot /// 104*47f27155SAlexandre Courbot /// The standard library's [`From`] implementations do not cover conversions that are not portable 105*47f27155SAlexandre Courbot /// or future-proof. For instance, even though it is safe today, [`From<usize>`] is not implemented 106*47f27155SAlexandre Courbot /// for [`u64`] because of the possibility of needing to support larger-than-64bit architectures in 107*47f27155SAlexandre Courbot /// the future. 108*47f27155SAlexandre Courbot /// 109*47f27155SAlexandre Courbot /// The workaround is to either deal with the error handling of [`TryFrom`] for an operation that 110*47f27155SAlexandre Courbot /// technically cannot fail, or to use the `as` keyword, which can silently strip data if the 111*47f27155SAlexandre Courbot /// destination type is smaller than the source. 112*47f27155SAlexandre Courbot /// 113*47f27155SAlexandre Courbot /// Both options are hardly acceptable for the kernel. It is also a much more architecture 114*47f27155SAlexandre Courbot /// dependent environment, supporting only 32 and 64 bit architectures, with some modules 115*47f27155SAlexandre Courbot /// explicitly depending on a specific bus width that could greatly benefit from infallible 116*47f27155SAlexandre Courbot /// conversion operations. 117*47f27155SAlexandre Courbot /// 118*47f27155SAlexandre Courbot /// Thus this extension trait that provides, for all architectures supported by the kernel, 119*47f27155SAlexandre Courbot /// conversion methods between types for which such a cast is lossless. 120*47f27155SAlexandre Courbot /// 121*47f27155SAlexandre Courbot /// In other words, this trait is implemented if, for all supported targets and with `t: T`, the 122*47f27155SAlexandre Courbot /// `t as Self` operation is completely lossless. 123*47f27155SAlexandre Courbot /// 124*47f27155SAlexandre Courbot /// Prefer this over the `as` keyword to guarantee that no lossy casts are performed. 125*47f27155SAlexandre Courbot /// 126*47f27155SAlexandre Courbot /// If you need to perform a conversion in `const` context, use [`u32_as_usize`], [`usize_as_u64`], 127*47f27155SAlexandre Courbot /// etc. 128*47f27155SAlexandre Courbot /// 129*47f27155SAlexandre Courbot /// # Examples 130*47f27155SAlexandre Courbot /// 131*47f27155SAlexandre Courbot /// ``` 132*47f27155SAlexandre Courbot /// use kernel::num::casts::FromSafeCast; 133*47f27155SAlexandre Courbot /// 134*47f27155SAlexandre Courbot /// assert_eq!(usize::from_safe_cast(0xf00u32), 0xf00usize); 135*47f27155SAlexandre Courbot /// ``` 136*47f27155SAlexandre Courbot pub trait FromSafeCast<T> { 137*47f27155SAlexandre Courbot /// Create a [`Self`] from `value`. This operation is guaranteed to be lossless. 138*47f27155SAlexandre Courbot fn from_safe_cast(value: T) -> Self; 139*47f27155SAlexandre Courbot } 140*47f27155SAlexandre Courbot 141*47f27155SAlexandre Courbot // A `usize` fits into a `u64` on all supported platforms. 142*47f27155SAlexandre Courbot impl FromSafeCast<usize> for u64 { 143*47f27155SAlexandre Courbot #[inline] 144*47f27155SAlexandre Courbot fn from_safe_cast(value: usize) -> Self { 145*47f27155SAlexandre Courbot usize_as_u64(value) 146*47f27155SAlexandre Courbot } 147*47f27155SAlexandre Courbot } 148*47f27155SAlexandre Courbot 149*47f27155SAlexandre Courbot // A `u32` fits into a `usize` on all supported platforms. 150*47f27155SAlexandre Courbot impl FromSafeCast<u32> for usize { 151*47f27155SAlexandre Courbot #[inline] 152*47f27155SAlexandre Courbot fn from_safe_cast(value: u32) -> Self { 153*47f27155SAlexandre Courbot u32_as_usize(value) 154*47f27155SAlexandre Courbot } 155*47f27155SAlexandre Courbot } 156*47f27155SAlexandre Courbot 157*47f27155SAlexandre Courbot /// Counterpart to the [`FromSafeCast`] trait, i.e. this trait is to [`FromSafeCast`] what [`Into`] 158*47f27155SAlexandre Courbot /// is to [`From`]. 159*47f27155SAlexandre Courbot /// 160*47f27155SAlexandre Courbot /// See the documentation of [`FromSafeCast`] for the motivation. 161*47f27155SAlexandre Courbot /// 162*47f27155SAlexandre Courbot /// # Examples 163*47f27155SAlexandre Courbot /// 164*47f27155SAlexandre Courbot /// ``` 165*47f27155SAlexandre Courbot /// use kernel::num::casts::IntoSafeCast; 166*47f27155SAlexandre Courbot /// 167*47f27155SAlexandre Courbot /// assert_eq!(0xf00usize, 0xf00u32.into_safe_cast()); 168*47f27155SAlexandre Courbot /// ``` 169*47f27155SAlexandre Courbot pub trait IntoSafeCast<T> { 170*47f27155SAlexandre Courbot /// Convert `self` into a `T`. This operation is guaranteed to be lossless. 171*47f27155SAlexandre Courbot fn into_safe_cast(self) -> T; 172*47f27155SAlexandre Courbot } 173*47f27155SAlexandre Courbot 174*47f27155SAlexandre Courbot /// Reverse operation for types implementing [`FromSafeCast`]. 175*47f27155SAlexandre Courbot impl<S, T> IntoSafeCast<T> for S 176*47f27155SAlexandre Courbot where 177*47f27155SAlexandre Courbot T: FromSafeCast<S>, 178*47f27155SAlexandre Courbot { 179*47f27155SAlexandre Courbot #[inline] 180*47f27155SAlexandre Courbot fn into_safe_cast(self) -> T { 181*47f27155SAlexandre Courbot T::from_safe_cast(self) 182*47f27155SAlexandre Courbot } 183*47f27155SAlexandre Courbot } 184*47f27155SAlexandre Courbot 185*47f27155SAlexandre Courbot /// Implements lossless conversion of a constant from a larger type into a smaller one. 186*47f27155SAlexandre Courbot macro_rules! impl_const_into { 187*47f27155SAlexandre Courbot ($from:ty => { $($into:ty),* }) => { 188*47f27155SAlexandre Courbot $( 189*47f27155SAlexandre Courbot $crate::macros::paste! { 190*47f27155SAlexandre Courbot #[doc = ::core::concat!( 191*47f27155SAlexandre Courbot "Performs a build-time safe conversion of a [`", 192*47f27155SAlexandre Courbot ::core::stringify!($from), 193*47f27155SAlexandre Courbot "`] constant value into a [`", 194*47f27155SAlexandre Courbot ::core::stringify!($into), 195*47f27155SAlexandre Courbot "`].")] 196*47f27155SAlexandre Courbot /// 197*47f27155SAlexandre Courbot /// This checks at compile-time that the conversion is lossless, and triggers a build 198*47f27155SAlexandre Courbot /// error if it isn't. 199*47f27155SAlexandre Courbot /// 200*47f27155SAlexandre Courbot /// # Examples 201*47f27155SAlexandre Courbot /// 202*47f27155SAlexandre Courbot /// ``` 203*47f27155SAlexandre Courbot /// use kernel::num::casts; 204*47f27155SAlexandre Courbot /// 205*47f27155SAlexandre Courbot /// // Succeeds because the value of the source fits into the destination's type. 206*47f27155SAlexandre Courbot #[doc = ::core::concat!( 207*47f27155SAlexandre Courbot "assert_eq!(casts::", 208*47f27155SAlexandre Courbot ::core::stringify!($from), 209*47f27155SAlexandre Courbot "_into_", 210*47f27155SAlexandre Courbot ::core::stringify!($into), 211*47f27155SAlexandre Courbot "::<1", 212*47f27155SAlexandre Courbot ::core::stringify!($from), 213*47f27155SAlexandre Courbot ">(), 1", 214*47f27155SAlexandre Courbot ::core::stringify!($into), 215*47f27155SAlexandre Courbot ");")] 216*47f27155SAlexandre Courbot /// ``` 217*47f27155SAlexandre Courbot #[inline] 218*47f27155SAlexandre Courbot pub const fn [<$from _into_ $into>]<const N: $from>() -> $into { 219*47f27155SAlexandre Courbot // Make sure that the target type is smaller than the source one. 220*47f27155SAlexandre Courbot $crate::static_assert!($from::BITS >= $into::BITS); 221*47f27155SAlexandre Courbot // CAST: we statically enforced above that `$from` is larger than `$into`, so the 222*47f27155SAlexandre Courbot // `as` conversion will be lossless. 223*47f27155SAlexandre Courbot $crate::const_assert!(N >= $into::MIN as $from && N <= $into::MAX as $from); 224*47f27155SAlexandre Courbot 225*47f27155SAlexandre Courbot N as $into 226*47f27155SAlexandre Courbot } 227*47f27155SAlexandre Courbot } 228*47f27155SAlexandre Courbot )* 229*47f27155SAlexandre Courbot }; 230*47f27155SAlexandre Courbot } 231*47f27155SAlexandre Courbot 232*47f27155SAlexandre Courbot impl_const_into!(usize => { u8, u16, u32 }); 233*47f27155SAlexandre Courbot impl_const_into!(u64 => { u8, u16, u32 }); 234*47f27155SAlexandre Courbot impl_const_into!(u32 => { u8, u16 }); 235*47f27155SAlexandre Courbot impl_const_into!(u16 => { u8 }); 236*47f27155SAlexandre Courbot 237*47f27155SAlexandre Courbot /// Conversions that are only lossless for the current architecture. 238*47f27155SAlexandre Courbot /// 239*47f27155SAlexandre Courbot /// # Portability 240*47f27155SAlexandre Courbot /// 241*47f27155SAlexandre Courbot /// Callers of this module become dependent on the setting of `CONFIG_64BIT`. Use with caution, and 242*47f27155SAlexandre Courbot /// never in code that is portable across pointer sizes. 243*47f27155SAlexandre Courbot pub mod arch { 244*47f27155SAlexandre Courbot /// Trait identical to [`FromSafeCast`](super::FromSafeCast), but for conversions that are not 245*47f27155SAlexandre Courbot /// available on all architectures. 246*47f27155SAlexandre Courbot pub trait FromSafeCastArch<T> { 247*47f27155SAlexandre Courbot /// Create a [`Self`] from `value`. This operation is guaranteed to be lossless. 248*47f27155SAlexandre Courbot fn from_safe_cast_arch(value: T) -> Self; 249*47f27155SAlexandre Courbot } 250*47f27155SAlexandre Courbot 251*47f27155SAlexandre Courbot /// Trait identical to [`IntoSafeCast`](super::IntoSafeCast), but for conversions that are not 252*47f27155SAlexandre Courbot /// available on all architectures. 253*47f27155SAlexandre Courbot pub trait IntoSafeCastArch<T> { 254*47f27155SAlexandre Courbot /// Convert `self` into a `T`. This operation is guaranteed to be lossless. 255*47f27155SAlexandre Courbot fn into_safe_cast_arch(self) -> T; 256*47f27155SAlexandre Courbot } 257*47f27155SAlexandre Courbot 258*47f27155SAlexandre Courbot /// Reverse operation for types implementing [`FromSafeCastArch`]. 259*47f27155SAlexandre Courbot impl<S, T> IntoSafeCastArch<T> for S 260*47f27155SAlexandre Courbot where 261*47f27155SAlexandre Courbot T: FromSafeCastArch<S>, 262*47f27155SAlexandre Courbot { 263*47f27155SAlexandre Courbot #[inline] 264*47f27155SAlexandre Courbot fn into_safe_cast_arch(self) -> T { 265*47f27155SAlexandre Courbot T::from_safe_cast_arch(self) 266*47f27155SAlexandre Courbot } 267*47f27155SAlexandre Courbot } 268*47f27155SAlexandre Courbot 269*47f27155SAlexandre Courbot /// A [`u64`] fits into a [`usize`] on 64-bit platforms. 270*47f27155SAlexandre Courbot #[cfg(CONFIG_64BIT)] 271*47f27155SAlexandre Courbot #[inline] 272*47f27155SAlexandre Courbot pub const fn u64_as_usize(value: u64) -> usize { 273*47f27155SAlexandre Courbot value as usize 274*47f27155SAlexandre Courbot } 275*47f27155SAlexandre Courbot 276*47f27155SAlexandre Courbot #[cfg(CONFIG_64BIT)] 277*47f27155SAlexandre Courbot impl FromSafeCastArch<u64> for usize { 278*47f27155SAlexandre Courbot #[inline] 279*47f27155SAlexandre Courbot fn from_safe_cast_arch(value: u64) -> Self { 280*47f27155SAlexandre Courbot u64_as_usize(value) 281*47f27155SAlexandre Courbot } 282*47f27155SAlexandre Courbot } 283*47f27155SAlexandre Courbot 284*47f27155SAlexandre Courbot /// A [`usize`] fits into a [`u32`] on 32-bit platforms. 285*47f27155SAlexandre Courbot #[cfg(not(CONFIG_64BIT))] 286*47f27155SAlexandre Courbot #[inline] 287*47f27155SAlexandre Courbot pub const fn usize_as_u32(value: usize) -> u32 { 288*47f27155SAlexandre Courbot value as u32 289*47f27155SAlexandre Courbot } 290*47f27155SAlexandre Courbot 291*47f27155SAlexandre Courbot #[cfg(not(CONFIG_64BIT))] 292*47f27155SAlexandre Courbot impl FromSafeCastArch<usize> for u32 { 293*47f27155SAlexandre Courbot #[inline] 294*47f27155SAlexandre Courbot fn from_safe_cast_arch(value: usize) -> Self { 295*47f27155SAlexandre Courbot usize_as_u32(value) 296*47f27155SAlexandre Courbot } 297*47f27155SAlexandre Courbot } 298*47f27155SAlexandre Courbot } 299