1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{
4 ext::IdentExt,
5 parenthesized,
6 parse::{discouraged::Speculative, Parse, ParseStream},
7 parse_macro_input, Attribute, Expr, Ident, Token, Type, Visibility,
8};
9
10mod kw {
11 use syn::custom_keyword;
12
13 custom_keyword!(bool);
14 custom_keyword!(from);
15 custom_keyword!(getter);
16 custom_keyword!(into);
17 custom_keyword!(try_into);
18 custom_keyword!(mask);
19 custom_keyword!(only);
20 custom_keyword!(setter);
21}
22
23struct BitfieldMask {
26 ident: Ident,
27 ty: Type,
28}
29
30impl Parse for BitfieldMask {
31 fn parse(input: ParseStream) -> syn::Result<Self> {
32 let ident = input.parse()?;
33 let paren_content;
34 parenthesized!(paren_content in input);
35 let ty = paren_content.parse()?;
36 Ok(BitfieldMask { ident, ty })
37 }
38}
39
40enum BitfieldPosition {
41 Bit(Expr),
42 MsbLsb(Expr, Expr),
43 MsbLsbCount(Expr, Expr, Expr),
44}
45
46impl Parse for BitfieldPosition {
47 fn parse(input: ParseStream) -> syn::Result<Self> {
48 let bit_position_1 = input.parse()?;
49 if !input.peek(Token!(,)) {
50 return Ok(BitfieldPosition::Bit(bit_position_1));
51 }
52 input.parse::<Token!(,)>()?;
53 let bit_position_2 = input.parse()?;
54 if !input.peek(Token!(,)) {
55 return Ok(BitfieldPosition::MsbLsb(bit_position_1, bit_position_2));
56 }
57 input.parse::<Token!(,)>()?;
58 let bit_position_3 = input.parse()?;
59
60 Ok(BitfieldPosition::MsbLsbCount(
61 bit_position_1,
62 bit_position_2,
63 bit_position_3,
64 ))
65 }
66}
67
68enum FieldTy {
69 Bool,
70 Type(Type),
71 None,
72}
73
74impl FieldTy {
75 fn as_type(&self) -> Option<Type> {
76 match self {
77 FieldTy::Bool => Some(syn::parse_str("bool").unwrap()),
78 FieldTy::Type(ty) => Some(ty.clone()),
79 FieldTy::None => None,
80 }
81 }
82
83 fn is_none(&self) -> bool {
84 matches!(self, FieldTy::None)
85 }
86}
87
88impl From<Option<Type>> for FieldTy {
89 fn from(value: Option<Type>) -> Self {
90 match value {
91 Some(ty) => FieldTy::Type(ty),
92 None => FieldTy::None,
93 }
94 }
95}
96
97struct BitfieldField {
98 attrs: Vec<Attribute>,
99 vis: Visibility,
100 ty: FieldTy,
101 mask: Option<BitfieldMask>,
102 from: bool,
103 into: bool,
104 try_into: bool,
105 from_into_ty: Option<Type>,
106 getter: Ident,
107 setter: Ident,
108 bits_position: BitfieldPosition,
109}
110
111impl BitfieldField {
112 fn ty_from(&self) -> Option<Type> {
113 if self.from {
114 self.from_into_ty.clone()
115 } else {
116 self.ty.as_type()
117 }
118 }
119
120 fn ty_into(&self) -> Option<Type> {
121 if self.into || self.try_into {
122 self.from_into_ty.clone()
123 } else {
124 self.ty.as_type()
125 }
126 }
127}
128
129impl Parse for BitfieldField {
130 fn parse(input: ParseStream) -> syn::Result<Self> {
131 let attrs = input.call(Attribute::parse_outer)?;
132 let vis = input.parse()?;
133 let mut ty = FieldTy::None;
134 if input.peek(kw::bool) && input.peek2(Token!(,)) {
135 input.parse::<kw::bool>()?;
136 ty = FieldTy::Bool;
137 input.parse::<Token!(,)>()?;
138 } else {
139 let input_fork = input.fork();
140 if let Ok(parsed_ty) = input_fork.parse() {
141 if input_fork.peek(Token!(,)) && !input_fork.peek3(Token!(:)) {
142 ty = FieldTy::Type(parsed_ty);
143 input.advance_to(&input_fork);
144 input.parse::<Token!(,)>()?;
145 }
146 }
147 };
148
149 let mut mask = None;
150 if input.peek(kw::mask) && !input.peek2(Token!(,)) {
153 input.parse::<kw::mask>()?;
154 mask = Some(input.parse()?);
155 input.parse::<Token!(,)>()?;
156 }
157
158 let from = input.peek(kw::from) && !input.peek2(Token!(,));
159 if from {
160 input.parse::<kw::from>()?;
161 }
162
163 let into = input.peek(kw::into) && !input.peek2(Token!(,));
164
165 let mut try_into = false;
166 if into {
167 input.parse::<kw::into>()?;
168 } else {
169 try_into = input.peek(kw::try_into) && !input.peek2(Token!(,));
170 if try_into {
171 input.parse::<kw::try_into>()?;
172 }
173 }
174
175 let mut from_into_ty = None;
176 if from || into || try_into {
177 from_into_ty = Some(input.parse()?);
178 input.parse::<Token!(,)>()?;
179 };
180
181 let getter = input.call(Ident::parse_any)?;
182 input.parse::<Token!(,)>()?;
183 let setter = input.call(Ident::parse_any)?;
184 input.parse::<Token!(:)>()?;
185 let bits_position = input.parse()?;
186
187 Ok(BitfieldField {
188 attrs,
189 vis,
190 ty,
191 mask,
192 from,
193 into,
194 try_into,
195 from_into_ty,
196 getter,
197 setter,
198 bits_position,
199 })
200 }
201}
202
203enum BitfieldFieldLine {
204 NewDefaultType(Type),
205 Field(BitfieldField),
206}
207
208impl Parse for BitfieldFieldLine {
209 fn parse(input: ParseStream) -> syn::Result<Self> {
210 let input_fork = input.fork();
211
212 Ok(match input_fork.parse() {
213 Ok(ty) if (input_fork.is_empty() || input_fork.peek(Token!(;))) => {
216 input.advance_to(&input_fork);
217 BitfieldFieldLine::NewDefaultType(ty)
218 }
219 _ => BitfieldFieldLine::Field(input.parse()?),
220 })
221 }
222}
223
224struct BitfieldFieldLines(Vec<BitfieldFieldLine>);
225
226impl BitfieldFieldLines {
227 fn into_fields(self) -> Vec<BitfieldField> {
228 let mut result = vec![];
229 let mut default_ty = None;
230 for line in self.0 {
231 match line {
232 BitfieldFieldLine::NewDefaultType(ty) => default_ty = Some(ty),
233 BitfieldFieldLine::Field(mut field) => {
234 if field.ty.is_none() {
235 field.ty = default_ty.clone().into();
236 }
237 result.push(field)
238 }
239 }
240 }
241
242 result
243 }
244}
245
246impl Parse for BitfieldFieldLines {
247 fn parse(input: ParseStream) -> syn::Result<Self> {
248 let field_lines = input
249 .parse_terminated(BitfieldFieldLine::parse, Token!(;))?
250 .into_iter()
251 .collect();
252
253 Ok(BitfieldFieldLines(field_lines))
254 }
255}
256
257#[derive(Copy, Clone, Eq, PartialEq)]
258enum Only {
259 Getter,
260 Mask,
261 Setter,
262 None,
263}
264
265impl Only {
266 fn getter_or_none(&self) -> bool {
267 *self == Only::Getter || *self == Only::None
268 }
269
270 fn mask_or_none(&self) -> bool {
271 *self == Only::Mask || *self == Only::None
272 }
273
274 fn setter_or_none(&self) -> bool {
275 *self == Only::Setter || *self == Only::None
276 }
277}
278
279struct BitfieldFieldsWithOnly {
280 only: Only,
281 fields: BitfieldFieldLines,
282}
283
284impl Parse for BitfieldFieldsWithOnly {
285 fn parse(input: ParseStream) -> syn::Result<Self> {
286 let only = if input.peek(kw::only) {
287 input.parse::<kw::only>()?;
288 let only = if input.peek(kw::getter) {
289 input.parse::<kw::getter>()?;
290 Only::Getter
291 } else if input.peek(kw::setter) {
292 input.parse::<kw::setter>()?;
293 Only::Setter
294 } else if input.peek(kw::mask) {
295 input.parse::<kw::mask>()?;
296 Only::Mask
297 } else {
298 return Err(input
299 .error("after the only keyword, either getter, mask or setter is expected"));
300 };
301 input.parse::<Token!(;)>()?;
302 only
303 } else {
304 Only::None
305 };
306 let fields = input.parse()?;
307
308 Ok(BitfieldFieldsWithOnly { only, fields })
309 }
310}
311
312#[proc_macro]
387pub fn bitfield_fields(input: TokenStream) -> TokenStream {
388 let fields_with_only = parse_macro_input!(input as BitfieldFieldsWithOnly);
389
390 let only = fields_with_only.only;
391 let fields = fields_with_only.fields.into_fields();
392
393 let getters = if only.getter_or_none() {
394 generate_getters(&fields)
395 } else {
396 quote! {}
397 };
398
399 let setters = if only.setter_or_none() {
400 generate_setters(&fields)
401 } else {
402 quote! {}
403 };
404
405 let masks = if only.mask_or_none() {
406 generate_masks(&fields)
407 } else {
408 quote! {}
409 };
410
411 let expanded = quote! {
412 #getters
413 #setters
414 #masks
415 };
416 TokenStream::from(expanded)
417}
418static MISSING_TYPE_ERROR_MESSAGE: &str =
419 "For non single bit field, you need to either specify a default type or a type for each field";
420
421fn generate_getters(fields: &[BitfieldField]) -> proc_macro2::TokenStream {
422 let getters = fields.iter().flat_map(|field| {
423 if field.getter != "_" {
424 let attrs = &field.attrs;
425 let vis = &field.vis;
426 let getter = &field.getter;
427 Some(match &field.bits_position {
428 BitfieldPosition::Bit(bit) => {
429 quote! {
430 #(#attrs)*
431 #vis fn #getter(&self) -> bool {
432 use ::bitfield::Bit;
433 self.bit(#bit)
434 }
435 }
436 }
437 BitfieldPosition::MsbLsb(msb, lsb) => {
438 let ty = field.ty.as_type().expect(MISSING_TYPE_ERROR_MESSAGE);
439 let ty_into = field.ty_into().unwrap();
440 if field.try_into {
441 quote! {
442 #(#attrs)*
443 #vis fn #getter(&self) -> Result<#ty_into, <#ty_into as TryFrom<#ty>>::Error> {
444 use ::bitfield::BitRange;
445 let raw_value: #ty = self.bit_range(#msb, #lsb);
446 ::bitfield::TryInto::try_into(raw_value)
447 }
448 }
449 } else {
450 quote! {
451 #(#attrs)*
452 #vis fn #getter(&self) -> #ty_into {
453 use ::bitfield::BitRange;
454 let raw_value: #ty = self.bit_range(#msb, #lsb);
455 ::bitfield::Into::into(raw_value)
456 }
457 }
458 }
459 }
460 BitfieldPosition::MsbLsbCount(msb, lsb, count) => match &field.ty {
461 FieldTy::Bool => {
462 quote! {
463 #(#attrs)*
464 #vis fn #getter(&self, index: usize) -> bool {
465 use ::bitfield::Bit;
466 assert_eq!(#msb, #lsb);
467 use ::bitfield::BitRange;
468 debug_assert!(index < #count);
469 self.bit((#lsb)+index)
470 }
471 }
472 }
473 FieldTy::Type(ty) => {
474 let ty_into = field.ty_into().unwrap();
475 let (return_ty, last_line) = if field.try_into {
476 (
477 quote!{Result<#ty_into, <#ty_into as TryFrom<#ty>>::Error>},
478 quote!{::bitfield::TryInto::try_into(raw_value)}
479 )
480 } else {
481 (quote!{#ty_into}, quote!{::bitfield::Into::into(raw_value)})
482 };
483 quote! {
484 #(#attrs)*
485 #vis fn #getter(&self, index: usize) -> #return_ty {
486 use ::bitfield::BitRange;
487 ::bitfield::check_msb_lsb_order!(#msb, #lsb);
488 debug_assert!(index < #count);
489 #[allow(clippy::eq_op)]
490 #[allow(clippy::identity_op)]
491 let width = #msb - #lsb + 1;
492 let lsb = #lsb + index*width;
493 let msb = lsb + width - 1;
494 let raw_value: #ty = self.bit_range(msb, lsb);
495 #last_line
496 }
497 }
498 }
499 FieldTy::None => panic!("{}", MISSING_TYPE_ERROR_MESSAGE),
500 },
501 })
502 } else {
503 None
504 }
505 });
506 quote! { #(#getters)* }
507}
508
509fn generate_setters(fields: &[BitfieldField]) -> proc_macro2::TokenStream {
510 let setters = fields.iter().flat_map(|field| {
511 if field.setter != "_" {
512 let attrs = &field.attrs;
513 let vis = &field.vis;
514 let setter = &field.setter;
515 Some(match &field.bits_position {
516 BitfieldPosition::Bit(bit) => {
517 quote! {
518 #(#attrs)*
519 #vis fn #setter(&mut self, value: bool) {
520 use ::bitfield::BitMut;
521 self.set_bit(#bit, value);
522 }
523 }
524 }
525 BitfieldPosition::MsbLsb(msb, lsb) => {
526 let ty = field.ty.as_type().expect(MISSING_TYPE_ERROR_MESSAGE);
527 let ty_from = field.ty_from().unwrap();
528 quote! {
529 #(#attrs)*
530 #vis fn #setter(&mut self, value: #ty_from) {
531 use ::bitfield::BitRangeMut;
532 self.set_bit_range(#msb, #lsb, ::bitfield::Into::<#ty>::into(value));
533 }
534 }
535 }
536 BitfieldPosition::MsbLsbCount(msb, lsb, count) => match &field.ty {
537 FieldTy::Bool => {
538 let ty_from = field.ty_from().unwrap();
539 quote! {
540 #(#attrs)*
541 #vis fn #setter(&mut self, index: usize, value: #ty_from) {
542 use ::bitfield::BitMut;
543 debug_assert!(index < #count);;
544 self.set_bit(#lsb+index, ::bitfield::Into::<bool>::into(value));
545 }
546 }
547 }
548 FieldTy::Type(ty) => {
549 let ty_from = field.ty_from().unwrap();
550 quote! {
551 #(#attrs)*
552 #vis fn #setter(&mut self, index: usize, value: #ty_from) {
553 use ::bitfield::BitRangeMut;
554 ::bitfield::check_msb_lsb_order!(#msb, #lsb);
555 debug_assert!(index < #count);
556 #[allow(clippy::eq_op)]
557 #[allow(clippy::identity_op)]
558 let width = #msb - #lsb + 1;
559 let lsb = #lsb + index*width;
560 let msb = lsb + width - 1;
561 self.set_bit_range(msb, lsb, ::bitfield::Into::<#ty>::into(value));
562 }
563 }
564 }
565 FieldTy::None => panic!("{}", MISSING_TYPE_ERROR_MESSAGE),
566 },
567 })
568 } else {
569 None
570 }
571 });
572 quote! { #(#setters)* }
573}
574
575fn generate_masks(fields: &[BitfieldField]) -> proc_macro2::TokenStream {
576 let masks = fields.iter().flat_map(|field| {
577 if let Some(mask) = &field.mask {
578 let vis = &field.vis;
579 let mask_ident = &mask.ident;
580 let mask_ty = &mask.ty;
581 Some(match &field.bits_position {
582 BitfieldPosition::Bit(bit) => {
583 quote! {#vis const #mask_ident: #mask_ty = 1 << (#bit);}
584 }
585 BitfieldPosition::MsbLsb(msb, lsb) => {
586 quote! {
587 #vis const #mask_ident: #mask_ty = {
588 let msb = #msb;
589 let lsb = #lsb;
590 let mut i = lsb;
591 let mut acc = 0;
592 while i <= msb {
593 acc |= 1<<i;
594 i += 1;
595 }
596 acc
597 };
598 }
599 }
600 BitfieldPosition::MsbLsbCount(msb, lsb, count) => {
601 quote! {
602 #vis const #mask_ident: #mask_ty = {
603 let msb = #msb;
604 let lsb = #lsb;
605 let count = #count;
606 let width = msb - lsb;
607 let full_msb = msb + width * count;
608 let mut i = lsb;
609 let mut acc = 0;
610 while i <= full_msb {
611 acc |= 1<<i;
612 i += 1;
613 }
614 acc
615 };
616 }
617 }
618 })
619 } else {
620 None
621 }
622 });
623 quote! { #(#masks)* }
624}
625
626#[proc_macro]
628pub fn bitfield_constructor(input: TokenStream) -> TokenStream {
629 let fields_with_only = parse_macro_input!(input as BitfieldFieldsWithOnly);
630
631 let fields = fields_with_only.fields.into_fields();
632
633 let fields_with_setter: Vec<_> = fields
634 .into_iter()
635 .filter(|field| field.setter != "_")
636 .collect();
637 let args = fields_with_setter.iter().map(|field| {
638 let name = &field.setter;
639 match &field.bits_position {
640 BitfieldPosition::Bit(_) => {
641 quote! {
642 #name: bool
643 }
644 }
645 BitfieldPosition::MsbLsb(_, _) => {
646 let ty_from = field.ty_from().expect(MISSING_TYPE_ERROR_MESSAGE);
647 quote! {
648 #name: #ty_from
649 }
650 }
651 BitfieldPosition::MsbLsbCount(_, _, _) => {
652 panic!("Array fields as not supported in the `new` method generator")
653 }
654 }
655 });
656
657 let setter_idents = fields_with_setter.iter().map(|field| &field.setter);
658
659 let expanded = quote! {
660 #[allow(clippy::too_many_arguments, missing_docs)]
661 pub fn new(#(#args,)*) -> Self {
662 let mut value = Self(Default::default());
663 #(value.#setter_idents(#setter_idents);)*
664 value
665 }
666 };
667
668 TokenStream::from(expanded)
669}
670
671struct BitfieldDebugArgs {
672 name: Ident,
673 field_lines: BitfieldFieldLines,
674}
675
676impl Parse for BitfieldDebugArgs {
677 fn parse(input: ParseStream) -> syn::Result<Self> {
678 input.parse::<Token!(struct)>()?;
679 let name = input.parse()?;
680 input.parse::<Token!(;)>()?;
681 let field_lines = input.parse()?;
682
683 Ok(BitfieldDebugArgs { name, field_lines })
684 }
685}
686
687#[proc_macro]
724pub fn bitfield_debug(input: TokenStream) -> TokenStream {
725 let args = parse_macro_input!(input as BitfieldDebugArgs);
726
727 let name = args.name;
728 let fields = args.field_lines.into_fields();
729 let fields_expr = fields
730 .iter()
731 .filter(|field| field.getter != "_")
732 .map(|field| {
733 let getter = &field.getter;
734 match &field.bits_position {
735 BitfieldPosition::Bit(_) | BitfieldPosition::MsbLsb(_, _) => {
736 quote! {
737 debug_struct.field(stringify!(#getter), &self.#getter());
738 }
739 }
740 BitfieldPosition::MsbLsbCount(_, _, count) => {
741 quote! {
742 let mut array = [self.#getter(0); #count];
743 for (i, e) in (&mut array).into_iter().enumerate() {
744 *e = self.#getter(i);
745 }
746 debug_struct.field(stringify!(#getter), &array);
747 }
748 }
749 }
750 });
751
752 let expanded = quote! {
753 fn fmt(&self, f: &mut ::bitfield::fmt::Formatter) -> ::bitfield::fmt::Result {
754 let mut debug_struct = f.debug_struct(stringify!(#name));
755 debug_struct.field(".0", &self.0);
756 #(#fields_expr)*
757 debug_struct.finish()
758 }
759 };
760
761 TokenStream::from(expanded)
762}