1#![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
75pub trait EasyToken: EasyPeek + Parse + Spanned {
79 fn display() -> &'static str;
81}
82
83#[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
98pub trait EasyPeek: Parse {
102 fn peek(lookahead1: &Lookahead1) -> bool;
104
105 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#[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#[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#[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#[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#[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#[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#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
570pub enum EasyMaybe<T> {
571 Nothing,
573
574 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#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
599pub enum EasySubArgument<V, T = V> {
600 Value(V),
602
603 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#[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#[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
922pub trait EasyArgument: EasyPeek {
926 fn name_display() -> &'static str;
928
929 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#[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#[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#[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
1338pub trait EasyArgumentGroup {
1342 fn try_parse(lookahead1: &Lookahead1, stream: ParseStream) -> syn::Result<Option<Self>>
1347 where
1348 Self: Sized;
1349
1350 fn overlap_error(&self, other: &Self) -> syn::Error;
1356
1357 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#[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
1464pub trait EasyArgumentField {
1469 fn try_parse(lookahead1: &Lookahead1, stream: ParseStream) -> syn::Result<Option<Self>>
1474 where
1475 Self: Sized;
1476
1477 fn try_extend(&mut self, lookahead1: &Lookahead1, stream: ParseStream) -> syn::Result<bool>;
1483
1484 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#[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#[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#[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
1932pub trait EasyAttributes {
1935 fn parse(attrs: &[Attribute], span: Span) -> syn::Result<Self>
1937 where
1938 Self: Sized;
1939
1940 fn parse_in(namespace: &syn::Ident, attrs: &[Attribute], span: Span) -> syn::Result<Self>
1942 where
1943 Self: Sized;
1944}
1945
1946#[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 #[derive(Clone, Debug, PartialEq, Eq)]
2043 pub enum ReferenceExpr {
2044 ! Member {
2046 member: syn::Member,
2048 },
2049 Expr {
2051 const_: syn::Token![const],
2053
2054 expr: syn::Expr,
2056 },
2057 }
2058}
2059
2060#[cfg(any(test, doc))]
2061#[allow(missing_docs)]
2062pub mod examples {
2063 easy_flags! {
2064 pub Nya(nya) | pub Nyas(nyas) {
2066 Puk(puk),
2068 Pak(pak),
2070 }
2071 }
2072
2073 easy_parse! {
2074 #[derive(Clone, Debug)]
2076 pub struct Foo {
2077 pub foo: syn::Ident,
2079 }
2080 }
2081
2082 easy_parse! {
2083 #[derive(Clone, Copy, Debug)]
2085 pub struct Bar;
2086 }
2087
2088 easy_parse! {
2089 #[derive(Clone, Debug)]
2091 pub struct Baz(pub syn::Member);
2092 }
2093
2094 easy_parse! {
2095 #[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 #[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 #[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)]
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 pub Nya(nya) |
2165 Nyas(nyas) {
2167 Puk(puk),
2169 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 #[derive(Clone, Debug)]
2184 pub struct A {
2185 pub a: a,
2187
2188 pub ident: syn::Ident,
2190 }
2191 }
2192
2193 easy_argument_value! {
2194 #[derive(Clone, Debug)]
2196 pub struct B {
2197 pub b: b,
2199
2200 pub lit: syn::LitInt,
2202 }
2203 }
2204
2205 easy_argument_tuple! {
2206 #[derive(Clone, Debug)]
2208 pub struct Foo {
2209 pub name: foo,
2211 pub a: A,
2213 pub b: B,
2215 }
2216 }
2217
2218 easy_argument! {
2219 #[derive(Clone, Debug)]
2221 pub struct Bar {
2222 pub name: bar,
2224 pub ident: syn::Ident,
2226 }
2227 }
2228
2229 easy_argument_group! {
2230 #[derive(Clone, Debug)]
2232 pub enum Group {
2233 Foo(
2235 Foo
2237 ),
2238 Bar(
2240 Bar
2242 ),
2243 }
2244 }
2245
2246 easy_attributes! {
2247 @(easy)
2248 #[derive(Clone, Default)]
2250 pub struct Attributes {
2251 pub foo: std::option::Option<Foo>,
2253 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 pub struct Foo {
2364 pub fns: std::vec::Vec<Fn>,
2366 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 pub struct Foo {
2404 pub fns: std::vec::Vec<Fn>,
2406 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}