1use proc_macro::TokenStream;
2use proc_macro2::Span;
3use quote::{format_ident, quote};
4use syn::{spanned::Spanned, Attribute, ItemEnum, ItemStruct};
5
6#[proc_macro_attribute]
21pub fn parse_more(_args: TokenStream, input: TokenStream) -> TokenStream {
22 if let Ok(mut struct_item) = syn::parse::<ItemStruct>(input.clone()) {
23 let struct_ident = &struct_item.ident;
24
25 let mut parsed = vec![];
26 let mut field_idents = vec![];
27
28 let edit_attributes = |attrs: &mut Vec<Attribute>, parsed: &mut Vec<_>| {
29 attrs.iter().cloned().enumerate().filter_map(|(i, attribute)| {
31 if attribute.path().segments.last().is_some_and(|arg | arg.ident == "filler") {
32 let path = attribute.path();
33 let path_struct = format_ident!("__AvoidImportWarning{}", i);
34 match attribute.parse_args::<syn::Type>() {
35 Err(e) => Some(Err(e)),
36 Ok(ty) => {
37 parsed.push(quote! {
38 input.parse::<parse_more::ParseMoreWrapper<#ty>>()?;
39 #[#path]
40 struct #path_struct;
41 });
42 None
43 }
44 }
45 } else {
46 Some(Ok(attribute))
47 }
48 }).collect::<Result<Vec<_>, _>>()
49 };
50
51 for field in &mut struct_item.fields {
52 let field_ident = &field.ident;
53 let field_type = &field.ty;
54
55 field.attrs = match edit_attributes(&mut field.attrs, &mut parsed) {
57 Ok(attrs) => attrs,
58 Err(e) => return e.into_compile_error().into(),
59 };
60
61 field_idents.push(field_ident.clone());
63 parsed.push(quote! {
64 let #field_ident = input.parse::<parse_more::ParseMoreWrapper<#field_type>>()?.0;
65 });
66 }
67
68 quote! {
69 #struct_item
70 impl parse_more::ParseMore for #struct_ident {
71 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
72 #(#parsed)*
73 Ok(Self {
74 #(#field_idents),*
75 })
76 }
77 }
78 }
79 } else if let Ok(enum_item) = syn::parse::<ItemEnum>(input) {
80 let enum_ident = &enum_item.ident;
81
82 let mut parsed = vec![];
83
84 for (i, variant) in enum_item.variants.iter().enumerate() {
85 let variant_ident = &variant.ident;
86 if variant.fields.len() != 1 {
89 return syn::Error::new(variant.fields.span(), "ParseMore derive macro require that enum variants contains exactly one type.").into_compile_error().into();
90 }
91 let variant_type = &variant.fields.iter().next().unwrap().ty;
92
93 let error = if i == 0 {
95 quote! {
96 err = e
97 }
98 } else {
99 quote! {
100 err.combine(e)
101 }
102 };
103 parsed.push(quote! {
106 match input.fork().parse::<parse_more::ParseMoreWrapper<#variant_type>>() {
107 Ok(_) => return Ok(Self::#variant_ident(input.parse::<parse_more::ParseMoreWrapper<#variant_type>>().unwrap().0)),
108 Err(e) => #error,
109 }
110 });
111 }
112
113 quote! {
114 #enum_item
115 impl parse_more::ParseMore for #enum_ident {
116 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
117 let mut err;
118 #(#parsed)*
119 Err(err)
120 }
121 }
122 }
123 } else {
124 syn::Error::new(
125 Span::call_site(),
126 "This macro attribute must be applied on a struct or an enum",
127 )
128 .into_compile_error()
129 }
130 .into()
131}
132
133#[proc_macro_attribute]
148pub fn filler(_args: TokenStream, _input: TokenStream) -> TokenStream {
149 TokenStream::new()
150}