1use proc_macro2::TokenStream;
2use proc_macro_error::{abort, abort_call_site, emit_error, proc_macro_error};
3use quote::quote;
4use syn::{
5 parenthesized,
6 parse::{Parse, ParseStream},
7 parse_macro_input, token, Data, Ident, LitStr, Token,
8};
9
10#[proc_macro_error]
11#[proc_macro_derive(Verify, attributes(verify))]
12pub fn derive_verify(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
13 let input = parse_macro_input!(input as syn::DeriveInput);
14
15 let mut options = VerifyOptions::default();
16
17 for a in &input.attrs {
18 if a.path.is_ident("verify") {
19 let tokens = a.tokens.clone().into();
20 options.merge(parse_macro_input!(tokens as VerifyOptions));
21 }
22 }
23
24 match &input.data {
25 Data::Struct(_) => Verify::new(input, options).derive().into(),
26 Data::Enum(_) => Verify::new(input, options).derive().into(),
27 Data::Union(u) => {
28 abort!(u.union_token, "unions are not supported by Verify");
29 }
30 }
31}
32
33#[derive(Default)]
34struct VerifyOptions {
35 verifier: Option<Ident>,
36 verifier_name: Option<(Ident, TokenStream)>,
37 verifier_create: Option<(Ident, TokenStream)>,
38 verifier_error: Option<(Ident, TokenStream)>,
39
40 is_serde: Option<Ident>,
41 serde_spans: Option<(Ident, TokenStream)>,
42
43 is_schemars: Option<Ident>,
44}
45
46impl VerifyOptions {
47 fn merge(&mut self, other: VerifyOptions) {
48 if let Some(v) = other.verifier {
49 if let Some(existing_v) = &self.verifier {
50 emit_error!(existing_v, "{} defined here", existing_v);
51 abort!(v, r#"duplicate keys "{}""#, v);
52 }
53
54 self.verifier = v.into();
55 }
56
57 if let Some(v) = other.verifier_name {
58 if let Some(existing_v) = &self.verifier_name {
59 emit_error!(existing_v.0, "{} defined here", existing_v.0);
60 abort!(v.0, r#"duplicate keys "{}""#, v.0);
61 }
62
63 self.verifier_name = v.into();
64 }
65
66 if let Some(v) = other.verifier_create {
67 if let Some(existing_v) = &self.verifier_create {
68 emit_error!(existing_v.0, "{} defined here", existing_v.0);
69 abort!(v.0, r#"duplicate keys "{}""#, v.0);
70 }
71
72 self.verifier_create = v.into();
73 }
74
75 if let Some(v) = other.verifier_error {
76 if let Some(existing_v) = &self.verifier_error {
77 emit_error!(existing_v.0, "{} defined here", existing_v.0);
78 abort!(v.0, r#"duplicate keys "{}""#, v.0);
79 }
80
81 self.verifier_error = v.into();
82 }
83
84 if let Some(v) = other.is_serde {
85 if let Some(existing_v) = &self.is_serde {
86 emit_error!(existing_v, "{} defined here", existing_v);
87 abort!(v, r#"duplicate keys "{}""#, v);
88 }
89
90 self.is_serde = v.into();
91 }
92
93 if let Some(v) = other.serde_spans {
94 if let Some(existing_v) = &self.serde_spans {
95 emit_error!(existing_v.0, "{} defined here", existing_v.0);
96 abort!(v.0, r#"duplicate keys "{}""#, v.0);
97 }
98
99 self.serde_spans = v.into();
100 }
101
102 if let Some(v) = other.is_schemars {
103 if let Some(existing_v) = &self.is_schemars {
104 emit_error!(existing_v, "{} defined here", existing_v);
105 abort!(v, r#"duplicate keys "{}""#, v);
106 }
107
108 self.is_schemars = v.into();
109 }
110 }
111
112 fn parse_serde_options(&mut self, content: ParseStream) -> syn::Result<()> {
113 if content.is_empty() {
114 return Ok(());
115 }
116
117 let serde_id: Ident = content.parse()?;
118
119 if serde_id == "spans" {
120 content.parse::<Token![=]>()?;
121 let s = content.parse::<LitStr>()?;
122 let ts: TokenStream = s.parse()?;
123 self.serde_spans = Some((serde_id, ts));
124 } else {
125 abort!(serde_id, r#"unknown serde option "{}""#, serde_id);
126 }
127
128 Ok(())
129 }
130
131 fn parse_verifier_options(&mut self, content: ParseStream) -> syn::Result<()> {
132 loop {
133 if content.is_empty() {
134 return Ok(());
135 }
136
137 let id: Ident = content.parse()?;
138
139 if id == "name" {
140 content.parse::<Token![=]>()?;
141 let s = content.parse::<LitStr>()?;
142 let ts: TokenStream = s.parse()?;
143 self.verifier_name = Some((id, ts));
144 } else if id == "error" {
145 content.parse::<Token![=]>()?;
146 let s = content.parse::<LitStr>()?;
147 let ts: TokenStream = s.parse()?;
148 self.verifier_error = Some((id, ts));
149 } else if id == "create" {
150 content.parse::<Token![=]>()?;
151 let s = content.parse::<LitStr>()?;
152 let ts: TokenStream = s.parse()?;
153 self.verifier_create = Some((id, ts));
154 } else {
155 abort!(id, r#"unknown verifier option "{}""#, id);
156 }
157
158 if content.peek(Token![,]) {
159 content.parse::<Token!(,)>()?;
160 }
161 }
162 }
163
164 fn parse_option(&mut self, content: ParseStream) -> syn::Result<()> {
165 let id = content.parse::<Ident>()?;
166
167 if id == "serde" {
168 self.is_serde = Some(id);
169 if content.peek(token::Paren) {
170 let serde_content;
171 parenthesized!(serde_content in content);
172 self.parse_serde_options(&serde_content)?;
173 }
174
175 return Ok(());
176 }
177
178 if id == "verifier" {
179 self.verifier = id.clone().into();
180 if content.peek(token::Paren) {
181 let verifier_content;
182 parenthesized!(verifier_content in content);
183 self.parse_verifier_options(&verifier_content)?;
184 } else {
185 content.parse::<Token![=]>()?;
186 let s = content.parse::<LitStr>()?;
187 let ts: TokenStream = s.parse()?;
188 self.verifier_name = Some((id, ts));
189 }
190
191 return Ok(());
192 }
193
194 if id == "schemars" {
195 self.is_schemars = Some(id);
196 return Ok(());
197 }
198
199 abort!(id, r#"unknown option "{}""#, id);
200 }
201}
202
203impl Parse for VerifyOptions {
204 fn parse(input: ParseStream) -> syn::Result<Self> {
205 let mut opts = VerifyOptions::default();
206
207 if !input.peek(token::Paren) {
208 return Ok(opts);
209 }
210 let content;
211 parenthesized!(content in input);
212 loop {
213 if content.is_empty() {
214 break;
215 }
216
217 opts.parse_option(&content)?;
218
219 if content.peek(Token![,]) {
220 content.parse::<Token![,]>()?;
221 }
222 }
223
224 Ok(opts)
225 }
226}
227
228struct Verify {
229 input: syn::DeriveInput,
230 options: VerifyOptions,
231}
232
233impl Verify {
234 fn new(input: syn::DeriveInput, options: VerifyOptions) -> Self {
235 Self { input, options }
236 }
237
238 fn check_options(&self) {
239 if let Some(is_schemars) = &self.options.is_schemars {
240 if self.options.is_serde.is_none() {
241 abort!(
242 is_schemars,
243 r#"Serde is required for Schemars, use the "serde" option to enable it"#
244 );
245 }
246 }
247 }
248
249 fn derive(self) -> TokenStream {
250 self.check_options();
251
252 if self.options.is_serde.is_some() {
253 return self.derive_serde();
254 }
255
256 let ident = self.input.ident;
257 let (impl_gen, ty_gen, where_gen) = self.input.generics.split_for_impl();
258
259 let verifier_name = self
260 .options
261 .verifier_name
262 .unwrap_or_else(|| abort_call_site!("verifier name is required"))
263 .1;
264
265 let verifier_error = match self.options.verifier_error {
266 Some(e) => e.1,
267 None => {
268 quote! {
269 <#verifier_name as ::verify::Verifier<<Self as ::verify::span::Spanned>::Span>>::Error
270 }
271 }
272 };
273
274 let verifier_create = match self.options.verifier_create {
275 Some(e) => e.1,
276 None => {
277 quote! {
278 #verifier_name::default()
279 }
280 }
281 };
282
283 quote! {
284 impl#impl_gen ::verify::Verify for #ident#ty_gen #where_gen {
285 type Error = #verifier_error;
286
287 fn verify(&self) -> Result<(), Self::Error> {
288 let __v = #verifier_create;
289 <#verifier_name as ::verify::Verifier<<Self as ::verify::span::Spanned>::Span>>::verify_value(
290 &__v,
291 self,
292 )
293 }
294 }
295 }
296 }
297
298 fn derive_serde(self) -> TokenStream {
299 if self.options.is_schemars.is_some() {
300 return self.derive_schemars();
301 }
302
303 let ident = self.input.ident;
304 let (impl_gen, ty_gen, where_gen) = self.input.generics.split_for_impl();
305
306 let spans = match self.options.serde_spans {
307 Some((_, s)) => s,
308 None => {
309 quote! {::verify::serde::KeySpans}
310 }
311 };
312
313 let verifier_name = self
314 .options
315 .verifier_name
316 .unwrap_or_else(|| abort_call_site!("verifier name is required"))
317 .1;
318
319 let verifier_error = match self.options.verifier_error {
320 Some(e) => e.1,
321 None => {
322 quote! {
323 <#verifier_name as ::verify::Verifier<<#spans as ::verify::serde::Spans>::Span>>::Error
324 }
325 }
326 };
327
328 let verifier_create = match self.options.verifier_create {
329 Some(e) => e.1,
330 None => {
331 quote! {
332 #verifier_name::default()
333 }
334 }
335 };
336
337 quote! {
338 impl#impl_gen ::verify::Verify for #ident#ty_gen #where_gen {
339 type Error = #verifier_error;
340
341 fn verify(&self) -> Result<(), Self::Error> {
342 let __v = #verifier_create;
343 <#verifier_name as ::verify::Verifier<<#spans as ::verify::serde::Spans>::Span>>::verify_value(
344 &__v,
345 &::verify::serde::Spanned::new(self, #spans::default()),
346 )
347 }
348 }
349 }
350 }
351
352 fn derive_schemars(self) -> TokenStream {
353 let ident = self.input.ident;
354 let (impl_gen, ty_gen, where_gen) = self.input.generics.split_for_impl();
355
356 let spans = match self.options.serde_spans {
357 Some((_, s)) => s,
358 None => {
359 quote! {::verify::serde::KeySpans}
360 }
361 };
362
363 if let Some(v) = self.options.verifier {
364 abort!(v, "verifier option is not supported with Schemars");
365 }
366
367 if let Some(v) = self.options.verifier {
368 abort!(v, "verifier option is not supported with Schemars");
369 }
370
371 let verifier_error = quote! {
372 ::verify::schemars::errors::Errors<<#spans as ::verify::serde::Spans>::Span>
373 };
374
375 quote! {
376 impl#impl_gen ::verify::Verify for #ident#ty_gen #where_gen {
377 type Error = #verifier_error;
378
379 fn verify(&self) -> Result<(), Self::Error> {
380 let __root = schemars::schema_for!(Self);
381
382 <schemars::schema::RootSchema as ::verify::Verifier<_>>::verify_value(
383 &__root,
384 &::verify::serde::Spanned::new(self, #spans::default()),
385 )
386 }
387 }
388 }
389 }
390}