xref: /linux/rust/kernel/bitfield.rs (revision 85cdaca6970028bf6f544c355c90035586836ddf)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 //! Support for defining bitfields as Rust structures.
4 //!
5 //! The [`bitfield!`](kernel::bitfield!) macro declares integer types that are split into distinct
6 //! bit fields of arbitrary length. Each field is typed using [`Bounded`](kernel::num::Bounded) to
7 //! ensure values are properly validated and to avoid implicit data loss.
8 //!
9 //! # Example
10 //!
11 //! ```rust
12 //! use kernel::bitfield;
13 //! use kernel::num::Bounded;
14 //!
15 //! bitfield! {
16 //!     pub struct Rgb(u16) {
17 //!         15:11 blue;
18 //!         10:5 green;
19 //!         4:0 red;
20 //!     }
21 //! }
22 //!
23 //! // Valid value for the `blue` field.
24 //! let blue = Bounded::<u16, 5>::new::<0x18>();
25 //!
26 //! // Setters can be chained. Values ranges are checked at compile-time.
27 //! let color = Rgb::zeroed()
28 //!     // Compile-time bounds check of constant value.
29 //!     .with_const_red::<0x10>()
30 //!     .with_const_green::<0x1f>()
31 //!     // A `Bounded` can also be passed.
32 //!     .with_blue(blue);
33 //!
34 //! assert_eq!(color.red(), 0x10);
35 //! assert_eq!(color.green(), 0x1f);
36 //! assert_eq!(color.blue(), 0x18);
37 //! assert_eq!(
38 //!     color.into_raw(),
39 //!     (0x18 << Rgb::BLUE_SHIFT) + (0x1f << Rgb::GREEN_SHIFT) + 0x10,
40 //! );
41 //!
42 //! // Convert to/from the backing storage type.
43 //! let raw: u16 = color.into();
44 //! assert_eq!(Rgb::from(raw), color);
45 //! ```
46 //!
47 //! # Syntax
48 //!
49 //! ```text
50 //! bitfield! {
51 //!     #[attributes]
52 //!     // Documentation for `Name`.
53 //!     pub struct Name(storage_type) {
54 //!         // `field_1` documentation.
55 //!         hi:lo field_1;
56 //!         // `field_2` documentation.
57 //!         hi:lo field_2 => ConvertedType;
58 //!         // `field_3` documentation.
59 //!         hi:lo field_3 ?=> ConvertedType;
60 //!         ...
61 //!     }
62 //! }
63 //! ```
64 //!
65 //! - `storage_type`: The underlying unsigned integer type ([`u8`], [`u16`], [`u32`], [`u64`]).
66 //!   Signed integer storage types are not supported.
67 //! - `hi:lo`: Bit range (inclusive), where `hi >= lo`.
68 //! - `=> Type`: Optional infallible conversion (see [below](#infallible-conversion-)).
69 //! - `?=> Type`: Optional fallible conversion (see [below](#fallible-conversion-)).
70 //! - Documentation strings and attributes are optional.
71 //!
72 //! # Generated code
73 //!
74 //! Each field is internally represented as a [`Bounded`] parameterized by its bit width. Field
75 //! values can either be set/retrieved directly, or converted from/to another type.
76 //!
77 //! The use of [`Bounded`] for each field enforces bounds-checking (at build time or runtime) of
78 //! every value assigned to a field. This ensures that data is never accidentally truncated.
79 //!
80 //! The macro generates the bitfield type, [`From`] and [`Into`] implementations for its storage
81 //! type, as well as [`Debug`] and [`Zeroable`](pin_init::Zeroable) implementations.
82 //!
83 //! For each field, it also generates:
84 //!
85 //! - `field()`: Getter method for the field value.
86 //! - `with_field(value)`: Infallible setter; the argument type must fit within the field's width.
87 //! - `with_const_field::<VALUE>()`: `const` setter; the value is validated at compile time.
88 //!   Usually shorter to use than `with_field` for constant values as it doesn't require
89 //!   constructing a [`Bounded`].
90 //! - `try_with_field(value)`: Fallible setter. Returns an error if the value is out of range.
91 //! - `FIELD_MASK`, `FIELD_SHIFT`, `FIELD_RANGE`: Constants for manual bit manipulation.
92 //!
93 //! # Reserved names for field identifiers
94 //!
95 //! Field identifiers are used to generate methods and associated constants on the bitfield type.
96 //! For a field named `field`, the macro may generate methods named `field`, `with_field`,
97 //! `with_const_field`, `try_with_field`, `__field` and `__with_field`, as well as constants named
98 //! `FIELD_MASK`, `FIELD_SHIFT` and `FIELD_RANGE`.
99 //!
100 //! Therefore, field identifiers must not use names that would collide with generated items for
101 //! any field in the same bitfield. The following prefixes are thus reserved for field identifiers:
102 //!
103 //! - `with_`
104 //! - `const_`
105 //! - `try_with_`
106 //! - `__`
107 //!
108 //! The field identifiers `from_raw`, `into_raw`, and `into` are also reserved.
109 //!
110 //! In addition, field identifiers should follow Rust `snake_case` conventions, since the associated
111 //! constants are generated by uppercasing the field name.
112 //!
113 //! # Implicit conversions
114 //!
115 //! Types that fit entirely within a field's bit width can be used directly with setters. For
116 //! example, [`bool`] works with single-bit fields, and [`u8`] works with 8-bit fields:
117 //!
118 //! ```rust
119 //! use kernel::bitfield;
120 //!
121 //! bitfield! {
122 //!     pub struct Flags(u32) {
123 //!         15:8 byte_field;
124 //!         0:0 flag;
125 //!     }
126 //! }
127 //!
128 //! let flags = Flags::zeroed()
129 //!     .with_byte_field(0x42_u8)
130 //!     .with_flag(true);
131 //!
132 //! assert_eq!(flags.into_raw(), (0x42 << Flags::BYTE_FIELD_SHIFT) | 1);
133 //! ```
134 //!
135 //! # Runtime bounds checking
136 //!
137 //! When a value is not known at compile time, use `try_with_field()` to check bounds at runtime:
138 //!
139 //! ```rust
140 //! use kernel::bitfield;
141 //!
142 //! bitfield! {
143 //!     pub struct Config(u8) {
144 //!         3:0 nibble;
145 //!     }
146 //! }
147 //!
148 //! fn set_nibble(config: Config, value: u8) -> Result<Config, Error> {
149 //!     // Returns `EOVERFLOW` if `value > 0xf`.
150 //!     config.try_with_nibble(value)
151 //! }
152 //! # Ok::<(), Error>(())
153 //! ```
154 //!
155 //! # Type conversion
156 //!
157 //! Fields can be automatically converted to/from a custom type using `=>` (infallible) or `?=>`
158 //! (fallible). The custom type must implement the appropriate [`From`] or [`TryFrom`] traits with
159 //! [`Bounded`].
160 //!
161 //! ## Infallible conversion (`=>`)
162 //!
163 //! Use this when all possible bit patterns of a field map to valid values:
164 //!
165 //! ```rust
166 //! use kernel::bitfield;
167 //! use kernel::num::Bounded;
168 //!
169 //! #[derive(Debug, Clone, Copy, PartialEq)]
170 //! enum Power {
171 //!     Off,
172 //!     On,
173 //! }
174 //!
175 //! impl From<Bounded<u32, 1>> for Power {
176 //!     fn from(v: Bounded<u32, 1>) -> Self {
177 //!         match *v {
178 //!             0 => Power::Off,
179 //!             _ => Power::On,
180 //!         }
181 //!     }
182 //! }
183 //!
184 //! impl From<Power> for Bounded<u32, 1> {
185 //!     fn from(p: Power) -> Self {
186 //!         (p as u32 != 0).into()
187 //!     }
188 //! }
189 //!
190 //! bitfield! {
191 //!     pub struct Control(u32) {
192 //!         0:0 power => Power;
193 //!     }
194 //! }
195 //!
196 //! let ctrl = Control::zeroed().with_power(Power::On);
197 //! assert_eq!(ctrl.power(), Power::On);
198 //! ```
199 //!
200 //! ## Fallible conversion (`?=>`)
201 //!
202 //! Use this when some bit patterns of a field are invalid. The getter returns a [`Result`]:
203 //!
204 //! ```rust
205 //! use kernel::bitfield;
206 //! use kernel::num::Bounded;
207 //!
208 //! #[derive(Debug, Clone, Copy, PartialEq)]
209 //! enum Mode {
210 //!     Low = 0,
211 //!     High = 1,
212 //!     Auto = 2,
213 //!     // 3 is invalid
214 //! }
215 //!
216 //! impl TryFrom<Bounded<u32, 2>> for Mode {
217 //!     type Error = u32;
218 //!
219 //!     fn try_from(v: Bounded<u32, 2>) -> Result<Self, u32> {
220 //!         match *v {
221 //!             0 => Ok(Mode::Low),
222 //!             1 => Ok(Mode::High),
223 //!             2 => Ok(Mode::Auto),
224 //!             n => Err(n),
225 //!         }
226 //!     }
227 //! }
228 //!
229 //! impl From<Mode> for Bounded<u32, 2> {
230 //!     fn from(m: Mode) -> Self {
231 //!         match m {
232 //!             Mode::Low => Bounded::<u32, _>::new::<0>(),
233 //!             Mode::High => Bounded::<u32, _>::new::<1>(),
234 //!             Mode::Auto => Bounded::<u32, _>::new::<2>(),
235 //!         }
236 //!     }
237 //! }
238 //!
239 //! bitfield! {
240 //!     pub struct Config(u32) {
241 //!         1:0 mode ?=> Mode;
242 //!     }
243 //! }
244 //!
245 //! let cfg = Config::zeroed().with_mode(Mode::Auto);
246 //! assert_eq!(cfg.mode(), Ok(Mode::Auto));
247 //!
248 //! // Invalid bit pattern returns an error.
249 //! assert_eq!(Config::from(0b11).mode(), Err(3));
250 //! ```
251 //!
252 //! # Bits outside of declared fields
253 //!
254 //! Bits of the storage type that are not part of any declared field are preserved by the setter
255 //! methods, and can only be modified through `from_raw` or the [`From`] implementation from the
256 //! storage type.
257 //!
258 //! ```rust
259 //! use kernel::bitfield;
260 //!
261 //! bitfield! {
262 //!     pub struct Sparse(u8) {
263 //!         7:6 high;
264 //!         // Bits 5:1 are not covered by any field.
265 //!         0:0 low;
266 //!     }
267 //! }
268 //!
269 //! // Set the gap bits via `from_raw`, then mutate the declared fields.
270 //! let val = Sparse::from_raw(0b0010_1010)
271 //!     .with_const_high::<0b11>()
272 //!     .with_low(true);
273 //!
274 //! // Bits 5:1 are unchanged.
275 //! assert_eq!(val.into_raw(), 0b1110_1011);
276 //! ```
277 //!
278 //! # Signed field values
279 //!
280 //! Bitfield storage types are unsigned. Since field getter methods return a [`Bounded`] of the
281 //! storage type, fields are also unsigned by default.
282 //!
283 //! If a field needs to encode a signed value, use a custom conversion type with `=>` or `?=>` to
284 //! perform the sign interpretation explicitly.
285 //!
286 //! [`Bounded`]: kernel::num::Bounded
287 
288 /// Defines a bitfield struct with bounds-checked accessors for individual bit ranges.
289 ///
290 /// See the [`mod@kernel::bitfield`] module for full documentation and examples.
291 #[macro_export]
292 macro_rules! bitfield {
293     // Entry point defining the bitfield struct, its implementations and its field accessors.
294     (
295         $(#[$attr:meta])* $vis:vis struct $name:ident($storage:ty) { $($fields:tt)* }
296     ) => {
297         $crate::bitfield!(@core
298             #[allow(non_camel_case_types)]
299             $(#[$attr])* $vis $name $storage
300         );
301         $crate::bitfield!(@fields $vis $name $storage { $($fields)* });
302     };
303 
304     // All rules below are helpers.
305 
306     // Defines the wrapper `$name` type and its conversions from/to the storage type.
307     (@core $(#[$attr:meta])* $vis:vis $name:ident $storage:ty) => {
308         $(#[$attr])*
309         #[repr(transparent)]
310         #[derive(Clone, Copy, PartialEq, Eq)]
311         $vis struct $name {
312             inner: $storage,
313         }
314 
315         #[allow(dead_code)]
316         impl $name {
317             /// Creates a bitfield from a raw value.
318             #[inline(always)]
319             $vis const fn from_raw(value: $storage) -> Self {
320                 Self{ inner: value }
321             }
322 
323             /// Turns this bitfield into its raw value.
324             ///
325             /// This is similar to the [`From`] implementation, but is shorter to invoke in
326             /// most cases.
327             #[inline(always)]
328             $vis const fn into_raw(self) -> $storage {
329                 self.inner
330             }
331         }
332 
333         // SAFETY: `$storage` is `Zeroable` and `$name` is transparent.
334         unsafe impl ::pin_init::Zeroable for $name {}
335 
336         impl ::core::convert::From<$name> for $storage {
337             #[inline(always)]
338             fn from(val: $name) -> $storage {
339                 val.into_raw()
340             }
341         }
342 
343         impl ::core::convert::From<$storage> for $name {
344             #[inline(always)]
345             fn from(val: $storage) -> $name {
346                 Self::from_raw(val)
347             }
348         }
349     };
350 
351     // Definitions requiring knowledge of individual fields: private and public field accessors,
352     // and `Debug` implementation.
353     (@fields $vis:vis $name:ident $storage:ty {
354         $($(#[doc = $doc:expr])* $hi:literal:$lo:literal $field:ident
355             $(?=> $try_into_type:ty)?
356             $(=> $into_type:ty)?
357         ;
358         )*
359     }
360     ) => {
361         #[allow(dead_code)]
362         impl $name {
363         $(
364         $crate::bitfield!(@private_field_accessors $vis $name $storage : $hi:$lo $field);
365         $crate::bitfield!(
366             @public_field_accessors $(#[doc = $doc])* $vis $name $storage : $hi:$lo $field
367             $(?=> $try_into_type)?
368             $(=> $into_type)?
369         );
370         )*
371         }
372 
373         $crate::bitfield!(@debug $name { $($field;)* });
374     };
375 
376     // Private field accessors working with the exact `Bounded` type for the field.
377     (
378         @private_field_accessors $vis:vis $name:ident $storage:ty : $hi:tt:$lo:tt $field:ident
379     ) => {
380         ::kernel::macros::paste!(
381         $vis const [<$field:upper _RANGE>]: ::core::ops::RangeInclusive<u8> = $lo..=$hi;
382         $vis const [<$field:upper _MASK>]: $storage =
383             ((((1 << $hi) - 1) << 1) + 1) - ((1 << $lo) - 1);
384         $vis const [<$field:upper _SHIFT>]: u32 = $lo;
385         );
386 
387         ::kernel::macros::paste!(
388         #[inline(always)]
389         fn [<__ $field>](self) ->
390             ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> {
391             // Left shift to align the field's MSB with the storage MSB.
392             const ALIGN_TOP: u32 = $storage::BITS - ($hi + 1);
393             // Right shift to move the top-aligned field to bit 0 of the storage.
394             const ALIGN_BOTTOM: u32 = ALIGN_TOP + $lo;
395 
396             // Extract the field using two shifts. `Bounded::shr` produces the correctly-sized
397             // output type.
398             let val = ::kernel::num::Bounded::<$storage, { $storage::BITS }>::from(
399                 self.inner << ALIGN_TOP
400             );
401             val.shr::<ALIGN_BOTTOM, { $hi + 1 - $lo } >()
402         }
403 
404         #[inline(always)]
405         const fn [<__with_ $field>](
406             mut self,
407             value: ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>,
408         ) -> Self
409         {
410             const MASK: $storage = <$name>::[<$field:upper _MASK>];
411             const SHIFT: u32 = <$name>::[<$field:upper _SHIFT>];
412 
413             let value = value.get() << SHIFT;
414             self.inner = (self.inner & !MASK) | value;
415 
416             self
417         }
418         );
419     };
420 
421     // Public accessors for fields infallibly (`=>`) converted to a type.
422     (
423         @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty :
424             $hi:literal:$lo:literal $field:ident => $into_type:ty
425     ) => {
426         ::kernel::macros::paste!(
427 
428         $(#[doc = $doc])*
429         #[doc = "Returns the value of this field."]
430         #[inline(always)]
431         $vis fn $field(self) -> $into_type
432         {
433             self.[<__ $field>]().into()
434         }
435 
436         $(#[doc = $doc])*
437         #[doc = "Sets this field to the given `value`."]
438         #[inline(always)]
439         $vis fn [<with_ $field>](self, value: $into_type) -> Self
440         {
441             self.[<__with_ $field>](value.into())
442         }
443 
444         );
445     };
446 
447     // Public accessors for fields fallibly (`?=>`) converted to a type.
448     (
449         @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty :
450             $hi:tt:$lo:tt $field:ident ?=> $try_into_type:ty
451     ) => {
452         ::kernel::macros::paste!(
453 
454         $(#[doc = $doc])*
455         #[doc = "Returns the value of this field."]
456         #[inline(always)]
457         $vis fn $field(self) ->
458             ::core::result::Result<
459                 $try_into_type,
460                 <$try_into_type as ::core::convert::TryFrom<
461                     ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>
462                 >>::Error
463             >
464         {
465             self.[<__ $field>]().try_into()
466         }
467 
468         $(#[doc = $doc])*
469         #[doc = "Sets this field to the given `value`."]
470         #[inline(always)]
471         $vis fn [<with_ $field>](self, value: $try_into_type) -> Self
472         {
473             self.[<__with_ $field>](value.into())
474         }
475 
476         );
477     };
478 
479     // Public accessors for fields not converted to a type.
480     (
481         @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty :
482             $hi:tt:$lo:tt $field:ident
483     ) => {
484         ::kernel::macros::paste!(
485 
486         $(#[doc = $doc])*
487         #[doc = "Returns the value of this field."]
488         #[inline(always)]
489         $vis fn $field(self) ->
490             ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>
491         {
492             self.[<__ $field>]()
493         }
494 
495         $(#[doc = $doc])*
496         #[doc = "Sets this field to the compile-time constant `VALUE`."]
497         #[inline(always)]
498         $vis const fn [<with_const_ $field>]<const VALUE: $storage>(self) -> Self {
499             self.[<__with_ $field>](
500                 ::kernel::num::Bounded::<$storage, { $hi + 1 - $lo }>::new::<VALUE>()
501             )
502         }
503 
504         $(#[doc = $doc])*
505         #[doc = "Sets this field to the given `value`."]
506         #[inline(always)]
507         $vis fn [<with_ $field>]<T>(
508             self,
509             value: T,
510         ) -> Self
511             where T: ::core::convert::Into<::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>>,
512         {
513             self.[<__with_ $field>](value.into())
514         }
515 
516         $(#[doc = $doc])*
517         #[doc = "Tries to set this field to `value`, returning an error if it is out of range."]
518         #[inline(always)]
519         $vis fn [<try_with_ $field>]<T>(
520             self,
521             value: T,
522         ) -> ::kernel::error::Result<Self>
523             where T: ::kernel::num::TryIntoBounded<$storage, { $hi + 1 - $lo }>,
524         {
525             Ok(
526                 self.[<__with_ $field>](
527                     value.try_into_bounded().ok_or(::kernel::error::code::EOVERFLOW)?
528                 )
529             )
530         }
531 
532         );
533     };
534 
535     // `Debug` implementation.
536     (@debug $name:ident { $($field:ident;)* }) => {
537         impl ::kernel::fmt::Debug for $name {
538             #[inline]
539             fn fmt(&self, f: &mut ::kernel::fmt::Formatter<'_>) -> ::kernel::fmt::Result {
540                 f.debug_struct(stringify!($name))
541                     .field("<raw>", &::kernel::prelude::fmt!("{:#x}", self.inner))
542                 $(
543                     .field(stringify!($field), &self.$field())
544                 )*
545                     .finish()
546             }
547         }
548     };
549 }
550 
551 #[cfg(CONFIG_RUST_BITFIELD_KUNIT_TEST)]
552 #[::kernel::macros::kunit_tests(rust_kernel_bitfield)]
553 mod tests {
554     use core::convert::TryFrom;
555 
556     use pin_init::Zeroable;
557 
558     use kernel::num::Bounded;
559 
560     // Enum types for testing `=>` and `?=>` conversions.
561 
562     #[derive(Debug, Clone, Copy, PartialEq)]
563     enum MemoryType {
564         Unmapped = 0,
565         Normal = 1,
566         Device = 2,
567         Reserved = 3,
568     }
569 
570     impl TryFrom<Bounded<u64, 4>> for MemoryType {
571         type Error = u64;
572         fn try_from(value: Bounded<u64, 4>) -> Result<Self, Self::Error> {
573             match value.get() {
574                 0 => Ok(MemoryType::Unmapped),
575                 1 => Ok(MemoryType::Normal),
576                 2 => Ok(MemoryType::Device),
577                 3 => Ok(MemoryType::Reserved),
578                 _ => Err(value.get()),
579             }
580         }
581     }
582 
583     impl From<MemoryType> for Bounded<u64, 4> {
584         #[inline(always)]
585         fn from(mt: MemoryType) -> Bounded<u64, 4> {
586             Bounded::from_expr(mt as u64)
587         }
588     }
589 
590     #[derive(Debug, Clone, Copy, PartialEq)]
591     enum Priority {
592         Low = 0,
593         Medium = 1,
594         High = 2,
595         Critical = 3,
596     }
597 
598     impl From<Bounded<u16, 2>> for Priority {
599         fn from(value: Bounded<u16, 2>) -> Self {
600             match value & 0x3 {
601                 0 => Priority::Low,
602                 1 => Priority::Medium,
603                 2 => Priority::High,
604                 _ => Priority::Critical,
605             }
606         }
607     }
608 
609     impl From<Priority> for Bounded<u16, 2> {
610         #[inline(always)]
611         fn from(p: Priority) -> Bounded<u16, 2> {
612             Bounded::from_expr(p as u16)
613         }
614     }
615 
616     bitfield! {
617         struct TestU64(u64) {
618             63:63     field_63;
619             61:52     field_61_52;
620             51:16     field_51_16;
621             15:12     field_15_12 ?=> MemoryType;
622             11:9      field_11_9;
623             1:1       field_1;
624             0:0       field_0;
625         }
626     }
627 
628     bitfield! {
629         struct TestU16(u16) {
630             15:8      field_15_8;
631             7:4       field_7_4; // Partial overlap with `field_5_4`.
632             5:4       field_5_4 => Priority;
633             3:1       field_3_1;
634             0:0       field_0;
635         }
636     }
637 
638     bitfield! {
639         struct TestU8(u8) {
640             7:0       field_7_0; // Full byte overlap.
641             7:4       field_7_4;
642             3:2       field_3_2;
643             1:1       field_1;
644             0:0       field_0;
645         }
646     }
647 
648     // Single and multi-bit fields basic access.
649     #[test]
650     fn test_basic_access() {
651         // `TestU64`.
652         let mut val = TestU64::zeroed();
653         assert_eq!(val.into_raw(), 0x0);
654 
655         val = val.with_field_0(true);
656         assert!(val.field_0().into_bool());
657         assert_eq!(val.into_raw(), 0x1);
658 
659         val = val.with_field_1(true);
660         assert!(val.field_1().into_bool());
661         val = val.with_field_1(false);
662         assert!(!val.field_1().into_bool());
663         assert_eq!(val.into_raw(), 0x1);
664 
665         val = val.with_const_field_11_9::<0x5>();
666         assert_eq!(val.field_11_9(), 0x5);
667         assert_eq!(val.into_raw(), 0xA01);
668 
669         val = val.with_const_field_51_16::<0x123456>();
670         assert_eq!(val.field_51_16(), 0x123456);
671         assert_eq!(val.into_raw(), 0x0012_3456_0A01);
672 
673         const MAX_FIELD_51_16: u64 = ::kernel::bits::genmask_u64(0..=35);
674         val = val.with_const_field_51_16::<{ MAX_FIELD_51_16 }>();
675         assert_eq!(val.field_51_16(), MAX_FIELD_51_16);
676 
677         val = val.with_const_field_61_52::<0x3FF>();
678         assert_eq!(val.field_61_52(), 0x3FF);
679 
680         val = val.with_field_63(true);
681         assert!(val.field_63().into_bool());
682 
683         // `TestU16`.
684         let mut val = TestU16::zeroed();
685         assert_eq!(val.into_raw(), 0x0);
686 
687         val = val.with_field_0(true);
688         assert!(val.field_0().into_bool());
689         assert_eq!(val.into_raw(), 0x1);
690 
691         val = val.with_const_field_3_1::<0x5>();
692         assert_eq!(val.field_3_1(), 0x5);
693         assert_eq!(val.into_raw(), 0xB);
694 
695         val = val.with_const_field_7_4::<0xA>();
696         assert_eq!(val.field_7_4(), 0xA);
697         assert_eq!(val.into_raw(), 0xAB);
698 
699         val = val.with_const_field_15_8::<0x42>();
700         assert_eq!(val.field_15_8(), 0x42);
701         assert_eq!(val.into_raw(), 0x42AB);
702 
703         // `TestU8`.
704         let mut val = TestU8::zeroed();
705         assert_eq!(val.into_raw(), 0x0);
706 
707         val = val.with_field_0(true);
708         assert!(val.field_0().into_bool());
709         assert_eq!(val.into_raw(), 0x1);
710 
711         val = val.with_field_1(true);
712         assert!(val.field_1().into_bool());
713         assert_eq!(val.into_raw(), 0x3);
714 
715         val = val.with_const_field_3_2::<0x3>();
716         assert_eq!(val.field_3_2(), 0x3);
717         assert_eq!(val.into_raw(), 0xF);
718 
719         val = val.with_const_field_7_4::<0xA>();
720         assert_eq!(val.field_7_4(), 0xA);
721         assert_eq!(val.into_raw(), 0xAF);
722     }
723 
724     // `=>` infallible conversion.
725     #[test]
726     fn test_infallible_conversion() {
727         let mut val = TestU16::zeroed();
728 
729         val = val.with_field_5_4(Priority::Low);
730         assert_eq!(val.field_5_4(), Priority::Low);
731         assert_eq!(val.into_raw() & 0x30, 0x00);
732 
733         val = val.with_field_5_4(Priority::Medium);
734         assert_eq!(val.field_5_4(), Priority::Medium);
735         assert_eq!(val.into_raw() & 0x30, 0x10);
736 
737         val = val.with_field_5_4(Priority::High);
738         assert_eq!(val.field_5_4(), Priority::High);
739         assert_eq!(val.into_raw() & 0x30, 0x20);
740 
741         val = val.with_field_5_4(Priority::Critical);
742         assert_eq!(val.field_5_4(), Priority::Critical);
743         assert_eq!(val.into_raw() & 0x30, 0x30);
744     }
745 
746     // `?=>` fallible conversion.
747     #[test]
748     fn test_fallible_conversion() {
749         let mut val = TestU64::zeroed();
750 
751         val = val.with_field_15_12(MemoryType::Unmapped);
752         assert_eq!(val.field_15_12(), Ok(MemoryType::Unmapped));
753         val = val.with_field_15_12(MemoryType::Normal);
754         assert_eq!(val.field_15_12(), Ok(MemoryType::Normal));
755         val = val.with_field_15_12(MemoryType::Device);
756         assert_eq!(val.field_15_12(), Ok(MemoryType::Device));
757         val = val.with_field_15_12(MemoryType::Reserved);
758         assert_eq!(val.field_15_12(), Ok(MemoryType::Reserved));
759 
760         // `field_15_12` is 4 bits wide (0-15); `MemoryType` only covers 0-3, so 4-15 return `Err`.
761         let raw = (val.into_raw() & !::kernel::bits::genmask_u64(12..=15)) | (0x7 << 12);
762         assert_eq!(TestU64::from_raw(raw).field_15_12(), Err(0x7));
763     }
764 
765     // Test that setting an overlapping field affects the overlapped one as expected.
766     #[test]
767     fn test_overlapping_fields() {
768         let mut val = TestU16::zeroed();
769 
770         val = val.with_field_5_4(Priority::High); // High == 2 == 0b10.
771         assert_eq!(val.field_5_4(), Priority::High);
772         assert_eq!(val.field_7_4(), 0x2); // Bits 7:6 == 0, bits 5:4 == 0b10.
773 
774         val = val.with_const_field_7_4::<0xF>();
775         assert_eq!(val.field_7_4(), 0xF);
776         assert_eq!(val.field_5_4(), Priority::Critical); // Bits 5:4 == 0b11.
777 
778         // `field_7_0` should encompass all other fields.
779         let mut val = TestU8::zeroed()
780             .with_field_0(true)
781             .with_field_1(true)
782             .with_const_field_3_2::<0x3>()
783             .with_const_field_7_4::<0xA>();
784         assert_eq!(val.into_raw(), 0xAF);
785 
786         val = val.with_field_7_0(0x55);
787         assert_eq!(val.field_7_0(), 0x55);
788         assert!(val.field_0().into_bool());
789         assert!(!val.field_1().into_bool());
790         assert_eq!(val.field_3_2(), 0x1);
791         assert_eq!(val.field_7_4(), 0x5);
792     }
793 
794     // Checks that bits not mapped to any field are left untouched.
795     #[test]
796     fn test_unallocated_bits() {
797         let gap_bits = (1u64 << 62) | 0x1FC;
798 
799         let set_all_fields = |val: TestU64| {
800             val.with_field_63(true)
801                 .with_const_field_61_52::<0x155>()
802                 .with_const_field_51_16::<0x123456>()
803                 .with_field_15_12(MemoryType::Device)
804                 .with_const_field_11_9::<0x5>()
805                 .with_field_1(true)
806                 .with_field_0(true)
807         };
808 
809         // Gap bits to 0.
810         let val = set_all_fields(TestU64::from_raw(0));
811         assert_eq!(val.into_raw() & gap_bits, 0);
812 
813         // Gap bits to 1.
814         let val = set_all_fields(TestU64::from_raw(gap_bits));
815         assert_eq!(val.into_raw() & gap_bits, gap_bits);
816     }
817 
818     #[test]
819     fn test_try_with() {
820         let val = TestU64::zeroed().try_with_field_51_16(0x123456).unwrap();
821         assert_eq!(val.field_51_16(), 0x123456);
822 
823         let err = TestU64::zeroed().try_with_field_51_16(u64::MAX);
824         assert_eq!(err, Err(::kernel::error::code::EOVERFLOW));
825 
826         let val = TestU64::zeroed()
827             .try_with_field_51_16(0xABCDEF)
828             .and_then(|p| p.try_with_field_0(1))
829             .unwrap();
830         assert_eq!(val.field_51_16(), 0xABCDEF);
831         assert!(val.field_0().into_bool());
832     }
833 
834     // `from_raw`/`into_raw` and `From`/`Into` round-trips.
835     #[test]
836     fn test_raw() {
837         let raw: u64 = 0xBFF0_0000_3123_3E03;
838         let val = TestU64::from_raw(raw);
839         assert_eq!(u64::from(val), raw);
840         assert!(val.field_0().into_bool());
841         assert!(val.field_1().into_bool());
842         assert_eq!(val.field_11_9(), 0x7);
843         assert_eq!(val.field_51_16(), 0x3123);
844         assert_eq!(val.field_15_12(), Ok(MemoryType::Reserved));
845         assert_eq!(val.field_61_52(), 0x3FF);
846         assert!(val.field_63().into_bool());
847 
848         let raw: u16 = 0x42AB;
849         let val = TestU16::from_raw(raw);
850         assert_eq!(u16::from(val), raw);
851         assert!(val.field_0().into_bool());
852         assert_eq!(val.field_3_1(), 0x5);
853         assert_eq!(val.field_7_4(), 0xA);
854         assert_eq!(val.field_15_8(), 0x42);
855 
856         let raw: u8 = 0xAF;
857         let val = TestU8::from_raw(raw);
858         assert_eq!(u8::from(val), raw);
859         assert!(val.field_0().into_bool());
860         assert!(val.field_1().into_bool());
861         assert_eq!(val.field_3_2(), 0x3);
862         assert_eq!(val.field_7_4(), 0xA);
863         assert_eq!(val.field_7_0(), 0xAF);
864     }
865 }
866