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            #[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)]
552mod 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}