Files
linux/rust/kernel/num.rs
Alexandre Courbot 47f27155f1 rust: add functions and traits for lossless integer conversions
The core 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 of supporting larger-than-64bit architectures in the future.

However, the kernel supports a narrower set of architectures, with a
considerable amount of code that is architecture-specific. This makes it
helpful and desirable to provide more infallible conversions, lest we
rely on the `as` keyword and carry the risk of silently losing data.

Thus, introduce a new module `num::casts` that provides safe const
functions performing more conversions allowed by the build target, as
well as `FromSafeCast` and `IntoSafeCast` traits that are just
extensions of `From` and `Into` to conversions that are known to be
lossless.

Some conversions are architecture-specific: for instance, converting a
`u64` to a `usize` is only lossless on 64-bit platforms. These
conversions are made available via a dedicated `arch` sub-module.

Suggested-by: Danilo Krummrich <dakr@kernel.org>
Link: https://lore.kernel.org/rust-for-linux/DDK4KADWJHMG.1FUPL3SDR26XF@kernel.org/
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
Reviewed-by: Danilo Krummrich <dakr@kernel.org>
Link: https://patch.msgid.link/20260806-as_casts-v2-1-cb76a4d3a6ef@nvidia.com
[ Added a few more intra-doc links. - Miguel ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2026-08-13 13:41:28 +02:00

82 lines
1.6 KiB
Rust

// SPDX-License-Identifier: GPL-2.0
//! Additional numerical features for the kernel.
use core::ops;
pub mod bounded;
pub mod casts;
pub use bounded::*;
/// Designates unsigned primitive types.
pub enum Unsigned {}
/// Designates signed primitive types.
pub enum Signed {}
/// Describes core properties of integer types.
pub trait Integer:
Sized
+ Copy
+ Clone
+ PartialEq
+ Eq
+ PartialOrd
+ Ord
+ ops::Add<Output = Self>
+ ops::AddAssign
+ ops::Sub<Output = Self>
+ ops::SubAssign
+ ops::Mul<Output = Self>
+ ops::MulAssign
+ ops::Div<Output = Self>
+ ops::DivAssign
+ ops::Rem<Output = Self>
+ ops::RemAssign
+ ops::BitAnd<Output = Self>
+ ops::BitAndAssign
+ ops::BitOr<Output = Self>
+ ops::BitOrAssign
+ ops::BitXor<Output = Self>
+ ops::BitXorAssign
+ ops::Shl<u32, Output = Self>
+ ops::ShlAssign<u32>
+ ops::Shr<u32, Output = Self>
+ ops::ShrAssign<u32>
+ ops::Not
{
/// Whether this type is [`Signed`] or [`Unsigned`].
type Signedness;
/// Number of bits used for value representation.
const BITS: u32;
}
macro_rules! impl_integer {
($($type:ty: $signedness:ty), *) => {
$(
impl Integer for $type {
type Signedness = $signedness;
const BITS: u32 = <$type>::BITS;
}
)*
};
}
impl_integer!(
u8: Unsigned,
u16: Unsigned,
u32: Unsigned,
u64: Unsigned,
u128: Unsigned,
usize: Unsigned,
i8: Signed,
i16: Signed,
i32: Signed,
i64: Signed,
i128: Signed,
isize: Signed
);