Skip to main content

bitfld_macro/
lib.rs

1// Copyright (c) 2025 Joshua Seaton
2//
3// Use of this source code is governed by a MIT-style
4// license that can be found in the LICENSE file or at
5// https://opensource.org/licenses/MIT#
6
7use std::str::FromStr;
8
9use proc_macro::TokenStream;
10use proc_macro2::{Literal, Span, TokenStream as TokenStream2};
11use quote::{ToTokens, format_ident, quote};
12use syn::parse::{Error, Parse, ParseStream, Result};
13use syn::spanned::Spanned;
14use syn::{
15    Expr, ExprLit, Fields, GenericArgument, Ident, ItemStruct, Lit, Pat, Path,
16    PathArguments, Stmt, Type, braced, parse_macro_input, parse_quote,
17};
18
19#[proc_macro_attribute]
20pub fn bitfield_repr(attr: TokenStream, item: TokenStream) -> TokenStream {
21    let attr: TokenStream2 = attr.into();
22    let item: TokenStream2 = item.into();
23    quote! {
24        #[repr(#attr)]
25        #[derive(
26            Debug,
27            Eq,
28            PartialEq,
29            ::zerocopy::Immutable,
30            ::zerocopy::IntoBytes,
31            ::zerocopy::TryFromBytes,
32        )]
33        #item
34    }
35    .into()
36}
37
38#[proc_macro]
39pub fn layout(item: TokenStream) -> TokenStream {
40    parse_macro_input!(item as Bitfields)
41        .to_token_stream()
42        .into()
43}
44
45//
46// Parsing of the bitfld type.
47//
48
49enum BaseType {
50    U8,
51    U16,
52    U32,
53    U64,
54    U128,
55}
56
57impl BaseType {
58    const fn high_bit(&self) -> usize {
59        match *self {
60            Self::U8 => 7,
61            Self::U16 => 15,
62            Self::U32 => 31,
63            Self::U64 => 63,
64            Self::U128 => 127,
65        }
66    }
67}
68
69struct BaseTypeDef {
70    def: Type,
71    ty: BaseType,
72}
73
74impl TryFrom<Type> for BaseTypeDef {
75    type Error = Error;
76
77    fn try_from(type_def: Type) -> Result<Self> {
78        const INVALID_BASE_TYPE: &str =
79            "base type must be an unsigned integral type";
80        let Type::Path(ref path_ty) = type_def else {
81            return Err(Error::new_spanned(type_def, INVALID_BASE_TYPE));
82        };
83        let path = &path_ty.path;
84        let ty = if path.is_ident("u8") {
85            BaseType::U8
86        } else if path.is_ident("u16") {
87            BaseType::U16
88        } else if path.is_ident("u32") {
89            BaseType::U32
90        } else if path.is_ident("u64") {
91            BaseType::U64
92        } else if path.is_ident("u128") {
93            BaseType::U128
94        } else {
95            return Err(Error::new_spanned(path, INVALID_BASE_TYPE));
96        };
97        Ok(Self { def: type_def, ty })
98    }
99}
100
101struct TypeDef {
102    def: ItemStruct,
103    base: BaseTypeDef,
104}
105
106impl Parse for TypeDef {
107    fn parse(input: ParseStream) -> Result<Self> {
108        let mut strct: ItemStruct = input.parse()?;
109
110        // Check for any redundant derives; all other derives are forwarded. If
111        // no repr is specified, then we default to repr(transparent).
112        let mut repr = false;
113        for attr in &strct.attrs {
114            if attr.path().is_ident("derive") {
115                attr.parse_nested_meta(|meta| {
116                    for t in &[
117                        "Copy",
118                        "Clone",
119                        "Debug",
120                        "Default",
121                        "Eq",
122                        "PartialEq",
123                    ] {
124                        if meta.path.is_ident(t) {
125                            return Err(Error::new_spanned(
126                                meta.path,
127                                format!("layout! already derives {t}"),
128                            ));
129                        }
130                    }
131                    Ok(())
132                })?;
133                continue;
134            }
135
136            if attr.path().is_ident("repr") {
137                repr = true;
138            }
139        }
140        if !repr {
141            strct.attrs.push(parse_quote!(#[repr(transparent)]));
142        }
143
144        //
145        let base_type = if let Fields::Unnamed(fields) = &strct.fields {
146            if fields.unnamed.is_empty() {
147                return Err(Error::new_spanned(
148                    &fields.unnamed,
149                    "no base type provided",
150                ));
151            }
152            if fields.unnamed.len() > 1 {
153                return Err(Error::new_spanned(
154                    &fields.unnamed,
155                    "too many tuple fields; only the base type should be provided",
156                ));
157            }
158            BaseTypeDef::try_from(fields.unnamed.first().unwrap().ty.clone())?
159        } else {
160            return Err(Error::new_spanned(
161                &strct.fields,
162                "bitfld type must be defined as a tuple struct",
163            ));
164        };
165
166        Ok(Self {
167            def: strct,
168            base: base_type,
169        })
170    }
171}
172
173//
174// Parsing and binding for an individual bitfield.
175//
176
177struct Bitfield {
178    span: Span,
179    name: Option<Ident>,
180    high_bit: usize,
181    low_bit: usize,
182    repr: Option<Type>,
183
184    //
185    default: Option<Box<Expr>>,
186
187    //
188    shifted_mask: TokenStream2,
189}
190
191impl Bitfield {
192    fn new(
193        span: Span,
194        name: Option<Ident>,
195        high_bit: usize,
196        low_bit: usize,
197        repr: Option<Type>,
198        default: Option<Box<Expr>>,
199    ) -> Self {
200        let shifted_mask = {
201            let num_ones = high_bit - low_bit + 1;
202            let mut mask_str = "0x".to_string();
203
204            // If the first hex digit is not 'f', write that out now. After that,
205            // the remaining width will be a multiple of four, and the remaining
206            // digits will be either f or 0.
207            if !num_ones.is_multiple_of(4) {
208                mask_str.push(match num_ones % 4 {
209                    1 => '1',
210                    2 => '3',
211                    3 => '7',
212                    _ => unreachable!(),
213                });
214            }
215
216            let mut remaining = num_ones / 4;
217            while remaining > 0 {
218                if mask_str.len() > 2 && remaining.is_multiple_of(4) {
219                    mask_str.push('_');
220                }
221                mask_str.push('f');
222                remaining -= 1;
223            }
224            TokenStream2::from_str(&mask_str).unwrap()
225        };
226
227        Self {
228            span,
229            name,
230            high_bit,
231            low_bit,
232            repr,
233            default,
234            shifted_mask,
235        }
236    }
237
238    const fn is_reserved(&self) -> bool {
239        self.name.is_none()
240    }
241
242    const fn bit_width(&self) -> usize {
243        self.high_bit - self.low_bit + 1
244    }
245
246    fn minimum_width_integral_type(&self) -> TokenStream2 {
247        match self.bit_width() {
248            2..=8 => quote! {u8},
249            9..=16 => quote! {u16},
250            17..=32 => quote! {u32},
251            33..=64 => quote! {u64},
252            65..=128 => quote! {u128},
253            width => panic!("unexpected integral bit width: {width}"),
254        }
255    }
256
257    fn getter_and_setter(&self, ty: &TypeDef) -> TokenStream2 {
258        debug_assert!(!self.is_reserved());
259
260        let name = self.name.as_ref().unwrap();
261        let setter_name = format_ident!("set_{}", name);
262
263        let base_type = &ty.base.def;
264        let ty = &ty.def.ident;
265        let low_bit = Literal::usize_unsuffixed(self.low_bit);
266        let bit_width = self.bit_width();
267
268        if bit_width == 1 {
269            let get_doc = format!(
270                "Returns the value of the `{name}` bit (i.e., {ty}[{}]).",
271                self.low_bit,
272            );
273            let set_doc = format!(
274                "Sets the value of the `{name}` bit (i.e., {ty}[{}]).",
275                self.low_bit,
276            );
277            return quote! {
278                #[doc = #get_doc]
279                #[inline]
280                pub const fn #name(&self) -> bool {
281                    (self.0 & (1 << #low_bit)) != 0
282                }
283
284                #[doc = #set_doc]
285                #[inline]
286                pub const fn #setter_name(&mut self, value: bool) -> &mut Self {
287                    if value {
288                        self.0 |= (1 << #low_bit);
289                    } else {
290                        self.0 &= (1 << #low_bit);
291                    }
292                    self
293                }
294            };
295        }
296
297        let get_doc = format!(
298            "Returns the value of the `{name}` field (i.e., `{ty}[{}:{}]`).",
299            self.high_bit, self.low_bit,
300        );
301        let set_doc = format!(
302            "Sets the value of the `{name}` field (i.e., `{ty}[{}:{}]`).",
303            self.high_bit, self.low_bit,
304        );
305
306        let min_width = self.minimum_width_integral_type();
307        let shifted_mask = &self.shifted_mask;
308        let get_value =
309            quote! { ((self.0 >> #low_bit) & #shifted_mask) as #min_width };
310        let getter = if let Some(repr) = &self.repr {
311            quote! {
312                #[doc = #get_doc]
313                #[inline]
314                pub fn #name(&self)
315                    -> ::core::result::Result<#repr, ::bitfld::InvalidBits<#min_width>>
316                where
317                    #repr: ::zerocopy::TryFromBytes,
318                {
319                    use ::zerocopy::IntoBytes;
320                    use ::zerocopy::TryFromBytes;
321                    let value = #get_value;
322                    #repr::try_read_from_bytes(value.as_bytes())
323                        .map_err(|_| ::bitfld::InvalidBits(value))
324                }
325            }
326        } else {
327            quote! {
328                #[doc = #get_doc]
329                #[inline]
330                pub const fn #name(&self) -> #min_width {
331                    #get_value
332                }
333            }
334        };
335
336        let set_value = {
337            let value_check = if bit_width >= 8 && bit_width.is_power_of_two() {
338                quote! {}
339            } else {
340                quote! { debug_assert!((value & !#shifted_mask) == 0); }
341            };
342            quote! {
343                #value_check
344                self.0 &= !(#shifted_mask << #low_bit);
345                self.0 |= ((value & #shifted_mask) as #base_type) << #low_bit;
346            }
347        };
348
349        let setter = if let Some(repr) = &self.repr {
350            quote! {
351                #[doc = #set_doc]
352                #[inline]
353                pub fn #setter_name(&mut self, value: #repr) -> &mut Self
354                where
355                    #repr: ::zerocopy::IntoBytes + ::zerocopy::Immutable
356                 {
357                    use ::zerocopy::IntoBytes;
358                    use ::zerocopy::FromBytes;
359                    const { assert!(::core::mem::size_of::<#repr>() == ::core::mem::size_of::<#min_width>()) }
360                    let value = #min_width::read_from_bytes(value.as_bytes()).unwrap();
361                    #set_value
362                    self
363                }
364            }
365        } else {
366            quote! {
367                #[doc = #set_doc]
368                #[inline]
369                pub const fn #setter_name(&mut self, value: #min_width) -> &mut Self {
370                    #set_value
371                    self
372                }
373            }
374        };
375
376        quote! {
377            #getter
378            #setter
379        }
380    }
381}
382
383impl Parse for Bitfield {
384    fn parse(input: ParseStream) -> Result<Self> {
385        const INVALID_BITFIELD_DECL_FORM: &str = "bitfield declaration should take one of the following forms:\n\
386            * `let $name: Bit<$bit> (= $default)?;`\n\
387            * `let $name: Bits<$high, $low (, $repr)?> (= $default)?;`\n\
388            * `let _: Bit<$bit> (= $value)?;`\n\
389            * `let _: Bits<$high, $low> (= $value)?;`";
390        let err = |spanned: &dyn ToTokens| {
391            Error::new_spanned(spanned, INVALID_BITFIELD_DECL_FORM)
392        };
393
394        let stmt = input.parse::<Stmt>()?;
395        let Stmt::Local(ref local) = stmt else {
396            return Err(err(&stmt));
397        };
398        let Pat::Type(ref pat_type) = local.pat else {
399            return Err(err(&local));
400        };
401
402        let name: Option<Ident> = match *pat_type.pat {
403            Pat::Ident(ref pat_ident) => {
404                if let Some(by_ref) = &pat_ident.by_ref {
405                    return Err(err(by_ref));
406                }
407                if let Some(mutability) = &pat_ident.mutability {
408                    return Err(err(mutability));
409                }
410                if let Some(subpat) = &pat_ident.subpat {
411                    return Err(err(&subpat.0));
412                }
413                Some(pat_ident.ident.clone())
414            }
415            Pat::Wild(_) => None,
416            _ => return Err(err(&*pat_type.pat)),
417        };
418
419        let path: &Path = if let Type::Path(ref type_path) = *pat_type.ty {
420            if type_path.qself.is_some() {
421                return Err(err(&*pat_type.ty));
422            }
423            &type_path.path
424        } else {
425            return Err(err(&*pat_type.ty));
426        };
427
428        let get_bits_and_repr = |bits: &mut [usize]| -> Result<Option<Type>> {
429            let args = &path.segments.first().unwrap().arguments;
430            let args = if let PathArguments::AngleBracketed(bracketed) = args {
431                &bracketed.args
432            } else {
433                return Err(err(&args));
434            };
435            if args.len() < bits.len() || args.len() > bits.len() + 1 {
436                return Err(err(&args));
437            }
438            for (i, bit) in bits.iter_mut().enumerate() {
439                let arg = args.get(i).unwrap();
440                match arg {
441                    GenericArgument::Const(Expr::Lit(ExprLit {
442                        lit: Lit::Int(b),
443                        ..
444                    })) => {
445                        *bit = b.base10_parse()?;
446                    }
447                    _ => return Err(err(&arg)),
448                }
449            }
450            if args.len() == bits.len() + 1 {
451                let arg = args.last().unwrap();
452                if let GenericArgument::Type(repr) = arg {
453                    Ok(Some(repr.clone()))
454                } else {
455                    Err(err(&arg))
456                }
457            } else {
458                Ok(None)
459            }
460        };
461
462        let type_ident = &path.segments.first().unwrap().ident;
463        let (high, low, repr) = if type_ident == "Bits" {
464            let mut bits = [0usize; 2];
465            let repr = get_bits_and_repr(&mut bits)?;
466            if bits[0] < bits[1] {
467                Err(Error::new_spanned(
468                    &path.segments,
469                    "first high bit, then low",
470                ))
471            } else {
472                Ok((bits[0], bits[1], repr))
473            }
474        } else if type_ident == "Bit" {
475            let mut bit = [0usize; 1];
476            let repr = get_bits_and_repr(&mut bit)?;
477            Ok((bit[0], bit[0], repr))
478        } else {
479            Err(err(path))
480        }?;
481
482        let default_or_value = if let Some(ref init) = local.init {
483            if init.diverge.is_some() {
484                return Err(err(local));
485            }
486            Some(init.expr.clone())
487        } else {
488            None
489        };
490
491        if repr.is_some() {
492            if name.is_none() {
493                return Err(Error::new_spanned(
494                    repr,
495                    "custom representations are not permitted for reserved fields",
496                ));
497            }
498            if high == low {
499                return Err(Error::new_spanned(
500                    repr,
501                    "custom representations are not permitted for bits",
502                ));
503            }
504        }
505
506        Ok(Bitfield::new(
507            stmt.span(),
508            name,
509            high,
510            low,
511            repr,
512            default_or_value,
513        ))
514    }
515}
516
517struct Bitfields {
518    ty: TypeDef,
519    named: Vec<Bitfield>,
520    reserved: Vec<Bitfield>,
521}
522
523impl Bitfields {
524    fn constants(&self) -> TokenStream2 {
525        let base = &self.ty.base.def;
526
527        let mut field_constants = Vec::new();
528        let mut field_metadata = Vec::new();
529        let mut checks = Vec::new();
530        let mut default_values = vec![quote! {Self::RSVD1_MASK}];
531
532        for field in &self.named {
533            let name_lower = field.name.as_ref().unwrap().to_string();
534            let name_upper = name_lower.clone().to_uppercase();
535            let low_bit = Literal::usize_unsuffixed(field.low_bit);
536            let shifted_mask = &field.shifted_mask;
537
538            if field.bit_width() == 1 {
539                let bit_name = format_ident!("{name_upper}_BIT");
540                let doc = format!("Bit position of the `{name_lower}` field.",);
541                field_constants.push(quote! {
542                    #[doc = #doc]
543                    pub const #bit_name: usize = #low_bit;
544                });
545            } else {
546                let mask_name = format_ident!("{name_upper}_MASK");
547                let shift_name = format_ident!("{name_upper}_SHIFT");
548                let mask_doc =
549                    format!("Unshifted bitmask of the `{name_lower}` field.");
550                let shift_doc = format!(
551                    "Bit shift (i.e., the low bit) of the `{name_lower}` field."
552                );
553                field_constants.push(quote! {
554                    #[doc = #mask_doc]
555                    pub const #mask_name: #base = #shifted_mask;
556                    #[doc = #shift_doc]
557                    pub const #shift_name: usize = #low_bit;
558                });
559            }
560
561            if let Some(default) = &field.default {
562                let default_name = format_ident!("{name_upper}_DEFAULT");
563                let doc = format!(
564                    "Pre-shifted default value of the `{name_lower}` field.",
565                );
566                field_constants.push(quote! {
567                    #[doc = #doc]
568                    pub const #default_name: #base = ((#default) as #base) << #low_bit;
569                });
570                checks.push(quote! {
571                    const { assert!(Self::#default_name & !(#shifted_mask << #low_bit) == 0) }
572                });
573                default_values.push(quote! { Self::#default_name });
574            }
575
576            let high_bit = Literal::usize_unsuffixed(field.high_bit);
577            let default = if let Some(default) = &field.default {
578                quote! { #default }
579            } else {
580                quote! { 0 }
581            };
582            field_metadata.push(quote! {
583                ::bitfld::FieldMetadata::<#base>{
584                    name: #name_lower,
585                    high_bit: #high_bit,
586                    low_bit: #low_bit,
587                    default: #default as #base,
588                },
589            });
590        }
591
592        let mut rsvd1_values = Vec::new();
593        let mut rsvd0_values = Vec::new();
594        for rsvd in &self.reserved {
595            let rsvd_value = rsvd.default.as_ref().unwrap();
596            let low_bit = Literal::usize_unsuffixed(rsvd.low_bit);
597            let shifted_mask = &rsvd.shifted_mask;
598            let name = format_ident!("RSVD_{}_{}", rsvd.high_bit, rsvd.low_bit);
599
600            field_constants.push(quote! {
601                const #name: #base = (#rsvd_value as #base) << #low_bit;
602            });
603            checks.push(quote! {
604                const { assert!(Self::#name & !(#shifted_mask << #low_bit) == 0) }
605            });
606            rsvd1_values.push(quote! { Self::#name });
607            rsvd0_values.push(quote! {
608                (!Self::#name & (#shifted_mask << #low_bit))
609            });
610        }
611
612        let num_fields = Literal::usize_unsuffixed(self.named.len());
613        let field_metadata = field_metadata.into_iter();
614        field_constants.push(
615            quote! {
616                /// Metadata of all named fields in the layout.
617                pub const FIELDS: [::bitfld::FieldMetadata::<#base>; #num_fields] = [
618                    #(#field_metadata)*
619                ];
620            }
621        );
622
623        let field_constants = field_constants.into_iter();
624
625        let check_fn = if checks.is_empty() {
626            quote! {}
627        } else {
628            let checks = checks.into_iter();
629            quote! {
630                #[forbid(overflowing_literals)]
631                const fn check_defaults() -> () {
632                    #(#checks)*
633                }
634            }
635        };
636
637        if self.reserved.is_empty() {
638            rsvd1_values.push(quote! {0});
639            rsvd0_values.push(quote! {0});
640        }
641        let rsvd1_values = rsvd1_values.into_iter();
642        let rsvd0_values = rsvd0_values.into_iter();
643        let default_values = default_values.into_iter();
644
645        quote! {
646            /// Mask of all reserved-as-1 bits.
647            pub const RSVD1_MASK: #base = #(#rsvd1_values)|* ;
648            /// Mask of all reserved-as-0 bits.
649            pub const RSVD0_MASK: #base = #(#rsvd0_values)|* ;
650            /// The default value of the layout, combining all field
651            /// defaults and reserved-as values.
652            pub const DEFAULT: #base = #(#default_values)|* ;
653
654            #(#field_constants)*
655
656            #check_fn
657        }
658    }
659
660    fn iter_impl(&self) -> TokenStream2 {
661        let ty = &self.ty.def.ident;
662        let base = &self.ty.base.def;
663        let iter_type = format_ident!("{}Iter", ty);
664        let vis = &self.ty.def.vis;
665        let num_fields = Literal::usize_unsuffixed(self.named.len());
666
667        quote! {
668            #[doc(hidden)]
669            #vis struct #iter_type(#base, usize);
670
671            impl ::core::iter::Iterator for #iter_type {
672                type Item = (&'static ::bitfld::FieldMetadata<#base>, #base);
673
674                fn next(&mut self) -> Option<Self::Item> {
675                    if self.1 >= #num_fields {
676                        return None;
677                    }
678                    let metadata = &#ty::FIELDS[self.1];
679                    let shifted_mask = (1 << (metadata.high_bit - metadata.low_bit + 1)) - 1;
680                    let value = (self.0 >> metadata.low_bit) & shifted_mask;
681                    self.1 += 1;
682                    Some((metadata, value))
683                }
684            }
685
686            impl #ty {
687                /// Returns an iterator over (metadata, value) pairs for each
688                /// field.
689                pub fn iter(&self) -> impl ::core::iter::Iterator<Item = (&'static ::bitfld::FieldMetadata<#base>, #base, )> {
690                    #iter_type(self.0, 0)
691                }
692            }
693
694            impl ::core::iter::IntoIterator for #ty {
695                type Item = (&'static ::bitfld::FieldMetadata<#base>, #base);
696                type IntoIter = #iter_type;
697
698                fn into_iter(self) -> Self::IntoIter { #iter_type(self.0, 0) }
699            }
700
701            impl<'a> ::core::iter::IntoIterator for &'a #ty {
702                type Item = (&'static ::bitfld::FieldMetadata<#base>, #base);
703                type IntoIter = #iter_type;
704
705                fn into_iter(self) -> Self::IntoIter { #iter_type(self.0, 0) }
706            }
707        }
708    }
709
710    fn getters_and_setters(&self) -> impl Iterator<Item = TokenStream2> + '_ {
711        self.named
712            .iter()
713            .map(|field| field.getter_and_setter(&self.ty))
714    }
715
716    fn fmt_fn(&self, integral_specifier: &str) -> TokenStream2 {
717        let ty_str = &self.ty.def.ident.to_string();
718
719        let mut custom_repr_fields = self
720            .named
721            .iter()
722            .filter(|field| field.repr.is_some())
723            .peekable();
724
725        let where_clause = if custom_repr_fields.peek().is_some() {
726            let bounds = custom_repr_fields.map(|field| {
727                let repr = field.repr.as_ref().unwrap();
728                quote! {#repr: ::core::fmt::Debug,}
729            });
730            quote! {
731                where
732                    #(#bounds)*
733            }
734        } else {
735            quote! {}
736        };
737
738        let fmt_fields = self.named.iter().enumerate().map(|(idx, field)| {
739            let name = &field.name;
740            let name_str = name.as_ref().unwrap().to_string();
741            let default_specifier = if field.bit_width() == 1 {
742                ""
743            } else {
744                integral_specifier
745            };
746            let comma = if idx < self.named.len() - 1 { "," } else { "" };
747            if field.repr.is_some() {
748                let ok_format_string = format!("{{indent}}{name_str}: {{:#?}}{comma}{{sep}}");
749                let ok_format_string = Literal::string(&ok_format_string);
750                let err_format_string = format!(
751                    "{{indent}}{name_str}: InvalidBits({{{default_specifier}}}){comma}{{sep}}"
752                );
753                let err_format_string = Literal::string(&err_format_string);
754                quote! {
755                    match self.#name() {
756                        Ok(value) => write!(f, #ok_format_string, value),
757                        Err(invalid) => write!(f, #err_format_string, invalid.0),
758                    }?;
759                }
760            } else {
761                let format_string =
762                    format!("{{indent}}{name_str}: {{{default_specifier}}}{comma}{{sep}}");
763                let format_string = Literal::string(&format_string);
764                quote! {write!(f, #format_string, self.#name())?;}
765            }
766        });
767
768        quote! {
769            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result
770            #where_clause
771            {
772                let (sep, indent) = if f.alternate() {
773                    ('\n', "    ")
774                } else {
775                    (' ', "")
776                };
777                write!(f, "{} {{{sep}", #ty_str)?;
778                #(#fmt_fields)*
779                write!(f, "}}")
780            }
781        }
782    }
783
784    fn fmt_impls(&self) -> TokenStream2 {
785        let ty = &self.ty.def.ident;
786        let lower_hex_fmt = self.fmt_fn(":#x");
787        let upper_hex_fmt = self.fmt_fn(":#X");
788        let binary_fmt = self.fmt_fn(":#b");
789        let octal_fmt = self.fmt_fn(":#o");
790        quote! {
791            impl ::core::fmt::Debug for #ty {
792                fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
793                    ::core::fmt::LowerHex::fmt(self, f)
794                }
795            }
796
797            impl ::core::fmt::Binary for #ty {
798                #binary_fmt
799            }
800
801            impl ::core::fmt::LowerHex for #ty {
802                #lower_hex_fmt
803            }
804
805            impl ::core::fmt::UpperHex for #ty {
806                #upper_hex_fmt
807            }
808
809            impl ::core::fmt::Octal for #ty {
810                #octal_fmt
811            }
812        }
813    }
814}
815
816impl Parse for Bitfields {
817    fn parse(input: ParseStream) -> Result<Self> {
818        let input = {
819            let content;
820            braced!(content in input);
821            content
822        };
823
824        let ty = input.parse::<TypeDef>()?;
825
826        let input = {
827            let content;
828            braced!(content in input);
829            content
830        };
831
832        let mut fields = Vec::new();
833        while !input.is_empty() {
834            fields.push(input.parse::<Bitfield>()?);
835        }
836        fields.sort_by_key(|field| field.low_bit);
837
838        for i in 1..fields.len() {
839            let prev = &fields[i - 1];
840            let curr = &fields[i];
841            if prev.high_bit >= curr.low_bit {
842                // TODO(https://github.com/rust-lang/rust/issues/54725): It
843                // would be nice to Span::join() the two spans, but that's still
844                // experimental.
845                return Err(Error::new(
846                    curr.span,
847                    format!(
848                        "field overlaps with another: [{}:{}] vs. [{}:{}]",
849                        prev.high_bit,
850                        prev.low_bit,
851                        curr.high_bit,
852                        curr.low_bit
853                    ),
854                ));
855            }
856        }
857
858        if let Some(highest) = fields.last() {
859            let highest_possible = ty.base.ty.high_bit();
860            if highest.high_bit > highest_possible {
861                return Err(Error::new(
862                    highest.span,
863                    format!(
864                        "high bit {} exceeds the highest possible value of {highest_possible}",
865                        highest.high_bit
866                    ),
867                ));
868            }
869        }
870
871        let mut bitfld = Self {
872            ty,
873            named: vec![],
874            reserved: vec![],
875        };
876
877        while let Some(field) = fields.pop() {
878            if field.is_reserved() {
879                if field.default.is_some() {
880                    bitfld.reserved.push(field);
881                }
882            } else {
883                bitfld.named.push(field);
884            }
885        }
886
887        Ok(bitfld)
888    }
889}
890
891impl ToTokens for Bitfields {
892    fn to_tokens(&self, tokens: &mut TokenStream2) {
893        let type_def = &self.ty.def;
894        let type_name = &type_def.ident;
895        let base = &self.ty.base.def;
896
897        let constants = self.constants();
898        let getters_and_setters = self.getters_and_setters();
899        let iter_impl = self.iter_impl();
900        let fmt_impls = self.fmt_impls();
901        quote! {
902            #[derive(Copy, Clone, Eq, PartialEq)]
903            #type_def
904
905            impl #type_name {
906                #constants
907
908                /// Creates a new instance with reserved-as-1 bits set and
909                /// all other bits zeroed (i.e., with a value of
910                /// [`Self::RSVD1_MASK`]).
911                pub const fn new() -> Self {
912                    Self(Self::RSVD1_MASK)
913                }
914
915                #(#getters_and_setters)*
916            }
917
918            impl ::core::default::Default for #type_name {
919                /// Returns an instance with the default bits set (i.e,. with a
920                /// value of [`Self::DEFAULT`].
921                fn default() -> Self {
922                    Self(Self::DEFAULT)
923                }
924            }
925
926            impl ::core::convert::From<#base> for #type_name {
927                // `RSVD{0,1}_MASK` may be zero, in which case the following
928                // mask conditions might be trivially true.
929                #[allow(clippy::bad_bit_mask)]
930                fn from(value: #base) -> Self {
931                    debug_assert!(
932                        value & Self::RSVD1_MASK == Self::RSVD1_MASK,
933                        "from(): Invalid base value ({value:#x}) has reserved-as-1 bits ({:#x}) unset",
934                        Self::RSVD1_MASK,
935                    );
936                    debug_assert!(
937                        !value & Self::RSVD0_MASK == Self::RSVD0_MASK,
938                        "from(): Invalid base value ({value:#x}) has reserved-as-0 bits ({:#x}) set",
939                        Self::RSVD0_MASK,
940                    );
941                    Self(value)
942                }
943            }
944
945            impl ::core::ops::Deref for #type_name {
946                type Target = #base;
947
948                fn deref(&self) -> &Self::Target {
949                    &self.0
950                }
951            }
952
953            impl ::core::ops::DerefMut for #type_name {
954                fn deref_mut(&mut self) -> &mut Self::Target {
955                    &mut self.0
956                }
957            }
958
959            #iter_impl
960
961            #fmt_impls
962        }
963        .to_tokens(tokens);
964    }
965}