proc_easy/
lib.rs

1//!
2//! Macros to make writing proc-macro crates easy.
3//!
4//! This crate provides mainly macros and supporting types and traits
5//! to reduce amount of boilerplate required for working with [`syn`].
6//!
7//! Currently most of the macros are targeted to construct types
8//! that then can be parses to configure proc-macro and proc-derive-macro implementation.
9//!
10//! [`easy_token!`] - defines new custom token from ident. To be used in other structs.
11//!
12//! [`easy_parse!`] - defines struct or enum that can be parsed and peeked from stream.
13//!
14//! [`easy_argument!`] - defines struct with a token as a name and the rest to be parsed as-is.
15//!
16//! [`easy_argument_group!`] - defines a group of arguments as enum of arguments.
17//!
18//! [`easy_argument_tuple!`] - specialized version of [`easy_argument!`] that parses fields starting from 2nd as [`EasyArgumentField`]s inside parenthesis and in any order.
19//!
20//! [`easy_argument_value!`] - specialized version of [`easy_argument!`] for 2 field structs. It defines 2nd field as a value that can be parsed after `=` token or inside parenthesis.
21//!
22//! [`easy_separated!`] - defines struct that parses fields as [`EasyArgumentField`]s in any order. Does not accept trailing punctuation.
23//!
24//! [`easy_terminated!`] - defines struct that parses fields as [`EasyArgumentField`]s in any order. Accepts trailing punctuation. Parses whole stream.
25//!
26//! [`easy_attributes!`] - defines struct that parses fields as [`EasyArgumentField`]s from a slice of [`Attribute`]s with specified namespace.
27//!
28//! [`EasyArgumentField`] is implemented for types defined with [`easy_token!`], [`easy_argument!`], [`easy_argument_tuple!`], [`easy_argument_value!`] and [`easy_argument_group!`] possibly wrapped in [`Option`] or [`Vec`].
29//!
30
31#![deny(missing_docs)]
32#![deny(missing_copy_implementations)]
33#![deny(missing_debug_implementations)]
34
35use std::{marker::PhantomData, ops::Deref};
36
37use proc_macro2::Span;
38
39use quote::ToTokens;
40use syn::{
41    parse::{Lookahead1, Parse, ParseStream},
42    spanned::Spanned,
43    token::{Paren, Token},
44    Attribute,
45};
46
47#[doc(hidden)]
48pub mod private {
49    pub use std::{
50        concat, default::Default, format, mem::discriminant, option::Option, result::Result,
51        string::String, stringify, vec::Vec,
52    };
53
54    pub use bool;
55    pub use proc_macro2::Span;
56    pub use quote::ToTokens;
57    pub use syn::{
58        custom_keyword, parenthesized,
59        parse::{Lookahead1, Parse, ParseStream},
60        punctuated::Punctuated,
61        spanned::Spanned,
62        token::{Comma, Eq, Paren},
63        Attribute, Error, Ident, Token,
64    };
65}
66
67#[doc(hidden)]
68#[macro_export]
69macro_rules! easy_replace_tokens {
70    ($with:tt, $($t:tt)*) => {
71        $with
72    };
73}
74
75/// Peekable and parsable single token.
76///
77/// [`easy_token!`] macro produces types that implement this trait.
78pub trait EasyToken: EasyPeek + Parse + Spanned {
79    /// Display the token for the user.
80    fn display() -> &'static str;
81}
82
83/// Defines a type with specified name that implement [`EasyToken`] and can be parsed from that name ident.
84#[macro_export]
85macro_rules! easy_token {
86    ($name:ident) => {
87        $crate::private::custom_keyword!($name);
88
89        impl $crate::EasyToken for $name {
90            #[inline]
91            fn display() -> &'static str {
92                $crate::private::concat!("`", $crate::private::stringify!($name), "`")
93            }
94        }
95    };
96}
97
98/// Provides interface for peeking first token before parsing.
99///
100/// May be implemented for complex structures by peeking first field.
101pub trait EasyPeek: Parse {
102    /// Peek head token before parsing.
103    fn peek(lookahead1: &Lookahead1) -> bool;
104
105    /// Peek head token before parsing.
106    fn peek_stream(stream: ParseStream) -> bool;
107}
108
109impl<T> EasyPeek for T
110where
111    T: Token + Parse,
112{
113    #[inline]
114    fn peek(lookahead1: &Lookahead1) -> bool {
115        lookahead1.peek(|v| -> T { match v {} })
116    }
117
118    #[inline]
119    fn peek_stream(stream: ParseStream) -> bool {
120        stream.peek(|v| -> T { match v {} })
121    }
122}
123
124macro_rules! easy_syn_token {
125    ($token:tt) => {
126        impl EasyToken for syn::Token![$token] {
127            #[inline]
128            fn display() -> &'static str {
129                $crate::private::concat!("`", $crate::private::stringify!($token), "`")
130            }
131        }
132    };
133}
134
135easy_syn_token![abstract];
136easy_syn_token![as];
137easy_syn_token![async];
138easy_syn_token![auto];
139easy_syn_token![await];
140easy_syn_token![become];
141easy_syn_token![box];
142easy_syn_token![break];
143easy_syn_token![const];
144easy_syn_token![continue];
145easy_syn_token![crate];
146easy_syn_token![default];
147easy_syn_token![do];
148easy_syn_token![dyn];
149easy_syn_token![else];
150easy_syn_token![enum];
151easy_syn_token![extern];
152easy_syn_token![final];
153easy_syn_token![fn];
154easy_syn_token![for];
155easy_syn_token![if];
156easy_syn_token![impl];
157easy_syn_token![in];
158easy_syn_token![let];
159easy_syn_token![loop];
160easy_syn_token![macro];
161easy_syn_token![match];
162easy_syn_token![mod];
163easy_syn_token![move];
164easy_syn_token![mut];
165easy_syn_token![override];
166easy_syn_token![priv];
167easy_syn_token![pub];
168easy_syn_token![ref];
169easy_syn_token![return];
170easy_syn_token![Self];
171easy_syn_token![self];
172easy_syn_token![static];
173easy_syn_token![struct];
174easy_syn_token![super];
175easy_syn_token![trait];
176easy_syn_token![try];
177easy_syn_token![type];
178easy_syn_token![typeof];
179easy_syn_token![union];
180easy_syn_token![unsafe];
181easy_syn_token![unsized];
182easy_syn_token![use];
183easy_syn_token![virtual];
184easy_syn_token![where];
185easy_syn_token![while];
186easy_syn_token![yield];
187easy_syn_token![+];
188easy_syn_token![+=];
189easy_syn_token![&];
190easy_syn_token![&&];
191easy_syn_token![&=];
192easy_syn_token![@];
193easy_syn_token![!];
194easy_syn_token![^];
195easy_syn_token![^=];
196easy_syn_token![:];
197easy_syn_token![::];
198easy_syn_token![,];
199easy_syn_token![/];
200easy_syn_token![/=];
201easy_syn_token![$];
202easy_syn_token![.];
203easy_syn_token![..];
204easy_syn_token![...];
205easy_syn_token![..=];
206easy_syn_token![=];
207easy_syn_token![==];
208easy_syn_token![>=];
209easy_syn_token![>];
210easy_syn_token![<=];
211easy_syn_token![<];
212easy_syn_token![*=];
213easy_syn_token![!=];
214easy_syn_token![|];
215easy_syn_token![|=];
216easy_syn_token![||];
217easy_syn_token![#];
218easy_syn_token![?];
219easy_syn_token![->];
220easy_syn_token![<-];
221easy_syn_token![%];
222easy_syn_token![%=];
223easy_syn_token![=>];
224easy_syn_token![;];
225easy_syn_token![<<];
226easy_syn_token![<<=];
227easy_syn_token![>>];
228easy_syn_token![>>=];
229easy_syn_token![*];
230easy_syn_token![-];
231easy_syn_token![-=];
232easy_syn_token![~];
233easy_syn_token![_];
234
235/// HACK around trivial bounds error.
236#[doc(hidden)]
237#[allow(missing_debug_implementations)]
238pub struct EasyPeekHack<'a, T>(#[allow(unused)] &'a PhantomData<T>);
239
240impl<'a, T> Parse for EasyPeekHack<'a, T> {
241    fn parse(_: ParseStream) -> syn::Result<Self> {
242        panic!("This function must not be called");
243    }
244}
245
246impl<'a, T> EasyPeek for EasyPeekHack<'a, T>
247where
248    T: EasyPeek,
249{
250    fn peek(lookahead1: &Lookahead1) -> bool {
251        T::peek(lookahead1)
252    }
253
254    fn peek_stream(stream: ParseStream) -> bool {
255        T::peek_stream(stream)
256    }
257}
258
259/// Parses inner type parenthesized.
260/// Implements [`EasyPeek`] and peeks opening parenthesis.
261#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
262pub struct EasyParenthesized<T>(pub T);
263
264impl<T> Deref for EasyParenthesized<T> {
265    type Target = T;
266
267    fn deref(&self) -> &T {
268        &self.0
269    }
270}
271
272impl<T> ToTokens for EasyParenthesized<T>
273where
274    T: ToTokens,
275{
276    #[inline]
277    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
278        self.0.to_tokens(tokens)
279    }
280
281    #[inline]
282    fn to_token_stream(&self) -> proc_macro2::TokenStream {
283        self.0.to_token_stream()
284    }
285
286    #[inline]
287    fn into_token_stream(self) -> proc_macro2::TokenStream {
288        self.0.into_token_stream()
289    }
290}
291
292impl<T> EasyPeek for EasyParenthesized<T>
293where
294    T: Parse,
295{
296    #[inline]
297    fn peek(lookahead1: &Lookahead1) -> bool {
298        lookahead1.peek(syn::token::Paren)
299    }
300
301    #[inline]
302    fn peek_stream(stream: ParseStream) -> bool {
303        stream.peek(syn::token::Paren)
304    }
305}
306
307impl<T> Parse for EasyParenthesized<T>
308where
309    T: Parse,
310{
311    #[inline]
312    fn parse(input: ParseStream) -> syn::Result<Self> {
313        let content;
314        syn::parenthesized!(content in input);
315        let inner = T::parse(&content)?;
316        if content.is_empty() {
317            Ok(EasyParenthesized(inner))
318        } else {
319            Err(content.error("Expected closing parentheses"))
320        }
321    }
322}
323
324/// Parses inner type braced.
325/// Implements [`EasyPeek`] and peeks opening brace.
326#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
327pub struct EasyBraced<T>(pub T);
328
329impl<T> Deref for EasyBraced<T> {
330    type Target = T;
331
332    fn deref(&self) -> &T {
333        &self.0
334    }
335}
336
337impl<T> ToTokens for EasyBraced<T>
338where
339    T: ToTokens,
340{
341    #[inline]
342    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
343        self.0.to_tokens(tokens)
344    }
345
346    #[inline]
347    fn to_token_stream(&self) -> proc_macro2::TokenStream {
348        self.0.to_token_stream()
349    }
350
351    #[inline]
352    fn into_token_stream(self) -> proc_macro2::TokenStream {
353        self.0.into_token_stream()
354    }
355}
356
357impl<T> EasyPeek for EasyBraced<T>
358where
359    T: Parse,
360{
361    #[inline]
362    fn peek(lookahead1: &Lookahead1) -> bool {
363        lookahead1.peek(syn::token::Brace)
364    }
365
366    #[inline]
367    fn peek_stream(stream: ParseStream) -> bool {
368        stream.peek(syn::token::Brace)
369    }
370}
371
372impl<T> Parse for EasyBraced<T>
373where
374    T: Parse,
375{
376    #[inline]
377    fn parse(input: ParseStream) -> syn::Result<Self> {
378        let content;
379        syn::braced!(content in input);
380        let inner = T::parse(&content)?;
381        if content.is_empty() {
382            Ok(EasyBraced(inner))
383        } else {
384            Err(content.error("Expected closing parentheses"))
385        }
386    }
387}
388
389/// Parses inner type bracketed.
390/// Implements [`EasyPeek`] and peeks opening bracket.
391#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
392pub struct EasyBracketed<T>(pub T);
393
394impl<T> Deref for EasyBracketed<T> {
395    type Target = T;
396
397    fn deref(&self) -> &T {
398        &self.0
399    }
400}
401
402impl<T> ToTokens for EasyBracketed<T>
403where
404    T: ToTokens,
405{
406    #[inline]
407    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
408        self.0.to_tokens(tokens)
409    }
410
411    #[inline]
412    fn to_token_stream(&self) -> proc_macro2::TokenStream {
413        self.0.to_token_stream()
414    }
415
416    #[inline]
417    fn into_token_stream(self) -> proc_macro2::TokenStream {
418        self.0.into_token_stream()
419    }
420}
421
422impl<T> EasyPeek for EasyBracketed<T>
423where
424    T: Parse,
425{
426    #[inline]
427    fn peek(lookahead1: &Lookahead1) -> bool {
428        lookahead1.peek(syn::token::Bracket)
429    }
430
431    #[inline]
432    fn peek_stream(stream: ParseStream) -> bool {
433        stream.peek(syn::token::Bracket)
434    }
435}
436
437impl<T> Parse for EasyBracketed<T>
438where
439    T: Parse,
440{
441    #[inline]
442    fn parse(input: ParseStream) -> syn::Result<Self> {
443        let content;
444        syn::bracketed!(content in input);
445        let inner = T::parse(&content)?;
446        if content.is_empty() {
447            Ok(EasyBracketed(inner))
448        } else {
449            Err(content.error("Expected closing parentheses"))
450        }
451    }
452}
453
454/// Similar to [`syn::punctuated::Punctuated`] but implements [`Parse`] and optionally [`EasyPeek`].
455///
456/// Parses one or more occurrences of T separated by punctuation of type P, not accepting trailing punctuation.
457/// Parsing continues as long as punctuation P is present at the head of the stream. This method returns upon parsing a T and observing that it is not followed by a P, even if there are remaining tokens in the stream.
458#[derive(Clone, Debug)]
459pub struct EasySeparated<T, P = syn::Token![,]> {
460    items: Vec<T>,
461    punctuation: PhantomData<P>,
462}
463
464impl<T, P> Deref for EasySeparated<T, P> {
465    type Target = [T];
466
467    fn deref(&self) -> &[T] {
468        &self.items
469    }
470}
471
472impl<T, P> Parse for EasySeparated<T, P>
473where
474    T: Parse,
475    P: EasyPeek,
476{
477    fn parse(input: ParseStream) -> syn::Result<Self> {
478        let mut items = Vec::new();
479
480        let item = input.parse::<T>()?;
481        items.push(item);
482
483        while P::peek_stream(input) {
484            let _ = input.parse::<P>()?;
485            let item = input.parse::<T>()?;
486            items.push(item);
487        }
488
489        Ok(EasySeparated {
490            items,
491            punctuation: PhantomData,
492        })
493    }
494}
495
496impl<T, P> EasyPeek for EasySeparated<T, P>
497where
498    T: EasyPeek,
499    P: EasyPeek,
500{
501    fn peek(lookahead1: &Lookahead1) -> bool {
502        T::peek(lookahead1)
503    }
504
505    fn peek_stream(stream: ParseStream) -> bool {
506        T::peek_stream(stream)
507    }
508}
509
510/// Similar to [`syn::punctuated::Punctuated`] but implements [`Parse`].
511///
512/// Parses zero or more occurrences of T separated by punctuation of type P, with optional trailing punctuation.
513/// Parsing continues until the end of this parse stream. The entire content of this parse stream must consist of T and P.
514#[derive(Clone, Debug)]
515pub struct EasyTerminated<T, P = syn::Token![,]> {
516    items: Vec<T>,
517    punctuation: PhantomData<P>,
518}
519
520impl<T, P> Deref for EasyTerminated<T, P> {
521    type Target = [T];
522
523    fn deref(&self) -> &[T] {
524        &self.items
525    }
526}
527
528impl<T, P> Parse for EasyTerminated<T, P>
529where
530    T: Parse,
531    P: EasyPeek,
532{
533    fn parse(input: ParseStream) -> syn::Result<Self> {
534        let mut items = Vec::new();
535
536        if input.is_empty() {
537            return Ok(EasyTerminated {
538                items,
539                punctuation: PhantomData,
540            });
541        }
542
543        let item = input.parse::<T>()?;
544        items.push(item);
545
546        loop {
547            if input.is_empty() {
548                break;
549            }
550            let _ = input.parse::<P>()?;
551            if input.is_empty() {
552                break;
553            }
554            let item = input.parse::<T>()?;
555            items.push(item);
556        }
557
558        Ok(EasyTerminated {
559            items,
560            punctuation: PhantomData,
561        })
562    }
563}
564
565/// Similar to [`Option`] but implements [`Parse`] when `T` implements [`EasyPeek`]
566///
567/// If stream doesn't start as `T` then no tokens are consumed and [`EasyMaybe::Nothing`] is returned.
568/// Otherwise `T` is parsed and returned wrapped in [`EasyMaybe::Just`].
569#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
570pub enum EasyMaybe<T> {
571    /// Nothing at all
572    Nothing,
573
574    /// Just a value
575    Just(T),
576}
577
578impl<T> Default for EasyMaybe<T> {
579    fn default() -> Self {
580        EasyMaybe::Nothing
581    }
582}
583
584impl<T> Parse for EasyMaybe<T>
585where
586    T: EasyPeek,
587{
588    fn parse(input: ParseStream) -> syn::Result<Self> {
589        if T::peek_stream(input) {
590            T::parse(input).map(EasyMaybe::Just)
591        } else {
592            Ok(EasyMaybe::Nothing)
593        }
594    }
595}
596
597/// Either a value preceded with `=` or parenthesized value.
598#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
599pub enum EasySubArgument<V, T = V> {
600    /// Simple value
601    Value(V),
602
603    /// Tuple sub-fields
604    Tuple(T),
605}
606
607impl<V, T> Parse for EasySubArgument<V, T>
608where
609    V: Parse,
610    T: Parse,
611{
612    fn parse(stream: ParseStream) -> syn::Result<Self> {
613        let lookahead1 = stream.lookahead1();
614        if lookahead1.peek(syn::Token![=]) {
615            stream.parse::<syn::Token![=]>()?;
616            Ok(EasySubArgument::Value(stream.parse::<V>()?))
617        } else if lookahead1.peek(Paren) {
618            let content;
619            syn::parenthesized!(content in stream);
620            let arg = content.parse::<T>()?;
621
622            if content.is_empty() {
623                Ok(EasySubArgument::Tuple(arg))
624            } else {
625                Err(content.error("Expected closing parentheses"))
626            }
627        } else {
628            Err(lookahead1.error())
629        }
630    }
631}
632
633impl<V, T> EasyPeek for EasySubArgument<V, T>
634where
635    V: Parse,
636    T: Parse,
637{
638    fn peek(lookahead1: &Lookahead1) -> bool {
639        lookahead1.peek(syn::Token![=]) || lookahead1.peek(Paren)
640    }
641
642    fn peek_stream(stream: ParseStream) -> bool {
643        stream.peek(syn::Token![=]) || stream.peek(Paren)
644    }
645}
646
647/// Defines structure or enum and implements [`Parse`] for it.
648///
649/// Implements [`EasyPeek`] for structs if first field implements [`EasyPeek`].
650///
651/// For enums, if first variant is prefixed by `!` it becomes a default variant that is parsed if no other variants peeking succeeds.
652/// Variants prefixed with `?` are skipped during parsing and peeking.
653///
654/// For enums [`EasyPeek`] is implemented if enum does not have a default variant.
655/// First field in  all non-default non-skipped variants must implement [`EasyPeek`].
656///
657/// Therefore unit and empty tuple and struct-like variants may be present but must be marked as default or skipped.
658#[macro_export]
659macro_rules! easy_parse {
660    (
661        $(#[$meta:meta])*
662        $vis:vis struct $name:ident;
663    ) => {
664        $(#[$meta])*
665        $vis struct $name;
666
667        impl $crate::private::Parse for $name {
668            fn parse(_input: $crate::private::ParseStream) -> $crate::private::Result<Self, $crate::private::Error> {
669                $crate::private::Result::Ok($name)
670            }
671        }
672    };
673    (
674        $(#[$meta:meta])*
675        $vis:vis struct $name:ident ();
676    ) => {
677        $(#[$meta])*
678        $vis struct $name ();
679
680        impl $crate::private::Parse for $name {
681            fn parse(_input: $crate::private::ParseStream) -> $crate::private::Result<Self, $crate::private::Error> {
682                $crate::private::Result::Ok($name ())
683            }
684        }
685    };
686    (
687        $(#[$meta:meta])*
688        $vis:vis struct $name:ident {}
689    ) => {
690        $(#[$meta])*
691        $vis struct $name {}
692
693        impl $crate::private::Parse for $name {
694            fn parse(_input: $crate::private::ParseStream) -> $crate::private::Result<Self, $crate::private::Error> {
695                $crate::private::Result::Ok($name {})
696            }
697        }
698    };
699    (
700        $(#[$meta:meta])*
701        $vis:vis struct $name:ident {
702            $(#[$hmeta:meta])* $hvis:vis $hname:ident : $htype:ty
703            $(, $(#[$fmeta:meta])* $fvis:vis $fname:ident : $ftype:ty)*
704            $(,)?
705        }
706    ) => {
707        $(#[$meta])*
708        $vis struct $name {
709            $(#[$hmeta])* $hvis $hname: $htype,
710            $($(#[$fmeta])* $fvis $fname: $ftype,)*
711        }
712
713        impl $crate::private::Parse for $name {
714            fn parse(input: $crate::private::ParseStream) -> $crate::private::Result<Self, $crate::private::Error> {
715                #![allow(unused_variables)]
716
717                let $hname = <$htype as $crate::private::Parse>::parse(input)?;
718
719                $(
720                    let $fname = <$ftype as $crate::private::Parse>::parse(input)?;
721                )*
722
723                $crate::private::Result::Ok($name {
724                    $hname,
725                    $( $fname, )*
726                })
727            }
728        }
729
730        impl $crate::EasyPeek for $name
731        where
732            for<'a> $crate::EasyPeekHack<'a, $htype>: $crate::EasyPeek,
733        {
734            #[inline]
735            fn peek(lookahead1: &$crate::private::Lookahead1) -> $crate::private::bool {
736                <$crate::EasyPeekHack<'static, $htype> as $crate::EasyPeek>::peek(lookahead1)
737            }
738
739            #[inline]
740            fn peek_stream(stream: $crate::private::ParseStream) -> $crate::private::bool {
741                <$crate::EasyPeekHack<'static, $htype> as $crate::EasyPeek>::peek_stream(stream)
742            }
743        }
744    };
745
746    (
747        $(#[$meta:meta])*
748        $vis:vis struct $name:ident (
749            $(#[$hmeta:meta])* $hvis:vis $htype:ty
750            $(, $(#[$fmeta:meta])* $fvis:vis $ftype:ty)*
751            $(,)?
752        );
753    ) => {
754        $(#[$meta])*
755        $vis struct $name (
756            $(#[$hmeta])* $hvis $htype,
757            $($(#[$fmeta])* $fvis $ftype,)*
758        );
759
760        impl $crate::private::Parse for $name {
761            fn parse(input: $crate::private::ParseStream) -> $crate::private::Result<Self, $crate::private::Error> {
762                #![allow(unused_variables)]
763
764                $crate::private::Result::Ok($name (
765                    <$htype as $crate::private::Parse>::parse(input)?,
766                    $(
767                        <$ftype as $crate::private::Parse>::parse(input)?,
768                    )*
769                ))
770            }
771        }
772
773        impl $crate::EasyPeek for $name
774        where
775            for<'a> $crate::EasyPeekHack<'a, $htype>: $crate::EasyPeek,
776        {
777            #[inline]
778            fn peek(lookahead1: &$crate::private::Lookahead1) -> $crate::private::bool {
779                <$crate::EasyPeekHack<'static, $htype> as $crate::EasyPeek>::peek(lookahead1)
780            }
781
782            #[inline]
783            fn peek_stream(stream: $crate::private::ParseStream) -> $crate::private::bool {
784                <$crate::EasyPeekHack<'static, $htype> as $crate::EasyPeek>::peek_stream(stream)
785            }
786        }
787    };
788    (
789        $(#[$meta:meta])*
790        $vis:vis enum $name:ident {
791            $(#[$vdmeta:meta])* ! $vdname:ident $( ( $($vdt:tt)* ) )? $( { $($vdr:tt)* } )?,
792            $($(#[$vmeta:meta])* $( ? $vsname:ident )? $( $vname:ident )? $( ( $($vt:tt)* ) )? $( { $($vr:tt)* } )?, )*
793        }
794    ) => {
795        $(#[$meta])*
796        $vis enum $name {
797            $(#[$vdmeta])* $vdname $( ( $($vdt)* ) )? $( { $($vdr)* } )?,
798            $( $(#[$vmeta])* $( $vsname )? $( $vname )? $( ( $($vt)* ) )? $( { $($vr)* } )?, )*
799        }
800
801        impl $crate::private::Parse for $name {
802            #[inline]
803            fn parse(input: $crate::private::ParseStream) -> $crate::private::Result<Self, $crate::private::Error> {
804                #![allow(unused_variables)]
805                let lookahead1 = input.lookahead1();
806                $(
807                    $crate::easy_parse_enum_variant!{parse lookahead1 input $name $( $vname )? $( ( $($vt)* ) )? $( { $($vr)* } )?}
808                )*
809
810                $crate::easy_parse_enum_variant!{parse_default input $name $vdname $( ( $($vdt)* ) )? $( { $($vdr)* } )?}
811            }
812        }
813    };
814    (
815        $(#[$meta:meta])*
816        $vis:vis enum $name:ident {
817            $($(#[$vmeta:meta])* $( ? $vsname:ident )? $( $vname:ident )? $( ( $($vt:tt)* ) )? $( { $($vr:tt)* } )?, )*
818        }
819    ) => {
820        $(#[$meta])*
821        $vis enum $name {
822            $( $(#[$vmeta])* $( $vsname )? $( $vname )? $( ( $($vt)* ) )? $( { $($vr)* } )? ),*
823        }
824
825        impl $crate::private::Parse for $name {
826            #[inline]
827            fn parse(input: $crate::private::ParseStream) -> $crate::private::Result<Self, $crate::private::Error> {
828                #![allow(unused_variables)]
829                let lookahead1 = input.lookahead1();
830
831                $(
832                    $crate::easy_parse_enum_variant!{parse lookahead1 input $name $( $vname )? $( ( $($vt)* ) )? $( { $($vr)* } )?}
833                )*
834
835                $crate::private::Result::Err(lookahead1.error())
836            }
837        }
838
839        impl $crate::EasyPeek for $name {
840            #[inline]
841            fn peek(lookahead1: &$crate::private::Lookahead1) -> $crate::private::bool {
842                $(
843                    $crate::easy_parse_enum_variant!{peek lookahead1 $($vname)? $( ( $($vt)* ) )? $( { $($vr)* } )?}
844                )*
845                false
846            }
847
848            #[inline]
849            fn peek_stream(stream: $crate::private::ParseStream) -> $crate::private::bool {
850                $(
851                    $crate::easy_parse_enum_variant!{peek_stream stream $($vname)? $( ( $($vt)* ) )? $( { $($vr)* } )?}
852                )*
853                false
854            }
855        }
856    };
857}
858
859/// Non-public macro used by [`easy_parse!`].
860#[doc(hidden)]
861#[macro_export]
862macro_rules! easy_parse_enum_variant {
863    (parse $lookahead1:ident $stream:ident $name:ident ( $(#[$vpmeta:meta])* $vptype:ty $(, $(#[$vfmeta:meta])* $vftype:ty )* $(,)? )) => {};
864    (parse $lookahead1:ident $stream:ident $name:ident $vname:ident ( $(#[$vpmeta:meta])* $vptype:ty $(, $(#[$vfmeta:meta])* $vftype:ty )* $(,)? )) => {
865        if <$vptype as $crate::EasyPeek>::peek(&$lookahead1) {
866            return $crate::private::Result::Ok($name::$vname(
867                <$vptype as $crate::private::Parse>::parse($stream)?,
868                $( <$vftype as $crate::private::Parse>::parse($stream)?, )*
869            ));
870        }
871    };
872    (peek $lookahead1:ident ( $(#[$vpmeta:meta])* $vptype:ty $(, $(#[$vfmeta:meta])* $vftype:ty )* $(,)? )) => {};
873    (peek $lookahead1:ident $vname:ident ( $(#[$vpmeta:meta])* $vptype:ty $(, $(#[$vfmeta:meta])* $vftype:ty )* $(,)? )) => {
874        if <$vptype as $crate::EasyPeek>::peek($lookahead1) {
875            return true;
876        }
877    };
878
879    (peek_stream $stream:ident ( $(#[$vpmeta:meta])* $vptype:ty $(, $(#[$vfmeta:meta])* $vftype:ty )* $(,)? )) => {};
880    (peek_stream $stream:ident $vname:ident ( $(#[$vpmeta:meta])* $vptype:ty $(, $(#[$vfmeta:meta])* $vftype:ty )* $(,)? )) => {
881        if <$vptype as $crate::EasyPeek>::peek_stream($stream) {
882            return true;
883        }
884    };
885
886    (parse $lookahead1:ident $stream:ident $name:ident { $(#[$vpmeta:meta])* $vpname:ident : $vptype:ty $(, $(#[$vfmeta:meta])* $vfname:ident : $vftype:ty )* $(,)? }) => {};
887    (parse $lookahead1:ident $stream:ident $name:ident $vname:ident { $(#[$vpmeta:meta])* $vpname:ident : $vptype:ty $(, $(#[$vfmeta:meta])* $vfname:ident : $vftype:ty )* $(,)? }) => {
888        if <$vptype as $crate::EasyPeek>::peek(&$lookahead1) {
889            let $vpname =  <$vptype as $crate::private::Parse>::parse($stream)?;
890            $( let $vfname = <$vftype as $crate::private::Parse>::parse($stream)?; )*
891
892            return $crate::private::Result::Ok($name :: $vname {
893                $vpname,
894                $($vfname,)*
895            })
896        }
897    };
898    (peek $lookahead1:ident { $(#[$vpmeta:meta])* $vpname:ident : $vptype:ty $(, $(#[$vfmeta:meta])* $vfname:ident : $vftype:ty )* $(,)? }) => {};
899    (peek $lookahead1:ident $vname:ident { $(#[$vpmeta:meta])* $vpname:ident : $vptype:ty $(, $(#[$vfmeta:meta])* $vfname:ident : $vftype:ty )* $(,)? }) => {
900        if <$vptype as $crate::EasyPeek>::peek($lookahead1) {
901            return true;
902        }
903    };
904    (peek_stream $stream:ident { $(#[$vpmeta:meta])* $vpname:ident : $vptype:ty $(, $(#[$vfmeta:meta])* $vfname:ident : $vftype:ty )* $(,)? }) => {};
905    (peek_stream $stream:ident $vname:ident { $(#[$vpmeta:meta])* $vpname:ident : $vptype:ty $(, $(#[$vfmeta:meta])* $vfname:ident : $vftype:ty )* $(,)? }) => {
906        if <$vptype as $crate::EasyPeek>::peek_stream($stream) {
907            return true;
908        }
909    };
910
911    (parse_default $stream:ident $name:ident $vname:ident) => {
912        $crate::private::Result::Ok( $name::$vname )
913    };
914    (parse_default $stream:ident $name:ident $vname:ident ( $( $(#[$vfmeta:meta])* $vftype:ty ),* $(,)? )) => {
915        $crate::private::Result::Ok( $name::$vname ( $( <$vftype as $crate::private::Parse>::parse($stream)?, )* ))
916    };
917    (parse_default $stream:ident $name:ident $vname:ident { $( $(#[$vfmeta:meta])* $vfname:ident : $vftype:ty),* $(,)? }) => {
918        $crate::private::Result::Ok( $name::$vname { $( $vfname: <$vftype as $crate::private::Parse>::parse($stream)?, )* })
919    };
920}
921
922/// Trait for parsable arguments.
923/// Arguments have a token as a name that is used for peeking.
924/// Name of the argument can be displayed for user in some error cases.
925pub trait EasyArgument: EasyPeek {
926    /// Returns attribute name for display purposes.
927    fn name_display() -> &'static str;
928
929    /// Returns attribute name for display purposes.
930    fn name_span(&self) -> Span;
931}
932
933impl<T> EasyArgument for T
934where
935    T: EasyToken,
936{
937    fn name_display() -> &'static str {
938        <T as EasyToken>::display()
939    }
940
941    fn name_span(&self) -> Span {
942        <T as Spanned>::span(self)
943    }
944}
945
946/// Defines argument structure.
947///
948/// First field is the argument name. It must implement [`EasyToken`].
949/// It must be used to for [`EasyPeek`] implementation.
950///
951/// The rest of the fields are parsed in order.
952///
953/// In case of errors, such as missing argument or unexpected duplicates, argument's name and span will be used.
954#[macro_export]
955macro_rules! easy_argument {
956    (
957        $(#[$meta:meta])*
958        $vis:vis struct $name:ident {
959            $(#[$nmeta:meta])* $nvis:vis $nname:ident: $ntype:ty
960            $(, $(#[$fmeta:meta])* $fvis:vis $fname:ident: $ftype:ty)*
961            $(,)?
962        }
963    ) => {
964        $crate::easy_parse!{
965            $(#[$meta])*
966            $vis struct $name {
967                $(#[$nmeta])* $nvis $nname: $ntype,
968                $($(#[$fmeta])* $fvis $fname: $ftype,)*
969            }
970        }
971
972        impl $crate::EasyArgument for $name {
973            fn name_display() -> &'static str {
974                <$ntype as $crate::EasyToken>::display()
975            }
976
977            fn name_span(&self) -> $crate::private::Span {
978                <$ntype as $crate::private::Spanned>::span(&self.$nname)
979            }
980        }
981    };
982    (
983        $(#[$meta:meta])*
984        $vis:vis struct $name:ident (
985            $(#[$nmeta:meta])* $nvis:vis $ntype:ty
986            $(, $(#[$fmeta:meta])* $fvis:vis $ftype:ty)*
987            $(,)?
988        );
989    ) => {
990        $crate::easy_parse!{
991            $(#[$meta])*
992            $vis struct $name (
993                $(#[$nmeta])* $nvis $ntype,
994                $( $(#[$fmeta])* $fvis $ftype,)*
995            );
996        }
997
998        impl $crate::EasyArgument for $name {
999            fn name_display() -> &'static str {
1000                <$ntype as $crate::EasyToken>::display()
1001            }
1002
1003            fn name_span(&self) -> $crate::private::Span {
1004                <$ntype as $crate::private::Spanned>::span(&self.0)
1005            }
1006        }
1007    };
1008}
1009
1010/// Defines argument structure.
1011///
1012/// First field is the argument name. It must implement [`EasyToken`].
1013/// It must be used to for [`EasyPeek`] implementation.
1014///
1015/// The rest of the fields must be [`EasyArgumentField`] and are expected to be in parenthesized and parsed in any order.
1016///
1017/// If name is not followed by parentheses, all fields are missing (which may be not an error for [`Option`] and [`Vec`] fields).
1018///
1019/// In case of errors, such as missing argument or unexpected duplicates, argument's name and span will be used.
1020#[macro_export]
1021macro_rules! easy_argument_tuple {
1022    (
1023        $(#[$meta:meta])*
1024        $vis:vis struct $name:ident {
1025            $(#[$nmeta:meta])* $nvis:vis $nname:ident: $ntype:ty
1026            $(, $(#[$fmeta:meta])* $fvis:vis $fname:ident: $ftype:ty)*
1027            $(,)?
1028        }
1029    ) => {
1030        $(#[$meta])*
1031        $vis struct $name {
1032            $(#[$nmeta])* $nvis $nname: $ntype,
1033            $($(#[$fmeta])* $fvis $fname: $ftype,)*
1034        }
1035
1036        impl $crate::EasyPeek for $name {
1037            fn peek(lookahead1: &$crate::private::Lookahead1) -> $crate::private::bool {
1038                <$ntype as $crate::EasyPeek>::peek(lookahead1)
1039            }
1040            fn peek_stream(stream: $crate::private::ParseStream) -> $crate::private::bool {
1041                <$ntype as $crate::EasyPeek>::peek_stream(stream)
1042            }
1043        }
1044
1045        impl $crate::private::Parse for $name {
1046            fn parse(stream: $crate::private::ParseStream) -> $crate::private::Result<Self, $crate::private::Error> {
1047                let $nname = stream.parse::<$ntype>()?;
1048
1049                $(let mut $fname = $crate::private::Option::None;)*
1050
1051                if stream.peek($crate::private::Paren) {
1052                    let content;
1053                    $crate::private::parenthesized!(content in stream);
1054
1055                    loop {
1056                        if content.is_empty() {
1057                            break;
1058                        }
1059                        let lookahead1 = content.lookahead1();
1060                        $(
1061                            match &mut $fname {
1062                                $crate::private::Option::None => {
1063                                    if let $crate::private::Option::Some(value) = <$ftype as $crate::EasyArgumentField>::try_parse(&lookahead1, &content)? {
1064                                        $fname = $crate::private::Option::Some(value);
1065                                        if content.is_empty() {
1066                                            break;
1067                                        }
1068                                        content.parse::<$crate::private::Comma>()?;
1069                                        continue
1070                                    }
1071                                }
1072                                $crate::private::Option::Some($fname) => {
1073                                    if <$ftype as $crate::EasyArgumentField>::try_extend($fname, &lookahead1, &content)? {
1074                                        if content.is_empty() {
1075                                            break;
1076                                        }
1077                                        content.parse::<$crate::private::Comma>()?;
1078                                        continue
1079                                    }
1080                                }
1081                            }
1082                        )*
1083                        return $crate::private::Result::Err(lookahead1.error());
1084                    }
1085                }
1086
1087                $crate::private::Result::Ok($name {
1088                    $nname,
1089                    $(
1090                        $fname: match $fname {
1091                            $crate::private::Option::None => <$ftype as $crate::EasyArgumentField>::missing().map_err(|msg| stream.error(msg))?,
1092                            $crate::private::Option::Some($fname) => $fname,
1093                        },
1094                    )*
1095                })
1096            }
1097        }
1098
1099        impl $crate::EasyArgument for $name {
1100            fn name_display() -> &'static str {
1101                <$ntype as $crate::EasyToken>::display()
1102            }
1103
1104            fn name_span(&self) -> $crate::private::Span {
1105                <$ntype as $crate::private::Spanned>::span(&self.$nname)
1106            }
1107        }
1108    };
1109}
1110
1111/// Defines argument structure with exactly two fields.
1112///
1113/// First field is the argument name. It must implement [`EasyToken`].
1114/// It must be used to for [`EasyPeek`] implementation.
1115///
1116/// Another field is a value. It is parsed preceded by `=` token or inside parentheses.
1117///
1118/// If name is not followed by `=` or parentheses, value field is missing (which may be not an error for [`Option`] and [`Vec`] field).
1119///
1120/// In case of errors, such as missing argument or unexpected duplicates, argument's name and span will be used.
1121#[macro_export]
1122macro_rules! easy_argument_value {
1123    (
1124        $(#[$meta:meta])*
1125        $vis:vis struct $name:ident {
1126            $(#[$nmeta:meta])* $nvis:vis $nname:ident: $ntype:ty,
1127            $(#[$vmeta:meta])* $vvis:vis $vname:ident: $vtype:ty
1128            $(,)?
1129        }
1130    ) => {
1131        $(#[$meta])*
1132        $vis struct $name {
1133            $(#[$nmeta])* $nvis $nname: $ntype,
1134            $(#[$vmeta])* $vvis $vname: $vtype,
1135        }
1136
1137        impl $crate::EasyPeek for $name {
1138            fn peek(lookahead1: &$crate::private::Lookahead1) -> $crate::private::bool {
1139                <$ntype as $crate::EasyPeek>::peek(lookahead1)
1140            }
1141            fn peek_stream(stream: $crate::private::ParseStream) -> $crate::private::bool {
1142                <$ntype as $crate::EasyPeek>::peek_stream(stream)
1143            }
1144        }
1145
1146        impl $crate::private::Parse for $name {
1147            fn parse(stream: $crate::private::ParseStream) -> $crate::private::Result<Self, $crate::private::Error> {
1148                let $nname = stream.parse::<$ntype>()?;
1149
1150                let lookahead1 = stream.lookahead1();
1151                if lookahead1.peek($crate::private::Eq) {
1152                    let _ = stream.parse::<$crate::private::Eq>()?;
1153                    let $vname = <$vtype as $crate::private::Parse>::parse(stream)?;
1154                    $crate::private::Result::Ok($name {
1155                        $nname,
1156                        $vname,
1157                    })
1158                } else if lookahead1.peek($crate::private::Paren) {
1159                    let content;
1160                    $crate::private::parenthesized!(content in stream);
1161                    let $vname = <$vtype as $crate::private::Parse>::parse(&content)?;
1162                    if content.is_empty() {
1163                        $crate::private::Result::Ok($name {
1164                            $nname,
1165                            $vname,
1166                        })
1167                    } else {
1168                        $crate::private::Result::Err(content.error("Expected closing parentheses"))
1169                    }
1170                } else {
1171                    $crate::private::Result::Err(lookahead1.error())
1172                }
1173            }
1174        }
1175
1176        impl $crate::EasyArgument for $name {
1177            fn name_display() -> &'static str {
1178                <$ntype as $crate::EasyToken>::display()
1179            }
1180
1181            fn name_span(&self) -> $crate::private::Span {
1182                <$ntype as $crate::private::Spanned>::span(&self.$nname)
1183            }
1184        }
1185    };
1186
1187    (
1188        $(#[$meta:meta])*
1189        $vis:vis struct $name:ident {
1190            $(#[$nmeta:meta])* $nvis:vis $nname:ident: $ntype:ty,
1191            $(#[$vmeta:meta])* ? $vvis:vis $vname:ident: $vtype:ty
1192            $(,)?
1193        }
1194    ) => {
1195        $(#[$meta])*
1196        $vis struct $name {
1197            $(#[$nmeta])* $nvis $nname: $ntype,
1198            $(#[$vmeta])* $vvis $vname: $vtype,
1199        }
1200
1201        impl $crate::EasyPeek for $name {
1202            fn peek(lookahead1: &$crate::private::Lookahead1) -> $crate::private::bool {
1203                <$ntype as $crate::EasyPeek>::peek(lookahead1)
1204            }
1205            fn peek_stream(stream: $crate::private::ParseStream) -> $crate::private::bool {
1206                <$ntype as $crate::EasyPeek>::peek_stream(stream)
1207            }
1208        }
1209
1210        impl $crate::private::Parse for $name {
1211            fn parse(stream: $crate::private::ParseStream) -> $crate::private::Result<Self, $crate::private::Error> {
1212                let $nname = stream.parse::<$ntype>()?;
1213
1214                if stream.is_empty() {
1215                    $crate::private::Result::Ok($name {
1216                        $nname,
1217                        $vname: <$vtype as $crate::private::Default>::default(),
1218                    })
1219                } else {
1220                    let _ = stream.parse::<$crate::private::Eq>()?;
1221                    let $vname = <$vtype as $crate::private::Parse>::parse(stream)?;
1222
1223                    $crate::private::Result::Ok($name {
1224                        $nname,
1225                        $vname,
1226                    })
1227                }
1228            }
1229        }
1230
1231        impl $crate::EasyArgument for $name {
1232            fn name_display() -> &'static str {
1233                <$ntype as $crate::EasyToken>::display()
1234            }
1235
1236            fn name_span(&self) -> $crate::private::Span {
1237                <$ntype as $crate::private::Spanned>::span(&self.$nname)
1238            }
1239        }
1240    };
1241
1242
1243    (
1244        $(#[$meta:meta])*
1245        $vis:vis struct $name:ident (
1246            $(#[$nmeta:meta])* $nvis:vis $ntype:ty,
1247            $(#[$vmeta:meta])* $vvis:vis $vtype:ty
1248            $(,)?
1249        );
1250    ) => {
1251        $(#[$meta])*
1252        $vis struct $name (
1253            $(#[$nmeta])* $nvis $ntype,
1254            $(#[$vmeta])* $vvis $vtype,
1255        );
1256
1257        impl $crate::EasyPeek for $name {
1258            fn peek(lookahead1: &$crate::private::Lookahead1) -> $crate::private::bool {
1259                <$ntype as $crate::EasyPeek>::peek(lookahead1)
1260            }
1261            fn peek_stream(stream: $crate::private::ParseStream) -> $crate::private::bool {
1262                <$ntype as $crate::EasyPeek>::peek_stream(stream)
1263            }
1264        }
1265
1266        impl $crate::private::Parse for $name {
1267            fn parse(stream: $crate::private::ParseStream) -> $crate::private::Result<Self, $crate::private::Error> {
1268                let name = stream.parse::<$ntype>()?;
1269
1270                let _ = stream.parse::<$crate::private::Eq>()?;
1271                let value = <$vtype as $crate::private::Parse>::parse(stream)?;
1272
1273                $crate::private::Result::Ok($name(name, value))
1274            }
1275        }
1276
1277        impl $crate::EasyArgument for $name {
1278            fn name_display() -> &'static str {
1279                <$ntype as $crate::EasyToken>::display()
1280            }
1281
1282            fn name_span(&self) -> $crate::private::Span {
1283                <$ntype as $crate::private::Spanned>::span(&self.0)
1284            }
1285        }
1286    };
1287
1288    (
1289        $(#[$meta:meta])*
1290        $vis:vis struct $name:ident (
1291            $(#[$nmeta:meta])* $nvis:vis $nname:ident: $ntype:ty,
1292            $(#[$vmeta:meta])* ? $vvis:vis $vname:ident: $vtype:ty
1293            $(,)?
1294        );
1295    ) => {
1296        $(#[$meta])*
1297        $vis struct $name (
1298            $(#[$nmeta])* $nvis $ntype,
1299            $(#[$vmeta])* $vvis $vtype,
1300        );
1301
1302        impl $crate::EasyPeek for $name {
1303            fn peek(lookahead1: &$crate::private::Lookahead1) -> $crate::private::bool {
1304                <$ntype as $crate::EasyPeek>::peek(lookahead1)
1305            }
1306            fn peek_stream(stream: $crate::private::ParseStream) -> $crate::private::bool {
1307                <$ntype as $crate::EasyPeek>::peek_stream(stream)
1308            }
1309        }
1310
1311        impl $crate::private::Parse for $name {
1312            fn parse(stream: $crate::private::ParseStream) -> $crate::private::Result<Self, $crate::private::Error> {
1313                let name = stream.parse::<$ntype>()?;
1314
1315                if stream.is_empty() {
1316                    $crate::private::Result::Ok($name(name, <$vtype as $crate::private::Default>::default()))
1317                } else {
1318                    let _ = stream.parse::<$crate::private::Eq>()?;
1319                    let value = <$vtype as $crate::private::Parse>::parse(stream)?;
1320
1321                    $crate::private::Result::Ok($name(name, value))
1322                }
1323            }
1324        }
1325
1326        impl $crate::EasyArgument for $name {
1327            fn name_display() -> &'static str {
1328                <$ntype as $crate::EasyToken>::display()
1329            }
1330
1331            fn name_span(&self) -> $crate::private::Span {
1332                <$ntype as $crate::private::Spanned>::span(&self.0)
1333            }
1334        }
1335    };
1336}
1337
1338/// Trait that should be implemented for enums of where each variant is an attribute.
1339/// It is also auto-implemented for all bare attributes.
1340/// This trait is used to implement [`EasyArgumentField`] for various types.
1341pub trait EasyArgumentGroup {
1342    /// Attempt to parse attribute group.
1343    /// Returns some attribute when parsing succeeds.
1344    /// Returns none if attribute peeking returns `false`, signalling that stream contains some other attribute.
1345    /// Returns error if peeking returns `true` but parsing fails.
1346    fn try_parse(lookahead1: &Lookahead1, stream: ParseStream) -> syn::Result<Option<Self>>
1347    where
1348        Self: Sized;
1349
1350    /// Produces error with appropriate message when the attribute group overlaps another instance.
1351    /// This is called by certain [`EasyArgumentField`] implementations.
1352    ///
1353    /// For example bare [`EasyArgumentGroup`] is used when attributes from group must be specified at most once.
1354    /// And this method will be called when attribute group is encountered second time.
1355    fn overlap_error(&self, other: &Self) -> syn::Error;
1356
1357    /// Produces error with appropriate message when the attribute group is missing.
1358    /// This is called by certain [`EasyArgumentField`] implementations.
1359    fn missing_error() -> String;
1360}
1361
1362impl<T> EasyArgumentGroup for T
1363where
1364    T: EasyArgument,
1365{
1366    #[inline]
1367    fn try_parse(lookahead1: &Lookahead1, stream: ParseStream) -> syn::Result<Option<Self>> {
1368        if <T as EasyPeek>::peek(lookahead1) {
1369            T::parse(stream).map(Some)
1370        } else {
1371            Ok(None)
1372        }
1373    }
1374
1375    fn overlap_error(&self, other: &Self) -> syn::Error {
1376        syn::Error::new(
1377            other.name_span(),
1378            format!(
1379                "{} can be specified at most once",
1380                <T as EasyArgument>::name_display()
1381            ),
1382        )
1383    }
1384
1385    fn missing_error() -> String {
1386        format!(
1387            "{} attribute is required",
1388            <T as EasyArgument>::name_display()
1389        )
1390    }
1391}
1392
1393/// Defines argument group as enum where each variant is argument type.
1394#[macro_export]
1395macro_rules! easy_argument_group {
1396    (
1397        $(#[$meta:meta])*
1398        $vis:vis enum $name:ident {
1399            $( $(#[$vmeta:meta])* $vname:ident ( $(#[$vtmeta:meta])* $vtype:ty ) ),*
1400            $(,)?
1401        }
1402    ) => {
1403        $crate::easy_parse! {
1404            $(#[$meta])*
1405            $vis enum $name {
1406                $( $(#[$vmeta])* $vname ( $(#[$vtmeta])* $vtype ), )*
1407            }
1408        }
1409
1410        impl $name {
1411            #[inline]
1412            pub fn name_display(&self) -> &'static str {
1413                match *self {
1414                    $( $name :: $vname (_) => <$vtype as $crate::EasyArgument>::name_display(), )*
1415                }
1416            }
1417
1418            #[inline]
1419            pub fn name_span(&self) -> $crate::private::Span {
1420                match *self {
1421                    $( $name :: $vname (ref var) => <$vtype as $crate::EasyArgument>::name_span(var), )*
1422                }
1423            }
1424        }
1425
1426        impl $crate::EasyArgumentGroup for $name {
1427            #[inline]
1428            fn try_parse(lookahead1: &$crate::private::Lookahead1, stream: $crate::private::ParseStream) -> $crate::private::Result<$crate::private::Option<Self>, $crate::private::Error> {
1429                #![allow(unused_variables)]
1430
1431                $(
1432                    if <$vtype as $crate::EasyPeek>::peek(&lookahead1) {
1433                        let variant = <$vtype as $crate::private::Parse>::parse(stream)?;
1434                        return $crate::private::Result::Ok($crate::private::Option::Some($name::$vname(variant)));
1435                    }
1436                )*
1437
1438                $crate::private::Result::Ok($crate::private::Option::None)
1439            }
1440
1441            #[inline]
1442            fn overlap_error(&self, other: &Self) -> $crate::private::Error {
1443                let msg = if $crate::private::discriminant(self) == $crate::private::discriminant(other) {
1444                    $crate::private::format!("{} can be specified only once", self.name_display())
1445                } else {
1446                    $crate::private::format!("{} is mutually exclusive with {}", self.name_display(), other.name_display())
1447                };
1448
1449                $crate::private::Error::new(other.name_span(), msg)
1450            }
1451
1452            fn missing_error() -> String {
1453                $crate::private::format!(
1454                    $crate::private::concat!("One of {{", $(
1455                        $crate::easy_replace_tokens!("{}, ", $vname),
1456                    )* "}} is expected"),
1457                    $(<$vtype as $crate::EasyArgument>::name_display(),)*
1458                )
1459            }
1460        }
1461    };
1462}
1463
1464/// Trait for types that can be used as fields in easy attributes structures.
1465/// Fields can parsed and extended when encountered again in parsing stream.
1466/// If field is never encountered - [`EasyArgumentField::missing`] value will be used.
1467/// If attribute type or group is not mandatory - wrap it into [`Option`].
1468pub trait EasyArgumentField {
1469    /// Attempt to parse attribute field.
1470    /// Returns some field when parsing succeeds.
1471    /// Returns none if attribute peeking returns `false`, signalling that stream contains some other attribute.
1472    /// Returns error if peeking returns `true` but parsing fails.
1473    fn try_parse(lookahead1: &Lookahead1, stream: ParseStream) -> syn::Result<Option<Self>>
1474    where
1475        Self: Sized;
1476
1477    /// Attempt to parse attribute field when it already has been successfully parsed.
1478    /// Field value should extend itself with newly parsed attribute or return error.
1479    /// Returns true when parsing and extending succeeds.
1480    /// Returns false if attribute peeking returns `false`, signalling that stream contains some other attribute.
1481    /// Returns error if peeking returns `true` but parsing or extending fails.
1482    fn try_extend(&mut self, lookahead1: &Lookahead1, stream: ParseStream) -> syn::Result<bool>;
1483
1484    /// Called if the attribute field was never parsed.
1485    /// Returns error if attribute is mandatory.
1486    /// Otherwise returns an instance that will be used to build attributes structure.
1487    fn missing() -> Result<Self, String>
1488    where
1489        Self: Sized;
1490}
1491
1492impl<T> EasyArgumentField for T
1493where
1494    T: EasyArgumentGroup,
1495{
1496    fn try_parse(lookahead1: &Lookahead1, stream: ParseStream) -> syn::Result<Option<Self>> {
1497        <T as EasyArgumentGroup>::try_parse(lookahead1, stream)
1498    }
1499
1500    fn try_extend(&mut self, lookahead1: &Lookahead1, stream: ParseStream) -> syn::Result<bool> {
1501        match <T as EasyArgumentGroup>::try_parse(lookahead1, stream)? {
1502            None => Ok(false),
1503            Some(other) => Err(self.overlap_error(&other)),
1504        }
1505    }
1506
1507    fn missing() -> Result<Self, String> {
1508        Err(T::missing_error())
1509    }
1510}
1511
1512impl<T> EasyArgumentField for Option<T>
1513where
1514    T: EasyArgumentField,
1515{
1516    fn try_parse(lookahead1: &Lookahead1, stream: ParseStream) -> syn::Result<Option<Option<T>>> {
1517        match <T as EasyArgumentField>::try_parse(lookahead1, stream) {
1518            Err(err) => Err(err),
1519            Ok(Some(t)) => Ok(Some(Some(t))),
1520            Ok(None) => Ok(None),
1521        }
1522    }
1523
1524    fn try_extend(&mut self, lookahead1: &Lookahead1, stream: ParseStream) -> syn::Result<bool> {
1525        match self {
1526            None => match <T as EasyArgumentField>::try_parse(lookahead1, stream)? {
1527                None => Ok(false),
1528                Some(attr) => {
1529                    *self = Some(attr);
1530                    Ok(true)
1531                }
1532            },
1533            Some(attr) => attr.try_extend(lookahead1, stream),
1534        }
1535    }
1536
1537    fn missing() -> Result<Self, String> {
1538        Ok(None)
1539    }
1540}
1541
1542impl<T> EasyArgumentField for Vec<T>
1543where
1544    T: EasyArgumentGroup,
1545{
1546    fn try_parse(lookahead1: &Lookahead1, stream: ParseStream) -> syn::Result<Option<Self>> {
1547        match <T as EasyArgumentGroup>::try_parse(lookahead1, stream)? {
1548            None => Ok(None),
1549            Some(attr) => Ok(Some(vec![attr])),
1550        }
1551    }
1552
1553    fn try_extend(&mut self, lookahead1: &Lookahead1, stream: ParseStream) -> syn::Result<bool> {
1554        match <T as EasyArgumentGroup>::try_parse(lookahead1, stream)? {
1555            None => Ok(false),
1556            Some(attr) => {
1557                self.push(attr);
1558                Ok(true)
1559            }
1560        }
1561    }
1562
1563    fn missing() -> Result<Self, String> {
1564        Ok(Vec::new())
1565    }
1566}
1567
1568/// Defines flags and attribute group and fields for them.
1569/// Flags can be parsed independently.
1570/// They can be parsed inside attribute that can contain only one flag.
1571/// They can be parsed inside attribute that accepts a list of flags if provided.
1572#[macro_export]
1573macro_rules! easy_flags {
1574    ( $(#[$onemeta:meta])* $ovis:vis $one:ident($onekw:ident) $(| $(#[$manymeta:meta])* $mvis:vis $many:ident($manykw:ident))? { $( $(#[$flagmeta:meta])* $flag:ident($flagkw:ident)),* $(,)? }) => {
1575        $($crate::easy_token!($flagkw);)*
1576        $crate::easy_token!($onekw);
1577
1578        $(#[$onemeta])*
1579        #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1580        $ovis enum $one {
1581            $( $(#[$flagmeta])* $flag($flagkw), )*
1582        }
1583
1584        impl $one {
1585            #[allow(dead_code)]
1586            $ovis fn try_parse_terminated<T: $crate::private::Parse>(lookahead1: &$crate::private::Lookahead1, stream: $crate::private::ParseStream) -> $crate::private::Result<$crate::private::Option<$crate::private::Punctuated<Self, $crate::private::Comma>>, $crate::private::Error> {
1587                if $( lookahead1.peek($flagkw) || )* false {
1588                    stream.parse_terminated::<Self, _>($crate::private::Parse::parse, $crate::private::Token![,]).map($crate::private::Option::Some)
1589                } else {
1590                    $crate::private::Result::Ok($crate::private::Option::None)
1591                }
1592            }
1593        }
1594
1595        impl $crate::private::ToTokens for $one {
1596            #[inline]
1597            fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
1598                match *self {
1599                    $( $one::$flag (ref flag) => $crate::private::ToTokens::to_tokens(flag, tokens), )*
1600                }
1601            }
1602
1603            #[inline]
1604            fn to_token_stream(&self) -> proc_macro2::TokenStream {
1605                match *self {
1606                    $( $one::$flag (ref flag) => $crate::private::ToTokens::to_token_stream(flag), )*
1607                }
1608            }
1609
1610            #[inline]
1611            fn into_token_stream(self) -> proc_macro2::TokenStream {
1612                match self {
1613                    $( $one::$flag (flag) => $crate::private::ToTokens::into_token_stream(flag), )*
1614                }
1615            }
1616        }
1617
1618        impl $crate::EasyArgumentGroup for $one {
1619            fn try_parse(lookahead1: &$crate::private::Lookahead1, stream: $crate::private::ParseStream) -> $crate::private::Result<$crate::private::Option<Self>, $crate::private::Error> {
1620                #![allow(unused_variables)]
1621
1622                $(
1623                    if lookahead1.peek($flagkw) {
1624                        let flag = stream.parse::<$flagkw>()?;
1625                        return $crate::private::Result::Ok( $crate::private::Option::Some( $one::$flag(flag)) );
1626                    }
1627                )*
1628
1629                $crate::private::Result::Ok($crate::private::Option::None)
1630            }
1631
1632            fn overlap_error(&self, other: &Self) -> $crate::private::Error {
1633                let msg = $crate::private::concat!("Only one flag {", $( $crate::private::stringify!($flagkw), ", ", )* "} is expected");
1634                $crate::private::Error::new(
1635                    $crate::private::Spanned::span(other),
1636                    msg,
1637                )
1638            }
1639
1640            fn missing_error() -> $crate::private::String {
1641                String::from($crate::private::concat!("One flag of {", $( $crate::private::stringify!($flagkw), ", ", )* "} is expected"))
1642            }
1643        }
1644
1645        impl $crate::private::Parse for $one {
1646            fn parse(stream: $crate::private::ParseStream) -> $crate::private::Result<Self, $crate::private::Error> {
1647                let lookahead1 = stream.lookahead1();
1648
1649                match <Self as $crate::EasyArgumentGroup>::try_parse(&lookahead1, stream)? {
1650                    $crate::private::Option::None => $crate::private::Result::Err(lookahead1.error()),
1651                    $crate::private::Option::Some(flag) => $crate::private::Result::Ok(flag),
1652                }
1653            }
1654        }
1655
1656        $(
1657            $crate::easy_token!($manykw);
1658
1659            $(#[$manymeta])*
1660            #[derive(Clone, Debug)]
1661            #[allow(dead_code)]
1662            $mvis struct $many {
1663                pub flags: $crate::private::Punctuated<$one, $crate::private::Comma>,
1664            }
1665
1666            impl $many {
1667                #[allow(dead_code)]
1668                pub fn new() -> Self {
1669                    $many {
1670                        flags: $crate::private::Punctuated::new(),
1671                    }
1672                }
1673            }
1674
1675            impl $crate::private::Default for $many {
1676                fn default() -> Self {
1677                    $many {
1678                        flags: $crate::private::Punctuated::default(),
1679                    }
1680                }
1681            }
1682
1683            impl $crate::private::ToTokens for $many {
1684                #[inline]
1685                fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
1686                    self.flags.to_tokens(tokens)
1687                }
1688
1689                #[inline]
1690                fn to_token_stream(&self) -> proc_macro2::TokenStream {
1691                    self.flags.to_token_stream()
1692                }
1693
1694                #[inline]
1695                fn into_token_stream(self) -> proc_macro2::TokenStream {
1696                    self.flags.into_token_stream()
1697                }
1698            }
1699
1700            impl $crate::EasyArgumentField for $many {
1701                fn try_parse(lookahead1: &$crate::private::Lookahead1, stream: $crate::private::ParseStream) -> $crate::private::Result<$crate::private::Option<Self>, $crate::private::Error> {
1702                    if lookahead1.peek($onekw) {
1703                        let _ = stream.parse::<$onekw>()?;
1704
1705                        let content;
1706                        $crate::private::parenthesized!(content in stream);
1707
1708                        let flag = content.parse::<$one>()?;
1709
1710                        if content.is_empty() {
1711                            $crate::private::Result::Ok($crate::private::Option::Some($many {
1712                                flags: {
1713                                    let mut flags = $crate::private::Punctuated::new();
1714                                    flags.push(flag);
1715                                    flags
1716                                },
1717                            }))
1718                        } else {
1719                            $crate::private::Result::Err(content.error("Expected closing parentheses"))
1720                        }
1721                    } else if lookahead1.peek($manykw) {
1722                        let _ = stream.parse::<$manykw>()?;
1723
1724                        let content;
1725                        $crate::private::parenthesized!(content in stream);
1726                        let flags = content.parse_terminated(<$one as $crate::private::Parse>::parse, $crate::private::Token![,])?;
1727
1728                        $crate::private::Result::Ok($crate::private::Option::Some($many {
1729                            flags,
1730                        }))
1731                    } else {
1732                        match $one::try_parse_terminated::<$crate::private::Comma>(lookahead1, stream)? {
1733                            $crate::private::Option::None => $crate::private::Result::Ok($crate::private::Option::None),
1734                            $crate::private::Option::Some(flags) => {
1735                                $crate::private::Result::Ok($crate::private::Option::Some($many {
1736                                    flags,
1737                                }))
1738                            }
1739                        }
1740                    }
1741                }
1742
1743                fn try_extend(&mut self, lookahead1: &$crate::private::Lookahead1, stream: $crate::private::ParseStream) -> $crate::private::Result<$crate::private::bool, $crate::private::Error> {
1744                    if lookahead1.peek($onekw) {
1745                        let _ = stream.parse::<$onekw>()?;
1746
1747                        let content;
1748                        $crate::private::parenthesized!(content in stream);
1749
1750                        let flag = content.parse::<$one>()?;
1751
1752                        if content.is_empty() {
1753                            self.flags.push(flag);
1754                            $crate::private::Result::Ok(true)
1755                        } else {
1756                            $crate::private::Result::Err(content.error("Expected closing parentheses"))
1757                        }
1758                    } else if lookahead1.peek($manykw) {
1759                        let _ = stream.parse::<$manykw>()?;
1760
1761                        let content;
1762                        $crate::private::parenthesized!(content in stream);
1763
1764                        let flags = content.parse_terminated::<_, _>(<$one as $crate::private::Parse>::parse, $crate::private::Token![,])?;
1765                        self.flags.extend(flags);
1766
1767                        $crate::private::Result::Ok(true)
1768                    } else {
1769                        match $one::try_parse_terminated::<$crate::private::Comma>(lookahead1, stream)? {
1770                            $crate::private::Option::None => $crate::private::Result::Ok(false),
1771                            $crate::private::Option::Some(flags) => {
1772                                self.flags.extend(flags);
1773                                $crate::private::Result::Ok(true)
1774                            }
1775                        }
1776                    }
1777                }
1778
1779                fn missing() -> $crate::private::Result<Self, $crate::private::String> {
1780                    $crate::private::Result::Err(<$one as $crate::EasyArgumentGroup>::missing_error())
1781                }
1782            }
1783
1784            impl $crate::private::Parse for $many {
1785                fn parse(stream: $crate::private::ParseStream) -> $crate::private::Result<Self, $crate::private::Error> {
1786                    let lookahead1 = stream.lookahead1();
1787
1788                    match <Self as $crate::EasyArgumentField>::try_parse(&lookahead1, stream)? {
1789                        $crate::private::Option::None => $crate::private::Result::Err(lookahead1.error()),
1790                        $crate::private::Option::Some(flag) => $crate::private::Result::Ok(flag),
1791                    }
1792                }
1793            }
1794        )?
1795    };
1796}
1797
1798/// Defines structure and implements [`Parse`] for it.
1799///
1800/// Fields will be parsed in any order separated by specified punctuation.
1801/// Parsing continues until the end of this parse stream.
1802#[macro_export]
1803macro_rules! easy_terminated {
1804    (
1805        @($punct:ty)
1806        $(#[$meta:meta])*
1807        $vis:vis struct $name:ident {
1808            $($(#[$fmeta:meta])* $fvis:vis $fname:ident : $ftype:ty),*
1809            $(,)?
1810        }
1811    ) => {
1812        $(#[$meta])*
1813        $vis struct $name {
1814            $($(#[$fmeta])* $fvis $fname : $ftype,)*
1815        }
1816
1817        impl $crate::private::Parse for $name {
1818            fn parse(stream: $crate::private::ParseStream) -> $crate::private::Result<Self, $crate::private::Error> {
1819                $(let mut $fname = $crate::private::Option::None;)*
1820
1821                loop {
1822                    if stream.is_empty() {
1823                        break;
1824                    }
1825                    let lookahead1 = stream.lookahead1();
1826                    $(
1827                        match &mut $fname {
1828                            $crate::private::Option::None => {
1829                                if let $crate::private::Option::Some(value) = <$ftype as $crate::EasyArgumentField>::try_parse(&lookahead1, stream)? {
1830                                    $fname = $crate::private::Option::Some(value);
1831                                    if stream.is_empty() {
1832                                        break;
1833                                    }
1834                                    stream.parse::<$punct>()?;
1835                                    continue
1836                                }
1837                            }
1838                            $crate::private::Option::Some($fname) => {
1839                                if <$ftype as $crate::EasyArgumentField>::try_extend($fname, &lookahead1, stream)? {
1840                                    if stream.is_empty() {
1841                                        break;
1842                                    }
1843                                    stream.parse::<$punct>()?;
1844                                    continue
1845                                }
1846                            }
1847                        }
1848                    )*
1849                    return $crate::private::Result::Err(lookahead1.error());
1850                }
1851
1852                $crate::private::Result::Ok($name {
1853                    $(
1854                        $fname: match $fname {
1855                            $crate::private::Option::None => <$ftype as $crate::EasyArgumentField>::missing().map_err(|msg| stream.error(msg))?,
1856                            $crate::private::Option::Some($fname) => $fname,
1857                        },
1858                    )*
1859                })
1860            }
1861        }
1862    };
1863}
1864
1865/// Defines structure and implements [`Parse`] for it.
1866///
1867/// Fields will be parsed in any order separated by specified punctuation, not accepting trailing punctuation.
1868/// Parsing continues as long as punctuation $punct is present at the head of the stream.
1869#[macro_export]
1870macro_rules! easy_separated {
1871    (
1872        @($punct:ty)
1873        $(#[$meta:meta])*
1874        $vis:vis struct $name:ident {
1875            $($(#[$fmeta:meta])* $fvis:vis $fname:ident : $ftype:ty),*
1876            $(,)?
1877        }
1878    ) => {
1879        $(#[$meta])*
1880        $vis struct $name {
1881            $($(#[$fmeta])* $fvis $fname : $ftype,)*
1882        }
1883
1884        impl $crate::private::Parse for $name {
1885            fn parse(stream: $crate::private::ParseStream) -> $crate::private::Result<Self, $crate::private::Error> {
1886                $(let mut $fname = $crate::private::Option::None;)*
1887
1888                loop {
1889                    if stream.is_empty() {
1890                        break;
1891                    }
1892                    let lookahead1 = stream.lookahead1();
1893                    $(
1894                        match &mut $fname {
1895                            $crate::private::Option::None => {
1896                                if let $crate::private::Option::Some(value) = <$ftype as $crate::EasyArgumentField>::try_parse(&lookahead1, stream)? {
1897                                    $fname = $crate::private::Option::Some(value);
1898                                    if !<$punct as $crate::EasyPeek>::peek_stream(stream) {
1899                                        break;
1900                                    }
1901                                    stream.parse::<$punct>()?;
1902                                    continue
1903                                }
1904                            }
1905                            $crate::private::Option::Some($fname) => {
1906                                if <$ftype as $crate::EasyArgumentField>::try_extend($fname, &lookahead1, stream)? {
1907                                    if !<$punct as $crate::EasyPeek>::peek_stream(stream) {
1908                                        break;
1909                                    }
1910                                    stream.parse::<$punct>()?;
1911                                    continue
1912                                }
1913                            }
1914                        }
1915                    )*
1916                    return $crate::private::Result::Err(lookahead1.error());
1917                }
1918
1919                $crate::private::Result::Ok($name {
1920                    $(
1921                        $fname: match $fname {
1922                            $crate::private::Option::None => <$ftype as $crate::EasyArgumentField>::missing().map_err(|msg| stream.error(msg))?,
1923                            $crate::private::Option::Some($fname) => $fname,
1924                        },
1925                    )*
1926                })
1927            }
1928        }
1929    };
1930}
1931
1932/// Collection of attributes that can be parsed from array of attributes.
1933/// Can be easily applied to attributes vector parsed by [`syn`].
1934pub trait EasyAttributes {
1935    /// Parse attributes array.
1936    fn parse(attrs: &[Attribute], span: Span) -> syn::Result<Self>
1937    where
1938        Self: Sized;
1939
1940    /// Parse attributes array within specifeid namespace.
1941    fn parse_in(namespace: &syn::Ident, attrs: &[Attribute], span: Span) -> syn::Result<Self>
1942    where
1943        Self: Sized;
1944}
1945
1946/// Defines struct and implement [`EasyAttributes`] for it.
1947///
1948/// Each field's type must implement [`EasyArgumentField`].
1949/// Fields are parsed in any order.
1950#[macro_export]
1951macro_rules! easy_attributes {
1952    (
1953        @($namespace:ident)
1954        $(#[$meta:meta])*
1955        $vis:vis struct $name:ident {
1956            $( $(#[$fmeta:meta])* $fvis:vis $fname:ident : $ftype:ty),*
1957            $(,)?
1958        }
1959    ) => {
1960        $(#[$meta])*
1961        $vis struct $name {
1962            $( $(#[$fmeta])* $fvis $fname : $ftype,)*
1963        }
1964
1965        impl $crate::EasyAttributes for $name {
1966            fn parse(attrs: &[$crate::private::Attribute], span: $crate::private::Span) -> $crate::private::Result<Self, $crate::private::Error> {
1967                Self::parse_in(&$crate::private::Ident::new($crate::private::stringify!($namespace), $crate::private::Span::call_site()), attrs, span)
1968            }
1969
1970            fn parse_in(namespace: &$crate::private::Ident, attrs: &[$crate::private::Attribute], span: $crate::private::Span) -> $crate::private::Result<Self, $crate::private::Error> {
1971                $(let mut $fname = $crate::private::Option::None;)*
1972
1973                for attr in attrs {
1974                    if attr.path().is_ident(namespace) {
1975                        attr.parse_args_with(|stream: $crate::private::ParseStream| {
1976                            loop {
1977                                if stream.is_empty() {
1978                                    return $crate::private::Result::Ok(());
1979                                }
1980                                let lookahead1 = stream.lookahead1();
1981                                $(
1982                                    match &mut $fname {
1983                                        $crate::private::Option::None => {
1984                                            if let $crate::private::Option::Some(value) = <$ftype as $crate::EasyArgumentField>::try_parse(&lookahead1, stream)? {
1985                                                $fname = $crate::private::Option::Some(value);
1986                                                if stream.is_empty() {
1987                                                    return $crate::private::Result::Ok(());
1988                                                }
1989                                                stream.parse::<$crate::private::Comma>()?;
1990                                                continue;
1991                                            }
1992                                        }
1993                                        $crate::private::Option::Some($fname) => {
1994                                            if <$ftype as $crate::EasyArgumentField>::try_extend($fname, &lookahead1, stream)? {
1995                                                if stream.is_empty() {
1996                                                    return $crate::private::Result::Ok(());
1997                                                }
1998                                                stream.parse::<$crate::private::Comma>()?;
1999                                                continue;
2000                                            }
2001                                        }
2002                                    }
2003                                )*
2004                                return $crate::private::Result::Err(lookahead1.error())
2005                            }
2006                        })?;
2007                    }
2008                }
2009
2010                $crate::private::Result::Ok($name {
2011                    $(
2012                        $fname: match $fname {
2013                            $crate::private::Option::None => <$ftype as $crate::EasyArgumentField>::missing().map_err(|msg| $crate::private::Error::new(span, msg))?,
2014                            $crate::private::Option::Some($fname) => $fname,
2015                        },
2016                    )*
2017                })
2018            }
2019        }
2020    };
2021}
2022
2023easy_parse! {
2024    /// Expression that may be a constant or a reference to member field.
2025    /// Often used pattern is having attribute that refer to a field or constant expression.
2026    ///
2027    /// # Examples
2028    ///
2029    /// ```
2030    /// # use {proc_easy::ReferenceExpr, syn::{parse_quote, Token}, quote::{quote, format_ident}};
2031    /// /// Peeking first `const` token it decides to parse `Expr` variant.
2032    /// let re: ReferenceExpr = parse_quote!(const 42);
2033    /// assert_eq!(re, ReferenceExpr::Expr { const_: parse_quote!(const), expr: parse_quote!(42) });
2034    /// ```
2035    ///
2036    /// ```
2037    /// # use {proc_easy::ReferenceExpr, syn::parse_quote, quote::{quote, format_ident}};
2038    /// /// Without `const` token it decides to parse `Member` variant.
2039    /// let re: ReferenceExpr = parse_quote!(foo);
2040    /// assert_eq!(re, ReferenceExpr::Member { member: format_ident!("foo").into() });
2041    /// ```
2042    #[derive(Clone, Debug, PartialEq, Eq)]
2043    pub enum ReferenceExpr {
2044        /// Member reference.
2045        ! Member {
2046            ///
2047            member: syn::Member,
2048        },
2049        /// Constant expression
2050        Expr {
2051            /// Const token.
2052            const_: syn::Token![const],
2053
2054            ///
2055            expr: syn::Expr,
2056        },
2057    }
2058}
2059
2060#[cfg(any(test, doc))]
2061#[allow(missing_docs)]
2062pub mod examples {
2063    easy_flags! {
2064        /// Nya flags documentation
2065        pub Nya(nya) | pub Nyas(nyas) {
2066            /// Puk documentation
2067            Puk(puk),
2068            /// Pak documentation
2069            Pak(pak),
2070        }
2071    }
2072
2073    easy_parse! {
2074        /// Foo
2075        #[derive(Clone, Debug)]
2076        pub struct Foo {
2077            /// Foo
2078            pub foo: syn::Ident,
2079        }
2080    }
2081
2082    easy_parse! {
2083        /// Bar
2084        #[derive(Clone, Copy, Debug)]
2085        pub struct Bar;
2086    }
2087
2088    easy_parse! {
2089        /// Baz
2090        #[derive(Clone, Debug)]
2091        pub struct Baz(pub syn::Member);
2092    }
2093
2094    easy_parse! {
2095        /// Baz
2096        #[derive(Clone, Debug)]
2097        pub enum FooBar {
2098            ! Bar(Bar),
2099            Foo(Foo),
2100        }
2101    }
2102
2103    easy_token!(arg);
2104
2105    easy_argument! {
2106        /// Baz
2107        #[derive(Clone, Debug)]
2108        pub struct Arg {
2109            pub arg: arg,
2110            pub foobar: FooBar,
2111        }
2112    }
2113
2114    easy_token!(outer);
2115
2116    easy_argument_tuple! {
2117        /// Baz
2118        #[derive(Clone, Debug)]
2119        pub struct Outer {
2120            pub outer: outer,
2121            pub arg: Arg,
2122        }
2123    }
2124}
2125
2126#[cfg(test)]
2127mod tests {
2128    use proc_macro2::Span;
2129    use syn::parse_quote;
2130
2131    use crate::*;
2132
2133    #[allow(warnings)]
2134    enum Option {}
2135
2136    // #[allow(warnings)]
2137    // const Some: () = (); // Commented due to bug in `syn`. Fixed by https://github.com/dtolnay/syn/pull/1171
2138    #[allow(warnings)]
2139    const None: () = ();
2140
2141    #[allow(warnings)]
2142    enum Result {}
2143    #[allow(warnings)]
2144    const Ok: () = ();
2145    #[allow(warnings)]
2146    const Err: () = ();
2147
2148    #[allow(warnings)]
2149    enum Vec {}
2150    #[allow(warnings)]
2151    macro_rules! vec {
2152        () => {
2153            compile_error!();
2154        };
2155    }
2156
2157    trait Default {}
2158
2159    #[allow(warnings)]
2160    enum bool {}
2161
2162    easy_flags! {
2163        /// Docs
2164        pub Nya(nya) |
2165        /// Docs
2166        Nyas(nyas) {
2167            /// Docs
2168            Puk(puk),
2169            /// Docs
2170            Pak(pak),
2171        }
2172    }
2173
2174    easy_token!(foo);
2175    easy_token!(bar);
2176    easy_token!(baz);
2177
2178    easy_token!(a);
2179    easy_token!(b);
2180
2181    easy_argument_value! {
2182        /// Docs
2183        #[derive(Clone, Debug)]
2184        pub struct A {
2185            /// Docs
2186            pub a: a,
2187
2188            /// Docs
2189            pub ident: syn::Ident,
2190        }
2191    }
2192
2193    easy_argument_value! {
2194        /// Docs
2195        #[derive(Clone, Debug)]
2196        pub struct B {
2197            /// Docs
2198            pub b: b,
2199
2200            /// Docs
2201            pub lit: syn::LitInt,
2202        }
2203    }
2204
2205    easy_argument_tuple! {
2206        /// Docs
2207        #[derive(Clone, Debug)]
2208        pub struct Foo {
2209            /// Docs
2210            pub name: foo,
2211            /// Docs
2212            pub a: A,
2213            /// Docs
2214            pub b: B,
2215        }
2216    }
2217
2218    easy_argument! {
2219        /// Docs
2220        #[derive(Clone, Debug)]
2221        pub struct Bar {
2222            /// Docs
2223            pub name: bar,
2224            /// Docs
2225            pub ident: syn::Ident,
2226        }
2227    }
2228
2229    easy_argument_group! {
2230        /// Docs
2231        #[derive(Clone, Debug)]
2232        pub enum Group {
2233            /// Docs
2234            Foo(
2235                /// Docs
2236                Foo
2237            ),
2238            /// Docs
2239            Bar(
2240                /// Docs
2241                Bar
2242            ),
2243        }
2244    }
2245
2246    easy_attributes! {
2247        @(easy)
2248        /// Docs
2249        #[derive(Clone, Default)]
2250        pub struct Attributes {
2251            /// Docs
2252            pub foo: std::option::Option<Foo>,
2253            /// Docs
2254            pub bar: std::option::Option<Bar>,
2255        }
2256    }
2257
2258    #[test]
2259    fn test1() {
2260        let attrs = quote::quote!(
2261            #[easy(foo(a = a, b = 42), bar b)]
2262        );
2263
2264        let attrs = syn::parse::Parser::parse2(syn::Attribute::parse_outer, attrs).unwrap();
2265
2266        let bar = Attributes::parse(&attrs, Span::call_site()).unwrap();
2267        match &bar.foo {
2268            std::option::Option::Some(Foo {
2269                a: A { ident, .. },
2270                b: B { lit, .. },
2271                ..
2272            }) => {
2273                assert_eq!(ident, "a");
2274                assert_eq!(lit.base10_parse::<u32>().unwrap(), 42);
2275            }
2276            _ => panic!(),
2277        }
2278
2279        match &bar.bar {
2280            std::option::Option::Some(bar) => assert_eq!(bar.ident, "b"),
2281            std::option::Option::None => panic!(),
2282        }
2283    }
2284
2285    #[test]
2286    fn test_argument_tuple() {
2287        mod kw {
2288            easy_token!(clear);
2289            easy_token!(load);
2290            easy_token!(store);
2291            easy_token!(attachment);
2292        }
2293
2294        easy_argument_value! {
2295            pub struct Clear(pub kw::clear, pub ReferenceExpr);
2296        }
2297
2298        easy_argument_value! {
2299            pub struct Load(pub kw::load, pub ReferenceExpr);
2300        }
2301
2302        easy_argument_group! {
2303            pub enum LoadOp {
2304                Clear(Clear),
2305                Load(Load),
2306            }
2307        }
2308
2309        easy_argument_value! {
2310            pub struct Store(pub kw::store, pub ReferenceExpr);
2311        }
2312
2313        easy_argument_group! {
2314            pub enum StoreOp {
2315                Store(Store),
2316            }
2317        }
2318
2319        easy_argument_tuple! {
2320            struct AttachmentAttribute {
2321                attachment: kw::attachment,
2322                load_op: core::option::Option<LoadOp>,
2323                store_op: core::option::Option<StoreOp>,
2324            }
2325        }
2326
2327        easy_attributes! {
2328            @(test_namespace)
2329            struct FieldAttributes {
2330                attachment: core::option::Option<AttachmentAttribute>,
2331            }
2332        }
2333
2334        let tokens = quote::quote!(#[test_namespace(attachment(store = const Layout::Present, clear = const ClearColor(0.02, 0.03, 0.03, 1.0)))]);
2335        let attrs = syn::parse::Parser::parse2(syn::Attribute::parse_outer, tokens).unwrap();
2336
2337        let attributes = FieldAttributes::parse(&attrs, Span::call_site()).unwrap();
2338        let attachment_attribute = attributes.attachment.unwrap();
2339
2340        drop(attachment_attribute.load_op);
2341        drop(attachment_attribute.store_op);
2342    }
2343
2344    #[test]
2345    fn test_separated() {
2346        easy_argument_value! {
2347            pub struct Fn {
2348                pub name: syn::Token![fn],
2349                pub ident: syn::Ident,
2350            }
2351        }
2352
2353        easy_argument_value! {
2354            pub struct Impl {
2355                pub name: syn::Token![impl],
2356                pub ident: syn::Ident,
2357            }
2358        }
2359
2360        easy_separated! {
2361            @(syn::Token![,])
2362            /// Docs
2363            pub struct Foo {
2364                /// Docs
2365                pub fns: std::vec::Vec<Fn>,
2366                /// Docs
2367                pub impls: std::vec::Vec<Impl>,
2368            }
2369        }
2370
2371        let foo: Foo = parse_quote! { fn = a, impl(b), fn = c, fn(d), impl = e };
2372
2373        assert_eq!(foo.fns.len(), 3);
2374        assert_eq!(foo.impls.len(), 2);
2375
2376        assert_eq!(foo.fns[0].ident, "a");
2377        assert_eq!(foo.fns[1].ident, "c");
2378        assert_eq!(foo.fns[2].ident, "d");
2379
2380        assert_eq!(foo.impls[0].ident, "b");
2381        assert_eq!(foo.impls[1].ident, "e");
2382    }
2383
2384    #[test]
2385    fn test_terminated() {
2386        easy_argument_value! {
2387            pub struct Fn {
2388                pub name: syn::Token![fn],
2389                pub ident: syn::Ident,
2390            }
2391        }
2392
2393        easy_argument_value! {
2394            pub struct Impl {
2395                pub name: syn::Token![impl],
2396                pub ident: syn::Ident,
2397            }
2398        }
2399
2400        easy_terminated! {
2401            @(syn::Token![,])
2402            /// Docs
2403            pub struct Foo {
2404                /// Docs
2405                pub fns: std::vec::Vec<Fn>,
2406                /// Docs
2407                pub impls: std::vec::Vec<Impl>,
2408            }
2409        }
2410
2411        let foo: Foo = parse_quote! { fn = a, impl(b), fn = c, fn(d), impl = e, };
2412
2413        assert_eq!(foo.fns.len(), 3);
2414        assert_eq!(foo.impls.len(), 2);
2415
2416        assert_eq!(foo.fns[0].ident, "a");
2417        assert_eq!(foo.fns[1].ident, "c");
2418        assert_eq!(foo.fns[2].ident, "d");
2419
2420        assert_eq!(foo.impls[0].ident, "b");
2421        assert_eq!(foo.impls[1].ident, "e");
2422    }
2423}