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