Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298// SPDX-License-Identifier: GPL-2.0
//! Numerical helpers functions and traits.//!//! This is essentially a staging module for code to mature until it can be moved to the `kernel`//! crate.
use kernel::{ macros::paste, prelude::*, //};
/// Implements safe `as` conversion functions from a given type into a series of target types.////// These functions can be used in place of `as`, with the guarantee that they will be lossless.macro_rules! impl_safe_as { ($from:ty as { $($into:ty),* }) => { $( paste! { #[doc = ::core::concat!( "Losslessly converts a [`", ::core::stringify!($from), "`] into a [`", ::core::stringify!($into), "`].")] /// /// This conversion is allowed as it is always lossless. Prefer this over the `as` /// keyword to ensure no lossy casts are performed. /// /// This is for use from a `const` context. For non `const` use, prefer the /// [`FromSafeCast`] and [`IntoSafeCast`] traits. /// /// # Examples /// /// ``` /// use crate::num; /// #[doc = ::core::concat!( "assert_eq!(num::", ::core::stringify!($from), "_as_", ::core::stringify!($into), "(1", ::core::stringify!($from), "), 1", ::core::stringify!($into), ");")] /// ``` #[allow(unused)] #[inline(always)] pub(crate) const fn [<$from _as_ $into>](value: $from) -> $into { ::kernel::build_assert::static_assert!(size_of::<$into>() >= size_of::<$from>());
value as $into } } )* };}
impl_safe_as!(u8 as { u16, u32, u64, usize });impl_safe_as!(u16 as { u32, u64, usize });impl_safe_as!(u32 as { u64, usize } );// `u64` and `usize` have the same size on 64-bit platforms.#[cfg(CONFIG_64BIT)]impl_safe_as!(u64 as { usize } );
// A `usize` fits into a `u64` on 32 and 64-bit platforms.#[cfg(any(CONFIG_32BIT, CONFIG_64BIT))]impl_safe_as!(usize as { u64 });
// A `usize` fits into a `u32` on 32-bit platforms.#[cfg(CONFIG_32BIT)]impl_safe_as!(usize as { u32 });
/// Extension trait providing guaranteed lossless cast to `Self` from `T`.////// The standard library's `From` implementations do not cover conversions that are not portable or/// future-proof. For instance, even though it is safe today, `From<usize>` is not implemented for/// [`u64`] because of the possibility to support larger-than-64bit architectures in the future.////// The workaround is to either deal with the error handling of [`TryFrom`] for an operation that/// technically cannot fail, or to use the `as` keyword, which can silently strip data if the/// destination type is smaller than the source.////// Both options are hardly acceptable for the kernel. It is also a much more architecture/// dependent environment, supporting only 32 and 64 bit architectures, with some modules/// explicitly depending on a specific bus width that could greatly benefit from infallible/// conversion operations.////// Thus this extension trait that provides, for the architecture the kernel is built for, safe/// conversion between types for which such cast is lossless.////// In other words, this trait is implemented if, for the current build target and with `t: T`, the/// `t as Self` operation is completely lossless.////// Prefer this over the `as` keyword to ensure no lossy casts are performed.////// If you need to perform a conversion in `const` context, use [`u64_as_usize`], [`u32_as_usize`],/// [`usize_as_u64`], etc.////// # Examples////// ```/// use crate::num::FromSafeCast;////// assert_eq!(usize::from_safe_cast(0xf00u32), 0xf00u32 as usize);/// ```pub(crate) trait FromSafeCast<T> { /// Create a `Self` from `value`. This operation is guaranteed to be lossless. fn from_safe_cast(value: T) -> Self;}
impl FromSafeCast<usize> for u64 { fn from_safe_cast(value: usize) -> Self { usize_as_u64(value) }}
#[cfg(CONFIG_32BIT)]impl FromSafeCast<usize> for u32 { fn from_safe_cast(value: usize) -> Self { usize_as_u32(value) }}
impl FromSafeCast<u32> for usize { fn from_safe_cast(value: u32) -> Self { u32_as_usize(value) }}
#[cfg(CONFIG_64BIT)]impl FromSafeCast<u64> for usize { fn from_safe_cast(value: u64) -> Self { u64_as_usize(value) }}
/// Counterpart to the [`FromSafeCast`] trait, i.e. this trait is to [`FromSafeCast`] what [`Into`]/// is to [`From`].////// See the documentation of [`FromSafeCast`] for the motivation.////// # Examples////// ```/// use crate::num::IntoSafeCast;////// assert_eq!(0xf00u32.into_safe_cast(), 0xf00u32 as usize);/// ```pub(crate) trait IntoSafeCast<T> { /// Convert `self` into a `T`. This operation is guaranteed to be lossless. fn into_safe_cast(self) -> T;}
/// Reverse operation for types implementing [`FromSafeCast`].impl<S, T> IntoSafeCast<T> for Swhere T: FromSafeCast<S>,{ fn into_safe_cast(self) -> T { T::from_safe_cast(self) }}
/// Implements lossless conversion of a constant from a larger type into a smaller one.macro_rules! impl_const_into { ($from:ty => { $($into:ty),* }) => { $( paste! { #[doc = ::core::concat!( "Performs a build-time safe conversion of a [`", ::core::stringify!($from), "`] constant value into a [`", ::core::stringify!($into), "`].")] /// /// This checks at compile-time that the conversion is lossless, and triggers a build /// error if it isn't. /// /// # Examples /// /// ``` /// use crate::num; /// /// // Succeeds because the value of the source fits into the destination's type. #[doc = ::core::concat!( "assert_eq!(num::", ::core::stringify!($from), "_into_", ::core::stringify!($into), "::<1", ::core::stringify!($from), ">(), 1", ::core::stringify!($into), ");")] /// ``` #[allow(unused)] pub(crate) const fn [<$from _into_ $into>]<const N: $from>() -> $into { // Make sure that the target type is smaller than the source one. static_assert!($from::BITS >= $into::BITS); // CAST: we statically enforced above that `$from` is larger than `$into`, so the // `as` conversion will be lossless. build_assert!(N >= $into::MIN as $from && N <= $into::MAX as $from);
N as $into } } )* };}
impl_const_into!(usize => { u8, u16, u32 });impl_const_into!(u64 => { u8, u16, u32 });impl_const_into!(u32 => { u8, u16 });impl_const_into!(u16 => { u8 });
/// Creates an enum type associated to a [`Bounded`](kernel::num::Bounded), with a [`From`]/// conversion to the associated `Bounded` and either a [`TryFrom`] or `From` conversion from the/// associated `Bounded`.// TODO[FPRI]: This is a temporary solution to be replaced with the corresponding derive macros// once they land.#[macro_export]macro_rules! bounded_enum { ( $(#[$enum_meta:meta])* $vis:vis enum $enum_type:ident with $from_impl:ident<Bounded<$width:ty, $length:literal>> { $( $(#[doc = $variant_doc:expr])* $variant:ident = $value:expr),* $(,)* } ) => { $(#[$enum_meta])* $vis enum $enum_type { $( $(#[doc = $variant_doc])* $variant = $value ),* }
impl core::convert::From<$enum_type> for kernel::num::Bounded<$width, $length> { fn from(value: $enum_type) -> Self { match value { $($enum_type::$variant => kernel::num::Bounded::<$width, _>::new::<{ $value }>()),* } } }
bounded_enum!(@impl_from $enum_type with $from_impl<Bounded<$width, $length>> { $($variant = $value),* }); };
// `TryFrom` implementation from associated `Bounded` to enum type. (@impl_from $enum_type:ident with TryFrom<Bounded<$width:ty, $length:literal>> { $($variant:ident = $value:expr),* $(,)* }) => { impl core::convert::TryFrom<kernel::num::Bounded<$width, $length>> for $enum_type { type Error = kernel::error::Error;
fn try_from( value: kernel::num::Bounded<$width, $length> ) -> kernel::error::Result<Self> { match value.get() { $( value if value == $value => Ok($enum_type::$variant), )* _ => Err(kernel::error::code::EINVAL), } } } };
// `From` implementation from associated `Bounded` to enum type. Triggers a build-time error if // all possible values of the `Bounded` are not covered by the enum type. (@impl_from $enum_type:ident with From<Bounded<$width:ty, $length:literal>> { $($variant:ident = $value:expr),* $(,)* }) => { impl core::convert::From<kernel::num::Bounded<$width, $length>> for $enum_type { fn from(value: kernel::num::Bounded<$width, $length>) -> Self { const MAX: $width = 1 << $length;
// Makes the compiler optimizer aware of the possible range of values. let value = value.get() & ((1 << $length) - 1); match value { $( $value => $enum_type::$variant, )* // PANIC: we cannot reach this arm as all possible variants are handled by the // match arms above. It is here to make the compiler complain if `$enum_type` // does not cover all values of the `0..MAX` range. MAX.. => unreachable!(), } } } }}