11use proc_macro:: TokenStream ;
22use proc_macro2:: { Ident , Span } ;
3- use syn:: { Item , Token , parse, parse:: Parser , punctuated:: Punctuated } ;
3+ use syn:: { Item , Token , parse, parse:: Parser , punctuated:: Punctuated , spanned :: Spanned } ;
44
55pub fn ram ( args : TokenStream , input : TokenStream ) -> TokenStream {
66 let attr_args = match Punctuated :: < syn:: Meta , Token ! [ , ] > :: parse_terminated. parse2 ( args. into ( ) ) {
@@ -15,30 +15,99 @@ pub fn ram(args: TokenStream, input: TokenStream) -> TokenStream {
1515 let mut zeroed = false ;
1616
1717 for attr_arg in & attr_args {
18- if let syn:: Meta :: Path ( path) = attr_arg {
19- let ident = match path. require_ident ( ) {
20- Ok ( i) => i,
21- Err ( e) => return e. into_compile_error ( ) . into ( ) ,
22- } ;
23- let arg = match ident {
24- i if i == "rtc_fast" => & mut rtc_fast,
25- i if i == "rtc_slow" => & mut rtc_slow,
26- i if i == "reclaimed" => & mut dram2_uninit,
27- i if i == "persistent" => & mut persistent,
28- i if i == "zeroed" => & mut zeroed,
29- i => {
30- return syn:: Error :: new ( i. span ( ) , format ! ( "Unknown argument `{i}`" ) )
18+ match attr_arg {
19+ syn:: Meta :: List ( list) if list. path . is_ident ( "unstable" ) => {
20+ let nested = & list. tokens ;
21+ let nested_args = match Punctuated :: < syn:: Meta , Token ! [ , ] > :: parse_terminated
22+ . parse2 ( nested. clone ( ) )
23+ {
24+ Ok ( v) => v,
25+ Err ( e) => return e. to_compile_error ( ) . into ( ) ,
26+ } ;
27+
28+ for meta in nested_args {
29+ match meta {
30+ syn:: Meta :: Path ( path) => {
31+ let Some ( ident) = path. get_ident ( ) else {
32+ return syn:: Error :: new (
33+ path. span ( ) ,
34+ "Expected identifier inside `unstable(...)`" ,
35+ )
36+ . into_compile_error ( )
37+ . into ( ) ;
38+ } ;
39+ let arg = match ident {
40+ i if i == "rtc_fast" => & mut rtc_fast,
41+ i if i == "rtc_slow" => & mut rtc_slow,
42+ i if i == "persistent" => & mut persistent,
43+ i if i == "zeroed" => & mut zeroed,
44+ i => {
45+ return syn:: Error :: new (
46+ i. span ( ) ,
47+ format ! ( "Unknown unstable argument `{i}`" ) ,
48+ )
49+ . into_compile_error ( )
50+ . into ( ) ;
51+ }
52+ } ;
53+
54+ if * arg {
55+ return syn:: Error :: new (
56+ ident. span ( ) ,
57+ format ! ( "Argument `{ident}` is already set" ) ,
58+ )
59+ . into_compile_error ( )
60+ . into ( ) ;
61+ }
62+
63+ * arg = true ;
64+ }
65+ _ => {
66+ return syn:: Error :: new (
67+ list. span ( ) ,
68+ "Expected identifiers inside `unstable(...)`" ,
69+ )
70+ . into_compile_error ( )
71+ . into ( ) ;
72+ }
73+ }
74+ }
75+ }
76+
77+ syn:: Meta :: Path ( path) => {
78+ let Some ( ident) = path. get_ident ( ) else {
79+ return syn:: Error :: new ( path. span ( ) , "Expected identifier" )
80+ . into_compile_error ( )
81+ . into ( ) ;
82+ } ;
83+ let arg = match ident {
84+ i if i == "reclaimed" => & mut dram2_uninit,
85+ _ => {
86+ return syn:: Error :: new (
87+ ident. span ( ) ,
88+ format ! ( "`{ident}` must be wrapped in `unstable(...)`" ) ,
89+ )
3190 . into_compile_error ( )
3291 . into ( ) ;
92+ }
93+ } ;
94+
95+ if * arg {
96+ return syn:: Error :: new (
97+ ident. span ( ) ,
98+ format ! ( "Argument `{ident}` is already set" ) ,
99+ )
100+ . into_compile_error ( )
101+ . into ( ) ;
33102 }
34- } ;
103+ * arg = true ;
104+ }
35105
36- if * arg {
37- return syn:: Error :: new ( ident . span ( ) , format ! ( "Argument `{ident}` is already set" ) )
106+ _ => {
107+ return syn:: Error :: new ( attr_arg . span ( ) , "Unsupported attribute syntax for `ram`" )
38108 . into_compile_error ( )
39109 . into ( ) ;
40110 }
41- * arg = true ;
42111 }
43112 }
44113
0 commit comments