xref: /linux/rust/kernel/num.rs (revision 12d5fc96ebbb3b948861805b32a4c3a96105ccd9)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 //! Additional numerical features for the kernel.
4 
5 use core::ops;
6 
7 pub mod bounded;
8 pub mod casts;
9 
10 pub use bounded::*;
11 
12 /// Designates unsigned primitive types.
13 pub enum Unsigned {}
14 
15 /// Designates signed primitive types.
16 pub enum Signed {}
17 
18 mod private {
19     pub trait Sealed {}
20 }
21 
22 /// Describes core properties of integer types.
23 pub trait Integer:
24     private::Sealed
25     + Sized
26     + Copy
27     + Clone
28     + PartialEq
29     + Eq
30     + PartialOrd
31     + Ord
32     + ops::Add<Output = Self>
33     + ops::AddAssign
34     + ops::Sub<Output = Self>
35     + ops::SubAssign
36     + ops::Mul<Output = Self>
37     + ops::MulAssign
38     + ops::Div<Output = Self>
39     + ops::DivAssign
40     + ops::Rem<Output = Self>
41     + ops::RemAssign
42     + ops::BitAnd<Output = Self>
43     + ops::BitAndAssign
44     + ops::BitOr<Output = Self>
45     + ops::BitOrAssign
46     + ops::BitXor<Output = Self>
47     + ops::BitXorAssign
48     + ops::Shl<u32, Output = Self>
49     + ops::ShlAssign<u32>
50     + ops::Shr<u32, Output = Self>
51     + ops::ShrAssign<u32>
52     + ops::Not
53 {
54     /// Whether this type is [`Signed`] or [`Unsigned`].
55     type Signedness;
56 
57     /// Number of bits used for value representation.
58     const BITS: u32;
59 }
60 
61 macro_rules! impl_integer {
62     ($($type:ty: $signedness:ty), *) => {
63         $(
64         impl private::Sealed for $type {}
65 
66         impl Integer for $type {
67             type Signedness = $signedness;
68 
69             const BITS: u32 = <$type>::BITS;
70         }
71         )*
72     };
73 }
74 
75 impl_integer!(
76     u8: Unsigned,
77     u16: Unsigned,
78     u32: Unsigned,
79     u64: Unsigned,
80     u128: Unsigned,
81     usize: Unsigned,
82     i8: Signed,
83     i16: Signed,
84     i32: Signed,
85     i64: Signed,
86     i128: Signed,
87     isize: Signed
88 );
89 
90 /// Creates a constant value ("cv") from an integer constant expression, with validity checked at
91 /// compile time.
92 ///
93 /// This works for any type that implements [`FromConst`], with the target type inferred from
94 /// the context, or named explicitly with `cv!(value => Type)`. It can also be used in const
95 /// contexts.
96 ///
97 /// # Pitfalls
98 ///
99 /// Only the target type is inferred from the context. The expression passed to [`cv!`] is typed by
100 /// itself. So, unsuffixed integer literal expressions default to [`i32`]. For example
101 /// `cv!(2 << 31)` does not evaluate to the same value as `cv!(2i64 << 31)`, since `2 << 31` is
102 /// treated as an [`i32`] before being widened to [`i128`] internally. Literals and arithmetic
103 /// expressions that overflow [`i32`] are a compile error, it's just left shifts that require care.
104 ///
105 /// # Examples
106 ///
107 /// ```
108 /// use core::num::NonZero;
109 ///
110 /// use kernel::{
111 ///     num::Bounded,
112 ///     ptr::Alignment, //
113 /// };
114 ///
115 /// let v: NonZero<usize> = cv!(8);
116 /// assert_eq!(v.get(), 8);
117 ///
118 /// // Any integer constant expression works, not only literals.
119 /// let m: NonZero<usize> = cv!(usize::MAX);
120 /// assert_eq!(m.get(), usize::MAX);
121 ///
122 /// let b: Bounded<u32, 4> = cv!(15);
123 /// assert_eq!(b.get(), 15);
124 ///
125 /// let a: Alignment = cv!(4096);
126 /// assert_eq!(a.as_usize(), 4096);
127 ///
128 /// // Checked narrowing of integer constants, including in `const` items.
129 /// const SMALL: u8 = cv!(200u32);
130 /// assert_eq!(SMALL, 200);
131 ///
132 /// const N: NonZero<u8> = cv!(5);
133 /// assert_eq!(N.get(), 5);
134 ///
135 /// // The target type can be given explicitly.
136 /// let e = cv!(200u32 => u8);
137 /// assert_eq!(e, 200);
138 ///
139 /// // With an explicit primitive target, the expression can use generic parameters.
140 /// const fn as_u64<const KEY: u16>() -> u64 {
141 ///     cv!(KEY => u64)
142 /// }
143 /// assert_eq!(as_u64::<0x40>(), 0x40);
144 /// ```
145 #[macro_export]
146 #[doc(hidden)]
147 macro_rules! cv {
148     (@cast $v:expr => $t:ty) => {
149         const {
150             #[allow(unused_comparisons, unused_assignments, clippy::as_underscore)]
151             {
152                 let v = $v;
153                 let r = v as $t;
154                 // Pin `back` to `v`'s type so `as _` casts back to the source type.
155                 let mut back = v;
156                 back = r as _;
157 
158                 ::core::assert!(
159                     back == v && (v < 0) == (r < 0),
160                     "value does not fit into the target type"
161                 );
162 
163                 r
164             }
165         }
166     };
167 
168     // Using `FromConst<V>::VALUE` means const generic expressions can't be used, since it requires
169     // the `generic_const_exprs` feature. Provide a special path for each primitive type that allows
170     // const generic expressions.
171     ($v:expr => u8) => { $crate::cv!(@cast $v => u8) };
172     ($v:expr => u16) => { $crate::cv!(@cast $v => u16) };
173     ($v:expr => u32) => { $crate::cv!(@cast $v => u32) };
174     ($v:expr => u64) => { $crate::cv!(@cast $v => u64) };
175     ($v:expr => u128) => { $crate::cv!(@cast $v => u128) };
176     ($v:expr => usize) => { $crate::cv!(@cast $v => usize) };
177     ($v:expr => i8) => { $crate::cv!(@cast $v => i8) };
178     ($v:expr => i16) => { $crate::cv!(@cast $v => i16) };
179     ($v:expr => i32) => { $crate::cv!(@cast $v => i32) };
180     ($v:expr => i64) => { $crate::cv!(@cast $v => i64) };
181     ($v:expr => i128) => { $crate::cv!(@cast $v => i128) };
182     ($v:expr => isize) => { $crate::cv!(@cast $v => isize) };
183     ($v:expr => $t:ty) => {
184         <$t as $crate::num::FromConst<{ $crate::cv!(@cast $v => i128) }>>::VALUE
185     };
186     ($v:expr) => {
187         <_ as $crate::num::FromConst<{ $crate::cv!(@cast $v => i128) }>>::VALUE
188     };
189 }
190 #[doc(inline)]
191 pub use cv;
192 
193 /// Types that can be created from an integer constant expression validated at compile time.
194 ///
195 /// Implement this trait to make a type usable with [`cv!`]. Use the [`cv!`] macro, not this trait
196 /// directly, for creating values.
197 #[diagnostic::on_unimplemented(message = "`{Self}` cannot be converted from a constant")]
198 pub trait FromConst<const V: i128>: Sized {
199     /// The value that corresponds to the constant `V`.
200     ///
201     /// Fails the build if `V` is not a valid value for [`Self`].
202     const VALUE: Self;
203 }
204 
205 /// Implements [`FromConst`] for primitive integer types and their [`NonZero`](core::num::NonZero)
206 /// versions.
207 macro_rules! impl_from_const {
208     ($($type:ty)*) => {
209         $(
210         impl<const V: i128> FromConst<V> for $type {
211             const VALUE: Self = {
212                 // CAST: The macro is only used for types up to 64 bits wide, so `MIN` and `MAX`
213                 // widen to `i128` losslessly.
214                 assert!(
215                     V >= <$type>::MIN as i128 && V <= <$type>::MAX as i128,
216                     "constant cannot be represented by the target type"
217                 );
218 
219                 // CAST: The assert above confirmed that `V` fits in `$type`.
220                 V as $type
221             };
222         }
223 
224         impl<const V: i128> FromConst<V> for core::num::NonZero<$type> {
225             const VALUE: Self = match core::num::NonZero::new(<$type as FromConst<V>>::VALUE) {
226                 Some(value) => value,
227                 None => panic!("constant cannot be zero"),
228             };
229         }
230         )*
231     };
232 }
233 
234 impl_from_const!(
235     u8 u16 u32 u64 usize
236     i8 i16 i32 i64 isize
237 );
238