xref: /linux/rust/kernel/bitfield.rs (revision 6b3f7af57881f6d6250c6dcc4d910fe8e855a607)
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             fn fmt(&self, f: &mut ::kernel::fmt::Formatter<'_>) -> ::kernel::fmt::Result {
539                 f.debug_struct(stringify!($name))
540                     .field("<raw>", &::kernel::prelude::fmt!("{:#x}", self.inner))
541                 $(
542                     .field(stringify!($field), &self.$field())
543                 )*
544                     .finish()
545             }
546         }
547     };
548 }
549 
550 #[cfg(CONFIG_RUST_BITFIELD_KUNIT_TEST)]
551 #[::kernel::macros::kunit_tests(rust_kernel_bitfield)]
552 mod tests {
553     use core::convert::TryFrom;
554 
555     use pin_init::Zeroable;
556 
557     use kernel::num::Bounded;
558 
559     // Enum types for testing `=>` and `?=>` conversions.
560 
561     #[derive(Debug, Clone, Copy, PartialEq)]
562     enum MemoryType {
563         Unmapped = 0,
564         Normal = 1,
565         Device = 2,
566         Reserved = 3,
567     }
568 
569     impl TryFrom<Bounded<u64, 4>> for MemoryType {
570         type Error = u64;
571         fn try_from(value: Bounded<u64, 4>) -> Result<Self, Self::Error> {
572             match value.get() {
573                 0 => Ok(MemoryType::Unmapped),
574                 1 => Ok(MemoryType::Normal),
575                 2 => Ok(MemoryType::Device),
576                 3 => Ok(MemoryType::Reserved),
577                 _ => Err(value.get()),
578             }
579         }
580     }
581 
582     impl From<MemoryType> for Bounded<u64, 4> {
583         fn from(mt: MemoryType) -> Bounded<u64, 4> {
584             Bounded::from_expr(mt as u64)
585         }
586     }
587 
588     #[derive(Debug, Clone, Copy, PartialEq)]
589     enum Priority {
590         Low = 0,
591         Medium = 1,
592         High = 2,
593         Critical = 3,
594     }
595 
596     impl From<Bounded<u16, 2>> for Priority {
597         fn from(value: Bounded<u16, 2>) -> Self {
598             match value & 0x3 {
599                 0 => Priority::Low,
600                 1 => Priority::Medium,
601                 2 => Priority::High,
602                 _ => Priority::Critical,
603             }
604         }
605     }
606 
607     impl From<Priority> for Bounded<u16, 2> {
608         fn from(p: Priority) -> Bounded<u16, 2> {
609             Bounded::from_expr(p as u16)
610         }
611     }
612 
613     bitfield! {
614         struct TestU64(u64) {
615             63:63     field_63;
616             61:52     field_61_52;
617             51:16     field_51_16;
618             15:12     field_15_12 ?=> MemoryType;
619             11:9      field_11_9;
620             1:1       field_1;
621             0:0       field_0;
622         }
623     }
624 
625     bitfield! {
626         struct TestU16(u16) {
627             15:8      field_15_8;
628             7:4       field_7_4; // Partial overlap with `field_5_4`.
629             5:4       field_5_4 => Priority;
630             3:1       field_3_1;
631             0:0       field_0;
632         }
633     }
634 
635     bitfield! {
636         struct TestU8(u8) {
637             7:0       field_7_0; // Full byte overlap.
638             7:4       field_7_4;
639             3:2       field_3_2;
640             1:1       field_1;
641             0:0       field_0;
642         }
643     }
644 
645     // Single and multi-bit fields basic access.
646     #[test]
647     fn test_basic_access() {
648         // `TestU64`.
649         let mut val = TestU64::zeroed();
650         assert_eq!(val.into_raw(), 0x0);
651 
652         val = val.with_field_0(true);
653         assert!(val.field_0().into_bool());
654         assert_eq!(val.into_raw(), 0x1);
655 
656         val = val.with_field_1(true);
657         assert!(val.field_1().into_bool());
658         val = val.with_field_1(false);
659         assert!(!val.field_1().into_bool());
660         assert_eq!(val.into_raw(), 0x1);
661 
662         val = val.with_const_field_11_9::<0x5>();
663         assert_eq!(val.field_11_9(), 0x5);
664         assert_eq!(val.into_raw(), 0xA01);
665 
666         val = val.with_const_field_51_16::<0x123456>();
667         assert_eq!(val.field_51_16(), 0x123456);
668         assert_eq!(val.into_raw(), 0x0012_3456_0A01);
669 
670         const MAX_FIELD_51_16: u64 = ::kernel::bits::genmask_u64(0..=35);
671         val = val.with_const_field_51_16::<{ MAX_FIELD_51_16 }>();
672         assert_eq!(val.field_51_16(), MAX_FIELD_51_16);
673 
674         val = val.with_const_field_61_52::<0x3FF>();
675         assert_eq!(val.field_61_52(), 0x3FF);
676 
677         val = val.with_field_63(true);
678         assert!(val.field_63().into_bool());
679 
680         // `TestU16`.
681         let mut val = TestU16::zeroed();
682         assert_eq!(val.into_raw(), 0x0);
683 
684         val = val.with_field_0(true);
685         assert!(val.field_0().into_bool());
686         assert_eq!(val.into_raw(), 0x1);
687 
688         val = val.with_const_field_3_1::<0x5>();
689         assert_eq!(val.field_3_1(), 0x5);
690         assert_eq!(val.into_raw(), 0xB);
691 
692         val = val.with_const_field_7_4::<0xA>();
693         assert_eq!(val.field_7_4(), 0xA);
694         assert_eq!(val.into_raw(), 0xAB);
695 
696         val = val.with_const_field_15_8::<0x42>();
697         assert_eq!(val.field_15_8(), 0x42);
698         assert_eq!(val.into_raw(), 0x42AB);
699 
700         // `TestU8`.
701         let mut val = TestU8::zeroed();
702         assert_eq!(val.into_raw(), 0x0);
703 
704         val = val.with_field_0(true);
705         assert!(val.field_0().into_bool());
706         assert_eq!(val.into_raw(), 0x1);
707 
708         val = val.with_field_1(true);
709         assert!(val.field_1().into_bool());
710         assert_eq!(val.into_raw(), 0x3);
711 
712         val = val.with_const_field_3_2::<0x3>();
713         assert_eq!(val.field_3_2(), 0x3);
714         assert_eq!(val.into_raw(), 0xF);
715 
716         val = val.with_const_field_7_4::<0xA>();
717         assert_eq!(val.field_7_4(), 0xA);
718         assert_eq!(val.into_raw(), 0xAF);
719     }
720 
721     // `=>` infallible conversion.
722     #[test]
723     fn test_infallible_conversion() {
724         let mut val = TestU16::zeroed();
725 
726         val = val.with_field_5_4(Priority::Low);
727         assert_eq!(val.field_5_4(), Priority::Low);
728         assert_eq!(val.into_raw() & 0x30, 0x00);
729 
730         val = val.with_field_5_4(Priority::Medium);
731         assert_eq!(val.field_5_4(), Priority::Medium);
732         assert_eq!(val.into_raw() & 0x30, 0x10);
733 
734         val = val.with_field_5_4(Priority::High);
735         assert_eq!(val.field_5_4(), Priority::High);
736         assert_eq!(val.into_raw() & 0x30, 0x20);
737 
738         val = val.with_field_5_4(Priority::Critical);
739         assert_eq!(val.field_5_4(), Priority::Critical);
740         assert_eq!(val.into_raw() & 0x30, 0x30);
741     }
742 
743     // `?=>` fallible conversion.
744     #[test]
745     fn test_fallible_conversion() {
746         let mut val = TestU64::zeroed();
747 
748         val = val.with_field_15_12(MemoryType::Unmapped);
749         assert_eq!(val.field_15_12(), Ok(MemoryType::Unmapped));
750         val = val.with_field_15_12(MemoryType::Normal);
751         assert_eq!(val.field_15_12(), Ok(MemoryType::Normal));
752         val = val.with_field_15_12(MemoryType::Device);
753         assert_eq!(val.field_15_12(), Ok(MemoryType::Device));
754         val = val.with_field_15_12(MemoryType::Reserved);
755         assert_eq!(val.field_15_12(), Ok(MemoryType::Reserved));
756 
757         // `field_15_12` is 4 bits wide (0-15); `MemoryType` only covers 0-3, so 4-15 return `Err`.
758         let raw = (val.into_raw() & !::kernel::bits::genmask_u64(12..=15)) | (0x7 << 12);
759         assert_eq!(TestU64::from_raw(raw).field_15_12(), Err(0x7));
760     }
761 
762     // Test that setting an overlapping field affects the overlapped one as expected.
763     #[test]
764     fn test_overlapping_fields() {
765         let mut val = TestU16::zeroed();
766 
767         val = val.with_field_5_4(Priority::High); // High == 2 == 0b10.
768         assert_eq!(val.field_5_4(), Priority::High);
769         assert_eq!(val.field_7_4(), 0x2); // Bits 7:6 == 0, bits 5:4 == 0b10.
770 
771         val = val.with_const_field_7_4::<0xF>();
772         assert_eq!(val.field_7_4(), 0xF);
773         assert_eq!(val.field_5_4(), Priority::Critical); // Bits 5:4 == 0b11.
774 
775         // `field_7_0` should encompass all other fields.
776         let mut val = TestU8::zeroed()
777             .with_field_0(true)
778             .with_field_1(true)
779             .with_const_field_3_2::<0x3>()
780             .with_const_field_7_4::<0xA>();
781         assert_eq!(val.into_raw(), 0xAF);
782 
783         val = val.with_field_7_0(0x55);
784         assert_eq!(val.field_7_0(), 0x55);
785         assert!(val.field_0().into_bool());
786         assert!(!val.field_1().into_bool());
787         assert_eq!(val.field_3_2(), 0x1);
788         assert_eq!(val.field_7_4(), 0x5);
789     }
790 
791     // Checks that bits not mapped to any field are left untouched.
792     #[test]
793     fn test_unallocated_bits() {
794         let gap_bits = (1u64 << 62) | 0x1FC;
795 
796         let set_all_fields = |val: TestU64| {
797             val.with_field_63(true)
798                 .with_const_field_61_52::<0x155>()
799                 .with_const_field_51_16::<0x123456>()
800                 .with_field_15_12(MemoryType::Device)
801                 .with_const_field_11_9::<0x5>()
802                 .with_field_1(true)
803                 .with_field_0(true)
804         };
805 
806         // Gap bits to 0.
807         let val = set_all_fields(TestU64::from_raw(0));
808         assert_eq!(val.into_raw() & gap_bits, 0);
809 
810         // Gap bits to 1.
811         let val = set_all_fields(TestU64::from_raw(gap_bits));
812         assert_eq!(val.into_raw() & gap_bits, gap_bits);
813     }
814 
815     #[test]
816     fn test_try_with() {
817         let val = TestU64::zeroed().try_with_field_51_16(0x123456).unwrap();
818         assert_eq!(val.field_51_16(), 0x123456);
819 
820         let err = TestU64::zeroed().try_with_field_51_16(u64::MAX);
821         assert_eq!(err, Err(::kernel::error::code::EOVERFLOW));
822 
823         let val = TestU64::zeroed()
824             .try_with_field_51_16(0xABCDEF)
825             .and_then(|p| p.try_with_field_0(1))
826             .unwrap();
827         assert_eq!(val.field_51_16(), 0xABCDEF);
828         assert!(val.field_0().into_bool());
829     }
830 
831     // `from_raw`/`into_raw` and `From`/`Into` round-trips.
832     #[test]
833     fn test_raw() {
834         let raw: u64 = 0xBFF0_0000_3123_3E03;
835         let val = TestU64::from_raw(raw);
836         assert_eq!(u64::from(val), raw);
837         assert!(val.field_0().into_bool());
838         assert!(val.field_1().into_bool());
839         assert_eq!(val.field_11_9(), 0x7);
840         assert_eq!(val.field_51_16(), 0x3123);
841         assert_eq!(val.field_15_12(), Ok(MemoryType::Reserved));
842         assert_eq!(val.field_61_52(), 0x3FF);
843         assert!(val.field_63().into_bool());
844 
845         let raw: u16 = 0x42AB;
846         let val = TestU16::from_raw(raw);
847         assert_eq!(u16::from(val), raw);
848         assert!(val.field_0().into_bool());
849         assert_eq!(val.field_3_1(), 0x5);
850         assert_eq!(val.field_7_4(), 0xA);
851         assert_eq!(val.field_15_8(), 0x42);
852 
853         let raw: u8 = 0xAF;
854         let val = TestU8::from_raw(raw);
855         assert_eq!(u8::from(val), raw);
856         assert!(val.field_0().into_bool());
857         assert!(val.field_1().into_bool());
858         assert_eq!(val.field_3_2(), 0x3);
859         assert_eq!(val.field_7_4(), 0xA);
860         assert_eq!(val.field_7_0(), 0xAF);
861     }
862 }
863