xref: /linux/rust/kernel/bitfield.rs (revision 12d5fc96ebbb3b948861805b32a4c3a96105ccd9)
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             $(#[$attr])* $vis $name $storage
299         );
300         $crate::bitfield!(@fields $vis $name $storage { $($fields)* });
301     };
302 
303     // All rules below are helpers.
304 
305     // Defines the wrapper `$name` type and its conversions from/to the storage type.
306     (@core $(#[$attr:meta])* $vis:vis $name:ident $storage:ty) => {
307         $(#[$attr])*
308         #[repr(transparent)]
309         #[derive(Clone, Copy, PartialEq, Eq)]
310         $vis struct $name {
311             inner: $storage,
312         }
313 
314         #[allow(dead_code)]
315         impl $name {
316             /// Creates a bitfield from a raw value.
317             #[inline(always)]
318             $vis const fn from_raw(value: $storage) -> Self {
319                 Self{ inner: value }
320             }
321 
322             /// Turns this bitfield into its raw value.
323             ///
324             /// This is similar to the [`From`] implementation, but is shorter to invoke in
325             /// most cases.
326             #[inline(always)]
327             $vis const fn into_raw(self) -> $storage {
328                 self.inner
329             }
330         }
331 
332         // SAFETY: `$storage` is `Zeroable` and `$name` is transparent.
333         unsafe impl ::pin_init::Zeroable for $name {}
334 
335         impl ::core::convert::From<$name> for $storage {
336             #[inline(always)]
337             fn from(val: $name) -> $storage {
338                 val.into_raw()
339             }
340         }
341 
342         impl ::core::convert::From<$storage> for $name {
343             #[inline(always)]
344             fn from(val: $storage) -> $name {
345                 Self::from_raw(val)
346             }
347         }
348     };
349 
350     // Definitions requiring knowledge of individual fields: private and public field accessors,
351     // and `Debug` implementation.
352     (@fields $vis:vis $name:ident $storage:ty {
353         $($(#[doc = $doc:expr])* $hi:literal:$lo:literal $field:ident
354             $(?=> $try_into_type:ty)?
355             $(=> $into_type:ty)?
356         ;
357         )*
358     }
359     ) => {
360         #[allow(dead_code)]
361         impl $name {
362         $(
363         $crate::bitfield!(@private_field_accessors $vis $name $storage : $hi:$lo $field);
364         $crate::bitfield!(
365             @public_field_accessors $(#[doc = $doc])* $vis $name $storage : $hi:$lo $field
366             $(?=> $try_into_type)?
367             $(=> $into_type)?
368         );
369         )*
370         }
371 
372         $crate::bitfield!(@debug $name { $($field;)* });
373     };
374 
375     // Private field accessors working with the exact `Bounded` type for the field.
376     (
377         @private_field_accessors $vis:vis $name:ident $storage:ty : $hi:tt:$lo:tt $field:ident
378     ) => {
379         ::kernel::macros::paste!(
380         $vis const [<$field:upper _RANGE>]: ::core::ops::RangeInclusive<u8> = $lo..=$hi;
381         $vis const [<$field:upper _MASK>]: $storage =
382             ((((1 << $hi) - 1) << 1) + 1) - ((1 << $lo) - 1);
383         $vis const [<$field:upper _SHIFT>]: u32 = $lo;
384         );
385 
386         ::kernel::macros::paste!(
387         #[inline(always)]
388         fn [<__ $field>](self) ->
389             ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> {
390             // Left shift to align the field's MSB with the storage MSB.
391             const ALIGN_TOP: u32 = $storage::BITS - ($hi + 1);
392             // Right shift to move the top-aligned field to bit 0 of the storage.
393             const ALIGN_BOTTOM: u32 = ALIGN_TOP + $lo;
394 
395             // Extract the field using two shifts. `Bounded::shr` produces the correctly-sized
396             // output type.
397             let val = ::kernel::num::Bounded::<$storage, { $storage::BITS }>::from(
398                 self.inner << ALIGN_TOP
399             );
400             val.shr::<ALIGN_BOTTOM, { $hi + 1 - $lo } >()
401         }
402 
403         #[inline(always)]
404         const fn [<__with_ $field>](
405             mut self,
406             value: ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>,
407         ) -> Self
408         {
409             const MASK: $storage = <$name>::[<$field:upper _MASK>];
410             const SHIFT: u32 = <$name>::[<$field:upper _SHIFT>];
411 
412             let value = value.get() << SHIFT;
413             self.inner = (self.inner & !MASK) | value;
414 
415             self
416         }
417         );
418     };
419 
420     // Public accessors for fields infallibly (`=>`) converted to a type.
421     (
422         @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty :
423             $hi:literal:$lo:literal $field:ident => $into_type:ty
424     ) => {
425         ::kernel::macros::paste!(
426 
427         $(#[doc = $doc])*
428         #[doc = "Returns the value of this field."]
429         #[inline(always)]
430         $vis fn $field(self) -> $into_type
431         {
432             self.[<__ $field>]().into()
433         }
434 
435         $(#[doc = $doc])*
436         #[doc = "Sets this field to the given `value`."]
437         #[inline(always)]
438         $vis fn [<with_ $field>](self, value: $into_type) -> Self
439         {
440             self.[<__with_ $field>](value.into())
441         }
442 
443         );
444     };
445 
446     // Public accessors for fields fallibly (`?=>`) converted to a type.
447     (
448         @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty :
449             $hi:tt:$lo:tt $field:ident ?=> $try_into_type:ty
450     ) => {
451         ::kernel::macros::paste!(
452 
453         $(#[doc = $doc])*
454         #[doc = "Returns the value of this field."]
455         #[inline(always)]
456         $vis fn $field(self) ->
457             ::core::result::Result<
458                 $try_into_type,
459                 <$try_into_type as ::core::convert::TryFrom<
460                     ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>
461                 >>::Error
462             >
463         {
464             self.[<__ $field>]().try_into()
465         }
466 
467         $(#[doc = $doc])*
468         #[doc = "Sets this field to the given `value`."]
469         #[inline(always)]
470         $vis fn [<with_ $field>](self, value: $try_into_type) -> Self
471         {
472             self.[<__with_ $field>](value.into())
473         }
474 
475         );
476     };
477 
478     // Public accessors for fields not converted to a type.
479     (
480         @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty :
481             $hi:tt:$lo:tt $field:ident
482     ) => {
483         ::kernel::macros::paste!(
484 
485         $(#[doc = $doc])*
486         #[doc = "Returns the value of this field."]
487         #[inline(always)]
488         $vis fn $field(self) ->
489             ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>
490         {
491             self.[<__ $field>]()
492         }
493 
494         $(#[doc = $doc])*
495         #[doc = "Sets this field to the compile-time constant `VALUE`."]
496         #[inline(always)]
497         $vis const fn [<with_const_ $field>]<const VALUE: $storage>(self) -> Self {
498             self.[<__with_ $field>](
499                 ::kernel::num::Bounded::<$storage, { $hi + 1 - $lo }>::new::<VALUE>()
500             )
501         }
502 
503         $(#[doc = $doc])*
504         #[doc = "Sets this field to the given `value`."]
505         #[inline(always)]
506         $vis fn [<with_ $field>]<T>(
507             self,
508             value: T,
509         ) -> Self
510             where T: ::core::convert::Into<::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>>,
511         {
512             self.[<__with_ $field>](value.into())
513         }
514 
515         $(#[doc = $doc])*
516         #[doc = "Tries to set this field to `value`, returning an error if it is out of range."]
517         #[inline(always)]
518         $vis fn [<try_with_ $field>]<T>(
519             self,
520             value: T,
521         ) -> ::kernel::error::Result<Self>
522             where T: ::kernel::num::TryIntoBounded<$storage, { $hi + 1 - $lo }>,
523         {
524             Ok(
525                 self.[<__with_ $field>](
526                     value.try_into_bounded().ok_or(::kernel::error::code::EOVERFLOW)?
527                 )
528             )
529         }
530 
531         );
532     };
533 
534     // `Debug` implementation.
535     (@debug $name:ident { $($field:ident;)* }) => {
536         impl ::kernel::fmt::Debug for $name {
537             #[inline]
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         #[inline(always)]
584         fn from(mt: MemoryType) -> Bounded<u64, 4> {
585             Bounded::from_expr(mt as u64)
586         }
587     }
588 
589     #[derive(Debug, Clone, Copy, PartialEq)]
590     enum Priority {
591         Low = 0,
592         Medium = 1,
593         High = 2,
594         Critical = 3,
595     }
596 
597     impl From<Bounded<u16, 2>> for Priority {
598         fn from(value: Bounded<u16, 2>) -> Self {
599             match value & 0x3 {
600                 0 => Priority::Low,
601                 1 => Priority::Medium,
602                 2 => Priority::High,
603                 _ => Priority::Critical,
604             }
605         }
606     }
607 
608     impl From<Priority> for Bounded<u16, 2> {
609         #[inline(always)]
610         fn from(p: Priority) -> Bounded<u16, 2> {
611             Bounded::from_expr(p as u16)
612         }
613     }
614 
615     bitfield! {
616         struct TestU64(u64) {
617             63:63     field_63;
618             61:52     field_61_52;
619             51:16     field_51_16;
620             15:12     field_15_12 ?=> MemoryType;
621             11:9      field_11_9;
622             1:1       field_1;
623             0:0       field_0;
624         }
625     }
626 
627     bitfield! {
628         struct TestU16(u16) {
629             15:8      field_15_8;
630             7:4       field_7_4; // Partial overlap with `field_5_4`.
631             5:4       field_5_4 => Priority;
632             3:1       field_3_1;
633             0:0       field_0;
634         }
635     }
636 
637     bitfield! {
638         struct TestU8(u8) {
639             7:0       field_7_0; // Full byte overlap.
640             7:4       field_7_4;
641             3:2       field_3_2;
642             1:1       field_1;
643             0:0       field_0;
644         }
645     }
646 
647     // Single and multi-bit fields basic access.
648     #[test]
649     fn test_basic_access() {
650         // `TestU64`.
651         let mut val = TestU64::zeroed();
652         assert_eq!(val.into_raw(), 0x0);
653 
654         val = val.with_field_0(true);
655         assert!(val.field_0().into_bool());
656         assert_eq!(val.into_raw(), 0x1);
657 
658         val = val.with_field_1(true);
659         assert!(val.field_1().into_bool());
660         val = val.with_field_1(false);
661         assert!(!val.field_1().into_bool());
662         assert_eq!(val.into_raw(), 0x1);
663 
664         val = val.with_const_field_11_9::<0x5>();
665         assert_eq!(val.field_11_9(), 0x5);
666         assert_eq!(val.into_raw(), 0xA01);
667 
668         val = val.with_const_field_51_16::<0x123456>();
669         assert_eq!(val.field_51_16(), 0x123456);
670         assert_eq!(val.into_raw(), 0x0012_3456_0A01);
671 
672         const MAX_FIELD_51_16: u64 = ::kernel::bits::genmask_u64(0..=35);
673         val = val.with_const_field_51_16::<{ MAX_FIELD_51_16 }>();
674         assert_eq!(val.field_51_16(), MAX_FIELD_51_16);
675 
676         val = val.with_const_field_61_52::<0x3FF>();
677         assert_eq!(val.field_61_52(), 0x3FF);
678 
679         val = val.with_field_63(true);
680         assert!(val.field_63().into_bool());
681 
682         // `TestU16`.
683         let mut val = TestU16::zeroed();
684         assert_eq!(val.into_raw(), 0x0);
685 
686         val = val.with_field_0(true);
687         assert!(val.field_0().into_bool());
688         assert_eq!(val.into_raw(), 0x1);
689 
690         val = val.with_const_field_3_1::<0x5>();
691         assert_eq!(val.field_3_1(), 0x5);
692         assert_eq!(val.into_raw(), 0xB);
693 
694         val = val.with_const_field_7_4::<0xA>();
695         assert_eq!(val.field_7_4(), 0xA);
696         assert_eq!(val.into_raw(), 0xAB);
697 
698         val = val.with_const_field_15_8::<0x42>();
699         assert_eq!(val.field_15_8(), 0x42);
700         assert_eq!(val.into_raw(), 0x42AB);
701 
702         // `TestU8`.
703         let mut val = TestU8::zeroed();
704         assert_eq!(val.into_raw(), 0x0);
705 
706         val = val.with_field_0(true);
707         assert!(val.field_0().into_bool());
708         assert_eq!(val.into_raw(), 0x1);
709 
710         val = val.with_field_1(true);
711         assert!(val.field_1().into_bool());
712         assert_eq!(val.into_raw(), 0x3);
713 
714         val = val.with_const_field_3_2::<0x3>();
715         assert_eq!(val.field_3_2(), 0x3);
716         assert_eq!(val.into_raw(), 0xF);
717 
718         val = val.with_const_field_7_4::<0xA>();
719         assert_eq!(val.field_7_4(), 0xA);
720         assert_eq!(val.into_raw(), 0xAF);
721     }
722 
723     // `=>` infallible conversion.
724     #[test]
725     fn test_infallible_conversion() {
726         let mut val = TestU16::zeroed();
727 
728         val = val.with_field_5_4(Priority::Low);
729         assert_eq!(val.field_5_4(), Priority::Low);
730         assert_eq!(val.into_raw() & 0x30, 0x00);
731 
732         val = val.with_field_5_4(Priority::Medium);
733         assert_eq!(val.field_5_4(), Priority::Medium);
734         assert_eq!(val.into_raw() & 0x30, 0x10);
735 
736         val = val.with_field_5_4(Priority::High);
737         assert_eq!(val.field_5_4(), Priority::High);
738         assert_eq!(val.into_raw() & 0x30, 0x20);
739 
740         val = val.with_field_5_4(Priority::Critical);
741         assert_eq!(val.field_5_4(), Priority::Critical);
742         assert_eq!(val.into_raw() & 0x30, 0x30);
743     }
744 
745     // `?=>` fallible conversion.
746     #[test]
747     fn test_fallible_conversion() {
748         let mut val = TestU64::zeroed();
749 
750         val = val.with_field_15_12(MemoryType::Unmapped);
751         assert_eq!(val.field_15_12(), Ok(MemoryType::Unmapped));
752         val = val.with_field_15_12(MemoryType::Normal);
753         assert_eq!(val.field_15_12(), Ok(MemoryType::Normal));
754         val = val.with_field_15_12(MemoryType::Device);
755         assert_eq!(val.field_15_12(), Ok(MemoryType::Device));
756         val = val.with_field_15_12(MemoryType::Reserved);
757         assert_eq!(val.field_15_12(), Ok(MemoryType::Reserved));
758 
759         // `field_15_12` is 4 bits wide (0-15); `MemoryType` only covers 0-3, so 4-15 return `Err`.
760         let raw = (val.into_raw() & !::kernel::bits::genmask_u64(12..=15)) | (0x7 << 12);
761         assert_eq!(TestU64::from_raw(raw).field_15_12(), Err(0x7));
762     }
763 
764     // Test that setting an overlapping field affects the overlapped one as expected.
765     #[test]
766     fn test_overlapping_fields() {
767         let mut val = TestU16::zeroed();
768 
769         val = val.with_field_5_4(Priority::High); // High == 2 == 0b10.
770         assert_eq!(val.field_5_4(), Priority::High);
771         assert_eq!(val.field_7_4(), 0x2); // Bits 7:6 == 0, bits 5:4 == 0b10.
772 
773         val = val.with_const_field_7_4::<0xF>();
774         assert_eq!(val.field_7_4(), 0xF);
775         assert_eq!(val.field_5_4(), Priority::Critical); // Bits 5:4 == 0b11.
776 
777         // `field_7_0` should encompass all other fields.
778         let mut val = TestU8::zeroed()
779             .with_field_0(true)
780             .with_field_1(true)
781             .with_const_field_3_2::<0x3>()
782             .with_const_field_7_4::<0xA>();
783         assert_eq!(val.into_raw(), 0xAF);
784 
785         val = val.with_field_7_0(0x55);
786         assert_eq!(val.field_7_0(), 0x55);
787         assert!(val.field_0().into_bool());
788         assert!(!val.field_1().into_bool());
789         assert_eq!(val.field_3_2(), 0x1);
790         assert_eq!(val.field_7_4(), 0x5);
791     }
792 
793     // Checks that bits not mapped to any field are left untouched.
794     #[test]
795     fn test_unallocated_bits() {
796         let gap_bits = (1u64 << 62) | 0x1FC;
797 
798         let set_all_fields = |val: TestU64| {
799             val.with_field_63(true)
800                 .with_const_field_61_52::<0x155>()
801                 .with_const_field_51_16::<0x123456>()
802                 .with_field_15_12(MemoryType::Device)
803                 .with_const_field_11_9::<0x5>()
804                 .with_field_1(true)
805                 .with_field_0(true)
806         };
807 
808         // Gap bits to 0.
809         let val = set_all_fields(TestU64::from_raw(0));
810         assert_eq!(val.into_raw() & gap_bits, 0);
811 
812         // Gap bits to 1.
813         let val = set_all_fields(TestU64::from_raw(gap_bits));
814         assert_eq!(val.into_raw() & gap_bits, gap_bits);
815     }
816 
817     #[test]
818     fn test_try_with() {
819         let val = TestU64::zeroed().try_with_field_51_16(0x123456).unwrap();
820         assert_eq!(val.field_51_16(), 0x123456);
821 
822         let err = TestU64::zeroed().try_with_field_51_16(u64::MAX);
823         assert_eq!(err, Err(::kernel::error::code::EOVERFLOW));
824 
825         let val = TestU64::zeroed()
826             .try_with_field_51_16(0xABCDEF)
827             .and_then(|p| p.try_with_field_0(1))
828             .unwrap();
829         assert_eq!(val.field_51_16(), 0xABCDEF);
830         assert!(val.field_0().into_bool());
831     }
832 
833     // `from_raw`/`into_raw` and `From`/`Into` round-trips.
834     #[test]
835     fn test_raw() {
836         let raw: u64 = 0xBFF0_0000_3123_3E03;
837         let val = TestU64::from_raw(raw);
838         assert_eq!(u64::from(val), raw);
839         assert!(val.field_0().into_bool());
840         assert!(val.field_1().into_bool());
841         assert_eq!(val.field_11_9(), 0x7);
842         assert_eq!(val.field_51_16(), 0x3123);
843         assert_eq!(val.field_15_12(), Ok(MemoryType::Reserved));
844         assert_eq!(val.field_61_52(), 0x3FF);
845         assert!(val.field_63().into_bool());
846 
847         let raw: u16 = 0x42AB;
848         let val = TestU16::from_raw(raw);
849         assert_eq!(u16::from(val), raw);
850         assert!(val.field_0().into_bool());
851         assert_eq!(val.field_3_1(), 0x5);
852         assert_eq!(val.field_7_4(), 0xA);
853         assert_eq!(val.field_15_8(), 0x42);
854 
855         let raw: u8 = 0xAF;
856         let val = TestU8::from_raw(raw);
857         assert_eq!(u8::from(val), raw);
858         assert!(val.field_0().into_bool());
859         assert!(val.field_1().into_bool());
860         assert_eq!(val.field_3_2(), 0x3);
861         assert_eq!(val.field_7_4(), 0xA);
862         assert_eq!(val.field_7_0(), 0xAF);
863     }
864 }
865