// SPDX-License-Identifier: GPL-2.0 //! Support for defining bitfields as Rust structures.//!//! The [`bitfield!`](kernel::bitfield!) macro declares integer types that are split into distinct//! bit fields of arbitrary length. Each field is typed using [`Bounded`](kernel::num::Bounded) to//! ensure values are properly validated and to avoid implicit data loss.//!//! # Example//!//! ```rust//! use kernel::bitfield;//! use kernel::num::Bounded;//!//! bitfield! {//! pub struct Rgb(u16) {//! 15:11 blue;//! 10:5 green;//! 4:0 red;//! }//! }//!//! // Valid value for the `blue` field.//! let blue = Bounded::<u16, 5>::new::<0x18>();//!//! // Setters can be chained. Values ranges are checked at compile-time.//! let color = Rgb::zeroed()//! // Compile-time bounds check of constant value.//! .with_const_red::<0x10>()//! .with_const_green::<0x1f>()//! // A `Bounded` can also be passed.//! .with_blue(blue);//!//! assert_eq!(color.red(), 0x10);//! assert_eq!(color.green(), 0x1f);//! assert_eq!(color.blue(), 0x18);//! assert_eq!(//! color.into_raw(),//! (0x18 << Rgb::BLUE_SHIFT) + (0x1f << Rgb::GREEN_SHIFT) + 0x10,//! );//!//! // Convert to/from the backing storage type.//! let raw: u16 = color.into();//! assert_eq!(Rgb::from(raw), color);//! ```//!//! # Syntax//!//! ```text//! bitfield! {//! #[attributes]//! // Documentation for `Name`.//! pub struct Name(storage_type) {//! // `field_1` documentation.//! hi:lo field_1;//! // `field_2` documentation.//! hi:lo field_2 => ConvertedType;//! // `field_3` documentation.//! hi:lo field_3 ?=> ConvertedType;//! ...//! }//! }//! ```//!//! - `storage_type`: The underlying unsigned integer type ([`u8`], [`u16`], [`u32`], [`u64`]).//! Signed integer storage types are not supported.//! - `hi:lo`: Bit range (inclusive), where `hi >= lo`.//! - `=> Type`: Optional infallible conversion (see [below](#infallible-conversion-)).//! - `?=> Type`: Optional fallible conversion (see [below](#fallible-conversion-)).//! - Documentation strings and attributes are optional.//!//! # Generated code//!//! Each field is internally represented as a [`Bounded`] parameterized by its bit width. Field//! values can either be set/retrieved directly, or converted from/to another type.//!//! The use of [`Bounded`] for each field enforces bounds-checking (at build time or runtime) of//! every value assigned to a field. This ensures that data is never accidentally truncated.//!//! The macro generates the bitfield type, [`From`] and [`Into`] implementations for its storage//! type, as well as [`Debug`] and [`Zeroable`](pin_init::Zeroable) implementations.//!//! For each field, it also generates://!//! - `field()`: Getter method for the field value.//! - `with_field(value)`: Infallible setter; the argument type must fit within the field's width.//! - `with_const_field::<VALUE>()`: `const` setter; the value is validated at compile time.//! Usually shorter to use than `with_field` for constant values as it doesn't require//! constructing a [`Bounded`].//! - `try_with_field(value)`: Fallible setter. Returns an error if the value is out of range.//! - `FIELD_MASK`, `FIELD_SHIFT`, `FIELD_RANGE`: Constants for manual bit manipulation.//!//! # Reserved names for field identifiers//!//! Field identifiers are used to generate methods and associated constants on the bitfield type.//! For a field named `field`, the macro may generate methods named `field`, `with_field`,//! `with_const_field`, `try_with_field`, `__field` and `__with_field`, as well as constants named//! `FIELD_MASK`, `FIELD_SHIFT` and `FIELD_RANGE`.//!//! Therefore, field identifiers must not use names that would collide with generated items for//! any field in the same bitfield. The following prefixes are thus reserved for field identifiers://!//! - `with_`//! - `const_`//! - `try_with_`//! - `__`//!//! The field identifiers `from_raw`, `into_raw`, and `into` are also reserved.//!//! In addition, field identifiers should follow Rust `snake_case` conventions, since the associated//! constants are generated by uppercasing the field name.//!//! # Implicit conversions//!//! Types that fit entirely within a field's bit width can be used directly with setters. For//! example, [`bool`] works with single-bit fields, and [`u8`] works with 8-bit fields://!//! ```rust//! use kernel::bitfield;//!//! bitfield! {//! pub struct Flags(u32) {//! 15:8 byte_field;//! 0:0 flag;//! }//! }//!//! let flags = Flags::zeroed()//! .with_byte_field(0x42_u8)//! .with_flag(true);//!//! assert_eq!(flags.into_raw(), (0x42 << Flags::BYTE_FIELD_SHIFT) | 1);//! ```//!//! # Runtime bounds checking//!//! When a value is not known at compile time, use `try_with_field()` to check bounds at runtime://!//! ```rust//! use kernel::bitfield;//!//! bitfield! {//! pub struct Config(u8) {//! 3:0 nibble;//! }//! }//!//! fn set_nibble(config: Config, value: u8) -> Result<Config, Error> {//! // Returns `EOVERFLOW` if `value > 0xf`.//! config.try_with_nibble(value)//! }//! # Ok::<(), Error>(())//! ```//!//! # Type conversion//!//! Fields can be automatically converted to/from a custom type using `=>` (infallible) or `?=>`//! (fallible). The custom type must implement the appropriate [`From`] or [`TryFrom`] traits with//! [`Bounded`].//!//! ## Infallible conversion (`=>`)//!//! Use this when all possible bit patterns of a field map to valid values://!//! ```rust//! use kernel::bitfield;//! use kernel::num::Bounded;//!//! #[derive(Debug, Clone, Copy, PartialEq)]//! enum Power {//! Off,//! On,//! }//!//! impl From<Bounded<u32, 1>> for Power {//! fn from(v: Bounded<u32, 1>) -> Self {//! match *v {//! 0 => Power::Off,//! _ => Power::On,//! }//! }//! }//!//! impl From<Power> for Bounded<u32, 1> {//! fn from(p: Power) -> Self {//! (p as u32 != 0).into()//! }//! }//!//! bitfield! {//! pub struct Control(u32) {//! 0:0 power => Power;//! }//! }//!//! let ctrl = Control::zeroed().with_power(Power::On);//! assert_eq!(ctrl.power(), Power::On);//! ```//!//! ## Fallible conversion (`?=>`)//!//! Use this when some bit patterns of a field are invalid. The getter returns a [`Result`]://!//! ```rust//! use kernel::bitfield;//! use kernel::num::Bounded;//!//! #[derive(Debug, Clone, Copy, PartialEq)]//! enum Mode {//! Low = 0,//! High = 1,//! Auto = 2,//! // 3 is invalid//! }//!//! impl TryFrom<Bounded<u32, 2>> for Mode {//! type Error = u32;//!//! fn try_from(v: Bounded<u32, 2>) -> Result<Self, u32> {//! match *v {//! 0 => Ok(Mode::Low),//! 1 => Ok(Mode::High),//! 2 => Ok(Mode::Auto),//! n => Err(n),//! }//! }//! }//!//! impl From<Mode> for Bounded<u32, 2> {//! fn from(m: Mode) -> Self {//! match m {//! Mode::Low => Bounded::<u32, _>::new::<0>(),//! Mode::High => Bounded::<u32, _>::new::<1>(),//! Mode::Auto => Bounded::<u32, _>::new::<2>(),//! }//! }//! }//!//! bitfield! {//! pub struct Config(u32) {//! 1:0 mode ?=> Mode;//! }//! }//!//! let cfg = Config::zeroed().with_mode(Mode::Auto);//! assert_eq!(cfg.mode(), Ok(Mode::Auto));//!//! // Invalid bit pattern returns an error.//! assert_eq!(Config::from(0b11).mode(), Err(3));//! ```//!//! # Bits outside of declared fields//!//! Bits of the storage type that are not part of any declared field are preserved by the setter//! methods, and can only be modified through `from_raw` or the [`From`] implementation from the//! storage type.//!//! ```rust//! use kernel::bitfield;//!//! bitfield! {//! pub struct Sparse(u8) {//! 7:6 high;//! // Bits 5:1 are not covered by any field.//! 0:0 low;//! }//! }//!//! // Set the gap bits via `from_raw`, then mutate the declared fields.//! let val = Sparse::from_raw(0b0010_1010)//! .with_const_high::<0b11>()//! .with_low(true);//!//! // Bits 5:1 are unchanged.//! assert_eq!(val.into_raw(), 0b1110_1011);//! ```//!//! # Signed field values//!//! Bitfield storage types are unsigned. Since field getter methods return a [`Bounded`] of the//! storage type, fields are also unsigned by default.//!//! If a field needs to encode a signed value, use a custom conversion type with `=>` or `?=>` to//! perform the sign interpretation explicitly.//!//! [`Bounded`]: kernel::num::Bounded /// Defines a bitfield struct with bounds-checked accessors for individual bit ranges.////// See the [`mod@kernel::bitfield`] module for full documentation and examples.#[macro_export]macro_rules! bitfield { // Entry point defining the bitfield struct, its implementations and its field accessors. ( $(#[$attr:meta])* $vis:vis struct $name:ident($storage:ty) { $($fields:tt)* } ) => { $crate::bitfield!(@core #[allow(non_camel_case_types)] $(#[$attr])* $vis $name $storage ); $crate::bitfield!(@fields $vis $name $storage { $($fields)* }); }; // All rules below are helpers. // Defines the wrapper `$name` type and its conversions from/to the storage type. (@core $(#[$attr:meta])* $vis:vis $name:ident $storage:ty) => { $(#[$attr])* #[repr(transparent)] #[derive(Clone, Copy, PartialEq, Eq)] $vis struct $name { inner: $storage, } #[allow(dead_code)] impl $name { /// Creates a bitfield from a raw value. #[inline(always)] $vis const fn from_raw(value: $storage) -> Self { Self{ inner: value } } /// Turns this bitfield into its raw value. /// /// This is similar to the [`From`] implementation, but is shorter to invoke in /// most cases. #[inline(always)] $vis const fn into_raw(self) -> $storage { self.inner } } // SAFETY: `$storage` is `Zeroable` and `$name` is transparent. unsafe impl ::pin_init::Zeroable for $name {} impl ::core::convert::From<$name> for $storage { #[inline(always)] fn from(val: $name) -> $storage { val.into_raw() } } impl ::core::convert::From<$storage> for $name { #[inline(always)] fn from(val: $storage) -> $name { Self::from_raw(val) } } }; // Definitions requiring knowledge of individual fields: private and public field accessors, // and `Debug` implementation. (@fields $vis:vis $name:ident $storage:ty { $($(#[doc = $doc:expr])* $hi:literal:$lo:literal $field:ident $(?=> $try_into_type:ty)? $(=> $into_type:ty)? ; )* } ) => { #[allow(dead_code)] impl $name { $( $crate::bitfield!(@private_field_accessors $vis $name $storage : $hi:$lo $field); $crate::bitfield!( @public_field_accessors $(#[doc = $doc])* $vis $name $storage : $hi:$lo $field $(?=> $try_into_type)? $(=> $into_type)? ); )* } $crate::bitfield!(@debug $name { $($field;)* }); }; // Private field accessors working with the exact `Bounded` type for the field. ( @private_field_accessors $vis:vis $name:ident $storage:ty : $hi:tt:$lo:tt $field:ident ) => { ::kernel::macros::paste!( $vis const [<$field:upper _RANGE>]: ::core::ops::RangeInclusive<u8> = $lo..=$hi; $vis const [<$field:upper _MASK>]: $storage = ((((1 << $hi) - 1) << 1) + 1) - ((1 << $lo) - 1); $vis const [<$field:upper _SHIFT>]: u32 = $lo; ); ::kernel::macros::paste!( #[inline(always)] fn [<__ $field>](self) -> ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> { // Left shift to align the field's MSB with the storage MSB. const ALIGN_TOP: u32 = $storage::BITS - ($hi + 1); // Right shift to move the top-aligned field to bit 0 of the storage. const ALIGN_BOTTOM: u32 = ALIGN_TOP + $lo; // Extract the field using two shifts. `Bounded::shr` produces the correctly-sized // output type. let val = ::kernel::num::Bounded::<$storage, { $storage::BITS }>::from( self.inner << ALIGN_TOP ); val.shr::<ALIGN_BOTTOM, { $hi + 1 - $lo } >() } #[inline(always)] const fn [<__with_ $field>]( mut self, value: ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>, ) -> Self { const MASK: $storage = <$name>::[<$field:upper _MASK>]; const SHIFT: u32 = <$name>::[<$field:upper _SHIFT>]; let value = value.get() << SHIFT; self.inner = (self.inner & !MASK) | value; self } ); }; // Public accessors for fields infallibly (`=>`) converted to a type. ( @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty : $hi:literal:$lo:literal $field:ident => $into_type:ty ) => { ::kernel::macros::paste!( $(#[doc = $doc])* #[doc = "Returns the value of this field."] #[inline(always)] $vis fn $field(self) -> $into_type { self.[<__ $field>]().into() } $(#[doc = $doc])* #[doc = "Sets this field to the given `value`."] #[inline(always)] $vis fn [<with_ $field>](self, value: $into_type) -> Self { self.[<__with_ $field>](value.into()) } ); }; // Public accessors for fields fallibly (`?=>`) converted to a type. ( @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty : $hi:tt:$lo:tt $field:ident ?=> $try_into_type:ty ) => { ::kernel::macros::paste!( $(#[doc = $doc])* #[doc = "Returns the value of this field."] #[inline(always)] $vis fn $field(self) -> ::core::result::Result< $try_into_type, <$try_into_type as ::core::convert::TryFrom< ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> >>::Error > { self.[<__ $field>]().try_into() } $(#[doc = $doc])* #[doc = "Sets this field to the given `value`."] #[inline(always)] $vis fn [<with_ $field>](self, value: $try_into_type) -> Self { self.[<__with_ $field>](value.into()) } ); }; // Public accessors for fields not converted to a type. ( @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty : $hi:tt:$lo:tt $field:ident ) => { ::kernel::macros::paste!( $(#[doc = $doc])* #[doc = "Returns the value of this field."] #[inline(always)] $vis fn $field(self) -> ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> { self.[<__ $field>]() } $(#[doc = $doc])* #[doc = "Sets this field to the compile-time constant `VALUE`."] #[inline(always)] $vis const fn [<with_const_ $field>]<const VALUE: $storage>(self) -> Self { self.[<__with_ $field>]( ::kernel::num::Bounded::<$storage, { $hi + 1 - $lo }>::new::<VALUE>()Lines 1–500 of 863. Load more
// SPDX-License-Identifier: GPL-2.0 //! Support for defining bitfields as Rust structures. //! //! The [`bitfield!`](kernel::bitfield!) macro declares integer types that are split into distinct //! bit fields of arbitrary length. Each field is typed using [`Bounded`](kernel::num::Bounded) to //! ensure values are properly validated and to avoid implicit data loss. //! //! # Example //! //! ```rust //! use kernel::bitfield; //! use kernel::num::Bounded; //! //! bitfield! { //! pub struct Rgb(u16) { //! 15:11 blue; //! 10:5 green; //! 4:0 red; //! } //! } //! //! // Valid value for the `blue` field. //! let blue = Bounded::<u16, 5>::new::<0x18>(); //! //! // Setters can be chained. Values ranges are checked at compile-time. //! let color = Rgb::zeroed() //! // Compile-time bounds check of constant value. //! .with_const_red::<0x10>() //! .with_const_green::<0x1f>() //! // A `Bounded` can also be passed. //! .with_blue(blue); //! //! assert_eq!(color.red(), 0x10); //! assert_eq!(color.green(), 0x1f); //! assert_eq!(color.blue(), 0x18); //! assert_eq!( //! color.into_raw(), //! (0x18 << Rgb::BLUE_SHIFT) + (0x1f << Rgb::GREEN_SHIFT) + 0x10, //! ); //! //! // Convert to/from the backing storage type. //! let raw: u16 = color.into(); //! assert_eq!(Rgb::from(raw), color); //! ``` //! //! # Syntax //! //! ```text //! bitfield! { //! #[attributes] //! // Documentation for `Name`. //! pub struct Name(storage_type) { //! // `field_1` documentation. //! hi:lo field_1; //! // `field_2` documentation. //! hi:lo field_2 => ConvertedType; //! // `field_3` documentation. //! hi:lo field_3 ?=> ConvertedType; //! ... //! } //! } //! ``` //! //! - `storage_type`: The underlying unsigned integer type ([`u8`], [`u16`], [`u32`], [`u64`]). //! Signed integer storage types are not supported. //! - `hi:lo`: Bit range (inclusive), where `hi >= lo`. //! - `=> Type`: Optional infallible conversion (see [below](#infallible-conversion-)). //! - `?=> Type`: Optional fallible conversion (see [below](#fallible-conversion-)). //! - Documentation strings and attributes are optional. //! //! # Generated code //! //! Each field is internally represented as a [`Bounded`] parameterized by its bit width. Field //! values can either be set/retrieved directly, or converted from/to another type. //! //! The use of [`Bounded`] for each field enforces bounds-checking (at build time or runtime) of //! every value assigned to a field. This ensures that data is never accidentally truncated. //! //! The macro generates the bitfield type, [`From`] and [`Into`] implementations for its storage //! type, as well as [`Debug`] and [`Zeroable`](pin_init::Zeroable) implementations. //! //! For each field, it also generates: //! //! - `field()`: Getter method for the field value. //! - `with_field(value)`: Infallible setter; the argument type must fit within the field's width. //! - `with_const_field::<VALUE>()`: `const` setter; the value is validated at compile time. //! Usually shorter to use than `with_field` for constant values as it doesn't require //! constructing a [`Bounded`]. //! - `try_with_field(value)`: Fallible setter. Returns an error if the value is out of range. //! - `FIELD_MASK`, `FIELD_SHIFT`, `FIELD_RANGE`: Constants for manual bit manipulation. //! //! # Reserved names for field identifiers //! //! Field identifiers are used to generate methods and associated constants on the bitfield type. //! For a field named `field`, the macro may generate methods named `field`, `with_field`, //! `with_const_field`, `try_with_field`, `__field` and `__with_field`, as well as constants named //! `FIELD_MASK`, `FIELD_SHIFT` and `FIELD_RANGE`. //! //! Therefore, field identifiers must not use names that would collide with generated items for //! any field in the same bitfield. The following prefixes are thus reserved for field identifiers: //! //! - `with_` //! - `const_` //! - `try_with_` //! - `__` //! //! The field identifiers `from_raw`, `into_raw`, and `into` are also reserved. //! //! In addition, field identifiers should follow Rust `snake_case` conventions, since the associated //! constants are generated by uppercasing the field name. //! //! # Implicit conversions //! //! Types that fit entirely within a field's bit width can be used directly with setters. For //! example, [`bool`] works with single-bit fields, and [`u8`] works with 8-bit fields: //! //! ```rust //! use kernel::bitfield; //! //! bitfield! { //! pub struct Flags(u32) { //! 15:8 byte_field; //! 0:0 flag; //! } //! } //! //! let flags = Flags::zeroed() //! .with_byte_field(0x42_u8) //! .with_flag(true); //! //! assert_eq!(flags.into_raw(), (0x42 << Flags::BYTE_FIELD_SHIFT) | 1); //! ``` //! //! # Runtime bounds checking //! //! When a value is not known at compile time, use `try_with_field()` to check bounds at runtime: //! //! ```rust //! use kernel::bitfield; //! //! bitfield! { //! pub struct Config(u8) { //! 3:0 nibble; //! } //! } //! //! fn set_nibble(config: Config, value: u8) -> Result<Config, Error> { //! // Returns `EOVERFLOW` if `value > 0xf`. //! config.try_with_nibble(value) //! } //! # Ok::<(), Error>(()) //! ``` //! //! # Type conversion //! //! Fields can be automatically converted to/from a custom type using `=>` (infallible) or `?=>` //! (fallible). The custom type must implement the appropriate [`From`] or [`TryFrom`] traits with //! [`Bounded`]. //! //! ## Infallible conversion (`=>`) //! //! Use this when all possible bit patterns of a field map to valid values: //! //! ```rust //! use kernel::bitfield; //! use kernel::num::Bounded; //! //! #[derive(Debug, Clone, Copy, PartialEq)] //! enum Power { //! Off, //! On, //! } //! //! impl From<Bounded<u32, 1>> for Power { //! fn from(v: Bounded<u32, 1>) -> Self { //! match *v { //! 0 => Power::Off, //! _ => Power::On, //! } //! } //! } //! //! impl From<Power> for Bounded<u32, 1> { //! fn from(p: Power) -> Self { //! (p as u32 != 0).into() //! } //! } //! //! bitfield! { //! pub struct Control(u32) { //! 0:0 power => Power; //! } //! } //! //! let ctrl = Control::zeroed().with_power(Power::On); //! assert_eq!(ctrl.power(), Power::On); //! ``` //! //! ## Fallible conversion (`?=>`) //! //! Use this when some bit patterns of a field are invalid. The getter returns a [`Result`]: //! //! ```rust //! use kernel::bitfield; //! use kernel::num::Bounded; //! //! #[derive(Debug, Clone, Copy, PartialEq)] //! enum Mode { //! Low = 0, //! High = 1, //! Auto = 2, //! // 3 is invalid //! } //! //! impl TryFrom<Bounded<u32, 2>> for Mode { //! type Error = u32; //! //! fn try_from(v: Bounded<u32, 2>) -> Result<Self, u32> { //! match *v { //! 0 => Ok(Mode::Low), //! 1 => Ok(Mode::High), //! 2 => Ok(Mode::Auto), //! n => Err(n), //! } //! } //! } //! //! impl From<Mode> for Bounded<u32, 2> { //! fn from(m: Mode) -> Self { //! match m { //! Mode::Low => Bounded::<u32, _>::new::<0>(), //! Mode::High => Bounded::<u32, _>::new::<1>(), //! Mode::Auto => Bounded::<u32, _>::new::<2>(), //! } //! } //! } //! //! bitfield! { //! pub struct Config(u32) { //! 1:0 mode ?=> Mode; //! } //! } //! //! let cfg = Config::zeroed().with_mode(Mode::Auto); //! assert_eq!(cfg.mode(), Ok(Mode::Auto)); //! //! // Invalid bit pattern returns an error. //! assert_eq!(Config::from(0b11).mode(), Err(3)); //! ``` //! //! # Bits outside of declared fields //! //! Bits of the storage type that are not part of any declared field are preserved by the setter //! methods, and can only be modified through `from_raw` or the [`From`] implementation from the //! storage type. //! //! ```rust //! use kernel::bitfield; //! //! bitfield! { //! pub struct Sparse(u8) { //! 7:6 high; //! // Bits 5:1 are not covered by any field. //! 0:0 low; //! } //! } //! //! // Set the gap bits via `from_raw`, then mutate the declared fields. //! let val = Sparse::from_raw(0b0010_1010) //! .with_const_high::<0b11>() //! .with_low(true); //! //! // Bits 5:1 are unchanged. //! assert_eq!(val.into_raw(), 0b1110_1011); //! ``` //! //! # Signed field values //! //! Bitfield storage types are unsigned. Since field getter methods return a [`Bounded`] of the //! storage type, fields are also unsigned by default. //! //! If a field needs to encode a signed value, use a custom conversion type with `=>` or `?=>` to //! perform the sign interpretation explicitly. //! //! [`Bounded`]: kernel::num::Bounded /// Defines a bitfield struct with bounds-checked accessors for individual bit ranges. /// /// See the [`mod@kernel::bitfield`] module for full documentation and examples. #[macro_export] macro_rules! bitfield { // Entry point defining the bitfield struct, its implementations and its field accessors. ( $(#[$attr:meta])* $vis:vis struct $name:ident($storage:ty) { $($fields:tt)* } ) => { $crate::bitfield!(@core #[allow(non_camel_case_types)] $(#[$attr])* $vis $name $storage ); $crate::bitfield!(@fields $vis $name $storage { $($fields)* }); }; // All rules below are helpers. // Defines the wrapper `$name` type and its conversions from/to the storage type. (@core $(#[$attr:meta])* $vis:vis $name:ident $storage:ty) => { $(#[$attr])* #[repr(transparent)] #[derive(Clone, Copy, PartialEq, Eq)] $vis struct $name { inner: $storage, } #[allow(dead_code)] impl $name { /// Creates a bitfield from a raw value. #[inline(always)] $vis const fn from_raw(value: $storage) -> Self { Self{ inner: value } } /// Turns this bitfield into its raw value. /// /// This is similar to the [`From`] implementation, but is shorter to invoke in /// most cases. #[inline(always)] $vis const fn into_raw(self) -> $storage { self.inner } } // SAFETY: `$storage` is `Zeroable` and `$name` is transparent. unsafe impl ::pin_init::Zeroable for $name {} impl ::core::convert::From<$name> for $storage { #[inline(always)] fn from(val: $name) -> $storage { val.into_raw() } } impl ::core::convert::From<$storage> for $name { #[inline(always)] fn from(val: $storage) -> $name { Self::from_raw(val) } } }; // Definitions requiring knowledge of individual fields: private and public field accessors, // and `Debug` implementation. (@fields $vis:vis $name:ident $storage:ty { $($(#[doc = $doc:expr])* $hi:literal:$lo:literal $field:ident $(?=> $try_into_type:ty)? $(=> $into_type:ty)? ; )* } ) => { #[allow(dead_code)] impl $name { $( $crate::bitfield!(@private_field_accessors $vis $name $storage : $hi:$lo $field); $crate::bitfield!( @public_field_accessors $(#[doc = $doc])* $vis $name $storage : $hi:$lo $field $(?=> $try_into_type)? $(=> $into_type)? ); )* } $crate::bitfield!(@debug $name { $($field;)* }); }; // Private field accessors working with the exact `Bounded` type for the field. ( @private_field_accessors $vis:vis $name:ident $storage:ty : $hi:tt:$lo:tt $field:ident ) => { ::kernel::macros::paste!( $vis const [<$field:upper _RANGE>]: ::core::ops::RangeInclusive<u8> = $lo..=$hi; $vis const [<$field:upper _MASK>]: $storage = ((((1 << $hi) - 1) << 1) + 1) - ((1 << $lo) - 1); $vis const [<$field:upper _SHIFT>]: u32 = $lo; ); ::kernel::macros::paste!( #[inline(always)] fn [<__ $field>](self) -> ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> { // Left shift to align the field's MSB with the storage MSB. const ALIGN_TOP: u32 = $storage::BITS - ($hi + 1); // Right shift to move the top-aligned field to bit 0 of the storage. const ALIGN_BOTTOM: u32 = ALIGN_TOP + $lo; // Extract the field using two shifts. `Bounded::shr` produces the correctly-sized // output type. let val = ::kernel::num::Bounded::<$storage, { $storage::BITS }>::from( self.inner << ALIGN_TOP ); val.shr::<ALIGN_BOTTOM, { $hi + 1 - $lo } >() } #[inline(always)] const fn [<__with_ $field>]( mut self, value: ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>, ) -> Self { const MASK: $storage = <$name>::[<$field:upper _MASK>]; const SHIFT: u32 = <$name>::[<$field:upper _SHIFT>]; let value = value.get() << SHIFT; self.inner = (self.inner & !MASK) | value; self } ); }; // Public accessors for fields infallibly (`=>`) converted to a type. ( @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty : $hi:literal:$lo:literal $field:ident => $into_type:ty ) => { ::kernel::macros::paste!( $(#[doc = $doc])* #[doc = "Returns the value of this field."] #[inline(always)] $vis fn $field(self) -> $into_type { self.[<__ $field>]().into() } $(#[doc = $doc])* #[doc = "Sets this field to the given `value`."] #[inline(always)] $vis fn [<with_ $field>](self, value: $into_type) -> Self { self.[<__with_ $field>](value.into()) } ); }; // Public accessors for fields fallibly (`?=>`) converted to a type. ( @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty : $hi:tt:$lo:tt $field:ident ?=> $try_into_type:ty ) => { ::kernel::macros::paste!( $(#[doc = $doc])* #[doc = "Returns the value of this field."] #[inline(always)] $vis fn $field(self) -> ::core::result::Result< $try_into_type, <$try_into_type as ::core::convert::TryFrom< ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> >>::Error > { self.[<__ $field>]().try_into() } $(#[doc = $doc])* #[doc = "Sets this field to the given `value`."] #[inline(always)] $vis fn [<with_ $field>](self, value: $try_into_type) -> Self { self.[<__with_ $field>](value.into()) } ); }; // Public accessors for fields not converted to a type. ( @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty : $hi:tt:$lo:tt $field:ident ) => { ::kernel::macros::paste!( $(#[doc = $doc])* #[doc = "Returns the value of this field."] #[inline(always)] $vis fn $field(self) -> ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> { self.[<__ $field>]() } $(#[doc = $doc])* #[doc = "Sets this field to the compile-time constant `VALUE`."] #[inline(always)] $vis const fn [<with_const_ $field>]<const VALUE: $storage>(self) -> Self { self.[<__with_ $field>]( ::kernel::num::Bounded::<$storage, { $hi + 1 - $lo }>::new::<VALUE>()