precompile_utils_macro/precompile/
attr.rs1use proc_macro2::Span;
20use quote::ToTokens;
21use syn::spanned::Spanned;
22
23pub fn take_attributes<A>(attributes: &mut Vec<syn::Attribute>) -> syn::Result<Vec<A>>
24where
25 A: syn::parse::Parse,
26{
27 let mut output = vec![];
28 let pred = |attr: &syn::Attribute| {
29 attr.path()
30 .segments
31 .first()
32 .is_some_and(|segment| segment.ident == "precompile")
33 };
34
35 while let Some(index) = attributes.iter().position(pred) {
36 let attr = attributes.remove(index);
37 let attr = syn::parse2(attr.into_token_stream())?;
38 output.push(attr)
39 }
40 Ok(output)
41}
42
43pub mod keyword {
45 syn::custom_keyword!(precompile);
46 syn::custom_keyword!(public);
47 syn::custom_keyword!(fallback);
48 syn::custom_keyword!(payable);
49 syn::custom_keyword!(view);
50 syn::custom_keyword!(discriminant);
51 syn::custom_keyword!(precompile_set);
52 syn::custom_keyword!(test_concrete_types);
53 syn::custom_keyword!(pre_check);
54}
55
56#[allow(dead_code)]
58pub enum MethodAttr {
59 Public(Span, syn::LitStr),
60 Fallback(Span),
61 Payable(Span),
62 View(Span),
63 Discriminant(Span),
64 PreCheck(Span),
65}
66
67impl syn::parse::Parse for MethodAttr {
68 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
69 input.parse::<syn::Token![#]>()?;
70 let content;
71 syn::bracketed!(content in input);
72 content.parse::<keyword::precompile>()?;
73 content.parse::<syn::Token![::]>()?;
74
75 let lookahead = content.lookahead1();
76
77 if lookahead.peek(keyword::public) {
78 let span = content.parse::<keyword::public>()?.span();
79
80 let inner;
81 syn::parenthesized!(inner in content);
82 let signature = inner.parse::<syn::LitStr>()?;
83
84 Ok(MethodAttr::Public(span, signature))
85 } else if lookahead.peek(keyword::fallback) {
86 Ok(MethodAttr::Fallback(
87 content.parse::<keyword::fallback>()?.span(),
88 ))
89 } else if lookahead.peek(keyword::payable) {
90 Ok(MethodAttr::Payable(
91 content.parse::<keyword::payable>()?.span(),
92 ))
93 } else if lookahead.peek(keyword::view) {
94 Ok(MethodAttr::View(content.parse::<keyword::view>()?.span()))
95 } else if lookahead.peek(keyword::discriminant) {
96 Ok(MethodAttr::Discriminant(
97 content.parse::<keyword::discriminant>()?.span(),
98 ))
99 } else if lookahead.peek(keyword::pre_check) {
100 Ok(MethodAttr::PreCheck(
101 content.parse::<keyword::pre_check>()?.span(),
102 ))
103 } else {
104 Err(lookahead.error())
105 }
106 }
107}
108
109#[allow(dead_code)]
111pub enum ImplAttr {
112 PrecompileSet(Span),
113 TestConcreteTypes(Span, Vec<syn::Type>),
114}
115
116impl syn::parse::Parse for ImplAttr {
117 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
118 input.parse::<syn::Token![#]>()?;
119 let content;
120 syn::bracketed!(content in input);
121 content.parse::<keyword::precompile>()?;
122 content.parse::<syn::Token![::]>()?;
123
124 let lookahead = content.lookahead1();
125
126 if lookahead.peek(keyword::precompile_set) {
127 Ok(ImplAttr::PrecompileSet(
128 content.parse::<keyword::precompile_set>()?.span(),
129 ))
130 } else if lookahead.peek(keyword::test_concrete_types) {
131 let span = content.parse::<keyword::test_concrete_types>()?.span();
132
133 let inner;
134 syn::parenthesized!(inner in content);
135 let types = inner.parse_terminated(syn::Type::parse, syn::Token![,])?;
136
137 Ok(ImplAttr::TestConcreteTypes(
138 span,
139 types.into_iter().collect(),
140 ))
141 } else {
142 Err(lookahead.error())
143 }
144 }
145}