Skip to main content

kernel/
bitfield.rs

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