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::collections::HashSet;
8use std::str::FromStr;
9
10use proc_macro::TokenStream;
11use proc_macro2::{Literal, Span, TokenStream as TokenStream2};
12use quote::{ToTokens, format_ident, quote};
13use syn::parse::discouraged::Speculative;
14use syn::parse::{Error, Parse, ParseStream, Result};
15use syn::spanned::Spanned;
16use syn::{
17    Attribute, Expr, ExprLit, Fields, GenericArgument, Ident, ItemStruct, Lit,
18    MetaNameValue, Pat, Path, PathArguments, Stmt, Type, braced,
19    parse_macro_input, parse_quote,
20};
21
22#[proc_macro_attribute]
23pub fn bitfield_repr(attr: TokenStream, item: TokenStream) -> TokenStream {
24    let attr: TokenStream2 = attr.into();
25    let item: TokenStream2 = item.into();
26    quote! {
27        #[repr(#attr)]
28        #[derive(
29            Debug,
30            Eq,
31            PartialEq,
32            ::zerocopy::Immutable,
33            ::zerocopy::IntoBytes,
34            ::zerocopy::TryFromBytes,
35        )]
36        #item
37    }
38    .into()
39}
40
41#[proc_macro]
42pub fn layout(item: TokenStream) -> TokenStream {
43    parse_macro_input!(item as Bitfields)
44        .to_token_stream()
45        .into()
46}
47
48//
49// Parsing of the bitfld type.
50//
51
52enum BaseType {
53    U8,
54    U16,
55    U32,
56    U64,
57    U128,
58    Usize,
59}
60
61impl BaseType {
62    const fn high_bit(&self) -> Option<usize> {
63        match *self {
64            Self::U8 => Some(7),
65            Self::U16 => Some(15),
66            Self::U32 => Some(31),
67            Self::U64 => Some(63),
68            Self::U128 => Some(127),
69            Self::Usize => None,
70        }
71    }
72}
73
74struct BaseTypeDef {
75    def: Type,
76    ty: BaseType,
77}
78
79impl TryFrom<Type> for BaseTypeDef {
80    type Error = Error;
81
82    fn try_from(type_def: Type) -> Result<Self> {
83        const INVALID_BASE_TYPE: &str =
84            "base type must be an unsigned integral type";
85        let Type::Path(ref path_ty) = type_def else {
86            return Err(Error::new_spanned(type_def, INVALID_BASE_TYPE));
87        };
88        let path = &path_ty.path;
89        let ty = if path.is_ident("u8") {
90            BaseType::U8
91        } else if path.is_ident("u16") {
92            BaseType::U16
93        } else if path.is_ident("u32") {
94            BaseType::U32
95        } else if path.is_ident("u64") {
96            BaseType::U64
97        } else if path.is_ident("u128") {
98            BaseType::U128
99        } else if path.is_ident("usize") {
100            BaseType::Usize
101        } else {
102            return Err(Error::new_spanned(path, INVALID_BASE_TYPE));
103        };
104        Ok(Self { def: type_def, ty })
105    }
106}
107
108struct TypeDef {
109    def: ItemStruct,
110    base: BaseTypeDef,
111}
112
113impl Parse for TypeDef {
114    fn parse(input: ParseStream) -> Result<Self> {
115        let mut strct: ItemStruct = input.parse()?;
116
117        // Check for any redundant derives; all other derives are forwarded. If
118        // no repr is specified, then we default to repr(transparent).
119        let mut repr = false;
120        for attr in &strct.attrs {
121            if attr.path().is_ident("derive") {
122                attr.parse_nested_meta(|meta| {
123                    for t in &[
124                        "Copy",
125                        "Clone",
126                        "Debug",
127                        "Default",
128                        "Eq",
129                        "PartialEq",
130                    ] {
131                        if meta.path.is_ident(t) {
132                            return Err(Error::new_spanned(
133                                meta.path,
134                                format!("layout! already derives {t}"),
135                            ));
136                        }
137                    }
138                    Ok(())
139                })?;
140                continue;
141            }
142
143            if attr.path().is_ident("repr") {
144                repr = true;
145            }
146        }
147        if !repr {
148            strct.attrs.push(parse_quote!(#[repr(transparent)]));
149        }
150
151        //
152        let base_type = if let Fields::Unnamed(fields) = &strct.fields {
153            if fields.unnamed.is_empty() {
154                return Err(Error::new_spanned(
155                    &fields.unnamed,
156                    "no base type provided",
157                ));
158            }
159            if fields.unnamed.len() > 1 {
160                return Err(Error::new_spanned(
161                    &fields.unnamed,
162                    "too many tuple fields; only the base type should be provided",
163                ));
164            }
165            BaseTypeDef::try_from(fields.unnamed.first().unwrap().ty.clone())?
166        } else {
167            return Err(Error::new_spanned(
168                &strct.fields,
169                "bitfld type must be defined as a tuple struct",
170            ));
171        };
172
173        if let Some(param) = strct.generics.type_params().next() {
174            return Err(Error::new_spanned(
175                &param.ident,
176                "only const generic parameters are supported",
177            ));
178        }
179        if let Some(param) = strct.generics.lifetimes().next() {
180            return Err(Error::new_spanned(
181                param,
182                "only const generic parameters are supported",
183            ));
184        }
185
186        Ok(Self {
187            def: strct,
188            base: base_type,
189        })
190    }
191}
192
193//
194// Parsing and binding for an individual bitfield.
195//
196
197struct Bitfield {
198    span: Span,
199    name: Option<Ident>,
200    high_bit: usize,
201    low_bit: usize,
202    repr: Option<Type>,
203    cfg_pointer_width: Option<String>,
204
205    //
206    default: Option<Box<Expr>>,
207
208    //
209    shifted_mask: TokenStream2,
210}
211
212impl Bitfield {
213    fn new(
214        span: Span,
215        name: Option<Ident>,
216        high_bit: usize,
217        low_bit: usize,
218        repr: Option<Type>,
219        cfg_pointer_width: Option<String>,
220        default: Option<Box<Expr>>,
221    ) -> Self {
222        let shifted_mask = {
223            let num_ones = high_bit - low_bit + 1;
224            let mut mask_str = "0x".to_string();
225
226            // If the first hex digit is not 'f', write that out now. After that,
227            // the remaining width will be a multiple of four, and the remaining
228            // digits will be either f or 0.
229            if !num_ones.is_multiple_of(4) {
230                mask_str.push(match num_ones % 4 {
231                    1 => '1',
232                    2 => '3',
233                    3 => '7',
234                    _ => unreachable!(),
235                });
236            }
237
238            let mut remaining = num_ones / 4;
239            while remaining > 0 {
240                if mask_str.len() > 2 && remaining.is_multiple_of(4) {
241                    mask_str.push('_');
242                }
243                mask_str.push('f');
244                remaining -= 1;
245            }
246            TokenStream2::from_str(&mask_str).unwrap()
247        };
248
249        Self {
250            span,
251            name,
252            high_bit,
253            low_bit,
254            repr,
255            cfg_pointer_width,
256            default,
257            shifted_mask,
258        }
259    }
260
261    const fn is_reserved(&self) -> bool {
262        self.name.is_none()
263    }
264
265    fn display_name(&self) -> String {
266        match &self.name {
267            Some(name) => format!("`{name}`"),
268            None => "reserved".to_string(),
269        }
270    }
271
272    fn display_kind(&self) -> &'static str {
273        if self.bit_width() == 1 {
274            "bit"
275        } else {
276            "field"
277        }
278    }
279
280    fn display_range(&self) -> String {
281        if self.bit_width() == 1 {
282            format!("{}", self.low_bit)
283        } else {
284            format!("[{}:{}]", self.high_bit, self.low_bit)
285        }
286    }
287
288    const fn bit_width(&self) -> usize {
289        self.high_bit - self.low_bit + 1
290    }
291
292    fn minimum_width_integral_type(&self) -> TokenStream2 {
293        match self.bit_width() {
294            2..=8 => quote! {u8},
295            9..=16 => quote! {u16},
296            17..=32 => quote! {u32},
297            33..=64 => quote! {u64},
298            65..=128 => quote! {u128},
299            width => panic!("unexpected integral bit width: {width}"),
300        }
301    }
302
303    fn getter_and_setter(&self, ty: &TypeDef) -> TokenStream2 {
304        debug_assert!(!self.is_reserved());
305
306        let cfg_attr = cfg_attr(self);
307        let name = self.name.as_ref().unwrap();
308        let setter_name = format_ident!("set_{}", name);
309
310        let base_type = &ty.base.def;
311        let ty = &ty.def.ident;
312        let low_bit = Literal::usize_unsuffixed(self.low_bit);
313        let bit_width = self.bit_width();
314
315        if bit_width == 1 {
316            let get_doc = format!(
317                "Returns the value of the `{name}` bit (i.e., {ty}[{}]).",
318                self.low_bit,
319            );
320            let set_doc = format!(
321                "Sets the value of the `{name}` bit (i.e., {ty}[{}]).",
322                self.low_bit,
323            );
324            return quote! {
325                #cfg_attr
326                #[doc = #get_doc]
327                #[inline]
328                pub const fn #name(&self) -> bool {
329                    (self.0 & (1 << #low_bit)) != 0
330                }
331
332                #cfg_attr
333                #[doc = #set_doc]
334                #[inline]
335                pub const fn #setter_name(&mut self, value: bool) -> &mut Self {
336                    if value {
337                        self.0 |= (1 << #low_bit);
338                    } else {
339                        self.0 &= !(1 << #low_bit);
340                    }
341                    self
342                }
343            };
344        }
345
346        let get_doc = format!(
347            "Returns the value of the `{name}` field (i.e., `{ty}[{}:{}]`).",
348            self.high_bit, self.low_bit,
349        );
350        let set_doc = format!(
351            "Sets the value of the `{name}` field (i.e., `{ty}[{}:{}]`).",
352            self.high_bit, self.low_bit,
353        );
354
355        let min_width = self.minimum_width_integral_type();
356        let shifted_mask = &self.shifted_mask;
357        let get_value =
358            quote! { ((self.0 >> #low_bit) & #shifted_mask) as #min_width };
359        let getter = if let Some(repr) = &self.repr {
360            quote! {
361                #[doc = #get_doc]
362                #[inline]
363                pub fn #name(&self)
364                    -> ::core::result::Result<#repr, ::bitfld::InvalidBits<#min_width>>
365                where
366                    #repr: ::zerocopy::TryFromBytes,
367                {
368                    use ::zerocopy::IntoBytes;
369                    use ::zerocopy::TryFromBytes;
370                    let value = #get_value;
371                    #repr::try_read_from_bytes(value.as_bytes())
372                        .map_err(|_| ::bitfld::InvalidBits(value))
373                }
374            }
375        } else {
376            quote! {
377                #[doc = #get_doc]
378                #[inline]
379                pub const fn #name(&self) -> #min_width {
380                    #get_value
381                }
382            }
383        };
384
385        let set_value = {
386            let value_check = if bit_width >= 8 && bit_width.is_power_of_two() {
387                quote! {}
388            } else {
389                quote! { debug_assert!((value & !#shifted_mask) == 0); }
390            };
391            quote! {
392                #value_check
393                self.0 &= !(#shifted_mask << #low_bit);
394                self.0 |= ((value & #shifted_mask) as #base_type) << #low_bit;
395            }
396        };
397
398        let setter = if let Some(repr) = &self.repr {
399            quote! {
400                #[doc = #set_doc]
401                #[inline]
402                pub fn #setter_name(&mut self, value: #repr) -> &mut Self
403                where
404                    #repr: ::zerocopy::IntoBytes + ::zerocopy::Immutable
405                 {
406                    use ::zerocopy::IntoBytes;
407                    use ::zerocopy::FromBytes;
408                    const { assert!(::core::mem::size_of::<#repr>() == ::core::mem::size_of::<#min_width>()) }
409                    let value = #min_width::read_from_bytes(value.as_bytes()).unwrap();
410                    #set_value
411                    self
412                }
413            }
414        } else {
415            quote! {
416                #[doc = #set_doc]
417                #[inline]
418                pub const fn #setter_name(&mut self, value: #min_width) -> &mut Self {
419                    #set_value
420                    self
421                }
422            }
423        };
424
425        quote! {
426            #cfg_attr
427            #getter
428            #cfg_attr
429            #setter
430        }
431    }
432}
433
434fn cfg_attr(field: &Bitfield) -> Option<TokenStream2> {
435    field.cfg_pointer_width.as_ref().map(|w| {
436        quote! { #[cfg(target_pointer_width = #w)] }
437    })
438}
439
440impl Parse for Bitfield {
441    fn parse(input: ParseStream) -> Result<Self> {
442        const INVALID_BITFIELD_DECL_FORM: &str = "bitfield declaration should take one of the following forms:\n\
443            * `let $name: Bit<$bit> (= $default)?;`\n\
444            * `let $name: Bits<$high, $low (, $repr)?> (= $default)?;`\n\
445            * `let _: Bit<$bit> (= $value)?;`\n\
446            * `let _: Bits<$high, $low> (= $value)?;`";
447        let err = |spanned: &dyn ToTokens| {
448            Error::new_spanned(spanned, INVALID_BITFIELD_DECL_FORM)
449        };
450
451        let stmt = input.parse::<Stmt>()?;
452        let Stmt::Local(ref local) = stmt else {
453            return Err(err(&stmt));
454        };
455
456        if let Some(attr) = local.attrs.first() {
457            return Err(Error::new_spanned(
458                attr,
459                "attributes are not permitted on individual fields",
460            ));
461        }
462
463        let Pat::Type(ref pat_type) = local.pat else {
464            return Err(err(&local));
465        };
466
467        let name: Option<Ident> = match *pat_type.pat {
468            Pat::Ident(ref pat_ident) => {
469                if let Some(by_ref) = &pat_ident.by_ref {
470                    return Err(err(by_ref));
471                }
472                if let Some(mutability) = &pat_ident.mutability {
473                    return Err(err(mutability));
474                }
475                if let Some(subpat) = &pat_ident.subpat {
476                    return Err(err(&subpat.0));
477                }
478                Some(pat_ident.ident.clone())
479            }
480            Pat::Wild(_) => None,
481            _ => return Err(err(&*pat_type.pat)),
482        };
483
484        let path: &Path = if let Type::Path(ref type_path) = *pat_type.ty {
485            if type_path.qself.is_some() {
486                return Err(err(&*pat_type.ty));
487            }
488            &type_path.path
489        } else {
490            return Err(err(&*pat_type.ty));
491        };
492
493        let get_bits_and_repr = |bits: &mut [usize]| -> Result<Option<Type>> {
494            let args = &path.segments.first().unwrap().arguments;
495            let args = if let PathArguments::AngleBracketed(bracketed) = args {
496                &bracketed.args
497            } else {
498                return Err(err(&args));
499            };
500            if args.len() < bits.len() || args.len() > bits.len() + 1 {
501                return Err(err(&args));
502            }
503            for (i, bit) in bits.iter_mut().enumerate() {
504                let arg = args.get(i).unwrap();
505                match arg {
506                    GenericArgument::Const(Expr::Lit(ExprLit {
507                        lit: Lit::Int(b),
508                        ..
509                    })) => {
510                        *bit = b.base10_parse()?;
511                    }
512                    _ => return Err(err(&arg)),
513                }
514            }
515            if args.len() == bits.len() + 1 {
516                let arg = args.last().unwrap();
517                if let GenericArgument::Type(repr) = arg {
518                    Ok(Some(repr.clone()))
519                } else {
520                    Err(err(&arg))
521                }
522            } else {
523                Ok(None)
524            }
525        };
526
527        let type_ident = &path.segments.first().unwrap().ident;
528        let (high, low, repr) = if type_ident == "Bits" {
529            let mut bits = [0usize; 2];
530            let repr = get_bits_and_repr(&mut bits)?;
531            if bits[0] < bits[1] {
532                Err(Error::new_spanned(
533                    &path.segments,
534                    "first high bit, then low",
535                ))
536            } else {
537                Ok((bits[0], bits[1], repr))
538            }
539        } else if type_ident == "Bit" {
540            let mut bit = [0usize; 1];
541            let repr = get_bits_and_repr(&mut bit)?;
542            Ok((bit[0], bit[0], repr))
543        } else {
544            Err(err(path))
545        }?;
546
547        let default_or_value = if let Some(ref init) = local.init {
548            if init.diverge.is_some() {
549                return Err(err(local));
550            }
551            Some(init.expr.clone())
552        } else {
553            None
554        };
555
556        if repr.is_some() {
557            if name.is_none() {
558                return Err(Error::new_spanned(
559                    repr,
560                    "custom representations are not permitted for reserved fields",
561                ));
562            }
563            if high == low {
564                return Err(Error::new_spanned(
565                    repr,
566                    "custom representations are not permitted for bits",
567                ));
568            }
569        }
570
571        Ok(Bitfield::new(
572            stmt.span(),
573            name,
574            high,
575            low,
576            repr,
577            None,
578            default_or_value,
579        ))
580    }
581}
582
583/// Parses a `#[cfg(target_pointer_width = "...")]` attribute, returning the
584/// width value on success.
585fn parse_target_pointer_width_cfg(attr: &Attribute) -> Result<String> {
586    const ERROR_MSG: &str = "expected #[cfg(target_pointer_width = \"...\")]";
587    let meta = attr
588        .meta
589        .require_list()
590        .map_err(|_| Error::new_spanned(attr, ERROR_MSG))?;
591    let cfg: MetaNameValue = meta
592        .parse_args()
593        .map_err(|_| Error::new_spanned(attr, ERROR_MSG))?;
594    if !cfg.path.is_ident("target_pointer_width") {
595        return Err(Error::new_spanned(attr, ERROR_MSG));
596    }
597    match cfg.value {
598        Expr::Lit(ExprLit {
599            lit: Lit::Str(s), ..
600        }) => Ok(s.value()),
601        _ => Err(Error::new_spanned(attr, ERROR_MSG)),
602    }
603}
604
605struct Bitfields {
606    ty: TypeDef,
607    named: Vec<Bitfield>,
608    reserved: Vec<Bitfield>,
609    errors: Vec<Error>,
610}
611
612impl Bitfields {
613    fn constants(&self) -> TokenStream2 {
614        let base = &self.ty.base.def;
615        let is_usize = matches!(self.ty.base.ty, BaseType::Usize);
616
617        let mut field_constants = Vec::new();
618        let mut field_metadata = Vec::new();
619        let mut num_field_stmts = Vec::new();
620        let mut checks = Vec::new();
621        let mut default_stmts = Vec::new();
622
623        for field in &self.named {
624            let cfg_attr = cfg_attr(field);
625            let name_lower = field.name.as_ref().unwrap().to_string();
626            let name_upper = name_lower.to_uppercase();
627            let low_bit = Literal::usize_unsuffixed(field.low_bit);
628            let shifted_mask = &field.shifted_mask;
629
630            if field.bit_width() == 1 {
631                let bit_name = format_ident!("{name_upper}_BIT");
632                let doc = format!("Bit position of the `{name_lower}` field.",);
633                field_constants.push(quote! {
634                    #cfg_attr
635                    #[doc = #doc]
636                    pub const #bit_name: usize = #low_bit;
637                });
638            } else {
639                let mask_name = format_ident!("{name_upper}_MASK");
640                let shift_name = format_ident!("{name_upper}_SHIFT");
641                let mask_doc =
642                    format!("Unshifted bitmask of the `{name_lower}` field.");
643                let shift_doc = format!(
644                    "Bit shift (i.e., the low bit) of the `{name_lower}` field."
645                );
646                field_constants.push(quote! {
647                    #cfg_attr
648                    #[doc = #mask_doc]
649                    pub const #mask_name: #base = #shifted_mask;
650                    #cfg_attr
651                    #[doc = #shift_doc]
652                    pub const #shift_name: usize = #low_bit;
653                });
654            }
655
656            if let Some(default) = &field.default {
657                let default_name = format_ident!("{name_upper}_DEFAULT");
658                let doc = format!(
659                    "Pre-shifted default value of the `{name_lower}` field.",
660                );
661                field_constants.push(quote! {
662                    #cfg_attr
663                    #[doc = #doc]
664                    pub const #default_name: #base = ((#default) as #base) << #low_bit;
665                });
666                checks.push(quote! {
667                    #cfg_attr
668                    const { assert!(((#default) as #base) << #low_bit & !(#shifted_mask << #low_bit) == 0) }
669                });
670                default_stmts.push(quote! {
671                    #cfg_attr
672                    { v |= Self::#default_name; }
673                });
674            }
675
676            if is_usize {
677                let high_bit = Literal::usize_unsuffixed(field.high_bit);
678                checks.push(quote! {
679                    #cfg_attr
680                    const { assert!(#high_bit < usize::BITS as usize) }
681                });
682            }
683
684            let high_bit = Literal::usize_unsuffixed(field.high_bit);
685            let default = if let Some(default) = &field.default {
686                quote! { #default }
687            } else {
688                quote! { 0 }
689            };
690            field_metadata.push(quote! {
691                #cfg_attr
692                ::bitfld::FieldMetadata::<#base>{
693                    name: #name_lower,
694                    high_bit: #high_bit,
695                    low_bit: #low_bit,
696                    default: #default as #base,
697                },
698            });
699            num_field_stmts.push(quote! {
700                #cfg_attr
701                { n += 1; }
702            });
703        }
704
705        let mut rsvd1_stmts = Vec::new();
706        let mut rsvd0_stmts = Vec::new();
707        for rsvd in &self.reserved {
708            let cfg_attr = cfg_attr(rsvd);
709            let rsvd_value = rsvd.default.as_ref().unwrap();
710            let low_bit = Literal::usize_unsuffixed(rsvd.low_bit);
711            let shifted_mask = &rsvd.shifted_mask;
712            let name = format_ident!("RSVD_{}_{}", rsvd.high_bit, rsvd.low_bit);
713
714            field_constants.push(quote! {
715                #cfg_attr
716                const #name: #base = (#rsvd_value as #base) << #low_bit;
717            });
718            checks.push(quote! {
719                #cfg_attr
720                const { assert!((#rsvd_value as #base) << #low_bit & !(#shifted_mask << #low_bit) == 0) }
721            });
722            rsvd1_stmts.push(quote! {
723                #cfg_attr
724                { v |= Self::#name; }
725            });
726            rsvd0_stmts.push(quote! {
727                #cfg_attr
728                { v |= !Self::#name & (#shifted_mask << #low_bit); }
729            });
730
731            if is_usize {
732                let high_bit = Literal::usize_unsuffixed(rsvd.high_bit);
733                checks.push(quote! {
734                    #cfg_attr
735                    const { assert!(#high_bit < usize::BITS as usize) }
736                });
737            }
738        }
739
740        let num_fields_expr = quote! {
741            {
742                let mut n = 0usize;
743                #(#num_field_stmts)*
744                n
745            }
746        };
747        field_constants.push(quote! {
748            #[doc(hidden)]
749            const NUM_FIELDS: usize = #num_fields_expr;
750            /// Metadata of all named fields in the layout.
751            pub const FIELDS: [::bitfld::FieldMetadata::<#base>; #num_fields_expr] = [
752                #(#field_metadata)*
753            ];
754        });
755
756        let check_fn = if checks.is_empty() {
757            quote! {}
758        } else {
759            let checks = checks.into_iter();
760            quote! {
761                #[forbid(overflowing_literals)]
762                const fn check_defaults() -> () {
763                    #(#checks)*
764                }
765            }
766        };
767
768        quote! {
769            /// Mask of all reserved-as-1 bits.
770            pub const RSVD1_MASK: #base = {
771                let mut v: #base = 0;
772                #(#rsvd1_stmts)*
773                v
774            };
775            /// Mask of all reserved-as-0 bits.
776            pub const RSVD0_MASK: #base = {
777                let mut v: #base = 0;
778                #(#rsvd0_stmts)*
779                v
780            };
781            /// The default value of the layout, combining all field
782            /// defaults and reserved-as values.
783            pub const DEFAULT: #base = {
784                let mut v: #base = Self::RSVD1_MASK;
785                #(#default_stmts)*
786                v
787            };
788
789            #(#field_constants)*
790
791            #check_fn
792        }
793    }
794
795    fn iter_impl(&self) -> TokenStream2 {
796        let ty = &self.ty.def.ident;
797        let base = &self.ty.base.def;
798        let iter_type = format_ident!("{}Iter", ty);
799        let vis = &self.ty.def.vis;
800
801        let generics = &self.ty.def.generics;
802        let (impl_generics, ty_generics, where_clause) =
803            generics.split_for_impl();
804
805        let mut ref_generics = generics.clone();
806        ref_generics.params.insert(0, parse_quote!('a));
807        let (ref_impl_generics, _, _) = ref_generics.split_for_impl();
808
809        quote! {
810            #[doc(hidden)]
811            #vis struct #iter_type #impl_generics (#base, usize) #where_clause;
812
813            impl #impl_generics ::core::iter::Iterator for #iter_type #ty_generics #where_clause {
814                type Item = (&'static ::bitfld::FieldMetadata<#base>, #base);
815
816                fn next(&mut self) -> Option<Self::Item> {
817                    if self.1 >= <#ty #ty_generics>::NUM_FIELDS {
818                        return None;
819                    }
820                    let metadata = &<#ty #ty_generics>::FIELDS[self.1];
821                    let shifted_mask = (1 << (metadata.high_bit - metadata.low_bit + 1)) - 1;
822                    let value = (self.0 >> metadata.low_bit) & shifted_mask;
823                    self.1 += 1;
824                    Some((metadata, value))
825                }
826            }
827
828            impl #impl_generics #ty #ty_generics #where_clause {
829                /// Returns an iterator over (metadata, value) pairs for each
830                /// field.
831                pub fn iter(&self) -> #iter_type #ty_generics {
832                    #iter_type(self.0, 0)
833                }
834            }
835
836            impl #impl_generics ::core::iter::IntoIterator for #ty #ty_generics #where_clause {
837                type Item = (&'static ::bitfld::FieldMetadata<#base>, #base);
838                type IntoIter = #iter_type #ty_generics;
839
840                fn into_iter(self) -> Self::IntoIter { #iter_type(self.0, 0) }
841            }
842
843            impl #ref_impl_generics ::core::iter::IntoIterator for &'a #ty #ty_generics #where_clause {
844                type Item = (&'static ::bitfld::FieldMetadata<#base>, #base);
845                type IntoIter = #iter_type #ty_generics;
846
847                fn into_iter(self) -> Self::IntoIter { #iter_type(self.0, 0) }
848            }
849        }
850    }
851
852    fn getters_and_setters(&self) -> impl Iterator<Item = TokenStream2> + '_ {
853        self.named
854            .iter()
855            .map(|field| field.getter_and_setter(&self.ty))
856    }
857
858    fn fmt_fn(&self, integral_specifier: &str) -> TokenStream2 {
859        let ty_str = &self.ty.def.ident.to_string();
860
861        let mut custom_repr_fields = self
862            .named
863            .iter()
864            .filter(|field| field.repr.is_some())
865            .peekable();
866
867        let where_clause = if custom_repr_fields.peek().is_some() {
868            let bounds = custom_repr_fields.map(|field| {
869                let repr = field.repr.as_ref().unwrap();
870                quote! {#repr: ::core::fmt::Debug,}
871            });
872            quote! {
873                where
874                    #(#bounds)*
875            }
876        } else {
877            quote! {}
878        };
879
880        let fmt_fields = self.named.iter().map(|field| {
881            let cfg_attr = cfg_attr(field);
882            let name = &field.name;
883            let name_str = name.as_ref().unwrap().to_string();
884            let default_specifier = if field.bit_width() == 1 {
885                ""
886            } else {
887                integral_specifier
888            };
889            if field.repr.is_some() {
890                let ok_format_string =
891                    format!("{{indent}}{name_str}: {{:#?}},{{sep}}");
892                let ok_format_string = Literal::string(&ok_format_string);
893                let err_format_string = format!(
894                    "{{indent}}{name_str}: InvalidBits({{{default_specifier}}}),{{sep}}"
895                );
896                let err_format_string = Literal::string(&err_format_string);
897                quote! {
898                    #cfg_attr
899                    {
900                        match self.#name() {
901                            Ok(value) => write!(f, #ok_format_string, value),
902                            Err(invalid) => write!(f, #err_format_string, invalid.0),
903                        }?;
904                    }
905                }
906            } else {
907                let format_string = format!(
908                    "{{indent}}{name_str}: {{{default_specifier}}},{{sep}}"
909                );
910                let format_string = Literal::string(&format_string);
911                quote! {
912                    #cfg_attr
913                    { write!(f, #format_string, self.#name())?; }
914                }
915            }
916        });
917
918        quote! {
919            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result
920            #where_clause
921            {
922                let (sep, indent) = if f.alternate() {
923                    ('\n', "    ")
924                } else {
925                    (' ', "")
926                };
927                write!(f, "{} {{{sep}", #ty_str)?;
928                #(#fmt_fields)*
929                write!(f, "}}")
930            }
931        }
932    }
933
934    fn fmt_impls(&self) -> TokenStream2 {
935        let ty = &self.ty.def.ident;
936        let (impl_generics, ty_generics, where_clause) =
937            self.ty.def.generics.split_for_impl();
938        let lower_hex_fmt = self.fmt_fn(":#x");
939        let upper_hex_fmt = self.fmt_fn(":#X");
940        let binary_fmt = self.fmt_fn(":#b");
941        let octal_fmt = self.fmt_fn(":#o");
942        quote! {
943            impl #impl_generics ::core::fmt::Debug for #ty #ty_generics #where_clause {
944                fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
945                    ::core::fmt::LowerHex::fmt(self, f)
946                }
947            }
948
949            impl #impl_generics ::core::fmt::Binary for #ty #ty_generics #where_clause {
950                #binary_fmt
951            }
952
953            impl #impl_generics ::core::fmt::LowerHex for #ty #ty_generics #where_clause {
954                #lower_hex_fmt
955            }
956
957            impl #impl_generics ::core::fmt::UpperHex for #ty #ty_generics #where_clause {
958                #upper_hex_fmt
959            }
960
961            impl #impl_generics ::core::fmt::Octal for #ty #ty_generics #where_clause {
962                #octal_fmt
963            }
964        }
965    }
966}
967
968impl Parse for Bitfields {
969    fn parse(input: ParseStream) -> Result<Self> {
970        let input = {
971            let content;
972            braced!(content in input);
973            content
974        };
975
976        let ty = input.parse::<TypeDef>()?;
977
978        let input = {
979            let content;
980            braced!(content in input);
981            content
982        };
983
984        let mut fields = Vec::new();
985        let mut errors = Vec::new();
986        let is_usize = matches!(ty.base.ty, BaseType::Usize);
987
988        // Phase 1: parse cfg blocks. Each is `#[cfg(...)] { fields }`.
989        // We use a fork to distinguish a cfg block from a bare field with
990        // a stray attribute (which the field parser will reject).
991        let mut seen_widths = HashSet::new();
992        while input.peek(syn::Token![#]) {
993            let fork = input.fork();
994            let attrs = fork.call(Attribute::parse_outer)?;
995            if !fork.peek(syn::token::Brace) {
996                break;
997            }
998            input.advance_to(&fork);
999
1000            let attr = &attrs[0];
1001            if attrs.len() > 1 {
1002                return Err(Error::new_spanned(
1003                    &attrs[1],
1004                    "expected `{` after cfg attribute",
1005                ));
1006            }
1007            let width = parse_target_pointer_width_cfg(attr)?;
1008
1009            if !is_usize {
1010                errors.push(Error::new_spanned(
1011                    attr,
1012                    "#[cfg] blocks are only permitted in `usize`-based layouts",
1013                ));
1014            }
1015            if seen_widths.contains(width.as_str()) {
1016                errors.push(Error::new_spanned(
1017                    attr,
1018                    format!(
1019                        "duplicate cfg block for target_pointer_width = \"{width}\""
1020                    ),
1021                ));
1022            }
1023
1024            let block;
1025            braced!(block in input);
1026            if block.is_empty() {
1027                errors.push(Error::new_spanned(
1028                    attr,
1029                    "cfg block must contain at least one field",
1030                ));
1031            }
1032            while !block.is_empty() {
1033                let mut field = block.parse::<Bitfield>()?;
1034                field.cfg_pointer_width = Some(width.clone());
1035                fields.push(field);
1036            }
1037            seen_widths.insert(width);
1038        }
1039
1040        // Phase 2: bare fields.
1041        while !input.is_empty() {
1042            fields.push(input.parse::<Bitfield>()?);
1043        }
1044
1045        fields.sort_by_key(|field| field.low_bit);
1046
1047        for i in 0..fields.len() {
1048            let curr = &fields[i];
1049
1050            // The might be multiple overlapping fields, and some might be valid
1051            // if mutually excluded due to differing target pointer cfg
1052            // conditions.
1053            for next in fields.iter().skip(i + 1) {
1054                if curr.high_bit < next.low_bit {
1055                    break;
1056                }
1057                let can_overlap = curr.cfg_pointer_width.is_some()
1058                    && next.cfg_pointer_width.is_some()
1059                    && curr.cfg_pointer_width != next.cfg_pointer_width;
1060                if !can_overlap {
1061                    // TODO(https://github.com/rust-lang/rust/issues/54725): It
1062                    // would be nice to Span::join() the two spans, but that's still
1063                    // experimental.
1064                    errors.push(Error::new(
1065                        next.span,
1066                        format!(
1067                            "{} ({} {}) overlaps with {} ({} {})",
1068                            next.display_name(),
1069                            next.display_kind(),
1070                            next.display_range(),
1071                            curr.display_name(),
1072                            curr.display_kind(),
1073                            curr.display_range(),
1074                        ),
1075                    ));
1076                }
1077            }
1078        }
1079
1080        if let Some(highest_possible) = ty.base.ty.high_bit()
1081            && let Some(highest) = fields.last()
1082            && highest.high_bit > highest_possible
1083        {
1084            errors.push(Error::new(
1085                highest.span,
1086                format!(
1087                    "high bit {} exceeds the highest possible value \
1088                     of {highest_possible}",
1089                    highest.high_bit
1090                ),
1091            ));
1092        }
1093
1094        let mut bitfld = Self {
1095            ty,
1096            named: vec![],
1097            reserved: vec![],
1098            errors,
1099        };
1100
1101        while let Some(field) = fields.pop() {
1102            if field.is_reserved() {
1103                if field.default.is_some() {
1104                    bitfld.reserved.push(field);
1105                }
1106            } else {
1107                bitfld.named.push(field);
1108            }
1109        }
1110
1111        Ok(bitfld)
1112    }
1113}
1114
1115impl ToTokens for Bitfields {
1116    fn to_tokens(&self, tokens: &mut TokenStream2) {
1117        let type_def = &self.ty.def;
1118        let type_name = &type_def.ident;
1119        let base = &self.ty.base.def;
1120
1121        let (impl_generics, ty_generics, where_clause) =
1122            type_def.generics.split_for_impl();
1123
1124        if !self.errors.is_empty() {
1125            let errors = self.errors.iter().map(Error::to_compile_error);
1126            quote! {
1127                #[derive(Copy, Clone, Eq, PartialEq)]
1128                #type_def
1129                #(#errors)*
1130            }
1131            .to_tokens(tokens);
1132            return;
1133        }
1134
1135        let constants = self.constants();
1136        let getters_and_setters = self.getters_and_setters();
1137        let iter_impl = self.iter_impl();
1138        let fmt_impls = self.fmt_impls();
1139        quote! {
1140            #[derive(Copy, Clone, Eq, PartialEq)]
1141            #type_def
1142
1143            impl #impl_generics #type_name #ty_generics #where_clause {
1144                #constants
1145
1146                /// Creates a new instance with reserved-as-1 bits set and
1147                /// all other bits zeroed (i.e., with a value of
1148                /// [`Self::RSVD1_MASK`]).
1149                pub const fn new() -> Self {
1150                    Self(Self::RSVD1_MASK)
1151                }
1152
1153                #(#getters_and_setters)*
1154            }
1155
1156            impl #impl_generics ::core::default::Default for #type_name #ty_generics #where_clause {
1157                /// Returns an instance with the default bits set (i.e,. with a
1158                /// value of [`Self::DEFAULT`].
1159                fn default() -> Self {
1160                    Self(Self::DEFAULT)
1161                }
1162            }
1163
1164            impl #impl_generics ::core::convert::From<#base> for #type_name #ty_generics #where_clause {
1165                // `RSVD{0,1}_MASK` may be zero, in which case the following
1166                // mask conditions might be trivially true.
1167                #[allow(clippy::bad_bit_mask)]
1168                fn from(value: #base) -> Self {
1169                    debug_assert!(
1170                        value & Self::RSVD1_MASK == Self::RSVD1_MASK,
1171                        "from(): Invalid base value ({value:#x}) has reserved-as-1 bits ({:#x}) unset",
1172                        Self::RSVD1_MASK,
1173                    );
1174                    debug_assert!(
1175                        !value & Self::RSVD0_MASK == Self::RSVD0_MASK,
1176                        "from(): Invalid base value ({value:#x}) has reserved-as-0 bits ({:#x}) set",
1177                        Self::RSVD0_MASK,
1178                    );
1179                    Self(value)
1180                }
1181            }
1182
1183            impl #impl_generics ::core::ops::Deref for #type_name #ty_generics #where_clause {
1184                type Target = #base;
1185
1186                fn deref(&self) -> &Self::Target {
1187                    &self.0
1188                }
1189            }
1190
1191            impl #impl_generics ::core::ops::DerefMut for #type_name #ty_generics #where_clause {
1192                fn deref_mut(&mut self) -> &mut Self::Target {
1193                    &mut self.0
1194                }
1195            }
1196
1197            #iter_impl
1198
1199            #fmt_impls
1200        }
1201        .to_tokens(tokens);
1202    }
1203}