11mod codegen;
22mod parsing;
33
4+ use proc_macro:: Span ;
45use proc_macro:: TokenStream ;
6+ use proc_macro2:: Ident ;
57use proc_macro2:: TokenStream as TokenStream2 ;
6- use proc_macro2 :: { Ident , TokenTree } ;
8+ use quote :: TokenStreamExt ;
79use quote:: { quote, ToTokens } ;
810use std:: ops:: Range ;
911use std:: str:: FromStr ;
10- use syn:: { Attribute , Data , DeriveInput , Type } ;
12+ use syn:: meta:: ParseNestedMeta ;
13+ use syn:: { parse_macro_input, Attribute , Data , DeriveInput , LitInt , Token , Type } ;
1114
1215/// In the code below, bools are considered to have 0 bits. This lets us distinguish them
1316/// from u1
@@ -73,78 +76,82 @@ impl BaseDataSize {
7376 }
7477}
7578
76- pub fn bitfield ( args : TokenStream , input : TokenStream ) -> TokenStream {
77- let args: Vec < _ > = proc_macro2:: TokenStream :: from ( args) . into_iter ( ) . collect ( ) ;
79+ pub enum DefaultVal {
80+ Lit ( LitInt ) ,
81+ Constant ( Ident ) ,
82+ }
7883
79- if args. is_empty ( ) {
80- panic ! (
81- "bitfield! No arguments given, but need at least base data type (e.g. 'bitfield(u32)')"
82- ) ;
84+ impl ToTokens for DefaultVal {
85+ fn to_tokens ( & self , tokens : & mut TokenStream2 ) {
86+ match self {
87+ DefaultVal :: Lit ( lit) => lit. to_tokens ( tokens) ,
88+ DefaultVal :: Constant ( ident) => ident. to_tokens ( tokens) ,
89+ }
8390 }
91+ }
8492
85- // Parse arguments: the first argument is required and has the base data type. Further arguments are
86- // optional and are key:value pairs
87- let base_data_type = & args[ 0 ] ;
88- let mut default_value: Option < TokenStream2 > = None ;
93+ #[ derive( Default ) ]
94+ struct BitfieldAttributes {
95+ pub base_type : Option < Ident > ,
96+ pub default_val : Option < DefaultVal > ,
97+ pub debug_trait : bool ,
98+ }
8999
90- enum ArgumentType {
91- Default ,
92- }
93- let mut next_expected: Option < ArgumentType > = None ;
94-
95- fn handle_next_expected (
96- next_expected : & Option < ArgumentType > ,
97- default_value : & mut Option < TokenStream2 > ,
98- token_stream : TokenStream2 ,
99- ) {
100- match next_expected {
101- None => panic ! ( "bitfield!: Unexpected token {}. Example of valid syntax: #[bitfield(u32, default = 0)]" , token_stream) ,
102- Some ( ArgumentType :: Default ) => {
103- * default_value = Some ( token_stream) ;
104- }
100+ impl BitfieldAttributes {
101+ fn parse ( & mut self , meta : ParseNestedMeta , index : usize ) -> Result < ( ) , syn:: Error > {
102+ if index == 0 {
103+ self . base_type = Some ( meta. path . require_ident ( ) ?. clone ( ) ) ;
104+ return Ok ( ( ) ) ;
105105 }
106- }
107- for arg in args. iter ( ) . skip ( 1 ) {
108- match arg {
109- TokenTree :: Punct ( p) => match p. as_char ( ) {
110- ',' => next_expected = None ,
111- '=' | ':' => ( ) ,
112- _ => panic ! (
113- "bitfield!: Expected ',', '=' or ':' in argument list. Saw '{}'" ,
114- p
115- ) ,
116- } ,
117- TokenTree :: Ident ( sym) => {
118- if next_expected. is_some ( ) {
119- // We might end up here if we refer to a constant, like 'default = SOME_CONSTANT'
120- handle_next_expected ( & next_expected, & mut default_value, sym. to_token_stream ( ) ) ;
121- } else {
122- match sym. to_string ( ) . as_str ( ) {
123- "default" => {
124- if default_value. is_some ( ) {
125- panic ! ( "bitfield!: default must only be specified at most once" ) ;
126- }
127- next_expected = Some ( ArgumentType :: Default )
128- }
129- _ => panic ! (
130- "bitfield!: Unexpected argument {}. Supported: 'default'" ,
131- sym
132- ) ,
133- }
134- }
106+ if meta. path . is_ident ( "default" ) {
107+ let stream = & meta. input ;
108+
109+ // Try parsing either `:` or `=`
110+ if stream. parse :: < Token ! [ : ] > ( ) . is_err ( ) && stream. parse :: < Token ! [ =] > ( ) . is_err ( ) {
111+ return Err ( syn:: Error :: new (
112+ meta. input . span ( ) ,
113+ "Expected `:` or `=` after `default`" ,
114+ ) ) ;
115+ }
116+ let lit_int: Result < LitInt , syn:: Error > = stream. parse ( ) ;
117+ if lit_int. is_ok ( ) {
118+ self . default_val = Some ( DefaultVal :: Lit ( lit_int. unwrap ( ) ) ) ;
119+ return Ok ( ( ) ) ;
135120 }
136- TokenTree :: Literal ( literal) => {
137- // We end up here if we see a literal, like 'default = 0x1234'
138- handle_next_expected (
139- & next_expected,
140- & mut default_value,
141- literal. to_token_stream ( ) ,
142- ) ;
121+ let path: Result < Ident , syn:: Error > = stream. parse ( ) ;
122+ if path. is_ok ( ) {
123+ self . default_val = Some ( DefaultVal :: Constant ( path. unwrap ( ) ) ) ;
124+ return Ok ( ( ) ) ;
143125 }
144- t => panic ! ( "bitfield!: Unexpected token {}. Example of valid syntax: #[bitfield(u32, default = 0)]" , t ) ,
126+ return Ok ( ( ) ) ;
145127 }
128+ if meta. path . is_ident ( "debug" ) {
129+ self . debug_trait = true ;
130+ return Ok ( ( ) ) ;
131+ }
132+ Ok ( ( ) )
133+ }
134+ }
135+
136+ pub fn bitfield ( args : TokenStream , input : TokenStream ) -> TokenStream {
137+ let mut bitfield_attrs = BitfieldAttributes :: default ( ) ;
138+ let mut index = 0 ;
139+ let bitfield_parser = syn:: meta:: parser ( |meta| {
140+ let result = bitfield_attrs. parse ( meta, index) ;
141+ index += 1 ;
142+ result
143+ } ) ;
144+ if args. is_empty ( ) {
145+ return syn:: Error :: new (
146+ Span :: call_site ( ) . into ( ) ,
147+ "bitfield! No arguments given, but need at least a base data type (e.g. 'bitfield(u32)')" ) . to_compile_error ( ) . into ( ) ;
146148 }
149+ parse_macro_input ! ( args with bitfield_parser) ;
147150
151+ if bitfield_attrs. base_type . is_none ( ) {
152+ panic ! ( "bitfield!: First argument must be the base data type, e.g. 'bitfield(u32)'" , ) ;
153+ }
154+ let base_data_type = bitfield_attrs. base_type . as_ref ( ) . unwrap ( ) ;
148155 // If an arbitrary-int is specified as a base-type, we only use that when exposing it
149156 // (e.g. through raw_value() and for bounds-checks). The actual raw_value field will be the next
150157 // larger integer field
@@ -159,7 +166,7 @@ pub fn bitfield(args: TokenStream, input: TokenStream) -> TokenStream {
159166 }
160167 _ => {
161168 return syn:: Error :: new_spanned (
162- & base_data_type,
169+ base_data_type,
163170 format ! ( "bitfield!: Supported values for base data type are u8, u16, u32, u64, u128. {} is invalid" , base_data_type. to_string( ) . as_str( ) ) ,
164171 ) . to_compile_error ( ) . into ( ) ;
165172 }
@@ -184,7 +191,10 @@ pub fn bitfield(args: TokenStream, input: TokenStream) -> TokenStream {
184191 } ;
185192 let accessors = codegen:: generate ( & field_definitions, base_data_size, & internal_base_data_type) ;
186193
187- let ( default_constructor, default_trait) = if let Some ( default_value) = default_value. clone ( ) {
194+ let ( default_constructor, default_trait) = if let Some ( default_value) =
195+ & bitfield_attrs. default_val
196+ {
197+ let default_value = default_value. to_token_stream ( ) ;
188198 let constructor = {
189199 let comment = format ! ( "An instance that uses the default value {}" , default_value) ;
190200 let deprecated_warning = format ! (
@@ -224,9 +234,30 @@ pub fn bitfield(args: TokenStream, input: TokenStream) -> TokenStream {
224234 ( quote ! { } , quote ! { } )
225235 } ;
226236
237+ let mut debug_trait = TokenStream2 :: new ( ) ;
238+ if bitfield_attrs. debug_trait {
239+ let debug_fields: Vec < TokenStream2 > = field_definitions
240+ . iter ( )
241+ . map ( |field| {
242+ let field_name = & field. field_name ;
243+ quote ! {
244+ . field( stringify!( #field_name) , & self . #field_name( ) )
245+ }
246+ } )
247+ . collect ( ) ;
248+ debug_trait. append_all ( quote ! {
249+ impl core:: fmt:: Debug for #struct_name {
250+ fn fmt( & self , f: & mut std:: fmt:: Formatter <' _>) -> std:: fmt:: Result {
251+ f. debug_struct( stringify!( #struct_name) )
252+ #( #debug_fields) *
253+ . finish( )
254+ }
255+ }
256+ } ) ;
257+ }
227258 let ( new_with_constructor, new_with_builder_chain) = codegen:: make_builder (
228259 & struct_name,
229- default_value . is_some ( ) ,
260+ bitfield_attrs . default_val . is_some ( ) ,
230261 & struct_vis,
231262 & internal_base_data_type,
232263 base_data_type,
@@ -285,6 +316,7 @@ pub fn bitfield(args: TokenStream, input: TokenStream) -> TokenStream {
285316 #( #accessors ) *
286317 }
287318 #default_trait
319+ #debug_trait
288320 #( #new_with_builder_chain ) *
289321 } ;
290322 //println!("Expanded: {}", expanded.to_string());
0 commit comments