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}