xref: /linux/rust/kernel/bitfield.rs (revision fab183d632628381b466a41479489541ac0e29a0)
1b7b8b4ccSAlexandre Courbot // SPDX-License-Identifier: GPL-2.0
2b7b8b4ccSAlexandre Courbot 
3b7b8b4ccSAlexandre Courbot //! Support for defining bitfields as Rust structures.
4b7b8b4ccSAlexandre Courbot //!
5b7b8b4ccSAlexandre Courbot //! The [`bitfield!`](kernel::bitfield!) macro declares integer types that are split into distinct
6b7b8b4ccSAlexandre Courbot //! bit fields of arbitrary length. Each field is typed using [`Bounded`](kernel::num::Bounded) to
7b7b8b4ccSAlexandre Courbot //! ensure values are properly validated and to avoid implicit data loss.
8b7b8b4ccSAlexandre Courbot //!
9b7b8b4ccSAlexandre Courbot //! # Example
10b7b8b4ccSAlexandre Courbot //!
11b7b8b4ccSAlexandre Courbot //! ```rust
12b7b8b4ccSAlexandre Courbot //! use kernel::bitfield;
13b7b8b4ccSAlexandre Courbot //! use kernel::num::Bounded;
14b7b8b4ccSAlexandre Courbot //!
15b7b8b4ccSAlexandre Courbot //! bitfield! {
16b7b8b4ccSAlexandre Courbot //!     pub struct Rgb(u16) {
17b7b8b4ccSAlexandre Courbot //!         15:11 blue;
18b7b8b4ccSAlexandre Courbot //!         10:5 green;
19b7b8b4ccSAlexandre Courbot //!         4:0 red;
20b7b8b4ccSAlexandre Courbot //!     }
21b7b8b4ccSAlexandre Courbot //! }
22b7b8b4ccSAlexandre Courbot //!
23b7b8b4ccSAlexandre Courbot //! // Valid value for the `blue` field.
24b7b8b4ccSAlexandre Courbot //! let blue = Bounded::<u16, 5>::new::<0x18>();
25b7b8b4ccSAlexandre Courbot //!
26b7b8b4ccSAlexandre Courbot //! // Setters can be chained. Values ranges are checked at compile-time.
27b7b8b4ccSAlexandre Courbot //! let color = Rgb::zeroed()
28b7b8b4ccSAlexandre Courbot //!     // Compile-time bounds check of constant value.
29b7b8b4ccSAlexandre Courbot //!     .with_const_red::<0x10>()
30b7b8b4ccSAlexandre Courbot //!     .with_const_green::<0x1f>()
31b7b8b4ccSAlexandre Courbot //!     // A `Bounded` can also be passed.
32b7b8b4ccSAlexandre Courbot //!     .with_blue(blue);
33b7b8b4ccSAlexandre Courbot //!
34b7b8b4ccSAlexandre Courbot //! assert_eq!(color.red(), 0x10);
35b7b8b4ccSAlexandre Courbot //! assert_eq!(color.green(), 0x1f);
36b7b8b4ccSAlexandre Courbot //! assert_eq!(color.blue(), 0x18);
37b7b8b4ccSAlexandre Courbot //! assert_eq!(
38b7b8b4ccSAlexandre Courbot //!     color.into_raw(),
39b7b8b4ccSAlexandre Courbot //!     (0x18 << Rgb::BLUE_SHIFT) + (0x1f << Rgb::GREEN_SHIFT) + 0x10,
40b7b8b4ccSAlexandre Courbot //! );
41b7b8b4ccSAlexandre Courbot //!
42b7b8b4ccSAlexandre Courbot //! // Convert to/from the backing storage type.
43b7b8b4ccSAlexandre Courbot //! let raw: u16 = color.into();
44b7b8b4ccSAlexandre Courbot //! assert_eq!(Rgb::from(raw), color);
45b7b8b4ccSAlexandre Courbot //! ```
46b7b8b4ccSAlexandre Courbot //!
47b7b8b4ccSAlexandre Courbot //! # Syntax
48b7b8b4ccSAlexandre Courbot //!
49b7b8b4ccSAlexandre Courbot //! ```text
50b7b8b4ccSAlexandre Courbot //! bitfield! {
51b7b8b4ccSAlexandre Courbot //!     #[attributes]
52b7b8b4ccSAlexandre Courbot //!     // Documentation for `Name`.
53b7b8b4ccSAlexandre Courbot //!     pub struct Name(storage_type) {
54b7b8b4ccSAlexandre Courbot //!         // `field_1` documentation.
55b7b8b4ccSAlexandre Courbot //!         hi:lo field_1;
56b7b8b4ccSAlexandre Courbot //!         // `field_2` documentation.
57b7b8b4ccSAlexandre Courbot //!         hi:lo field_2 => ConvertedType;
58b7b8b4ccSAlexandre Courbot //!         // `field_3` documentation.
59b7b8b4ccSAlexandre Courbot //!         hi:lo field_3 ?=> ConvertedType;
60b7b8b4ccSAlexandre Courbot //!         ...
61b7b8b4ccSAlexandre Courbot //!     }
62b7b8b4ccSAlexandre Courbot //! }
63b7b8b4ccSAlexandre Courbot //! ```
64b7b8b4ccSAlexandre Courbot //!
65b7b8b4ccSAlexandre Courbot //! - `storage_type`: The underlying unsigned integer type ([`u8`], [`u16`], [`u32`], [`u64`]).
66b7b8b4ccSAlexandre Courbot //!   Signed integer storage types are not supported.
67b7b8b4ccSAlexandre Courbot //! - `hi:lo`: Bit range (inclusive), where `hi >= lo`.
68b7b8b4ccSAlexandre Courbot //! - `=> Type`: Optional infallible conversion (see [below](#infallible-conversion-)).
69b7b8b4ccSAlexandre Courbot //! - `?=> Type`: Optional fallible conversion (see [below](#fallible-conversion-)).
70b7b8b4ccSAlexandre Courbot //! - Documentation strings and attributes are optional.
71b7b8b4ccSAlexandre Courbot //!
72b7b8b4ccSAlexandre Courbot //! # Generated code
73b7b8b4ccSAlexandre Courbot //!
74b7b8b4ccSAlexandre Courbot //! Each field is internally represented as a [`Bounded`] parameterized by its bit width. Field
75b7b8b4ccSAlexandre Courbot //! values can either be set/retrieved directly, or converted from/to another type.
76b7b8b4ccSAlexandre Courbot //!
77b7b8b4ccSAlexandre Courbot //! The use of [`Bounded`] for each field enforces bounds-checking (at build time or runtime) of
78b7b8b4ccSAlexandre Courbot //! every value assigned to a field. This ensures that data is never accidentally truncated.
79b7b8b4ccSAlexandre Courbot //!
80b7b8b4ccSAlexandre Courbot //! The macro generates the bitfield type, [`From`] and [`Into`] implementations for its storage
81b7b8b4ccSAlexandre Courbot //! type, as well as [`Debug`] and [`Zeroable`](pin_init::Zeroable) implementations.
82b7b8b4ccSAlexandre Courbot //!
83b7b8b4ccSAlexandre Courbot //! For each field, it also generates:
84b7b8b4ccSAlexandre Courbot //!
85b7b8b4ccSAlexandre Courbot //! - `field()`: Getter method for the field value.
86b7b8b4ccSAlexandre Courbot //! - `with_field(value)`: Infallible setter; the argument type must fit within the field's width.
87b7b8b4ccSAlexandre Courbot //! - `with_const_field::<VALUE>()`: `const` setter; the value is validated at compile time.
88b7b8b4ccSAlexandre Courbot //!   Usually shorter to use than `with_field` for constant values as it doesn't require
89b7b8b4ccSAlexandre Courbot //!   constructing a [`Bounded`].
90b7b8b4ccSAlexandre Courbot //! - `try_with_field(value)`: Fallible setter. Returns an error if the value is out of range.
91b7b8b4ccSAlexandre Courbot //! - `FIELD_MASK`, `FIELD_SHIFT`, `FIELD_RANGE`: Constants for manual bit manipulation.
92b7b8b4ccSAlexandre Courbot //!
93b7b8b4ccSAlexandre Courbot //! # Reserved names for field identifiers
94b7b8b4ccSAlexandre Courbot //!
95b7b8b4ccSAlexandre Courbot //! Field identifiers are used to generate methods and associated constants on the bitfield type.
96b7b8b4ccSAlexandre Courbot //! For a field named `field`, the macro may generate methods named `field`, `with_field`,
97b7b8b4ccSAlexandre Courbot //! `with_const_field`, `try_with_field`, `__field` and `__with_field`, as well as constants named
98b7b8b4ccSAlexandre Courbot //! `FIELD_MASK`, `FIELD_SHIFT` and `FIELD_RANGE`.
99b7b8b4ccSAlexandre Courbot //!
100b7b8b4ccSAlexandre Courbot //! Therefore, field identifiers must not use names that would collide with generated items for
101b7b8b4ccSAlexandre Courbot //! any field in the same bitfield. The following prefixes are thus reserved for field identifiers:
102b7b8b4ccSAlexandre Courbot //!
103b7b8b4ccSAlexandre Courbot //! - `with_`
104b7b8b4ccSAlexandre Courbot //! - `const_`
105b7b8b4ccSAlexandre Courbot //! - `try_with_`
106b7b8b4ccSAlexandre Courbot //! - `__`
107b7b8b4ccSAlexandre Courbot //!
108b7b8b4ccSAlexandre Courbot //! The field identifiers `from_raw`, `into_raw`, and `into` are also reserved.
109b7b8b4ccSAlexandre Courbot //!
110b7b8b4ccSAlexandre Courbot //! In addition, field identifiers should follow Rust `snake_case` conventions, since the associated
111b7b8b4ccSAlexandre Courbot //! constants are generated by uppercasing the field name.
112b7b8b4ccSAlexandre Courbot //!
113b7b8b4ccSAlexandre Courbot //! # Implicit conversions
114b7b8b4ccSAlexandre Courbot //!
115b7b8b4ccSAlexandre Courbot //! Types that fit entirely within a field's bit width can be used directly with setters. For
116b7b8b4ccSAlexandre Courbot //! example, [`bool`] works with single-bit fields, and [`u8`] works with 8-bit fields:
117b7b8b4ccSAlexandre Courbot //!
118b7b8b4ccSAlexandre Courbot //! ```rust
119b7b8b4ccSAlexandre Courbot //! use kernel::bitfield;
120b7b8b4ccSAlexandre Courbot //!
121b7b8b4ccSAlexandre Courbot //! bitfield! {
122b7b8b4ccSAlexandre Courbot //!     pub struct Flags(u32) {
123b7b8b4ccSAlexandre Courbot //!         15:8 byte_field;
124b7b8b4ccSAlexandre Courbot //!         0:0 flag;
125b7b8b4ccSAlexandre Courbot //!     }
126b7b8b4ccSAlexandre Courbot //! }
127b7b8b4ccSAlexandre Courbot //!
128b7b8b4ccSAlexandre Courbot //! let flags = Flags::zeroed()
129b7b8b4ccSAlexandre Courbot //!     .with_byte_field(0x42_u8)
130b7b8b4ccSAlexandre Courbot //!     .with_flag(true);
131b7b8b4ccSAlexandre Courbot //!
132b7b8b4ccSAlexandre Courbot //! assert_eq!(flags.into_raw(), (0x42 << Flags::BYTE_FIELD_SHIFT) | 1);
133b7b8b4ccSAlexandre Courbot //! ```
134b7b8b4ccSAlexandre Courbot //!
135b7b8b4ccSAlexandre Courbot //! # Runtime bounds checking
136b7b8b4ccSAlexandre Courbot //!
137b7b8b4ccSAlexandre Courbot //! When a value is not known at compile time, use `try_with_field()` to check bounds at runtime:
138b7b8b4ccSAlexandre Courbot //!
139b7b8b4ccSAlexandre Courbot //! ```rust
140b7b8b4ccSAlexandre Courbot //! use kernel::bitfield;
141b7b8b4ccSAlexandre Courbot //!
142b7b8b4ccSAlexandre Courbot //! bitfield! {
143b7b8b4ccSAlexandre Courbot //!     pub struct Config(u8) {
144b7b8b4ccSAlexandre Courbot //!         3:0 nibble;
145b7b8b4ccSAlexandre Courbot //!     }
146b7b8b4ccSAlexandre Courbot //! }
147b7b8b4ccSAlexandre Courbot //!
148b7b8b4ccSAlexandre Courbot //! fn set_nibble(config: Config, value: u8) -> Result<Config, Error> {
149b7b8b4ccSAlexandre Courbot //!     // Returns `EOVERFLOW` if `value > 0xf`.
150b7b8b4ccSAlexandre Courbot //!     config.try_with_nibble(value)
151b7b8b4ccSAlexandre Courbot //! }
152b7b8b4ccSAlexandre Courbot //! # Ok::<(), Error>(())
153b7b8b4ccSAlexandre Courbot //! ```
154b7b8b4ccSAlexandre Courbot //!
155b7b8b4ccSAlexandre Courbot //! # Type conversion
156b7b8b4ccSAlexandre Courbot //!
157b7b8b4ccSAlexandre Courbot //! Fields can be automatically converted to/from a custom type using `=>` (infallible) or `?=>`
158b7b8b4ccSAlexandre Courbot //! (fallible). The custom type must implement the appropriate [`From`] or [`TryFrom`] traits with
159b7b8b4ccSAlexandre Courbot //! [`Bounded`].
160b7b8b4ccSAlexandre Courbot //!
161b7b8b4ccSAlexandre Courbot //! ## Infallible conversion (`=>`)
162b7b8b4ccSAlexandre Courbot //!
163b7b8b4ccSAlexandre Courbot //! Use this when all possible bit patterns of a field map to valid values:
164b7b8b4ccSAlexandre Courbot //!
165b7b8b4ccSAlexandre Courbot //! ```rust
166b7b8b4ccSAlexandre Courbot //! use kernel::bitfield;
167b7b8b4ccSAlexandre Courbot //! use kernel::num::Bounded;
168b7b8b4ccSAlexandre Courbot //!
169b7b8b4ccSAlexandre Courbot //! #[derive(Debug, Clone, Copy, PartialEq)]
170b7b8b4ccSAlexandre Courbot //! enum Power {
171b7b8b4ccSAlexandre Courbot //!     Off,
172b7b8b4ccSAlexandre Courbot //!     On,
173b7b8b4ccSAlexandre Courbot //! }
174b7b8b4ccSAlexandre Courbot //!
175b7b8b4ccSAlexandre Courbot //! impl From<Bounded<u32, 1>> for Power {
176b7b8b4ccSAlexandre Courbot //!     fn from(v: Bounded<u32, 1>) -> Self {
177b7b8b4ccSAlexandre Courbot //!         match *v {
178b7b8b4ccSAlexandre Courbot //!             0 => Power::Off,
179b7b8b4ccSAlexandre Courbot //!             _ => Power::On,
180b7b8b4ccSAlexandre Courbot //!         }
181b7b8b4ccSAlexandre Courbot //!     }
182b7b8b4ccSAlexandre Courbot //! }
183b7b8b4ccSAlexandre Courbot //!
184b7b8b4ccSAlexandre Courbot //! impl From<Power> for Bounded<u32, 1> {
185b7b8b4ccSAlexandre Courbot //!     fn from(p: Power) -> Self {
186b7b8b4ccSAlexandre Courbot //!         (p as u32 != 0).into()
187b7b8b4ccSAlexandre Courbot //!     }
188b7b8b4ccSAlexandre Courbot //! }
189b7b8b4ccSAlexandre Courbot //!
190b7b8b4ccSAlexandre Courbot //! bitfield! {
191b7b8b4ccSAlexandre Courbot //!     pub struct Control(u32) {
192b7b8b4ccSAlexandre Courbot //!         0:0 power => Power;
193b7b8b4ccSAlexandre Courbot //!     }
194b7b8b4ccSAlexandre Courbot //! }
195b7b8b4ccSAlexandre Courbot //!
196b7b8b4ccSAlexandre Courbot //! let ctrl = Control::zeroed().with_power(Power::On);
197b7b8b4ccSAlexandre Courbot //! assert_eq!(ctrl.power(), Power::On);
198b7b8b4ccSAlexandre Courbot //! ```
199b7b8b4ccSAlexandre Courbot //!
200b7b8b4ccSAlexandre Courbot //! ## Fallible conversion (`?=>`)
201b7b8b4ccSAlexandre Courbot //!
202b7b8b4ccSAlexandre Courbot //! Use this when some bit patterns of a field are invalid. The getter returns a [`Result`]:
203b7b8b4ccSAlexandre Courbot //!
204b7b8b4ccSAlexandre Courbot //! ```rust
205b7b8b4ccSAlexandre Courbot //! use kernel::bitfield;
206b7b8b4ccSAlexandre Courbot //! use kernel::num::Bounded;
207b7b8b4ccSAlexandre Courbot //!
208b7b8b4ccSAlexandre Courbot //! #[derive(Debug, Clone, Copy, PartialEq)]
209b7b8b4ccSAlexandre Courbot //! enum Mode {
210b7b8b4ccSAlexandre Courbot //!     Low = 0,
211b7b8b4ccSAlexandre Courbot //!     High = 1,
212b7b8b4ccSAlexandre Courbot //!     Auto = 2,
213b7b8b4ccSAlexandre Courbot //!     // 3 is invalid
214b7b8b4ccSAlexandre Courbot //! }
215b7b8b4ccSAlexandre Courbot //!
216b7b8b4ccSAlexandre Courbot //! impl TryFrom<Bounded<u32, 2>> for Mode {
217b7b8b4ccSAlexandre Courbot //!     type Error = u32;
218b7b8b4ccSAlexandre Courbot //!
219b7b8b4ccSAlexandre Courbot //!     fn try_from(v: Bounded<u32, 2>) -> Result<Self, u32> {
220b7b8b4ccSAlexandre Courbot //!         match *v {
221b7b8b4ccSAlexandre Courbot //!             0 => Ok(Mode::Low),
222b7b8b4ccSAlexandre Courbot //!             1 => Ok(Mode::High),
223b7b8b4ccSAlexandre Courbot //!             2 => Ok(Mode::Auto),
224b7b8b4ccSAlexandre Courbot //!             n => Err(n),
225b7b8b4ccSAlexandre Courbot //!         }
226b7b8b4ccSAlexandre Courbot //!     }
227b7b8b4ccSAlexandre Courbot //! }
228b7b8b4ccSAlexandre Courbot //!
229b7b8b4ccSAlexandre Courbot //! impl From<Mode> for Bounded<u32, 2> {
230b7b8b4ccSAlexandre Courbot //!     fn from(m: Mode) -> Self {
231b7b8b4ccSAlexandre Courbot //!         match m {
232b7b8b4ccSAlexandre Courbot //!             Mode::Low => Bounded::<u32, _>::new::<0>(),
233b7b8b4ccSAlexandre Courbot //!             Mode::High => Bounded::<u32, _>::new::<1>(),
234b7b8b4ccSAlexandre Courbot //!             Mode::Auto => Bounded::<u32, _>::new::<2>(),
235b7b8b4ccSAlexandre Courbot //!         }
236b7b8b4ccSAlexandre Courbot //!     }
237b7b8b4ccSAlexandre Courbot //! }
238b7b8b4ccSAlexandre Courbot //!
239b7b8b4ccSAlexandre Courbot //! bitfield! {
240b7b8b4ccSAlexandre Courbot //!     pub struct Config(u32) {
241b7b8b4ccSAlexandre Courbot //!         1:0 mode ?=> Mode;
242b7b8b4ccSAlexandre Courbot //!     }
243b7b8b4ccSAlexandre Courbot //! }
244b7b8b4ccSAlexandre Courbot //!
245b7b8b4ccSAlexandre Courbot //! let cfg = Config::zeroed().with_mode(Mode::Auto);
246b7b8b4ccSAlexandre Courbot //! assert_eq!(cfg.mode(), Ok(Mode::Auto));
247b7b8b4ccSAlexandre Courbot //!
248b7b8b4ccSAlexandre Courbot //! // Invalid bit pattern returns an error.
249b7b8b4ccSAlexandre Courbot //! assert_eq!(Config::from(0b11).mode(), Err(3));
250b7b8b4ccSAlexandre Courbot //! ```
251b7b8b4ccSAlexandre Courbot //!
252b7b8b4ccSAlexandre Courbot //! # Bits outside of declared fields
253b7b8b4ccSAlexandre Courbot //!
254b7b8b4ccSAlexandre Courbot //! Bits of the storage type that are not part of any declared field are preserved by the setter
255b7b8b4ccSAlexandre Courbot //! methods, and can only be modified through `from_raw` or the [`From`] implementation from the
256b7b8b4ccSAlexandre Courbot //! storage type.
257b7b8b4ccSAlexandre Courbot //!
258b7b8b4ccSAlexandre Courbot //! ```rust
259b7b8b4ccSAlexandre Courbot //! use kernel::bitfield;
260b7b8b4ccSAlexandre Courbot //!
261b7b8b4ccSAlexandre Courbot //! bitfield! {
262b7b8b4ccSAlexandre Courbot //!     pub struct Sparse(u8) {
263b7b8b4ccSAlexandre Courbot //!         7:6 high;
264b7b8b4ccSAlexandre Courbot //!         // Bits 5:1 are not covered by any field.
265b7b8b4ccSAlexandre Courbot //!         0:0 low;
266b7b8b4ccSAlexandre Courbot //!     }
267b7b8b4ccSAlexandre Courbot //! }
268b7b8b4ccSAlexandre Courbot //!
269b7b8b4ccSAlexandre Courbot //! // Set the gap bits via `from_raw`, then mutate the declared fields.
270b7b8b4ccSAlexandre Courbot //! let val = Sparse::from_raw(0b0010_1010)
271b7b8b4ccSAlexandre Courbot //!     .with_const_high::<0b11>()
272b7b8b4ccSAlexandre Courbot //!     .with_low(true);
273b7b8b4ccSAlexandre Courbot //!
274b7b8b4ccSAlexandre Courbot //! // Bits 5:1 are unchanged.
275b7b8b4ccSAlexandre Courbot //! assert_eq!(val.into_raw(), 0b1110_1011);
276b7b8b4ccSAlexandre Courbot //! ```
277b7b8b4ccSAlexandre Courbot //!
278b7b8b4ccSAlexandre Courbot //! # Signed field values
279b7b8b4ccSAlexandre Courbot //!
280b7b8b4ccSAlexandre Courbot //! Bitfield storage types are unsigned. Since field getter methods return a [`Bounded`] of the
281b7b8b4ccSAlexandre Courbot //! storage type, fields are also unsigned by default.
282b7b8b4ccSAlexandre Courbot //!
283b7b8b4ccSAlexandre Courbot //! If a field needs to encode a signed value, use a custom conversion type with `=>` or `?=>` to
284b7b8b4ccSAlexandre Courbot //! perform the sign interpretation explicitly.
285b7b8b4ccSAlexandre Courbot //!
286b7b8b4ccSAlexandre Courbot //! [`Bounded`]: kernel::num::Bounded
287b7b8b4ccSAlexandre Courbot 
288b7b8b4ccSAlexandre Courbot /// Defines a bitfield struct with bounds-checked accessors for individual bit ranges.
289b7b8b4ccSAlexandre Courbot ///
290b7b8b4ccSAlexandre Courbot /// See the [`mod@kernel::bitfield`] module for full documentation and examples.
291b7b8b4ccSAlexandre Courbot #[macro_export]
292b7b8b4ccSAlexandre Courbot macro_rules! bitfield {
293b7b8b4ccSAlexandre Courbot     // Entry point defining the bitfield struct, its implementations and its field accessors.
294b7b8b4ccSAlexandre Courbot     (
295b7b8b4ccSAlexandre Courbot         $(#[$attr:meta])* $vis:vis struct $name:ident($storage:ty) { $($fields:tt)* }
296b7b8b4ccSAlexandre Courbot     ) => {
297b7b8b4ccSAlexandre Courbot         $crate::bitfield!(@core
298b7b8b4ccSAlexandre Courbot             #[allow(non_camel_case_types)]
299b7b8b4ccSAlexandre Courbot             $(#[$attr])* $vis $name $storage
300b7b8b4ccSAlexandre Courbot         );
301b7b8b4ccSAlexandre Courbot         $crate::bitfield!(@fields $vis $name $storage { $($fields)* });
302b7b8b4ccSAlexandre Courbot     };
303b7b8b4ccSAlexandre Courbot 
304b7b8b4ccSAlexandre Courbot     // All rules below are helpers.
305b7b8b4ccSAlexandre Courbot 
306b7b8b4ccSAlexandre Courbot     // Defines the wrapper `$name` type and its conversions from/to the storage type.
307b7b8b4ccSAlexandre Courbot     (@core $(#[$attr:meta])* $vis:vis $name:ident $storage:ty) => {
308b7b8b4ccSAlexandre Courbot         $(#[$attr])*
309b7b8b4ccSAlexandre Courbot         #[repr(transparent)]
310b7b8b4ccSAlexandre Courbot         #[derive(Clone, Copy, PartialEq, Eq)]
311b7b8b4ccSAlexandre Courbot         $vis struct $name {
312b7b8b4ccSAlexandre Courbot             inner: $storage,
313b7b8b4ccSAlexandre Courbot         }
314b7b8b4ccSAlexandre Courbot 
315b7b8b4ccSAlexandre Courbot         #[allow(dead_code)]
316b7b8b4ccSAlexandre Courbot         impl $name {
317b7b8b4ccSAlexandre Courbot             /// Creates a bitfield from a raw value.
318b7b8b4ccSAlexandre Courbot             #[inline(always)]
319b7b8b4ccSAlexandre Courbot             $vis const fn from_raw(value: $storage) -> Self {
320b7b8b4ccSAlexandre Courbot                 Self{ inner: value }
321b7b8b4ccSAlexandre Courbot             }
322b7b8b4ccSAlexandre Courbot 
323b7b8b4ccSAlexandre Courbot             /// Turns this bitfield into its raw value.
324b7b8b4ccSAlexandre Courbot             ///
325b7b8b4ccSAlexandre Courbot             /// This is similar to the [`From`] implementation, but is shorter to invoke in
326b7b8b4ccSAlexandre Courbot             /// most cases.
327b7b8b4ccSAlexandre Courbot             #[inline(always)]
328b7b8b4ccSAlexandre Courbot             $vis const fn into_raw(self) -> $storage {
329b7b8b4ccSAlexandre Courbot                 self.inner
330b7b8b4ccSAlexandre Courbot             }
331b7b8b4ccSAlexandre Courbot         }
332b7b8b4ccSAlexandre Courbot 
333b7b8b4ccSAlexandre Courbot         // SAFETY: `$storage` is `Zeroable` and `$name` is transparent.
334b7b8b4ccSAlexandre Courbot         unsafe impl ::pin_init::Zeroable for $name {}
335b7b8b4ccSAlexandre Courbot 
336b7b8b4ccSAlexandre Courbot         impl ::core::convert::From<$name> for $storage {
337b7b8b4ccSAlexandre Courbot             #[inline(always)]
338b7b8b4ccSAlexandre Courbot             fn from(val: $name) -> $storage {
339b7b8b4ccSAlexandre Courbot                 val.into_raw()
340b7b8b4ccSAlexandre Courbot             }
341b7b8b4ccSAlexandre Courbot         }
342b7b8b4ccSAlexandre Courbot 
343b7b8b4ccSAlexandre Courbot         impl ::core::convert::From<$storage> for $name {
344b7b8b4ccSAlexandre Courbot             #[inline(always)]
345b7b8b4ccSAlexandre Courbot             fn from(val: $storage) -> $name {
346b7b8b4ccSAlexandre Courbot                 Self::from_raw(val)
347b7b8b4ccSAlexandre Courbot             }
348b7b8b4ccSAlexandre Courbot         }
349b7b8b4ccSAlexandre Courbot     };
350b7b8b4ccSAlexandre Courbot 
351b7b8b4ccSAlexandre Courbot     // Definitions requiring knowledge of individual fields: private and public field accessors,
352b7b8b4ccSAlexandre Courbot     // and `Debug` implementation.
353b7b8b4ccSAlexandre Courbot     (@fields $vis:vis $name:ident $storage:ty {
354b7b8b4ccSAlexandre Courbot         $($(#[doc = $doc:expr])* $hi:literal:$lo:literal $field:ident
355b7b8b4ccSAlexandre Courbot             $(?=> $try_into_type:ty)?
356b7b8b4ccSAlexandre Courbot             $(=> $into_type:ty)?
357b7b8b4ccSAlexandre Courbot         ;
358b7b8b4ccSAlexandre Courbot         )*
359b7b8b4ccSAlexandre Courbot     }
360b7b8b4ccSAlexandre Courbot     ) => {
361b7b8b4ccSAlexandre Courbot         #[allow(dead_code)]
362b7b8b4ccSAlexandre Courbot         impl $name {
363b7b8b4ccSAlexandre Courbot         $(
364b7b8b4ccSAlexandre Courbot         $crate::bitfield!(@private_field_accessors $vis $name $storage : $hi:$lo $field);
365b7b8b4ccSAlexandre Courbot         $crate::bitfield!(
366b7b8b4ccSAlexandre Courbot             @public_field_accessors $(#[doc = $doc])* $vis $name $storage : $hi:$lo $field
367b7b8b4ccSAlexandre Courbot             $(?=> $try_into_type)?
368b7b8b4ccSAlexandre Courbot             $(=> $into_type)?
369b7b8b4ccSAlexandre Courbot         );
370b7b8b4ccSAlexandre Courbot         )*
371b7b8b4ccSAlexandre Courbot         }
372b7b8b4ccSAlexandre Courbot 
373b7b8b4ccSAlexandre Courbot         $crate::bitfield!(@debug $name { $($field;)* });
374b7b8b4ccSAlexandre Courbot     };
375b7b8b4ccSAlexandre Courbot 
376b7b8b4ccSAlexandre Courbot     // Private field accessors working with the exact `Bounded` type for the field.
377b7b8b4ccSAlexandre Courbot     (
378b7b8b4ccSAlexandre Courbot         @private_field_accessors $vis:vis $name:ident $storage:ty : $hi:tt:$lo:tt $field:ident
379b7b8b4ccSAlexandre Courbot     ) => {
380b7b8b4ccSAlexandre Courbot         ::kernel::macros::paste!(
381b7b8b4ccSAlexandre Courbot         $vis const [<$field:upper _RANGE>]: ::core::ops::RangeInclusive<u8> = $lo..=$hi;
382b7b8b4ccSAlexandre Courbot         $vis const [<$field:upper _MASK>]: $storage =
383b7b8b4ccSAlexandre Courbot             ((((1 << $hi) - 1) << 1) + 1) - ((1 << $lo) - 1);
384b7b8b4ccSAlexandre Courbot         $vis const [<$field:upper _SHIFT>]: u32 = $lo;
385b7b8b4ccSAlexandre Courbot         );
386b7b8b4ccSAlexandre Courbot 
387b7b8b4ccSAlexandre Courbot         ::kernel::macros::paste!(
388b7b8b4ccSAlexandre Courbot         #[inline(always)]
389b7b8b4ccSAlexandre Courbot         fn [<__ $field>](self) ->
390b7b8b4ccSAlexandre Courbot             ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> {
391b7b8b4ccSAlexandre Courbot             // Left shift to align the field's MSB with the storage MSB.
392b7b8b4ccSAlexandre Courbot             const ALIGN_TOP: u32 = $storage::BITS - ($hi + 1);
393b7b8b4ccSAlexandre Courbot             // Right shift to move the top-aligned field to bit 0 of the storage.
394b7b8b4ccSAlexandre Courbot             const ALIGN_BOTTOM: u32 = ALIGN_TOP + $lo;
395b7b8b4ccSAlexandre Courbot 
396b7b8b4ccSAlexandre Courbot             // Extract the field using two shifts. `Bounded::shr` produces the correctly-sized
397b7b8b4ccSAlexandre Courbot             // output type.
398b7b8b4ccSAlexandre Courbot             let val = ::kernel::num::Bounded::<$storage, { $storage::BITS }>::from(
399b7b8b4ccSAlexandre Courbot                 self.inner << ALIGN_TOP
400b7b8b4ccSAlexandre Courbot             );
401b7b8b4ccSAlexandre Courbot             val.shr::<ALIGN_BOTTOM, { $hi + 1 - $lo } >()
402b7b8b4ccSAlexandre Courbot         }
403b7b8b4ccSAlexandre Courbot 
404b7b8b4ccSAlexandre Courbot         #[inline(always)]
405b7b8b4ccSAlexandre Courbot         const fn [<__with_ $field>](
406b7b8b4ccSAlexandre Courbot             mut self,
407b7b8b4ccSAlexandre Courbot             value: ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>,
408b7b8b4ccSAlexandre Courbot         ) -> Self
409b7b8b4ccSAlexandre Courbot         {
410b7b8b4ccSAlexandre Courbot             const MASK: $storage = <$name>::[<$field:upper _MASK>];
411b7b8b4ccSAlexandre Courbot             const SHIFT: u32 = <$name>::[<$field:upper _SHIFT>];
412b7b8b4ccSAlexandre Courbot 
413b7b8b4ccSAlexandre Courbot             let value = value.get() << SHIFT;
414b7b8b4ccSAlexandre Courbot             self.inner = (self.inner & !MASK) | value;
415b7b8b4ccSAlexandre Courbot 
416b7b8b4ccSAlexandre Courbot             self
417b7b8b4ccSAlexandre Courbot         }
418b7b8b4ccSAlexandre Courbot         );
419b7b8b4ccSAlexandre Courbot     };
420b7b8b4ccSAlexandre Courbot 
421b7b8b4ccSAlexandre Courbot     // Public accessors for fields infallibly (`=>`) converted to a type.
422b7b8b4ccSAlexandre Courbot     (
423b7b8b4ccSAlexandre Courbot         @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty :
424b7b8b4ccSAlexandre Courbot             $hi:literal:$lo:literal $field:ident => $into_type:ty
425b7b8b4ccSAlexandre Courbot     ) => {
426b7b8b4ccSAlexandre Courbot         ::kernel::macros::paste!(
427b7b8b4ccSAlexandre Courbot 
428b7b8b4ccSAlexandre Courbot         $(#[doc = $doc])*
429b7b8b4ccSAlexandre Courbot         #[doc = "Returns the value of this field."]
430b7b8b4ccSAlexandre Courbot         #[inline(always)]
431b7b8b4ccSAlexandre Courbot         $vis fn $field(self) -> $into_type
432b7b8b4ccSAlexandre Courbot         {
433b7b8b4ccSAlexandre Courbot             self.[<__ $field>]().into()
434b7b8b4ccSAlexandre Courbot         }
435b7b8b4ccSAlexandre Courbot 
436b7b8b4ccSAlexandre Courbot         $(#[doc = $doc])*
437b7b8b4ccSAlexandre Courbot         #[doc = "Sets this field to the given `value`."]
438b7b8b4ccSAlexandre Courbot         #[inline(always)]
439b7b8b4ccSAlexandre Courbot         $vis fn [<with_ $field>](self, value: $into_type) -> Self
440b7b8b4ccSAlexandre Courbot         {
441b7b8b4ccSAlexandre Courbot             self.[<__with_ $field>](value.into())
442b7b8b4ccSAlexandre Courbot         }
443b7b8b4ccSAlexandre Courbot 
444b7b8b4ccSAlexandre Courbot         );
445b7b8b4ccSAlexandre Courbot     };
446b7b8b4ccSAlexandre Courbot 
447b7b8b4ccSAlexandre Courbot     // Public accessors for fields fallibly (`?=>`) converted to a type.
448b7b8b4ccSAlexandre Courbot     (
449b7b8b4ccSAlexandre Courbot         @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty :
450b7b8b4ccSAlexandre Courbot             $hi:tt:$lo:tt $field:ident ?=> $try_into_type:ty
451b7b8b4ccSAlexandre Courbot     ) => {
452b7b8b4ccSAlexandre Courbot         ::kernel::macros::paste!(
453b7b8b4ccSAlexandre Courbot 
454b7b8b4ccSAlexandre Courbot         $(#[doc = $doc])*
455b7b8b4ccSAlexandre Courbot         #[doc = "Returns the value of this field."]
456b7b8b4ccSAlexandre Courbot         #[inline(always)]
457b7b8b4ccSAlexandre Courbot         $vis fn $field(self) ->
458b7b8b4ccSAlexandre Courbot             ::core::result::Result<
459b7b8b4ccSAlexandre Courbot                 $try_into_type,
460b7b8b4ccSAlexandre Courbot                 <$try_into_type as ::core::convert::TryFrom<
461b7b8b4ccSAlexandre Courbot                     ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>
462b7b8b4ccSAlexandre Courbot                 >>::Error
463b7b8b4ccSAlexandre Courbot             >
464b7b8b4ccSAlexandre Courbot         {
465b7b8b4ccSAlexandre Courbot             self.[<__ $field>]().try_into()
466b7b8b4ccSAlexandre Courbot         }
467b7b8b4ccSAlexandre Courbot 
468b7b8b4ccSAlexandre Courbot         $(#[doc = $doc])*
469b7b8b4ccSAlexandre Courbot         #[doc = "Sets this field to the given `value`."]
470b7b8b4ccSAlexandre Courbot         #[inline(always)]
471b7b8b4ccSAlexandre Courbot         $vis fn [<with_ $field>](self, value: $try_into_type) -> Self
472b7b8b4ccSAlexandre Courbot         {
473b7b8b4ccSAlexandre Courbot             self.[<__with_ $field>](value.into())
474b7b8b4ccSAlexandre Courbot         }
475b7b8b4ccSAlexandre Courbot 
476b7b8b4ccSAlexandre Courbot         );
477b7b8b4ccSAlexandre Courbot     };
478b7b8b4ccSAlexandre Courbot 
479b7b8b4ccSAlexandre Courbot     // Public accessors for fields not converted to a type.
480b7b8b4ccSAlexandre Courbot     (
481b7b8b4ccSAlexandre Courbot         @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty :
482b7b8b4ccSAlexandre Courbot             $hi:tt:$lo:tt $field:ident
483b7b8b4ccSAlexandre Courbot     ) => {
484b7b8b4ccSAlexandre Courbot         ::kernel::macros::paste!(
485b7b8b4ccSAlexandre Courbot 
486b7b8b4ccSAlexandre Courbot         $(#[doc = $doc])*
487b7b8b4ccSAlexandre Courbot         #[doc = "Returns the value of this field."]
488b7b8b4ccSAlexandre Courbot         #[inline(always)]
489b7b8b4ccSAlexandre Courbot         $vis fn $field(self) ->
490b7b8b4ccSAlexandre Courbot             ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>
491b7b8b4ccSAlexandre Courbot         {
492b7b8b4ccSAlexandre Courbot             self.[<__ $field>]()
493b7b8b4ccSAlexandre Courbot         }
494b7b8b4ccSAlexandre Courbot 
495b7b8b4ccSAlexandre Courbot         $(#[doc = $doc])*
496b7b8b4ccSAlexandre Courbot         #[doc = "Sets this field to the compile-time constant `VALUE`."]
497b7b8b4ccSAlexandre Courbot         #[inline(always)]
498b7b8b4ccSAlexandre Courbot         $vis const fn [<with_const_ $field>]<const VALUE: $storage>(self) -> Self {
499b7b8b4ccSAlexandre Courbot             self.[<__with_ $field>](
500b7b8b4ccSAlexandre Courbot                 ::kernel::num::Bounded::<$storage, { $hi + 1 - $lo }>::new::<VALUE>()
501b7b8b4ccSAlexandre Courbot             )
502b7b8b4ccSAlexandre Courbot         }
503b7b8b4ccSAlexandre Courbot 
504b7b8b4ccSAlexandre Courbot         $(#[doc = $doc])*
505b7b8b4ccSAlexandre Courbot         #[doc = "Sets this field to the given `value`."]
506b7b8b4ccSAlexandre Courbot         #[inline(always)]
507b7b8b4ccSAlexandre Courbot         $vis fn [<with_ $field>]<T>(
508b7b8b4ccSAlexandre Courbot             self,
509b7b8b4ccSAlexandre Courbot             value: T,
510b7b8b4ccSAlexandre Courbot         ) -> Self
511b7b8b4ccSAlexandre Courbot             where T: ::core::convert::Into<::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>>,
512b7b8b4ccSAlexandre Courbot         {
513b7b8b4ccSAlexandre Courbot             self.[<__with_ $field>](value.into())
514b7b8b4ccSAlexandre Courbot         }
515b7b8b4ccSAlexandre Courbot 
516b7b8b4ccSAlexandre Courbot         $(#[doc = $doc])*
517b7b8b4ccSAlexandre Courbot         #[doc = "Tries to set this field to `value`, returning an error if it is out of range."]
518b7b8b4ccSAlexandre Courbot         #[inline(always)]
519b7b8b4ccSAlexandre Courbot         $vis fn [<try_with_ $field>]<T>(
520b7b8b4ccSAlexandre Courbot             self,
521b7b8b4ccSAlexandre Courbot             value: T,
522b7b8b4ccSAlexandre Courbot         ) -> ::kernel::error::Result<Self>
523b7b8b4ccSAlexandre Courbot             where T: ::kernel::num::TryIntoBounded<$storage, { $hi + 1 - $lo }>,
524b7b8b4ccSAlexandre Courbot         {
525b7b8b4ccSAlexandre Courbot             Ok(
526b7b8b4ccSAlexandre Courbot                 self.[<__with_ $field>](
527b7b8b4ccSAlexandre Courbot                     value.try_into_bounded().ok_or(::kernel::error::code::EOVERFLOW)?
528b7b8b4ccSAlexandre Courbot                 )
529b7b8b4ccSAlexandre Courbot             )
530b7b8b4ccSAlexandre Courbot         }
531b7b8b4ccSAlexandre Courbot 
532b7b8b4ccSAlexandre Courbot         );
533b7b8b4ccSAlexandre Courbot     };
534b7b8b4ccSAlexandre Courbot 
535b7b8b4ccSAlexandre Courbot     // `Debug` implementation.
536b7b8b4ccSAlexandre Courbot     (@debug $name:ident { $($field:ident;)* }) => {
537b7b8b4ccSAlexandre Courbot         impl ::kernel::fmt::Debug for $name {
538*f09d2312SGary Guo             #[inline]
539b7b8b4ccSAlexandre Courbot             fn fmt(&self, f: &mut ::kernel::fmt::Formatter<'_>) -> ::kernel::fmt::Result {
540b7b8b4ccSAlexandre Courbot                 f.debug_struct(stringify!($name))
541b7b8b4ccSAlexandre Courbot                     .field("<raw>", &::kernel::prelude::fmt!("{:#x}", self.inner))
542b7b8b4ccSAlexandre Courbot                 $(
543b7b8b4ccSAlexandre Courbot                     .field(stringify!($field), &self.$field())
544b7b8b4ccSAlexandre Courbot                 )*
545b7b8b4ccSAlexandre Courbot                     .finish()
546b7b8b4ccSAlexandre Courbot             }
547b7b8b4ccSAlexandre Courbot         }
548b7b8b4ccSAlexandre Courbot     };
549b7b8b4ccSAlexandre Courbot }
5507f502747SJoel Fernandes 
5517f502747SJoel Fernandes #[cfg(CONFIG_RUST_BITFIELD_KUNIT_TEST)]
5527f502747SJoel Fernandes #[::kernel::macros::kunit_tests(rust_kernel_bitfield)]
5537f502747SJoel Fernandes mod tests {
5547f502747SJoel Fernandes     use core::convert::TryFrom;
5557f502747SJoel Fernandes 
5567f502747SJoel Fernandes     use pin_init::Zeroable;
5577f502747SJoel Fernandes 
5587f502747SJoel Fernandes     use kernel::num::Bounded;
5597f502747SJoel Fernandes 
5607f502747SJoel Fernandes     // Enum types for testing `=>` and `?=>` conversions.
5617f502747SJoel Fernandes 
5627f502747SJoel Fernandes     #[derive(Debug, Clone, Copy, PartialEq)]
5637f502747SJoel Fernandes     enum MemoryType {
5647f502747SJoel Fernandes         Unmapped = 0,
5657f502747SJoel Fernandes         Normal = 1,
5667f502747SJoel Fernandes         Device = 2,
5677f502747SJoel Fernandes         Reserved = 3,
5687f502747SJoel Fernandes     }
5697f502747SJoel Fernandes 
5707f502747SJoel Fernandes     impl TryFrom<Bounded<u64, 4>> for MemoryType {
5717f502747SJoel Fernandes         type Error = u64;
try_from(value: Bounded<u64, 4>) -> Result<Self, Self::Error>5727f502747SJoel Fernandes         fn try_from(value: Bounded<u64, 4>) -> Result<Self, Self::Error> {
5737f502747SJoel Fernandes             match value.get() {
5747f502747SJoel Fernandes                 0 => Ok(MemoryType::Unmapped),
5757f502747SJoel Fernandes                 1 => Ok(MemoryType::Normal),
5767f502747SJoel Fernandes                 2 => Ok(MemoryType::Device),
5777f502747SJoel Fernandes                 3 => Ok(MemoryType::Reserved),
5787f502747SJoel Fernandes                 _ => Err(value.get()),
5797f502747SJoel Fernandes             }
5807f502747SJoel Fernandes         }
5817f502747SJoel Fernandes     }
5827f502747SJoel Fernandes 
5837f502747SJoel Fernandes     impl From<MemoryType> for Bounded<u64, 4> {
5847f502747SJoel Fernandes         #[inline(always)]
from(mt: MemoryType) -> Bounded<u64, 4>5857f502747SJoel Fernandes         fn from(mt: MemoryType) -> Bounded<u64, 4> {
5867f502747SJoel Fernandes             Bounded::from_expr(mt as u64)
5877f502747SJoel Fernandes         }
5887f502747SJoel Fernandes     }
5897f502747SJoel Fernandes 
5907f502747SJoel Fernandes     #[derive(Debug, Clone, Copy, PartialEq)]
5917f502747SJoel Fernandes     enum Priority {
5927f502747SJoel Fernandes         Low = 0,
5937f502747SJoel Fernandes         Medium = 1,
5947f502747SJoel Fernandes         High = 2,
5957f502747SJoel Fernandes         Critical = 3,
5967f502747SJoel Fernandes     }
5977f502747SJoel Fernandes 
5987f502747SJoel Fernandes     impl From<Bounded<u16, 2>> for Priority {
from(value: Bounded<u16, 2>) -> Self5997f502747SJoel Fernandes         fn from(value: Bounded<u16, 2>) -> Self {
6007f502747SJoel Fernandes             match value & 0x3 {
6017f502747SJoel Fernandes                 0 => Priority::Low,
6027f502747SJoel Fernandes                 1 => Priority::Medium,
6037f502747SJoel Fernandes                 2 => Priority::High,
6047f502747SJoel Fernandes                 _ => Priority::Critical,
6057f502747SJoel Fernandes             }
6067f502747SJoel Fernandes         }
6077f502747SJoel Fernandes     }
6087f502747SJoel Fernandes 
6097f502747SJoel Fernandes     impl From<Priority> for Bounded<u16, 2> {
6107f502747SJoel Fernandes         #[inline(always)]
from(p: Priority) -> Bounded<u16, 2>6117f502747SJoel Fernandes         fn from(p: Priority) -> Bounded<u16, 2> {
6127f502747SJoel Fernandes             Bounded::from_expr(p as u16)
6137f502747SJoel Fernandes         }
6147f502747SJoel Fernandes     }
6157f502747SJoel Fernandes 
6167f502747SJoel Fernandes     bitfield! {
6177f502747SJoel Fernandes         struct TestU64(u64) {
6187f502747SJoel Fernandes             63:63     field_63;
6197f502747SJoel Fernandes             61:52     field_61_52;
6207f502747SJoel Fernandes             51:16     field_51_16;
6217f502747SJoel Fernandes             15:12     field_15_12 ?=> MemoryType;
6227f502747SJoel Fernandes             11:9      field_11_9;
6237f502747SJoel Fernandes             1:1       field_1;
6247f502747SJoel Fernandes             0:0       field_0;
6257f502747SJoel Fernandes         }
6267f502747SJoel Fernandes     }
6277f502747SJoel Fernandes 
6287f502747SJoel Fernandes     bitfield! {
6297f502747SJoel Fernandes         struct TestU16(u16) {
6307f502747SJoel Fernandes             15:8      field_15_8;
6317f502747SJoel Fernandes             7:4       field_7_4; // Partial overlap with `field_5_4`.
6327f502747SJoel Fernandes             5:4       field_5_4 => Priority;
6337f502747SJoel Fernandes             3:1       field_3_1;
6347f502747SJoel Fernandes             0:0       field_0;
6357f502747SJoel Fernandes         }
6367f502747SJoel Fernandes     }
6377f502747SJoel Fernandes 
6387f502747SJoel Fernandes     bitfield! {
6397f502747SJoel Fernandes         struct TestU8(u8) {
6407f502747SJoel Fernandes             7:0       field_7_0; // Full byte overlap.
6417f502747SJoel Fernandes             7:4       field_7_4;
6427f502747SJoel Fernandes             3:2       field_3_2;
6437f502747SJoel Fernandes             1:1       field_1;
6447f502747SJoel Fernandes             0:0       field_0;
6457f502747SJoel Fernandes         }
6467f502747SJoel Fernandes     }
6477f502747SJoel Fernandes 
6487f502747SJoel Fernandes     // Single and multi-bit fields basic access.
6497f502747SJoel Fernandes     #[test]
test_basic_access()6507f502747SJoel Fernandes     fn test_basic_access() {
6517f502747SJoel Fernandes         // `TestU64`.
6527f502747SJoel Fernandes         let mut val = TestU64::zeroed();
6537f502747SJoel Fernandes         assert_eq!(val.into_raw(), 0x0);
6547f502747SJoel Fernandes 
6557f502747SJoel Fernandes         val = val.with_field_0(true);
6567f502747SJoel Fernandes         assert!(val.field_0().into_bool());
6577f502747SJoel Fernandes         assert_eq!(val.into_raw(), 0x1);
6587f502747SJoel Fernandes 
6597f502747SJoel Fernandes         val = val.with_field_1(true);
6607f502747SJoel Fernandes         assert!(val.field_1().into_bool());
6617f502747SJoel Fernandes         val = val.with_field_1(false);
6627f502747SJoel Fernandes         assert!(!val.field_1().into_bool());
6637f502747SJoel Fernandes         assert_eq!(val.into_raw(), 0x1);
6647f502747SJoel Fernandes 
6657f502747SJoel Fernandes         val = val.with_const_field_11_9::<0x5>();
6667f502747SJoel Fernandes         assert_eq!(val.field_11_9(), 0x5);
6677f502747SJoel Fernandes         assert_eq!(val.into_raw(), 0xA01);
6687f502747SJoel Fernandes 
6697f502747SJoel Fernandes         val = val.with_const_field_51_16::<0x123456>();
6707f502747SJoel Fernandes         assert_eq!(val.field_51_16(), 0x123456);
6717f502747SJoel Fernandes         assert_eq!(val.into_raw(), 0x0012_3456_0A01);
6727f502747SJoel Fernandes 
6737f502747SJoel Fernandes         const MAX_FIELD_51_16: u64 = ::kernel::bits::genmask_u64(0..=35);
6747f502747SJoel Fernandes         val = val.with_const_field_51_16::<{ MAX_FIELD_51_16 }>();
6757f502747SJoel Fernandes         assert_eq!(val.field_51_16(), MAX_FIELD_51_16);
6767f502747SJoel Fernandes 
6777f502747SJoel Fernandes         val = val.with_const_field_61_52::<0x3FF>();
6787f502747SJoel Fernandes         assert_eq!(val.field_61_52(), 0x3FF);
6797f502747SJoel Fernandes 
6807f502747SJoel Fernandes         val = val.with_field_63(true);
6817f502747SJoel Fernandes         assert!(val.field_63().into_bool());
6827f502747SJoel Fernandes 
6837f502747SJoel Fernandes         // `TestU16`.
6847f502747SJoel Fernandes         let mut val = TestU16::zeroed();
6857f502747SJoel Fernandes         assert_eq!(val.into_raw(), 0x0);
6867f502747SJoel Fernandes 
6877f502747SJoel Fernandes         val = val.with_field_0(true);
6887f502747SJoel Fernandes         assert!(val.field_0().into_bool());
6897f502747SJoel Fernandes         assert_eq!(val.into_raw(), 0x1);
6907f502747SJoel Fernandes 
6917f502747SJoel Fernandes         val = val.with_const_field_3_1::<0x5>();
6927f502747SJoel Fernandes         assert_eq!(val.field_3_1(), 0x5);
6937f502747SJoel Fernandes         assert_eq!(val.into_raw(), 0xB);
6947f502747SJoel Fernandes 
6957f502747SJoel Fernandes         val = val.with_const_field_7_4::<0xA>();
6967f502747SJoel Fernandes         assert_eq!(val.field_7_4(), 0xA);
6977f502747SJoel Fernandes         assert_eq!(val.into_raw(), 0xAB);
6987f502747SJoel Fernandes 
6997f502747SJoel Fernandes         val = val.with_const_field_15_8::<0x42>();
7007f502747SJoel Fernandes         assert_eq!(val.field_15_8(), 0x42);
7017f502747SJoel Fernandes         assert_eq!(val.into_raw(), 0x42AB);
7027f502747SJoel Fernandes 
7037f502747SJoel Fernandes         // `TestU8`.
7047f502747SJoel Fernandes         let mut val = TestU8::zeroed();
7057f502747SJoel Fernandes         assert_eq!(val.into_raw(), 0x0);
7067f502747SJoel Fernandes 
7077f502747SJoel Fernandes         val = val.with_field_0(true);
7087f502747SJoel Fernandes         assert!(val.field_0().into_bool());
7097f502747SJoel Fernandes         assert_eq!(val.into_raw(), 0x1);
7107f502747SJoel Fernandes 
7117f502747SJoel Fernandes         val = val.with_field_1(true);
7127f502747SJoel Fernandes         assert!(val.field_1().into_bool());
7137f502747SJoel Fernandes         assert_eq!(val.into_raw(), 0x3);
7147f502747SJoel Fernandes 
7157f502747SJoel Fernandes         val = val.with_const_field_3_2::<0x3>();
7167f502747SJoel Fernandes         assert_eq!(val.field_3_2(), 0x3);
7177f502747SJoel Fernandes         assert_eq!(val.into_raw(), 0xF);
7187f502747SJoel Fernandes 
7197f502747SJoel Fernandes         val = val.with_const_field_7_4::<0xA>();
7207f502747SJoel Fernandes         assert_eq!(val.field_7_4(), 0xA);
7217f502747SJoel Fernandes         assert_eq!(val.into_raw(), 0xAF);
7227f502747SJoel Fernandes     }
7237f502747SJoel Fernandes 
7247f502747SJoel Fernandes     // `=>` infallible conversion.
7257f502747SJoel Fernandes     #[test]
test_infallible_conversion()7267f502747SJoel Fernandes     fn test_infallible_conversion() {
7277f502747SJoel Fernandes         let mut val = TestU16::zeroed();
7287f502747SJoel Fernandes 
7297f502747SJoel Fernandes         val = val.with_field_5_4(Priority::Low);
7307f502747SJoel Fernandes         assert_eq!(val.field_5_4(), Priority::Low);
7317f502747SJoel Fernandes         assert_eq!(val.into_raw() & 0x30, 0x00);
7327f502747SJoel Fernandes 
7337f502747SJoel Fernandes         val = val.with_field_5_4(Priority::Medium);
7347f502747SJoel Fernandes         assert_eq!(val.field_5_4(), Priority::Medium);
7357f502747SJoel Fernandes         assert_eq!(val.into_raw() & 0x30, 0x10);
7367f502747SJoel Fernandes 
7377f502747SJoel Fernandes         val = val.with_field_5_4(Priority::High);
7387f502747SJoel Fernandes         assert_eq!(val.field_5_4(), Priority::High);
7397f502747SJoel Fernandes         assert_eq!(val.into_raw() & 0x30, 0x20);
7407f502747SJoel Fernandes 
7417f502747SJoel Fernandes         val = val.with_field_5_4(Priority::Critical);
7427f502747SJoel Fernandes         assert_eq!(val.field_5_4(), Priority::Critical);
7437f502747SJoel Fernandes         assert_eq!(val.into_raw() & 0x30, 0x30);
7447f502747SJoel Fernandes     }
7457f502747SJoel Fernandes 
7467f502747SJoel Fernandes     // `?=>` fallible conversion.
7477f502747SJoel Fernandes     #[test]
test_fallible_conversion()7487f502747SJoel Fernandes     fn test_fallible_conversion() {
7497f502747SJoel Fernandes         let mut val = TestU64::zeroed();
7507f502747SJoel Fernandes 
7517f502747SJoel Fernandes         val = val.with_field_15_12(MemoryType::Unmapped);
7527f502747SJoel Fernandes         assert_eq!(val.field_15_12(), Ok(MemoryType::Unmapped));
7537f502747SJoel Fernandes         val = val.with_field_15_12(MemoryType::Normal);
7547f502747SJoel Fernandes         assert_eq!(val.field_15_12(), Ok(MemoryType::Normal));
7557f502747SJoel Fernandes         val = val.with_field_15_12(MemoryType::Device);
7567f502747SJoel Fernandes         assert_eq!(val.field_15_12(), Ok(MemoryType::Device));
7577f502747SJoel Fernandes         val = val.with_field_15_12(MemoryType::Reserved);
7587f502747SJoel Fernandes         assert_eq!(val.field_15_12(), Ok(MemoryType::Reserved));
7597f502747SJoel Fernandes 
7607f502747SJoel Fernandes         // `field_15_12` is 4 bits wide (0-15); `MemoryType` only covers 0-3, so 4-15 return `Err`.
7617f502747SJoel Fernandes         let raw = (val.into_raw() & !::kernel::bits::genmask_u64(12..=15)) | (0x7 << 12);
7627f502747SJoel Fernandes         assert_eq!(TestU64::from_raw(raw).field_15_12(), Err(0x7));
7637f502747SJoel Fernandes     }
7647f502747SJoel Fernandes 
7657f502747SJoel Fernandes     // Test that setting an overlapping field affects the overlapped one as expected.
7667f502747SJoel Fernandes     #[test]
test_overlapping_fields()7677f502747SJoel Fernandes     fn test_overlapping_fields() {
7687f502747SJoel Fernandes         let mut val = TestU16::zeroed();
7697f502747SJoel Fernandes 
7707f502747SJoel Fernandes         val = val.with_field_5_4(Priority::High); // High == 2 == 0b10.
7717f502747SJoel Fernandes         assert_eq!(val.field_5_4(), Priority::High);
7727f502747SJoel Fernandes         assert_eq!(val.field_7_4(), 0x2); // Bits 7:6 == 0, bits 5:4 == 0b10.
7737f502747SJoel Fernandes 
7747f502747SJoel Fernandes         val = val.with_const_field_7_4::<0xF>();
7757f502747SJoel Fernandes         assert_eq!(val.field_7_4(), 0xF);
7767f502747SJoel Fernandes         assert_eq!(val.field_5_4(), Priority::Critical); // Bits 5:4 == 0b11.
7777f502747SJoel Fernandes 
7787f502747SJoel Fernandes         // `field_7_0` should encompass all other fields.
7797f502747SJoel Fernandes         let mut val = TestU8::zeroed()
7807f502747SJoel Fernandes             .with_field_0(true)
7817f502747SJoel Fernandes             .with_field_1(true)
7827f502747SJoel Fernandes             .with_const_field_3_2::<0x3>()
7837f502747SJoel Fernandes             .with_const_field_7_4::<0xA>();
7847f502747SJoel Fernandes         assert_eq!(val.into_raw(), 0xAF);
7857f502747SJoel Fernandes 
7867f502747SJoel Fernandes         val = val.with_field_7_0(0x55);
7877f502747SJoel Fernandes         assert_eq!(val.field_7_0(), 0x55);
7887f502747SJoel Fernandes         assert!(val.field_0().into_bool());
7897f502747SJoel Fernandes         assert!(!val.field_1().into_bool());
7907f502747SJoel Fernandes         assert_eq!(val.field_3_2(), 0x1);
7917f502747SJoel Fernandes         assert_eq!(val.field_7_4(), 0x5);
7927f502747SJoel Fernandes     }
7937f502747SJoel Fernandes 
7947f502747SJoel Fernandes     // Checks that bits not mapped to any field are left untouched.
7957f502747SJoel Fernandes     #[test]
test_unallocated_bits()7967f502747SJoel Fernandes     fn test_unallocated_bits() {
7977f502747SJoel Fernandes         let gap_bits = (1u64 << 62) | 0x1FC;
7987f502747SJoel Fernandes 
7997f502747SJoel Fernandes         let set_all_fields = |val: TestU64| {
8007f502747SJoel Fernandes             val.with_field_63(true)
8017f502747SJoel Fernandes                 .with_const_field_61_52::<0x155>()
8027f502747SJoel Fernandes                 .with_const_field_51_16::<0x123456>()
8037f502747SJoel Fernandes                 .with_field_15_12(MemoryType::Device)
8047f502747SJoel Fernandes                 .with_const_field_11_9::<0x5>()
8057f502747SJoel Fernandes                 .with_field_1(true)
8067f502747SJoel Fernandes                 .with_field_0(true)
8077f502747SJoel Fernandes         };
8087f502747SJoel Fernandes 
8097f502747SJoel Fernandes         // Gap bits to 0.
8107f502747SJoel Fernandes         let val = set_all_fields(TestU64::from_raw(0));
8117f502747SJoel Fernandes         assert_eq!(val.into_raw() & gap_bits, 0);
8127f502747SJoel Fernandes 
8137f502747SJoel Fernandes         // Gap bits to 1.
8147f502747SJoel Fernandes         let val = set_all_fields(TestU64::from_raw(gap_bits));
8157f502747SJoel Fernandes         assert_eq!(val.into_raw() & gap_bits, gap_bits);
8167f502747SJoel Fernandes     }
8177f502747SJoel Fernandes 
8187f502747SJoel Fernandes     #[test]
test_try_with()8197f502747SJoel Fernandes     fn test_try_with() {
8207f502747SJoel Fernandes         let val = TestU64::zeroed().try_with_field_51_16(0x123456).unwrap();
8217f502747SJoel Fernandes         assert_eq!(val.field_51_16(), 0x123456);
8227f502747SJoel Fernandes 
8237f502747SJoel Fernandes         let err = TestU64::zeroed().try_with_field_51_16(u64::MAX);
8247f502747SJoel Fernandes         assert_eq!(err, Err(::kernel::error::code::EOVERFLOW));
8257f502747SJoel Fernandes 
8267f502747SJoel Fernandes         let val = TestU64::zeroed()
8277f502747SJoel Fernandes             .try_with_field_51_16(0xABCDEF)
8287f502747SJoel Fernandes             .and_then(|p| p.try_with_field_0(1))
8297f502747SJoel Fernandes             .unwrap();
8307f502747SJoel Fernandes         assert_eq!(val.field_51_16(), 0xABCDEF);
8317f502747SJoel Fernandes         assert!(val.field_0().into_bool());
8327f502747SJoel Fernandes     }
8337f502747SJoel Fernandes 
8347f502747SJoel Fernandes     // `from_raw`/`into_raw` and `From`/`Into` round-trips.
8357f502747SJoel Fernandes     #[test]
test_raw()8367f502747SJoel Fernandes     fn test_raw() {
8377f502747SJoel Fernandes         let raw: u64 = 0xBFF0_0000_3123_3E03;
8387f502747SJoel Fernandes         let val = TestU64::from_raw(raw);
8397f502747SJoel Fernandes         assert_eq!(u64::from(val), raw);
8407f502747SJoel Fernandes         assert!(val.field_0().into_bool());
8417f502747SJoel Fernandes         assert!(val.field_1().into_bool());
8427f502747SJoel Fernandes         assert_eq!(val.field_11_9(), 0x7);
8437f502747SJoel Fernandes         assert_eq!(val.field_51_16(), 0x3123);
8447f502747SJoel Fernandes         assert_eq!(val.field_15_12(), Ok(MemoryType::Reserved));
8457f502747SJoel Fernandes         assert_eq!(val.field_61_52(), 0x3FF);
8467f502747SJoel Fernandes         assert!(val.field_63().into_bool());
8477f502747SJoel Fernandes 
8487f502747SJoel Fernandes         let raw: u16 = 0x42AB;
8497f502747SJoel Fernandes         let val = TestU16::from_raw(raw);
8507f502747SJoel Fernandes         assert_eq!(u16::from(val), raw);
8517f502747SJoel Fernandes         assert!(val.field_0().into_bool());
8527f502747SJoel Fernandes         assert_eq!(val.field_3_1(), 0x5);
8537f502747SJoel Fernandes         assert_eq!(val.field_7_4(), 0xA);
8547f502747SJoel Fernandes         assert_eq!(val.field_15_8(), 0x42);
8557f502747SJoel Fernandes 
8567f502747SJoel Fernandes         let raw: u8 = 0xAF;
8577f502747SJoel Fernandes         let val = TestU8::from_raw(raw);
8587f502747SJoel Fernandes         assert_eq!(u8::from(val), raw);
8597f502747SJoel Fernandes         assert!(val.field_0().into_bool());
8607f502747SJoel Fernandes         assert!(val.field_1().into_bool());
8617f502747SJoel Fernandes         assert_eq!(val.field_3_2(), 0x3);
8627f502747SJoel Fernandes         assert_eq!(val.field_7_4(), 0xA);
8637f502747SJoel Fernandes         assert_eq!(val.field_7_0(), 0xAF);
864     }
865 }
866