mycelium_bitfield/
bitfield.rs

1/// Generates a typed bitfield struct.
2///
3/// By default, the [`fmt::Debug`], [`fmt::Display`], [`fmt::Binary`], [`Copy`],
4/// and [`Clone`] traits are automatically derived for bitfields.
5///
6/// All bitfield types are [`#[repr(transparent)]`][transparent].
7///
8/// For a complete example of the methods generated by the `bitfield!` macro,
9/// see the [`example`] module's [`ExampleBitfield`] type.
10///
11/// # Generated Implementations
12///
13/// The `bitfield!` macro generates a type with the following functions, where
14/// `{int}` is the integer type that represents the bitfield (one of [`u8`],
15/// [`u16`], [`u32`], [`u64`], [`u128`], or [`usize`]):
16///
17/// - `const fn new() -> Self`: Returns a new instance of the bitfield type with
18///   all bits zeroed.
19/// - `const fn from_bits(bits: {int}) -> Self`: Converts an `{int}` into an
20///   instance of the bitfield type.
21/// - `const fn bits(self) -> {int}`: Returns this bitfield's bits as a raw
22///   integer value.
23/// - `fn with<U>(self, packer: Self::Packer<U>, value: U) -> Self`: Given one
24///   of this type's generated packing specs for a `U`-typed value, and a
25///   `U`-typed value, returns a new instance of `Self` with the bit
26///   representation of `value` packed into the range represented by `packer`.
27/// - `fn set<U>(&mut self, packer: Self::Packer<U>, value: U) -> &mut Self`:
28///   Similar to `with`, except `self` is mutated in place, rather than
29///   returning a new  nstance of `Self`
30/// - `fn get<U>(&self, packer: Self::Packer<U>) -> U`: Given one of this type's
31///   generated packing specs for a `U`-typed value, unpacks the bit range
32///   represented by that value as a `U` and returns it. This method panics if
33///   the requested bit range does not contain a valid bit pattern for a
34///   `U`-typed value, as determined by `U`'s implementation of the [`FromBits`]
35///   trait.
36/// - `fn try_get<U>(&self, packer: Self::Packer<U>) -> Result<U, <U as
37///   FromBits>::Error>`: Like `get`, but returns a `Result` instead of
38///   panicking.
39/// - `fn assert_valid()`: Asserts that the generated bitfield type is valid.
40///   This is primarily intended to be used in tests; the macro cannot generate
41///   tests for a bitfield type on its own, so a test that simply calls
42///   `assert_valid` can be added to check the bitfield type's validity.
43/// - `fn display_ascii(&self) -> impl core::fmt::Display`: Returns a
44///   [`fmt::Display`] implementation that formats the bitfield in a multi-line
45///   format, using only ASCII characters. See [here](#example-display-output)
46///   for examples of this format.
47/// - `fn display_unicode(&self) -> impl core::fmt::Display`: Returns a
48///   [`fmt::Display`] implementation that formats the bitfield in a multi-line
49///   format, always using Unicode box-drawing characters. See
50///   [here](#example-display-output) for examples of this format.
51///
52/// The visibility of these methods depends on the visibility of the bitfield
53/// struct --- if the struct is defined as `pub(crate) struct MyBitfield<u16> {
54/// ... }`, then these functions will all be `pub(crate)` as well.
55///
56/// If a bitfield type is defined with one visibility, but particular subfields
57/// of that bitfield should not be public, the individual fields may also have
58/// visibility specifiers. For example, if the bitfield struct `MyBitfield` is
59/// `pub`, but the subfield named `PRIVATE_SUBFIELD` is `pub(crate)`, then
60/// `my_bitfield.get(MyBitfield::PRIVATE_SUBRANGE)` can only be called inside
61/// the crate defining the type, because the `PRIVATE_SUBRANGE` constant is not
62/// publicly visible.
63///
64/// In addition to the inherent methods discussed above, the following trait
65/// implementations are always generated:
66///
67/// - [`fmt::Debug`]: The `Debug` implementation prints the bitfield as a
68///   "struct", with a "field" for each packing spec in the bitfield. If any
69///   of the bitfield's packing specs pack typed values, that type's
70///   [`fmt::Debug`] implementation is used rather than printing the value
71///   as an integer.
72/// - [`fmt::Binary`]: Prints the raw bits of this bitfield as a binary number.
73/// - [`fmt::UpperHex`] and [`fmt::LowerHex`]: Prints the raw bits of this
74///   bitfield in hexadecimal.
75/// - [`fmt::Display`]: Pretty-prints the bitfield in a very nice-looking
76///   multi-line format which I'm rather proud of. See
77///   [here](#example-display-output) for examples of this format.
78/// - [`Copy`]: Behaves identically as the [`Copy`] implementation for the
79///   underlying integer type.
80/// - [`Clone`]: Behaves identically as the [`Clone`] implementation for the
81///   underlying integer type.
82/// - [`From`]`<{int}> for Self`: Converts a raw integer value into an instance
83///   of the bitfield type. This is equivalent to calling the bitfield type's
84///   `from_bits` function.
85/// - [`From`]`<Self> for {int}`: Converts an instance of the bitfield type into
86///   a raw integer value. This is equivalent to calling the bitfield type's
87///   `bits` method.
88///
89/// Additional traits may be derived for the bitfield type, such as
90/// [`PartialEq`], [`Eq`], and [`Default`]. These traits are not automatically
91/// derived, as custom implementations may also be desired, depending on the
92/// use-case. For example, the `Default` value for a bitfield may _not_ be all
93/// zeroes.
94///
95/// # Examples
96///
97/// Basic usage:
98///
99/// ```
100/// mycelium_bitfield::bitfield! {
101///     /// Bitfield types can have doc comments.
102///     #[derive(Eq, PartialEq)] // ...and attributes
103///     pub struct MyBitfield<u16> {
104///         // Generates a packing spec named `HELLO` for the first 6
105///         // least-significant bits.
106///         pub const HELLO = 6;
107///         // Fields with names starting with `_` can be used to mark bits as
108///         // reserved.
109///         const _RESERVED = 4;
110///         // Generates a packing spec named `WORLD` for the next 3 bits.
111///         pub const WORLD = 3;
112///     }
113/// }
114///
115/// // Bitfield types can be cheaply constructed from a raw numeric
116/// // representation:
117/// let bitfield = MyBitfield::from_bits(0b10100_0011_0101);
118///
119/// // `get` methods can be used to unpack fields from a bitfield type:
120/// assert_eq!(bitfield.get(MyBitfield::HELLO), 0b11_0101);
121/// assert_eq!(bitfield.get(MyBitfield::WORLD), 0b0101);
122///
123/// // `with` methods can be used to pack bits into a bitfield type by
124/// // value:
125/// let bitfield2 = MyBitfield::new()
126///     .with(MyBitfield::HELLO, 0b11_0101)
127///     .with(MyBitfield::WORLD, 0b0101);
128///
129/// assert_eq!(bitfield, bitfield2);
130///
131/// // `set` methods can be used to mutate a bitfield type in place:
132/// let mut bitfield3 = MyBitfield::new();
133///
134/// bitfield3
135///     .set(MyBitfield::HELLO, 0b011_0101)
136///     .set(MyBitfield::WORLD, 0b0101);
137///
138/// assert_eq!(bitfield, bitfield3);
139/// ```
140///
141/// Bitfields may also contain typed values, as long as those values implement
142/// the [`FromBits`] trait. [`FromBits`] may be manually implemented, or
143/// generated automatically for `enum` types using the [`enum_from_bits!`] macro:
144///
145/// ```
146/// use mycelium_bitfield::{bitfield, enum_from_bits, FromBits};
147///
148/// // An enum type can implement the `FromBits` trait if it has a
149/// // `#[repr(uN)]` attribute.
150/// #[repr(u8)]
151/// #[derive(Debug, Eq, PartialEq)]
152/// enum MyEnum {
153///     Foo = 0b00,
154///     Bar = 0b01,
155///     Baz = 0b10,
156/// }
157///
158/// impl FromBits<u32> for MyEnum {
159///     // Two bits can represent all possible `MyEnum` values.
160///     const BITS: u32 = 2;
161///     type Error = &'static str;
162///
163///     fn try_from_bits(bits: u32) -> Result<Self, Self::Error> {
164///         match bits as u8 {
165///             bits if bits == Self::Foo as u8 => Ok(Self::Foo),
166///             bits if bits == Self::Bar as u8 => Ok(Self::Bar),
167///             bits if bits == Self::Baz as u8 => Ok(Self::Baz),
168///             _ => Err("expected one of 0b00, 0b01, or 0b10"),
169///         }
170///     }
171///
172///     fn into_bits(self) -> u32 {
173///         self as u8 as u32
174///     }
175/// }
176///
177/// // Alternatively, the `enum_from_bits!` macro can be used to
178/// // automatically generate a `FromBits` implementation for an
179/// // enum type.
180/// //
181/// // The macro will generate very similar code to the example
182/// // manual implementation above.
183/// enum_from_bits! {
184///     #[derive(Debug, Eq, PartialEq)]
185///     pub enum MyGeneratedEnum<u8> {
186///         /// Isn't this cool?
187///         Wow = 0b1001,
188///         /// It sure is! :D
189///         Whoa = 0b0110,
190///     }
191/// }
192///
193/// bitfield! {
194///     pub struct TypedBitfield<u32> {
195///         /// Use the first two bits to represent a typed `MyEnum` value.
196///         const ENUM_VALUE: MyEnum;
197///
198///         /// Typed values and untyped raw bit fields can be used in the
199///         /// same bitfield type.
200///         pub const SOME_BITS = 6;
201///
202///         /// The `FromBits` trait is also implemented for `bool`, which
203///         /// can be used to implement bitflags.
204///         pub const FLAG_1: bool;
205///         pub const FLAG_2: bool;
206///
207///         /// `FromBits` is also implemented by (signed and unsigned) integer
208///         /// types. This will allow the next 8 bits to be treated as a `u8`.
209///         pub const A_BYTE: u8;
210///
211///         /// We can also use the automatically generated enum:
212///         pub const OTHER_ENUM: MyGeneratedEnum;
213///     }
214/// }
215///
216/// // Unpacking a typed value with `get` will return that value, or panic if
217/// // the bit pattern is invalid:
218/// let my_bitfield = TypedBitfield::from_bits(0b0010_0100_0011_0101_1001_1110);
219///
220/// assert_eq!(my_bitfield.get(TypedBitfield::ENUM_VALUE), MyEnum::Baz);
221/// assert_eq!(my_bitfield.get(TypedBitfield::FLAG_1), true);
222/// assert_eq!(my_bitfield.get(TypedBitfield::FLAG_2), false);
223/// assert_eq!(my_bitfield.get(TypedBitfield::OTHER_ENUM), MyGeneratedEnum::Wow);
224///
225/// // The `try_get` method will return an error rather than panicking if an
226/// // invalid bit pattern is encountered:
227///
228/// let invalid = TypedBitfield::from_bits(0b0011);
229///
230/// // There is no `MyEnum` variant for 0b11.
231/// assert!(invalid.try_get(TypedBitfield::ENUM_VALUE).is_err());
232/// ```
233///
234/// Packing specs from one bitfield type may *not* be used with a different
235/// bitfield type's `get`, `set`, or `with` methods. For example, the following
236/// is a type error:
237///
238/// ```compile_fail
239/// use mycelium_bitfield::bitfield;
240///
241/// bitfield! {
242///     struct Bitfield1<u8> {
243///         pub const FOO: bool;
244///         pub const BAR: bool;
245///         pub const BAZ = 6;
246///     }
247/// }
248///
249/// bitfield! {
250///     struct Bitfield2<u8> {
251///         pub const ALICE = 2;
252///         pub const BOB = 4;
253///         pub const CHARLIE = 2;
254///     }
255/// }
256///
257///
258/// // This is a *type error*, because `Bitfield2`'s field `ALICE` cannot be
259/// // used with a `Bitfield2` value:
260/// let bits = Bitfield1::new().with(Bitfield2::ALICE, 0b11);
261/// ```
262///
263/// ## Example `Display` Output
264///
265/// Bitfields will automatically generate a pretty, multi-line [`fmt::Display`]
266/// implementation. The default [`fmt::Display`] specifier uses only ASCII
267/// characters, but when Unicode box-drawing characters are also available, the
268/// alternate (`{:#}`) [`fmt::Display`] specifier may be used to select a
269/// `Display` implementation that uses those characters, and is (in my opinion)
270/// even prettier than the default.
271///
272/// For example:
273///
274/// ```
275/// # use mycelium_bitfield::{bitfield, FromBits};
276/// #
277/// # #[repr(u8)]
278/// # #[derive(Debug, Eq, PartialEq)]
279/// # enum MyEnum {
280/// #     Foo = 0b00,
281/// #     Bar = 0b01,
282/// #     Baz = 0b10,
283/// # }
284/// #
285/// # impl FromBits<u32> for MyEnum {
286/// #     const BITS: u32 = 2;
287/// #     type Error = &'static str;
288/// #
289/// #     fn try_from_bits(bits: u32) -> Result<Self, Self::Error> {
290/// #         match bits as u8 {
291/// #             bits if bits == Self::Foo as u8 => Ok(Self::Foo),
292/// #             bits if bits == Self::Bar as u8 => Ok(Self::Bar),
293/// #             bits if bits == Self::Baz as u8 => Ok(Self::Baz),
294/// #             _ => Err("expected one of 0b00, 0b01, or 0b10"),
295/// #         }
296/// #     }
297/// #
298/// #     fn into_bits(self) -> u32 {
299/// #         self as u8 as u32
300/// #     }
301/// # }
302/// # bitfield! {
303/// #      pub struct TypedBitfield<u32> {
304/// #          const ENUM_VALUE: MyEnum;
305/// #          pub const SOME_BITS = 6;
306/// #          pub const FLAG_1: bool;
307/// #          pub const FLAG_2: bool;
308/// #          pub const A_BYTE: u8;
309/// #      }
310/// # }
311/// // Create an example bitfield.
312/// let my_bitfield = TypedBitfield::from_bits(0b0011_0101_1001_1110);
313///
314/// // The default `Display` implementation uses only ASCII characters:
315/// let formatted_ascii = format!("{my_bitfield}");
316/// let expected = r#"
317/// 00000000000000000011010110011110
318///..............................10 ENUM_VALUE: Baz
319///........................100111.. SOME_BITS: 39
320///.......................1........ FLAG_1: true
321///......................0......... FLAG_2: false
322///..............00001101.......... A_BYTE: 13
323/// "#.trim_start();
324/// assert_eq!(formatted_ascii, expected);
325///
326/// // The alternate `Display` format uses Unicode box-drawing characters,
327/// // and looks even nicer:
328/// let formatted_unicode = format!("{my_bitfield:#}");
329/// let expected = r#"
330/// 00000000000000000011010110011110
331///               └┬─────┘││└┬───┘└┤
332///                │      ││ │     └ ENUM_VALUE: Baz (10)
333///                │      ││ └────── SOME_BITS: 39 (100111)
334///                │      │└─────────── FLAG_1: true (1)
335///                │      └──────────── FLAG_2: false (0)
336///                └─────────────────── A_BYTE: 13 (00001101)
337/// "#.trim_start();
338/// assert_eq!(formatted_unicode, expected);
339/// ```
340///
341/// For situations where the use of ASCII or Unicode formats is always desired
342/// regardless of the behavior of an upstream formatter (e.g., when returning a
343/// `fmt::Display` value that doesn't know what format specifier will be used),
344/// bitfield types also generate `display_ascii()` and `display_unicode()`
345/// methods. These methods return `impl fmt::Display` values that *always*
346/// select either the ASCII or Unicode `Display` implementations explicitly,
347/// regardless of whether or not the alternate formatting specifier is used.
348///
349/// [`fmt::Debug`]: core::fmt::Debug
350/// [`fmt::Display`]: core::fmt::Display
351/// [`fmt::Binary`]: core::fmt::Binary
352/// [`fmt::UpperHex`]: core::fmt::UpperHex
353/// [`fmt::LowerHex`]: core::fmt::LowerHex
354/// [transparent]: https://doc.rust-lang.org/reference/type-layout.html#the-transparent-representation
355/// [`example`]: crate::example
356/// [`ExampleBitfield`]: crate::example::ExampleBitfield
357/// [`FromBits`]: crate::FromBits
358/// [`enum_from_bits!`]: crate::enum_from_bits!
359#[macro_export]
360macro_rules! bitfield {
361    (
362        $(#[$($meta:meta)+])*
363        $vis:vis struct $Name:ident<$T:ident> {
364            $(
365                $(#[$field_meta:meta])*
366                $field_vis:vis const $Field:ident $(: $F:ty)? $( = $val:tt)?;
367            )+
368        }
369    ) => {
370        $(#[$($meta)+])*
371        #[derive(Copy, Clone)]
372        #[repr(transparent)]
373        $vis struct $Name($T);
374
375        #[automatically_derived]
376        impl core::fmt::Debug for $Name {
377            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
378                let mut dbg = f.debug_struct(stringify!($Name));
379                $(
380                    {
381                        // skip reserved fields (names starting with `_`).
382                        //
383                        // NOTE(eliza): i hope this `if` gets const-folded...we
384                        // could probably do this in a macro and guarantee that
385                        // it happens at compile-time, but this is fine for now.
386                        if !stringify!($Field).starts_with('_') {
387                            dbg.field(stringify!($Field), &self.get(Self::$Field));
388                        }
389                    }
390                )+
391                dbg.finish()
392
393            }
394        }
395
396        // Some generated methods may not always be used, which may emit dead
397        // code warnings if the type is private.
398        #[allow(dead_code)]
399        impl $Name {
400            $crate::bitfield! { @field<$T>:
401                $(
402                    $(#[$field_meta])*
403                    $field_vis const $Field $(: $F)? $( = $val)?;
404                )+
405            }
406
407            const FIELDS: &'static [(&'static str, $crate::bitfield! { @t $T, $T, Self })] = &[$(
408                (stringify!($Field), Self::$Field.typed())
409            ),+];
410
411            /// Constructs a new instance of `Self` from the provided raw bits.
412            #[inline]
413            #[must_use]
414            $vis const fn from_bits(bits: $T) -> Self {
415                Self(bits)
416            }
417
418            /// Constructs a new instance of `Self` with all bits set to 0.
419            #[inline]
420            #[must_use]
421            // Allow "new without default", as the user may wish to derive
422            // default or provide their own implementation with different values
423            // from `new`.
424            #[allow(clippy::new_without_default)]
425            $vis const fn new() -> Self {
426                Self(0)
427            }
428
429            /// Returns the raw bit representatiion of `self` as an integer.
430            #[inline]
431            $vis const fn bits(self) -> $T {
432                self.0
433            }
434
435            /// Packs the bit representation of `value` into `self` at the bit
436            /// range designated by `field`, returning a new bitfield.
437            $vis fn with<T>(self, field: $crate::bitfield! { @t $T, T, Self }, value: T) -> Self
438            where
439                T: $crate::FromBits<$T>,
440            {
441                Self(field.pack(value, self.0))
442            }
443
444
445            /// Packs the bit representation of `value` into `self` at the range
446            /// designated by `field`, mutating `self` in place.
447            $vis fn set<T>(&mut self, field: $crate::bitfield! { @t $T, T, Self }, value: T) -> &mut Self
448            where
449                T: $crate::FromBits<$T>,
450            {
451                field.pack_into(value, &mut self.0);
452                self
453            }
454
455            /// Unpacks the bit range represented by `field` from `self`, and
456            /// converts it into a `T`-typed value.
457            ///
458            /// # Panics
459            ///
460            /// This method panics if `self` does not contain a valid bit
461            /// pattern for a `T`-typed value, as determined by `T`'s
462            /// `FromBits::try_from_bits` implementation.
463            $vis fn get<T>(self, field: $crate::bitfield! { @t $T, T, Self }) -> T
464            where
465                T: $crate::FromBits<$T>,
466            {
467                field.unpack(self.0)
468            }
469
470            /// Unpacks the bit range represented by `field`
471            /// from `self` and attempts to convert it into a `T`-typed value.
472            ///
473            /// # Returns
474            ///
475            /// - `Ok(T)` if a `T`-typed value could be constructed from the
476            ///   bits in `src`
477            /// - `Err(T::Error)` if `src` does not contain a valid bit
478            ///   pattern for a `T`-typed value, as determined by `T`'s
479            ///   [`FromBits::try_from_bits` implementation.
480            $vis fn try_get<T>(self, field: $crate::bitfield! { @t $T, T, Self }) -> Result<T, T::Error>
481            where
482                T: $crate::FromBits<$T>,
483            {
484                field.try_unpack(self.0)
485            }
486
487            /// Asserts that all the packing specs for this type are valid.
488            ///
489            /// This is intended to be used in unit tests.
490            $vis fn assert_valid() {
491                <$crate::bitfield! { @t $T, $T, Self }>::assert_all_valid(&Self::FIELDS);
492            }
493
494            /// Returns a value that formats this bitfield in a multi-line
495            /// format, using only ASCII characters.
496            ///
497            /// This is equivalent to formatting this bitfield using a `{}`
498            /// display specifier, but will *never* use Unicode box-drawing
499            /// characters, even when an upstream formatter uses the `{:#}`
500            /// `fmt::Display` specifier. This is intended for use on platforms
501            /// where Unicode box drawing characters are never available.
502            $vis fn display_ascii(&self) -> impl core::fmt::Display {
503                struct DisplayAscii($Name);
504                impl core::fmt::Display for DisplayAscii {
505                    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
506                        self.0.fmt_ascii(f)
507                    }
508                }
509                DisplayAscii(*self)
510            }
511
512            /// Returns a value that formats this bitfield in a multi-line
513            /// format, always using Unicode box-drawing characters.
514            ///
515            /// This is equivalent to formatting this bitfield using a `{:#}`
516            /// format specifier, but will *always* use Unicode box-drawing
517            /// characters, even when an upstream formatter uses the `{}`
518            /// `fmt::Display` specifier.
519            $vis fn display_unicode(&self) -> impl core::fmt::Display {
520                struct DisplayUnicode($Name);
521                impl core::fmt::Display for DisplayUnicode {
522                    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
523                        self.0.fmt_unicode(f)
524                    }
525                }
526                DisplayUnicode(*self)
527            }
528
529            /// Returns a value that formats the bit value of the bitfield,
530            /// followed by any fields that have non-zero bits.
531            ///
532            /// If formatted using `{:#}`, the formatted representation is multi-line.
533            $vis fn display_set_bits(&self) -> impl core::fmt::Display {
534                struct DisplaySetBits($Name);
535                impl core::fmt::Display for DisplaySetBits {
536                    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
537                        self.0.fmt_set_bits(f)
538                    }
539                }
540                DisplaySetBits(*self)
541            }
542
543            fn fmt_set_bits(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
544                write!(f, "{:#0width$b}", self.0, width = $T::BITS as usize)?;
545                let mut wrote_any = false;
546
547                $({
548                    let field = Self::$Field;
549                    const NAME: &str = stringify!($Field);
550                    if !NAME.starts_with("_") {
551                        let bits = field.unpack_bits(self.0);
552                        if bits > 0 {
553                            if f.alternate() {
554                                if !wrote_any {
555                                    f.write_str("\n")?;
556                                }
557                                writeln!(f, "  {NAME}: {:?}", field.unpack(self.0))?;
558                            } else if !wrote_any {
559                                write!(f, " ({NAME}: {:?}", field.unpack(self.0))?;
560                            } else {
561                                write!(f, ", {NAME}: {:?}", field.unpack(self.0))?;
562                            }
563                            wrote_any = true;
564                        }
565                    }
566                })+
567
568                if wrote_any && !f.alternate() {
569                    f.write_str(")")?;
570                }
571
572                Ok(())
573            }
574
575            fn fmt_ascii(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
576                f.pad("")?;
577                writeln!(f, "{:0width$b}", self.0, width = $T::BITS as usize)?;
578                f.pad("")?;
579                $({
580                    let field = Self::$Field;
581                    const NAME: &str = stringify!($Field);
582                    if !NAME.starts_with("_") {
583                        f.pad("")?;
584                        let mut cur_pos = $T::BITS;
585                        while cur_pos > field.most_significant_index() {
586                            f.write_str(".")?;
587                            cur_pos -= 1;
588                        }
589                        write!(f, "{:0width$b}", field.unpack_bits(self.0), width = field.bits() as usize)?;
590                        cur_pos -= field.bits();
591                        while cur_pos > 0 {
592                            f.write_str(".")?;
593                            cur_pos -= 1;
594                        }
595                        writeln!(f, " {NAME}: {:?}", field.unpack(self.0))?
596                    }
597                })+
598
599                Ok(())
600            }
601
602            fn fmt_unicode(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
603                f.pad("")?;
604                writeln!(f, "{:0width$b}", self.0, width = $T::BITS as usize)?;
605                f.pad("")?;
606                let mut cur_pos = $T::BITS;
607                let mut max_len = 0;
608                let mut rem = 0;
609                let mut fields = Self::FIELDS.iter().rev().peekable();
610                while let Some((name, field)) = fields.next() {
611                    while cur_pos > field.most_significant_index() {
612                        f.write_str(" ")?;
613                        cur_pos -= 1;
614                    }
615                    let bits = field.bits();
616                    match (name, bits) {
617                        (name, bits) if name.starts_with("_") => {
618                            for _ in 0..bits {
619                                f.write_str(" ")?;
620                            }
621                            cur_pos -= bits;
622                            continue;
623                        }
624                        (_, 1) => f.write_str("│")?,
625                        (_, 2) => f.write_str("└┤")?,
626                        (_, bits) => {
627                            f.write_str("└┬")?;
628                            for _ in 0..(bits - 3) {
629                                f.write_str("─")?;
630                            }
631                            f.write_str("┘")?;
632                        }
633                    }
634
635                    if fields.peek().is_none() {
636                        rem = cur_pos - (bits - 1);
637                    }
638
639                    max_len = core::cmp::max(max_len, name.len());
640                    cur_pos -= field.bits()
641                }
642
643                f.write_str("\n")?;
644
645                $(
646                    let field = Self::$Field;
647                    let name = stringify!($Field);
648                    if !name.starts_with("_") {
649                        f.pad("")?;
650                        cur_pos = $T::BITS;
651                        for (cur_name, cur_field) in Self::FIELDS.iter().rev() {
652                            while cur_pos > cur_field.most_significant_index() {
653                                f.write_str(" ")?;
654                                cur_pos -= 1;
655                            }
656
657                            if field == cur_field {
658                                break;
659                            }
660
661                            let bits = cur_field.bits();
662                            match (cur_name, bits) {
663                                (name, bits) if name.starts_with("_") => {
664                                    for _ in 0..bits {
665                                        f.write_str(" ")?;
666                                    }
667                                }
668                                (_, 1) => f.write_str("│")?,
669                                (_, bits) => {
670                                    f.write_str(" │")?;
671                                    for _ in 0..(bits - 2) {
672                                        f.write_str(" ")?;
673                                    }
674                                }
675                            }
676
677                            cur_pos -= bits;
678                        }
679
680                        let field_bits = field.bits();
681                        if field_bits == 1 {
682                            f.write_str("└")?;
683                            cur_pos -= 1;
684                        } else {
685                            f.write_str(" └")?;
686                            cur_pos -= 2;
687                        }
688                        let len = cur_pos as usize + (max_len - name.len());
689                        for _ in rem as usize..len {
690                            f.write_str("─")?;
691                        }
692                        writeln!(f, " {}: {:?} ({:0width$b})", name, field.unpack(self.0), field.unpack_bits(self.0), width = field_bits as usize)?
693                    }
694
695                )+
696
697                Ok(())
698            }
699        }
700
701        #[automatically_derived]
702        impl core::fmt::Display for $Name {
703            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
704                if f.alternate() {
705                    self.fmt_unicode(f)
706                } else {
707                    self.fmt_ascii(f)
708                }
709            }
710        }
711
712        #[automatically_derived]
713        impl core::fmt::Binary for $Name {
714            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
715                if f.alternate() {
716                    write!(f, concat!(stringify!($Name), "({:#b})"), self.0)
717                } else {
718                    write!(f, concat!(stringify!($Name), "({:b})"), self.0)
719                }
720            }
721        }
722
723        #[automatically_derived]
724        impl core::fmt::UpperHex for $Name {
725            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
726                if f.alternate() {
727                    write!(f, concat!(stringify!($Name), "({:#X})"), self.0)
728                } else {
729                    write!(f, concat!(stringify!($Name), "({:X})"), self.0)
730                }
731            }
732        }
733
734        #[automatically_derived]
735        impl core::fmt::LowerHex for $Name {
736            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
737                if f.alternate() {
738                    write!(f, concat!(stringify!($Name), "({:#x})"), self.0)
739                } else {
740                    write!(f, concat!(stringify!($Name), "({:x})"), self.0)
741                }
742            }
743        }
744
745        #[automatically_derived]
746        impl From<$T> for $Name {
747            #[inline]
748            fn from(val: $T) -> Self {
749                Self::from_bits(val)
750            }
751        }
752
753        #[automatically_derived]
754        impl From<$Name> for $T {
755            #[inline]
756            fn from($Name(bits): $Name) -> Self {
757                bits
758            }
759        }
760    };
761    (@field<$T:ident>, prev: $Prev:ident:
762        $(#[$meta:meta])*
763        $vis:vis const $Field:ident = ..;
764    ) => {
765        $(#[$meta])*
766        $vis const $Field: $crate::bitfield!{ @t $T, $T, Self } = Self::$Prev.remaining();
767    };
768    (@field<$T:ident>, prev: $Prev:ident:
769        $(#[$meta:meta])*
770        $vis:vis const $Field:ident = $value:literal;
771        $($rest:tt)*
772    ) => {
773        $(#[$meta])*
774        $vis const $Field: $crate::bitfield!{ @t $T, $T, Self } = Self::$Prev.next($value);
775        $crate::bitfield!{ @field<$T>, prev: $Field: $($rest)* }
776    };
777
778    (@field<$T:ident>, prev: $Prev:ident:
779        $(#[$meta:meta])*
780        $vis:vis const $Field:ident: $Val:ty;
781        $($rest:tt)*
782    ) => {
783        $(#[$meta])*
784        $vis const $Field: $crate::bitfield!{ @t $T, $Val, Self } = Self::$Prev.then::<$Val>();
785        $crate::bitfield!{ @field<$T>, prev: $Field: $($rest)* }
786    };
787
788
789    (@field<$T:ident>, prev: $Prev:ident: ) => {  };
790    (@field<$T:ident>:
791        $(#[$meta:meta])*
792        $vis:vis const $Field:ident = $value:literal;
793        $($rest:tt)*
794    ) => {
795        $(#[$meta])*
796        $vis const $Field: $crate::bitfield!{ @t $T, $T, Self } = <$crate::bitfield!{ @t $T, $T, () }>::least_significant($value).typed();
797        $crate::bitfield!{ @field<$T>, prev: $Field: $($rest)* }
798    };
799
800    (@field<$T:ident>:
801        $(#[$meta:meta])*
802        $vis:vis const $Field:ident: $Val:ty;
803        $($rest:tt)*
804    ) => {
805        $(#[$meta])*
806        $vis const $Field: $crate::bitfield!{ @t $T, $Val, Self } = <$crate::bitfield!{ @t $T, $Val, Self } >::first();
807        $crate::bitfield!{ @field<$T>, prev: $Field: $($rest)* }
808    };
809
810
811    // (@process_meta $vis:vis struct $Name:ident<$T:ty> { $(#[$before:meta])* } #[derive($($Derive:path),+)] $(#[$after:meta])*) => {
812    //     $crate::bitfield! { @process_derives $vis struct $Name<$T> { } $($Derive),+ { $(#[$before])* $(#[$after])* } }
813
814    // };
815    // (@process_meta $vis:vis struct $Name:ident<$T:ty> {  }) => {
816    //     #[derive(Copy, Clone)]
817    //     #[repr(transparent)]
818    //     $vis struct $Name($T);
819    // };
820    // (@process_meta $vis:vis struct $Name:ident<$T:ty> { $(#[$before:meta])+ }) => {
821    //     $(#[$before])*
822    //     #[derive(Copy, Clone)]
823    //     #[repr(transparent)]
824    //     $vis struct $Name($T);
825    // };
826    // (@process_meta $vis:vis struct $Name:ident<$T:ty>  { $(#[$before:meta])* } #[$current:meta] $(#[$after:meta])*) => {
827    //     $crate::bitfield! { @process_meta $vis struct $Name<$T> { $(#[$before])* #[$current] } $(#[$after])* }
828    // };
829    // (@process_derives $vis:vis struct $Name:ident<$T:ty> { Debug, } { $($rest:tt)* }) => {
830    //     impl core::fmt::Debug for $Name {
831    //         fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
832    //             if f.alternate() {
833    //                 f.debug_tuple(stringify!($Name)).field(&format_args!("{}", self)).finish()
834    //             } else {
835    //                 f.debug_tuple(stringify!($Name)).field(&format_args!("{:#b}", self)).finish()
836    //             }
837
838    //         }
839    //     }
840    //     #[derive(Copy, Clone)]
841    //     #[repr(transparent)]
842    //     $($rest)*
843    //     $vis struct $Name($T);
844    // };
845
846    // (@process_derives $vis:vis struct $Name:ident<$T:ty> { Debug, $($Before:tt),+ } $($After:tt),+ { $($rest:tt)* }) => {
847    //     impl core::fmt::Debug for $Name {
848    //         fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
849    //             if f.alternate() {
850    //                 f.debug_tuple(stringify!($Name)).field(&format_args!("{}", self)).finish()
851    //             } else {
852    //                 f.debug_tuple(stringify!($Name)).field(&format_args!("{:#b}", self)).finish()
853    //             }
854
855    //         }
856    //     }
857    //     #[derive(Copy, Clone, $($Before),+ $($After),+)]
858    //     #[repr(transparent)]
859    //     $($rest)*
860    //     $vis struct $Name($T);
861    // };
862    // (@process_derives $vis:vis struct $Name:ident<$T:ty> { Debug, $($Before:tt),+ } { $($rest:tt)* }) => {
863
864    //     #[derive(Copy, Clone, $($Before),+)]
865    //     #[repr(transparent)]
866    //     $($rest)*
867    //     $vis struct $Name($T);
868    // };
869    // (@process_derives $vis:vis struct $Name:ident<$T:ty> { $($Before:tt),+ $(,)? } { $($rest:tt)* }) => {
870    //     #[derive($($Before),+)]
871    //     #[derive(Copy, Clone)]
872    //     #[repr(transparent)]
873    //     $($rest)*
874    //     $vis struct $Name($T);
875    // };
876    // (@process_derives $vis:vis struct $Name:ident<$T:ty> { $($Before:tt),* $(,)? } $Next:tt, $($After:tt),* { $($rest:tt)* }) => {
877    //     $crate::bitfield! { @process_derives $vis struct $Name<$T> { $Next, $($Before),*  } $($After),* { $($rest)* } }
878    // };
879    // (@process_derives $vis:vis struct $Name:ident<$T:ty> { $($Before:tt),* } $Next:tt { $($rest:tt)* }) => {
880    //     $crate::bitfield! { @process_derives $vis struct $Name<$T> { $Next, $($Before),* } { $($rest)* } }
881    // };
882
883    (@t usize, $V:ty, $F:ty) => { $crate::PackUsize<$V, $F> };
884    (@t u128, $V:ty, $F:ty) => { $crate::Pack128<$V, $F> };
885    (@t u64, $V:ty, $F:ty) => { $crate::Pack64<$V, $F> };
886    (@t u32, $V:ty, $F:ty) => { $crate::Pack32<$V, $F> };
887    (@t u16, $V:ty, $F:ty) => { $crate::Pack16<$V, $F> };
888    (@t u8, $V:ty, $F:ty) => { $crate::Pack8<$V, $F> };
889    (@t $T:ty, $V:ty, $F:ty) => { compile_error!(concat!("unsupported bitfield type `", stringify!($T), "`; expected one of `usize`, `u128`, `u64`, `u32`, `u16`, or `u8`")) }
890}
891
892#[cfg(test)]
893mod tests {
894    use crate::FromBits;
895
896    bitfield! {
897        #[allow(dead_code)]
898        struct TestBitfield<u32> {
899            const HELLO = 4;
900            const _RESERVED_1 = 3;
901            const WORLD: bool;
902            const HAVE: TestEnum;
903            const LOTS = 5;
904            const OF = 1;
905            const FUN = 6;
906        }
907    }
908
909    bitfield! {
910        /// This is only here to ensure it compiles...
911        #[allow(dead_code)]
912        struct TestBitfieldHuge<u128> {
913            const HELLO = 4;
914            const _RESERVED_1 = 3;
915            const WORLD: bool;
916            const HAVE: TestEnum;
917            const LOTS = 5;
918            const OF = 1;
919            const FUN = 6;
920            const REST = ..;
921        }
922    }
923
924    #[repr(u8)]
925    #[derive(Debug)]
926    enum TestEnum {
927        Foo = 0b00,
928        Bar = 0b01,
929        Baz = 0b10,
930        Qux = 0b11,
931    }
932
933    impl FromBits<u32> for TestEnum {
934        const BITS: u32 = 2;
935        type Error = core::convert::Infallible;
936
937        fn try_from_bits(bits: u32) -> Result<Self, Self::Error> {
938            Ok(match bits as u8 {
939                bits if bits == Self::Foo as u8 => Self::Foo,
940                bits if bits == Self::Bar as u8 => Self::Bar,
941                bits if bits == Self::Baz as u8 => Self::Baz,
942                bits if bits == Self::Qux as u8 => Self::Qux,
943                bits => unreachable!("all patterns are covered: {:#b}", bits),
944            })
945        }
946
947        fn into_bits(self) -> u32 {
948            self as u8 as u32
949        }
950    }
951
952    impl FromBits<u128> for TestEnum {
953        const BITS: u32 = 2;
954        type Error = core::convert::Infallible;
955
956        fn try_from_bits(bits: u128) -> Result<Self, Self::Error> {
957            FromBits::<u32>::try_from_bits(bits as u32)
958        }
959
960        fn into_bits(self) -> u128 {
961            self as u8 as u128
962        }
963    }
964
965    #[derive(Debug)]
966    #[allow(dead_code)]
967    struct TestDebug {
968        value: usize,
969        bits: TestBitfield,
970    }
971
972    #[test]
973    fn test_bitfield_format() {
974        let test_bitfield = TestBitfield::new()
975            .with(TestBitfield::HELLO, 0b1001)
976            .with(TestBitfield::WORLD, true)
977            .with(TestBitfield::HAVE, TestEnum::Bar)
978            .with(TestBitfield::LOTS, 0b11010)
979            .with(TestBitfield::OF, 0)
980            .with(TestBitfield::FUN, 9);
981
982        let ascii = test_bitfield.to_string();
983        assert_eq!(ascii, test_bitfield.display_ascii().to_string());
984
985        println!("test ASCII display:\n{ascii}");
986        println!("test unicode display:\n{test_bitfield:#}\n");
987
988        let test_debug = TestDebug {
989            value: 42,
990            bits: test_bitfield,
991        };
992
993        println!("test_debug(alt): {test_debug:#?}\n");
994
995        println!("test_debug: {test_debug:?}\n");
996    }
997
998    #[test]
999    fn macro_bitfield_valid() {
1000        TestBitfield::assert_valid();
1001    }
1002}