1use crate::syn_utils::*;
2use proc_macro2::{Span, TokenStream};
3use quote::{format_ident, quote, quote_spanned};
4use std::collections::BTreeMap;
5use syn::{
6 ext::IdentExt,
7 parse::{Parse, ParseStream},
8 parse_quote,
9 punctuated::Punctuated,
10 spanned::Spanned,
11 Attribute, Data, DeriveInput, Field, Fields, GenericArgument, Ident, LitStr, PathArguments,
12 Result, Token, Type,
13};
14
15pub fn derive_struct_meta(input: DeriveInput) -> Result<TokenStream> {
16 if let Data::Struct(data) = &input.data {
17 let mut args = ArgsForStruct::default();
18 for attr in &input.attrs {
19 if attr.path().is_ident("struct_meta") {
20 args.parse_from_attr(attr)?;
21 }
22 }
23 let ps = Params::from_fields(&data.fields, &args)?;
24 let body = ps.build();
25 impl_trait_result(
26 &input,
27 &parse_quote!(::structmeta::helpers::exports::syn::parse::Parse),
28 &[],
29 quote! {
30 fn parse(input: ::structmeta::helpers::exports::syn::parse::ParseStream<'_>) -> ::structmeta::helpers::exports::syn::Result<Self> {
31 #body
32 }
33 },
34 args.dump,
35 )
36 } else {
37 let span = input.span();
38 bail!(span, "`#[derive(StructMeta)]` supports only struct.")
39 }
40}
41struct Params<'a> {
42 fields: &'a Fields,
43 unnamed_required: Vec<UnnamedParam<'a>>,
44 unnamed_optional: Vec<UnnamedParam<'a>>,
45 unnamed_variadic: Option<UnnamedParam<'a>>,
46 named: BTreeMap<String, NamedParam<'a>>,
47 rest: Option<RestParam<'a>>,
48 name_filter: NameFilter,
49}
50impl<'a> Params<'a> {
51 fn from_fields(fields: &'a Fields, args: &ArgsForStruct) -> Result<Self> {
52 let mut unnamed_required = Vec::new();
53 let mut unnamed_optional = Vec::new();
54 let mut unnamed_variadic = None;
55 let mut named = BTreeMap::new();
56 let mut rest = None;
57 for (index, field) in fields.iter().enumerate() {
58 let span = field.span();
59 match Param::from_field(index, field)? {
60 Param::Unnamed(p) => {
61 if unnamed_variadic.is_some() {
62 bail!(
63 span,
64 "cannot use unnamed parameter after variadic parameter."
65 )
66 }
67 if p.is_vec {
68 unnamed_variadic = Some(p);
69 } else if p.is_option {
70 unnamed_optional.push(p);
71 } else {
72 if !unnamed_optional.is_empty() {
73 bail!(
74 span,
75 "cannot use non optional parameter after variadic parameter."
76 )
77 }
78 unnamed_required.push(p);
79 }
80 }
81 Param::Named(p) => {
82 if named.contains_key(&p.name) {
83 bail!(p.name_span, "`{}` is already exists.", p.name);
84 }
85 named.insert(p.name.clone(), p);
86 }
87 Param::Rest(p) => {
88 if rest.is_some() {
89 bail!(span, "cannot use rest parameter twice.")
90 }
91 rest = Some(p);
92 }
93 }
94 }
95 Ok(Self {
96 fields,
97 unnamed_required,
98 unnamed_optional,
99 unnamed_variadic,
100 named,
101 rest,
102 name_filter: args.name_filter(),
103 })
104 }
105 fn build(&self) -> TokenStream {
106 let mut is_next = false;
107 let mut ts = TokenStream::new();
108 let mut ctor_args = vec![TokenStream::new(); self.fields.len()];
109 for (index, p) in self.unnamed_required.iter().enumerate() {
110 if is_next {
111 let msg = format!(
112 "expected least {} arguments but {} argument was supplied",
113 self.unnamed_required.len(),
114 index,
115 );
116 ts.extend(quote! {
117 if input.is_empty () {
118 return Err(::structmeta::helpers::exports::syn::Error::new(input.span(), #msg));
119 }
120 input.parse::<::structmeta::helpers::exports::syn::Token![,]>()?;
121 });
122 }
123 is_next = true;
124 ts.extend(p.info.build_let_parse());
125 p.build_ctor_arg(false, &mut ctor_args);
126 }
127
128 let mut arms_unnamed = Vec::new();
129 for (index, p) in self.unnamed_optional.iter().enumerate() {
130 ts.extend(p.info.build_let_none());
131 arms_unnamed.push(p.build_arm_parse_value(index));
132 p.build_ctor_arg(true, &mut ctor_args);
133 }
134 if let Some(p) = &self.unnamed_variadic {
135 ts.extend(p.info.build_let_vec_new());
136 arms_unnamed.push(p.build_arm_parse_vec_item());
137 p.build_ctor_arg(false, &mut ctor_args);
138 } else {
139 arms_unnamed.push(quote! {
140 _ => { return Err(input.error("too many unnamed parameter")); }
141 });
142 }
143 for p in self.named.values() {
144 ts.extend(p.build_let());
145 p.build_ctor_arg(&mut ctor_args);
146 }
147 let (flag_ps, flag_rest) = self.named_ps(|p| p.is_flag());
148 let (name_value_ps, name_value_rest) = self.named_ps(|p| p.is_name_value());
149 let (name_args_ps, name_args_rest) = self.named_ps(|p| p.is_name_args());
150
151 let mut arms_named = Vec::new();
152 for (index, p) in flag_ps.iter().enumerate() {
153 arms_named.push(p.build_arm_parse(index, ArgKind::Flag));
154 }
155 for (index, p) in name_value_ps.iter().enumerate() {
156 arms_named.push(p.build_arm_parse(index, ArgKind::NameValue));
157 }
158 for (index, p) in name_args_ps.iter().enumerate() {
159 arms_named.push(p.build_arm_parse(index, ArgKind::NameArgs));
160 }
161 if let Some(p) = &self.rest {
162 ts.extend(p.build_let());
163 p.build_ctor_arg(&mut ctor_args);
164 if flag_rest {
165 arms_named.push(p.build_arm_parse(ArgKind::Flag));
166 }
167 if name_value_rest {
168 arms_named.push(p.build_arm_parse(ArgKind::NameValue));
169 }
170 if name_args_rest {
171 arms_named.push(p.build_arm_parse(ArgKind::NameArgs));
172 }
173 }
174
175 let flag_names = NamedParam::names(&flag_ps);
176 let name_value_names = NamedParam::names(&name_value_ps);
177 let name_args_names = NamedParam::names(&name_args_ps);
178 let no_unnamed = self.unnamed_optional.is_empty() && self.unnamed_variadic.is_none();
179 let ctor_args = match &self.fields {
180 Fields::Named(_) => {
181 quote!({ #(#ctor_args,)*})
182 }
183 Fields::Unnamed(_) => {
184 quote!(( #(#ctor_args,)*))
185 }
186 Fields::Unit => {
187 quote!()
188 }
189 };
190
191 let ts_parse_unnamed = if !self.unnamed_optional.is_empty()
192 || self.unnamed_variadic.is_some()
193 {
194 quote! {
195 if named_used {
196 return Err(input.error("cannot use unnamed parameter after named parameter"));
197 }
198 match unnamed_index {
199 #(#arms_unnamed)*
200 }
201 unnamed_index += 1;
202 }
203 } else {
204 quote! {
205 return Err(input.error("cannot use unnamed parameter"));
206 }
207 };
208 let name_filter = self.name_filter.to_code();
209
210 ts.extend(quote! {
211 let mut is_next = #is_next;
212 let mut unnamed_index = 0;
213 let mut named_used = false;
214 while !input.is_empty() {
215 if is_next {
216 input.parse::<::structmeta::helpers::exports::syn::Token![,]>()?;
217 if input.is_empty() {
218 break;
219 }
220 }
221 is_next = true;
222 if let Some((index, span)) = ::structmeta::helpers::try_parse_name(input,
223 &[#(#flag_names,)*],
224 #flag_rest,
225 &[#(#name_value_names,)*],
226 #name_value_rest,
227 &[#(#name_args_names,)*],
228 #name_args_rest,
229 #no_unnamed,
230 #name_filter)?
231 {
232 named_used = true;
233 match index {
234 #(#arms_named)*
235 _ => unreachable!()
236 }
237
238 } else {
239 #ts_parse_unnamed
240 }
241 }
242 Ok(Self #ctor_args)
243 });
244
245 ts
246 }
247 fn named_ps(&self, f: impl Fn(&NamedParamType<'a>) -> bool) -> (Vec<&NamedParam<'a>>, bool) {
248 (
249 self.named.values().filter(|p| f(&p.ty)).collect(),
250 if let Some(p) = &self.rest {
251 f(&p.ty)
252 } else {
253 false
254 },
255 )
256 }
257}
258
259enum Param<'a> {
260 Unnamed(UnnamedParam<'a>),
261 Named(NamedParam<'a>),
262 Rest(RestParam<'a>),
263}
264
265impl<'a> Param<'a> {
266 fn from_field(index: usize, field: &'a Field) -> Result<Self> {
267 let mut name = None;
268 let mut name_specified = false;
269 let mut unnamed = false;
270 for attr in &field.attrs {
271 if attr.path().is_ident("struct_meta") {
272 let a = attr.parse_args::<ArgsForField>()?;
273 if let Some(a_name) = a.name {
274 name = Some((a_name.value(), a_name.span()));
275 name_specified = true;
276 }
277 if a.unnamed {
278 unnamed = true;
279 }
280 }
281 }
282 if name.is_none() {
283 if let Some(ident) = &field.ident {
284 name = Some((ident.unraw().to_string(), ident.span()));
285 }
286 }
287 if unnamed {
288 name = None;
289 }
290
291 let mut is_map = false;
292 let mut is_option = false;
293
294 let ty = if let (false, Some(ty)) = (name_specified, get_hash_map_string_element(&field.ty))
295 {
296 is_map = true;
297 ty
298 } else if let Some(ty) = get_option_element(&field.ty) {
299 is_option = true;
300 ty
301 } else {
302 &field.ty
303 };
304
305 let info = ParamInfo::new(index, field, ty);
306 let ty = NamedParamType::from_type(ty, !is_map && !is_option);
307 let this = if is_map {
308 Param::Rest(RestParam { info, ty })
309 } else if let Some((name, name_span)) = name {
310 Param::Named(NamedParam {
311 info,
312 name,
313 name_span,
314 ty,
315 is_option,
316 })
317 } else if let NamedParamType::Value { ty, is_vec } = ty {
318 Param::Unnamed(UnnamedParam {
319 info,
320 ty,
321 is_option,
322 is_vec,
323 })
324 } else {
325 bail!(
326 info.span(),
327 "this field type cannot be used as unnamed parameter."
328 )
329 };
330 Ok(this)
331 }
332}
333
334struct ParamInfo<'a> {
335 index: usize,
336 field: &'a Field,
337 ty: &'a Type,
338 temp_ident: Ident,
339}
340impl<'a> ParamInfo<'a> {
341 fn new(index: usize, field: &'a Field, ty: &'a Type) -> Self {
342 let temp_ident = format_ident!("_value_{}", index);
343 Self {
344 index,
345 field,
346 ty,
347 temp_ident,
348 }
349 }
350 fn span(&self) -> Span {
351 self.field.span()
352 }
353 fn build_let_none(&self) -> TokenStream {
354 let temp_ident = &self.temp_ident;
355 let ty = &self.ty;
356 quote!(let mut #temp_ident : Option<#ty> = None;)
357 }
358 fn build_let_vec_new(&self) -> TokenStream {
359 let temp_ident = &self.temp_ident;
360 let ty = &self.ty;
361 quote!(let mut #temp_ident = <#ty>::new();)
362 }
363 fn build_let_parse(&self) -> TokenStream {
364 let temp_ident = &self.temp_ident;
365 let ty = &self.field.ty;
366 quote_spanned!(self.span()=> let #temp_ident = input.parse::<#ty>()?;)
367 }
368}
369
370struct RestParam<'a> {
371 info: ParamInfo<'a>,
372 ty: NamedParamType<'a>,
373}
374
375struct NamedParam<'a> {
376 info: ParamInfo<'a>,
377 name: String,
378 name_span: Span,
379 ty: NamedParamType<'a>,
380 is_option: bool,
381}
382
383struct UnnamedParam<'a> {
384 info: ParamInfo<'a>,
385 ty: &'a Type,
386 is_option: bool,
387 is_vec: bool,
388}
389impl<'a> NamedParam<'a> {
390 fn build_let(&self) -> TokenStream {
391 let temp_ident = &self.info.temp_ident;
392 quote!(let mut #temp_ident = None;)
393 }
394 fn build_arm_parse(&self, index: usize, kind: ArgKind) -> TokenStream {
395 let temp_ident = &self.info.temp_ident;
396 let msg = format!("parameter `{}` specified more than once", self.name);
397 let span = self.info.field.span();
398 let expr = self.ty.build_parse_expr(kind, span);
399 let var = kind.to_helper_name_index_variant();
400 quote_spanned! { span=>
401 ::structmeta::helpers::NameIndex::#var(Ok(#index)) => {
402 if #temp_ident.is_some() {
403 return Err(::structmeta::helpers::exports::syn::Error::new(span, #msg));
404 }
405 #temp_ident = Some(#expr);
406 }
407 }
408 }
409 fn names<'b>(ps: &[&'b Self]) -> Vec<&'b str> {
410 ps.iter().map(|x| x.name.as_str()).collect()
411 }
412 fn build_ctor_arg(&self, ctor_args: &mut [TokenStream]) {
413 let temp_ident = &self.info.temp_ident;
414 let value = if self.is_option {
415 quote!(#temp_ident)
416 } else {
417 match self.ty {
418 NamedParamType::Flag => quote!(::structmeta::Flag { span: #temp_ident }),
419 NamedParamType::Bool => quote!(#temp_ident.is_some()),
420 NamedParamType::Value { .. } | NamedParamType::NameValue { .. } => {
421 let msg = format!("missing argument `{} = ...`", self.name);
422 quote!(#temp_ident.ok_or_else(|| ::structmeta::helpers::exports::syn::Error::new(::structmeta::helpers::exports::proc_macro2::Span::call_site(), #msg))?)
423 }
424 NamedParamType::NameArgs { .. } => {
425 let msg = format!("missing argument `{}(...)`", self.name);
426 quote!(#temp_ident.ok_or_else(|| ::structmeta::helpers::exports::syn::Error::new(::structmeta::helpers::exports::proc_macro2::Span::call_site(), #msg))?)
427 }
428 }
429 };
430 build_ctor_arg(&self.info, value, ctor_args)
431 }
432}
433impl<'a> RestParam<'a> {
434 fn build_let(&self) -> TokenStream {
435 let temp_ident = &self.info.temp_ident;
436 quote!(let mut #temp_ident = ::std::collections::HashMap::new();)
437 }
438 fn build_arm_parse(&self, kind: ArgKind) -> TokenStream {
439 let temp_ident = &self.info.temp_ident;
440 let span = self.info.field.span();
441 let expr = self.ty.build_parse_expr(kind, span);
442 let var = kind.to_helper_name_index_variant();
443 quote_spanned! { span=>
444 ::structmeta::helpers::NameIndex::#var(Err(name)) => {
445 if #temp_ident.insert(name.to_string(), #expr).is_some() {
446 return Err(::structmeta::helpers::exports::syn::Error::new(span, format!("parameter `{}` specified more than once", name)));
447 }
448 }
449 }
450 }
451 fn build_ctor_arg(&self, ctor_args: &mut [TokenStream]) {
452 let temp_ident = &self.info.temp_ident;
453 build_ctor_arg(&self.info, quote!(#temp_ident), ctor_args)
454 }
455}
456impl<'a> UnnamedParam<'a> {
457 fn build_arm_parse_value(&self, index: usize) -> TokenStream {
458 let temp_ident = &self.info.temp_ident;
459 let span = self.info.field.span();
460 let expr = build_parse_expr(self.ty, span);
461 quote_spanned! { span=>
462 #index => {
463 #temp_ident = Some(#expr);
464 }
465 }
466 }
467 fn build_arm_parse_vec_item(&self) -> TokenStream {
468 let temp_ident = &self.info.temp_ident;
469 let span = self.info.field.span();
470 let expr = build_parse_expr(self.ty, span);
471 quote_spanned! { self.info.field.span()=>
472 _ => {
473 #temp_ident.push(#expr);
474 }
475 }
476 }
477 fn build_ctor_arg(&self, var_is_option: bool, ctor_args: &mut [TokenStream]) {
478 let temp_ident = &self.info.temp_ident;
479 let value = match (var_is_option, self.is_option) {
480 (false, false) | (true, true) => {
481 quote!(#temp_ident)
482 }
483 (true, false) => {
484 quote!(#temp_ident.unwrap())
485 }
486 _ => {
487 unreachable!()
488 }
489 };
490 build_ctor_arg(&self.info, value, ctor_args)
491 }
492}
493fn build_ctor_arg(info: &ParamInfo, value: TokenStream, ctor_args: &mut [TokenStream]) {
494 let value = if let Some(ident) = &info.field.ident {
495 quote!(#ident : #value)
496 } else {
497 value
498 };
499 ctor_args[info.index] = value;
500}
501
502mod kw {
503 use syn::custom_keyword;
504
505 custom_keyword!(dump);
506 custom_keyword!(name_filter);
507 custom_keyword!(name);
508 custom_keyword!(unnamed);
509}
510
511#[derive(Debug, Clone, Copy)]
512enum NameFilter {
513 None,
514 SnakeCase,
515}
516impl NameFilter {
517 fn to_code(self) -> TokenStream {
518 match self {
519 NameFilter::None => quote!(&|_| true),
520 NameFilter::SnakeCase => quote!(&::structmeta::helpers::is_snake_case),
521 }
522 }
523}
524
525#[derive(Debug, Default, Clone, Copy)]
526struct ArgsForStruct {
527 dump: bool,
528 name_filter: Option<NameFilter>,
529}
530impl ArgsForStruct {
531 fn parse_from_attr(&mut self, attr: &Attribute) -> Result<()> {
532 let args = attr.parse_args_with(Punctuated::<ArgForStruct, Token![,]>::parse_terminated)?;
533 for arg in args.into_iter() {
534 match arg {
535 ArgForStruct::Dump(_) => self.dump = true,
536 ArgForStruct::NameFilter { span, value } => {
537 if self.name_filter.is_some() {
538 bail!(span, "`name_filter` cannot be specified twice");
539 }
540 self.name_filter = Some(value);
541 }
542 }
543 }
544 Ok(())
545 }
546 fn name_filter(&self) -> NameFilter {
547 self.name_filter.unwrap_or(NameFilter::None)
548 }
549}
550
551enum ArgForStruct {
552 Dump(kw::dump),
553 NameFilter { span: Span, value: NameFilter },
554}
555impl Parse for ArgForStruct {
556 fn parse(input: ParseStream) -> Result<Self> {
557 if input.peek(kw::dump) {
558 return Ok(Self::Dump(input.parse()?));
559 }
560 if input.peek(kw::name_filter) {
561 let kw_name_filter: kw::name_filter = input.parse()?;
562 let _eq: Token![=] = input.parse()?;
563 let s: LitStr = input.parse()?;
564 let value = match s.value().as_str() {
565 "snake_case" => NameFilter::SnakeCase,
566 _ => {
567 bail!(s.span(), "expected \"snake_case\"")
568 }
569 };
570 return Ok(Self::NameFilter {
571 span: kw_name_filter.span,
572 value,
573 });
574 }
575 Err(input.error("usage : #[struct_meta(dump)]"))
576 }
577}
578
579struct ArgsForField {
580 name: Option<LitStr>,
581 unnamed: bool,
582}
583impl Parse for ArgsForField {
584 fn parse(input: ParseStream) -> Result<Self> {
585 let mut name = None;
586 let mut unnamed = false;
587 for p in Punctuated::<_, Token![,]>::parse_terminated(input)?.into_iter() {
588 match p {
589 ArgForField::Name { value, .. } => name = Some(value),
590 ArgForField::Unnamed { .. } => unnamed = true,
591 }
592 }
593 Ok(Self { name, unnamed })
594 }
595}
596
597enum ArgForField {
598 Name {
599 _name_token: kw::name,
600 _eq_token: Token![=],
601 value: LitStr,
602 },
603 Unnamed {
604 _unnamed_token: kw::unnamed,
605 },
606}
607impl Parse for ArgForField {
608 fn parse(input: ParseStream) -> Result<Self> {
609 if input.peek(kw::name) && input.peek2(Token![=]) {
610 let name_token = input.parse()?;
611 let eq_token = input.parse()?;
612 let value = input.parse()?;
613 Ok(Self::Name {
614 _name_token: name_token,
615 _eq_token: eq_token,
616 value,
617 })
618 } else if input.peek(kw::unnamed) {
619 Ok(Self::Unnamed {
620 _unnamed_token: input.parse()?,
621 })
622 } else {
623 Err(input.error("expected `name = \"...\"` or `unnamed`."))
624 }
625 }
626}
627
628enum NamedParamType<'a> {
629 Bool,
630 Flag,
631 Value {
632 ty: &'a Type,
633 is_vec: bool,
634 },
635 NameValue {
636 ty: &'a Type,
637 is_option: bool,
638 },
639 NameArgs {
640 ty: &'a Type,
641 is_option: bool,
642 is_vec: bool,
643 },
644}
645
646impl<'a> NamedParamType<'a> {
647 fn from_type(ty: &'a Type, may_flag: bool) -> Self {
648 if may_flag && is_bool(ty) {
649 Self::Bool
650 } else if may_flag && is_flag(ty) {
651 Self::Flag
652 } else if let Some(mut ty) = get_name_value_element(ty) {
653 let mut is_option = false;
654 if let Some(e) = get_option_element(ty) {
655 is_option = true;
656 ty = e;
657 }
658 Self::NameValue { ty, is_option }
659 } else if let Some(mut ty) = get_name_args_element(ty) {
660 let mut is_option = false;
661 if let Some(e) = get_option_element(ty) {
662 is_option = true;
663 ty = e;
664 }
665 let mut is_vec = false;
666 if let Some(e) = get_vec_element(ty) {
667 is_vec = true;
668 ty = e;
669 }
670 Self::NameArgs {
671 ty,
672 is_option,
673 is_vec,
674 }
675 } else {
676 let mut ty = ty;
677 let mut is_vec = false;
678 if let Some(e) = get_vec_element(ty) {
679 is_vec = true;
680 ty = e;
681 }
682 Self::Value { ty, is_vec }
683 }
684 }
685 fn is_flag(&self) -> bool {
686 match self {
687 NamedParamType::Bool | NamedParamType::Flag => true,
688 NamedParamType::Value { .. } => false,
689 NamedParamType::NameValue { is_option, .. }
690 | NamedParamType::NameArgs { is_option, .. } => *is_option,
691 }
692 }
693 fn is_name_value(&self) -> bool {
694 match self {
695 NamedParamType::Bool | NamedParamType::Flag => false,
696 NamedParamType::Value { is_vec, .. } => !is_vec,
697 NamedParamType::NameValue { .. } => true,
698 NamedParamType::NameArgs { .. } => false,
699 }
700 }
701 fn is_name_args(&self) -> bool {
702 match self {
703 NamedParamType::Bool | NamedParamType::Flag => false,
704 NamedParamType::Value { is_vec, .. } => *is_vec,
705 NamedParamType::NameValue { .. } => false,
706 NamedParamType::NameArgs { .. } => true,
707 }
708 }
709 fn build_parse_expr(&self, kind: ArgKind, span: Span) -> TokenStream {
710 match self {
711 NamedParamType::Bool | NamedParamType::Flag => quote!(span),
712 NamedParamType::Value { ty, is_vec } => {
713 if *is_vec {
714 build_parse_expr_name_args(ty, *is_vec, span)
715 } else {
716 build_parse_expr(ty, span)
717 }
718 }
719 NamedParamType::NameValue { ty, is_option } => {
720 let value = if kind == ArgKind::Flag && *is_option {
721 quote!(None)
722 } else {
723 let value = build_parse_expr(ty, span);
724 if *is_option {
725 quote!(Some(#value))
726 } else {
727 value
728 }
729 };
730 quote!(::structmeta::NameValue { name_span : span, value: #value })
731 }
732 NamedParamType::NameArgs {
733 ty,
734 is_option,
735 is_vec,
736 } => {
737 let args = if kind == ArgKind::Flag && *is_option {
738 quote!(None)
739 } else {
740 let args = build_parse_expr_name_args(ty, *is_vec, span);
741 if *is_option {
742 quote!(Some(#args))
743 } else {
744 args
745 }
746 };
747 quote!(structmeta::NameArgs { name_span : span, args: #args })
748 }
749 }
750 }
751}
752
753fn build_parse_expr(ty: &Type, span: Span) -> TokenStream {
754 quote_spanned!(span=> input.parse::<#ty>()?)
755}
756fn build_parse_expr_name_args(ty: &Type, is_vec: bool, span: Span) -> TokenStream {
757 let value = if is_vec {
758 quote_spanned!(span=> ::structmeta::helpers::exports::syn::punctuated::Punctuated::<#ty, ::structmeta::helpers::exports::syn::Token![,]>::parse_terminated(&content)?.into_iter().collect())
759 } else {
760 quote_spanned!(span=> content.parse::<#ty>()?)
761 };
762 quote! {
763 {
764 let content;
765 ::structmeta::helpers::exports::syn::parenthesized!(content in input);
766 #value
767 }
768 }
769}
770
771#[derive(Eq, PartialEq, Debug, Copy, Clone)]
772enum ArgKind {
773 Flag,
774 NameValue,
775 NameArgs,
776}
777impl ArgKind {
778 fn to_helper_name_index_variant(self) -> TokenStream {
779 match self {
780 Self::Flag => quote!(Flag),
781 Self::NameValue => quote!(NameValue),
782 Self::NameArgs => quote!(NameArgs),
783 }
784 }
785}
786
787fn get_option_element(ty: &Type) -> Option<&Type> {
788 get_element(ty, &[&["std", "option"], &["core", "option"]], "Option")
789}
790fn get_vec_element(ty: &Type) -> Option<&Type> {
791 get_element(ty, &[&["std", "vec"], &["alloc", "vec"]], "Vec")
792}
793fn get_name_value_element(ty: &Type) -> Option<&Type> {
794 get_element(ty, NS_STRUCTMETA, "NameValue")
795}
796fn get_name_args_element(ty: &Type) -> Option<&Type> {
797 get_element(ty, NS_STRUCTMETA, "NameArgs")
798}
799fn get_hash_map_element(ty: &Type) -> Option<(&Type, &Type)> {
800 get_element2(
801 ty,
802 &[&["std", "collections"], &["std", "collections", "hash_map"]],
803 "HashMap",
804 )
805}
806fn get_hash_map_string_element(ty: &Type) -> Option<&Type> {
807 let (ty_key, ty_value) = get_hash_map_element(ty)?;
808 if is_string(ty_key) {
809 Some(ty_value)
810 } else {
811 None
812 }
813}
814
815fn is_bool(ty: &Type) -> bool {
816 is_type(ty, NS_PRIMITIVE, "bool")
817}
818fn is_flag(ty: &Type) -> bool {
819 is_type(ty, NS_STRUCTMETA, "Flag")
820}
821fn is_string(ty: &Type) -> bool {
822 is_type(ty, &[&["std", "string"], &["alloc", "string"]], "String")
823}
824
825fn get_element<'a>(ty: &'a Type, ns: &[&[&str]], name: &str) -> Option<&'a Type> {
826 if let PathArguments::AngleBracketed(args) = get_arguments_of(ty, ns, name)? {
827 if args.args.len() == 1 {
828 if let GenericArgument::Type(ty) = &args.args[0] {
829 return Some(ty);
830 }
831 }
832 }
833 None
834}
835fn get_element2<'a>(ty: &'a Type, ns: &[&[&str]], name: &str) -> Option<(&'a Type, &'a Type)> {
836 if let PathArguments::AngleBracketed(args) = get_arguments_of(ty, ns, name)? {
837 if args.args.len() == 2 {
838 if let (GenericArgument::Type(ty0), GenericArgument::Type(ty1)) =
839 (&args.args[0], &args.args[1])
840 {
841 return Some((ty0, ty1));
842 }
843 }
844 }
845 None
846}
847
848const NS_STRUCTMETA: &[&[&str]] = &[&["structmeta"]];
849const NS_PRIMITIVE: &[&[&str]] = &[&["std", "primitive"], &["core", "primitive"]];
850
851#[cfg(test)]
852mod tests {
853 use super::*;
854 #[test]
855 fn test_is_option() {
856 assert_eq!(
857 get_option_element(&parse_quote!(Option<u8>)),
858 Some(&parse_quote!(u8))
859 );
860 }
861 #[test]
862 fn test_is_option_mod() {
863 assert_eq!(
864 get_option_element(&parse_quote!(option::Option<u8>)),
865 Some(&parse_quote!(u8))
866 );
867 }
868 #[test]
869 fn test_is_option_core() {
870 assert_eq!(
871 get_option_element(&parse_quote!(core::option::Option<u8>)),
872 Some(&parse_quote!(u8))
873 );
874 }
875 #[test]
876 fn test_is_option_std() {
877 assert_eq!(
878 get_option_element(&parse_quote!(std::option::Option<u8>)),
879 Some(&parse_quote!(u8))
880 );
881 }
882}