parse_display_derive/
lib.rs

1#![recursion_limit = "128"]
2#![allow(clippy::large_enum_variant)]
3
4//! The documentation for this crate is found in the parse-display crate.
5
6extern crate proc_macro;
7
8#[macro_use]
9mod regex_utils;
10
11#[macro_use]
12mod syn_utils;
13
14mod format_syntax;
15
16use crate::{format_syntax::*, regex_utils::*, syn_utils::*};
17use proc_macro2::{Span, TokenStream};
18use quote::{format_ident, quote, quote_spanned, ToTokens};
19use regex::{Captures, Regex};
20use regex_syntax::hir::Hir;
21use std::{
22    collections::{BTreeMap, HashMap},
23    fmt::{Display, Formatter},
24    ops::{Deref, DerefMut},
25};
26use structmeta::{Flag, StructMeta, ToTokens};
27use syn::{
28    ext::IdentExt,
29    parse::{discouraged::Speculative, Parse, ParseStream},
30    parse_macro_input, parse_quote, parse_str,
31    spanned::Spanned,
32    Attribute, Data, DataEnum, DataStruct, DeriveInput, Expr, Field, Fields, FieldsNamed,
33    FieldsUnnamed, Ident, LitStr, Member, Path, Result, Token, Type, Variant, WherePredicate,
34};
35
36#[proc_macro_derive(Display, attributes(display))]
37pub fn derive_display(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
38    let input = parse_macro_input!(input as DeriveInput);
39    into_macro_output(match &input.data {
40        Data::Struct(data) => derive_display_for_struct(&input, data),
41        Data::Enum(data) => derive_display_for_enum(&input, data),
42        Data::Union(_) => panic!("`#[derive(Display)]` supports only enum or struct."),
43    })
44}
45
46fn derive_display_for_struct(input: &DeriveInput, data: &DataStruct) -> Result<TokenStream> {
47    let hattrs = HelperAttributes::from(&input.attrs, false)?;
48    let context = DisplayContext::Struct {
49        data,
50        crate_path: &hattrs.crate_path,
51    };
52    let generics = GenericParamSet::new(&input.generics);
53
54    let mut format = hattrs.format;
55    if format.is_none() {
56        format = DisplayFormat::from_newtype_struct(data);
57    }
58    let Some(format) = format else {
59        bail!(
60            input.span(),
61            r#"`#[display("format")]` is required except newtype pattern."#,
62        )
63    };
64    let mut bounds = Bounds::from_data(hattrs.bound_display);
65    let write = format
66        .format_args(context, &None, &mut bounds, &generics)?
67        .build_write(quote!(f))?;
68    let trait_path = parse_quote!(::core::fmt::Display);
69    let wheres = bounds.build_wheres(&trait_path);
70    impl_trait_result(
71        input,
72        &trait_path,
73        &wheres,
74        quote! {
75            fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
76                #write
77            }
78        },
79        hattrs.dump_display,
80    )
81}
82fn derive_display_for_enum(input: &DeriveInput, data: &DataEnum) -> Result<TokenStream> {
83    fn make_arm(
84        hattrs_enum: &HelperAttributes,
85        variant: &Variant,
86        bounds: &mut Bounds,
87        generics: &GenericParamSet,
88    ) -> Result<TokenStream> {
89        let fields = match &variant.fields {
90            Fields::Named(fields) => {
91                let fields = FieldKey::from_fields_named(fields).map(|(key, ..)| {
92                    let var = key.binding_var();
93                    quote! { #key : ref #var }
94                });
95                quote! { { #(#fields,)* } }
96            }
97            Fields::Unnamed(fields) => {
98                let fields = FieldKey::from_fields_unnamed(fields).map(|(key, ..)| {
99                    let var = key.binding_var();
100                    quote! { ref #var }
101                });
102                quote! { ( #(#fields,)* ) }
103            }
104            Fields::Unit => quote! {},
105        };
106        let hattrs_variant = HelperAttributes::from(&variant.attrs, false)?;
107        let style = DisplayStyle::from_helper_attributes(hattrs_enum, &hattrs_variant);
108        let mut format = hattrs_variant.format;
109        if format.is_none() {
110            format.clone_from(&hattrs_enum.format);
111        }
112        if format.is_none() {
113            format = DisplayFormat::from_unit_variant(variant)?;
114        }
115        let Some(format) = format else {
116            bail!(
117                variant.span(),
118                r#"`#[display(\"format\")]` is required except unit variant."#
119            )
120        };
121        let variant_ident = &variant.ident;
122        let write = format
123            .format_args(
124                DisplayContext::Variant {
125                    variant,
126                    style,
127                    crate_path: &hattrs_enum.crate_path,
128                },
129                &None,
130                &mut bounds.child(hattrs_variant.bound_display),
131                generics,
132            )?
133            .build_write(quote!(f))?;
134        Ok(quote! {
135            & Self::#variant_ident #fields => {
136                #write
137            },
138        })
139    }
140    let hattrs = HelperAttributes::from(&input.attrs, false)?;
141    let mut bounds = Bounds::from_data(hattrs.bound_display.clone());
142    let generics = GenericParamSet::new(&input.generics);
143    let mut arms = Vec::new();
144    for variant in &data.variants {
145        arms.push(make_arm(&hattrs, variant, &mut bounds, &generics)?);
146    }
147    let trait_path = parse_quote!(::core::fmt::Display);
148    let contents = quote! {
149        fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
150            match self {
151                #(#arms)*
152            }
153        }
154    };
155    let wheres = bounds.build_wheres(&trait_path);
156    impl_trait_result(input, &trait_path, &wheres, contents, hattrs.dump_display)
157}
158
159#[proc_macro_derive(FromStr, attributes(display, from_str))]
160pub fn derive_from_str(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
161    let input = parse_macro_input!(input as DeriveInput);
162    into_macro_output(match &input.data {
163        Data::Struct(data) => derive_from_str_for_struct(&input, data),
164        Data::Enum(data) => derive_from_str_for_enum(&input, data),
165        Data::Union(_) => panic!("`#[derive(FromStr)]` supports only enum or struct."),
166    })
167}
168fn derive_from_str_for_struct(input: &DeriveInput, data: &DataStruct) -> Result<TokenStream> {
169    let hattrs = HelperAttributes::from(&input.attrs, true)?;
170    let p = ParserBuilder::from_struct(&hattrs, data)?;
171    let crate_path = &hattrs.crate_path;
172    let trait_path = parse_quote!(::core::str::FromStr);
173    let body = p.build_from_str_body(crate_path, parse_quote!(Self))?;
174    let generics = GenericParamSet::new(&input.generics);
175    let mut bounds = Bounds::from_data(hattrs.bound_from_str_resolved());
176    p.build_bounds(&generics, &mut bounds);
177    let wheres = bounds.build_wheres(&trait_path);
178    impl_trait_result(
179        input,
180        &trait_path,
181        &wheres,
182        quote! {
183            type Err = #crate_path::ParseError;
184            fn from_str(s: &str) -> ::core::result::Result<Self, Self::Err> {
185                #body
186            }
187        },
188        hattrs.dump_from_str,
189    )
190}
191fn derive_from_str_for_enum(input: &DeriveInput, data: &DataEnum) -> Result<TokenStream> {
192    let hattrs_enum = HelperAttributes::from(&input.attrs, true)?;
193    if let Some(span) = hattrs_enum.default_self {
194        bail!(span, "`#[from_str(default)]` cannot be specified for enum.");
195    }
196    let crate_path = &hattrs_enum.crate_path;
197    let trait_path = parse_quote!(::core::str::FromStr);
198    let mut bounds = Bounds::from_data(hattrs_enum.bound_from_str_resolved());
199    let generics = GenericParamSet::new(&input.generics);
200    let mut bodys = Vec::new();
201    let mut arms = Vec::new();
202    for variant in &data.variants {
203        let hattrs_variant = HelperAttributes::from(&variant.attrs, true)?;
204        if hattrs_variant.ignore.value() {
205            continue;
206        }
207        let variant_ident = &variant.ident;
208        let constructor = parse_quote!(Self::#variant_ident);
209        let p = ParserBuilder::from_variant(&hattrs_variant, &hattrs_enum, variant)?;
210        let mut bounds = bounds.child(hattrs_variant.bound_from_str_resolved());
211        p.build_bounds(&generics, &mut bounds);
212        match p.build_parse_variant_code(crate_path, constructor)? {
213            ParseVariantCode::MatchArm(arm) => arms.push(arm),
214            ParseVariantCode::Statement(body) => bodys.push(body),
215        }
216    }
217    let match_body = if arms.is_empty() {
218        quote! {}
219    } else {
220        quote! {
221            match s {
222                #(#arms,)*
223                _ => { }
224            }
225        }
226    };
227    let wheres = bounds.build_wheres(&trait_path);
228    impl_trait_result(
229        input,
230        &trait_path,
231        &wheres,
232        quote! {
233            type Err = #crate_path::ParseError;
234            fn from_str(s: &str) -> ::core::result::Result<Self, Self::Err> {
235                #match_body
236                #({ #bodys })*
237                ::core::result::Result::Err(#crate_path::ParseError::new())
238            }
239        },
240        hattrs_enum.dump_from_str,
241    )
242}
243struct With {
244    capture: String,
245    key: FieldKey,
246    expr: Expr,
247    ty: Type,
248}
249impl With {
250    fn new(capture: String, key: &FieldKey, expr: &Expr, ty: &Type) -> Self {
251        Self {
252            capture,
253            key: key.clone(),
254            expr: expr.clone(),
255            ty: ty.clone(),
256        }
257    }
258}
259
260struct ParserBuilder<'a> {
261    capture_next: usize,
262    parse_format: ParseFormat,
263    fields: BTreeMap<FieldKey, FieldEntry<'a>>,
264    with: Vec<With>,
265    source: &'a Fields,
266    use_default: bool,
267    span: Span,
268    new_expr: Option<Expr>,
269}
270struct FieldEntry<'a> {
271    hattrs: HelperAttributes,
272    deep_captures: BTreeMap<Vec<FieldKey>, usize>,
273    source: &'a Field,
274    capture: Option<usize>,
275    use_default: bool,
276    crate_path: &'a Path,
277}
278
279impl<'a> ParserBuilder<'a> {
280    fn new(source: &'a Fields, crate_path: &'a Path) -> Result<Self> {
281        let mut fields = BTreeMap::new();
282        for (key, field) in field_map(source) {
283            fields.insert(key, FieldEntry::new(field, crate_path)?);
284        }
285        Ok(Self {
286            source,
287            capture_next: 1,
288            parse_format: ParseFormat::new(),
289            fields,
290            with: Vec::new(),
291            use_default: false,
292            span: Span::call_site(),
293            new_expr: None,
294        })
295    }
296    fn from_struct(hattrs: &'a HelperAttributes, data: &'a DataStruct) -> Result<Self> {
297        let mut s = Self::new(&data.fields, &hattrs.crate_path)?;
298        let context = DisplayContext::Struct {
299            data,
300            crate_path: &hattrs.crate_path,
301        };
302        s.new_expr.clone_from(&hattrs.new_expr);
303        s.apply_attrs(hattrs)?;
304        s.push_attrs(hattrs, &context)?;
305        Ok(s)
306    }
307    fn from_variant(
308        hattrs_variant: &HelperAttributes,
309        hattrs_enum: &'a HelperAttributes,
310        variant: &'a Variant,
311    ) -> Result<Self> {
312        let mut s = Self::new(&variant.fields, &hattrs_enum.crate_path)?;
313        let context = DisplayContext::Variant {
314            variant,
315            style: DisplayStyle::from_helper_attributes(hattrs_enum, hattrs_variant),
316            crate_path: &hattrs_enum.crate_path,
317        };
318        s.new_expr.clone_from(&hattrs_variant.new_expr);
319        s.apply_attrs(hattrs_enum)?;
320        s.apply_attrs(hattrs_variant)?;
321        if !s.try_push_attrs(hattrs_variant, &context)? {
322            s.push_attrs(hattrs_enum, &context)?;
323        }
324        Ok(s)
325    }
326    fn apply_attrs(&mut self, hattrs: &HelperAttributes) -> Result<()> {
327        if hattrs.default_self.is_some() {
328            self.use_default = true;
329        }
330        for field in &hattrs.default_fields {
331            let key = FieldKey::from_member(&field.0);
332            let span = field.span();
333            self.field(&key, span)?.use_default = true;
334        }
335        if let Some(span) = hattrs.span_of_from_str_format() {
336            self.span = span;
337        }
338        Ok(())
339    }
340    fn field(&mut self, key: &FieldKey, span: Span) -> Result<&mut FieldEntry<'a>> {
341        field_of(&mut self.fields, key, span)
342    }
343    fn set_capture(
344        &mut self,
345        context: &DisplayContext,
346        keys: &[FieldKey],
347        span: Span,
348    ) -> Result<String> {
349        let field_key;
350        let sub_keys;
351        if let DisplayContext::Field { key, .. } = context {
352            field_key = *key;
353            sub_keys = keys;
354        } else {
355            if keys.is_empty() {
356                return Ok(CAPTURE_NAME_EMPTY.into());
357            }
358            field_key = &keys[0];
359            sub_keys = &keys[1..];
360        }
361        let field = field_of(&mut self.fields, field_key, span)?;
362        Ok(field.set_capture(sub_keys, &mut self.capture_next))
363    }
364
365    fn push_regex(
366        &mut self,
367        s: &LitStr,
368        context: &DisplayContext,
369        format: &Option<DisplayFormat>,
370    ) -> Result<()> {
371        const IDX_ESC: usize = 1;
372        const IDX_P: usize = 2;
373        const IDX_KEY: usize = 3;
374        fn is_escaped(s: &str) -> bool {
375            s.len() % 2 == 1
376        }
377
378        let regex_number = regex!("^[0-9]+$");
379        let regex_capture = regex!(r"(?<esc>\\*)\(\?(?<p>P?)<(?<key>[_0-9a-zA-Z.]*)>");
380
381        let text = s.value();
382        let text_debug = regex_capture.replace_all(&text, |c: &Captures| {
383            let esc = &c[IDX_ESC];
384            if is_escaped(esc) {
385                return c[0].to_owned();
386            }
387            let key = &c[IDX_KEY];
388            let key = if key.is_empty() {
389                "self".into()
390            } else {
391                key.replace('.', "_")
392            };
393            let key = regex_number.replace(&key, "_$0");
394            format!("{esc}(?<{key}>")
395        });
396        if let Err(e) = regex_syntax::ast::parse::Parser::new().parse(&text_debug) {
397            bail!(s.span(), "{e}")
398        }
399
400        let mut has_capture = false;
401        let mut has_capture_empty = false;
402        let mut p = "";
403        let mut text = try_replace_all(regex_capture, &text, |c: &Captures| -> Result<String> {
404            let esc = &c[IDX_ESC];
405            if is_escaped(esc) {
406                return Ok(c[0].to_owned());
407            }
408            has_capture = true;
409            let cp = &c[IDX_P];
410            let keys = FieldKey::from_str_deep(&c[IDX_KEY]);
411            let name = self.set_capture(context, &keys, s.span())?;
412            if name == CAPTURE_NAME_EMPTY {
413                if !cp.is_empty() {
414                    p = "P";
415                }
416                has_capture_empty = true;
417            }
418            Ok(format!("{esc}(?<{name}>"))
419        })?;
420
421        if has_capture_empty {
422            if let DisplayContext::Variant { variant, style, .. } = context {
423                let value = style.apply(&variant.ident);
424                self.parse_format
425                    .push_hir(to_hir_with_expand(&text, CAPTURE_NAME_EMPTY, &value));
426                return Ok(());
427            }
428            bail!(
429                s.span(),
430                "`(?{p}<>)` (empty capture name) is not allowed in struct's regex."
431            );
432        }
433        if let DisplayContext::Field { .. } = context {
434            if !has_capture {
435                if let Some(format) = format {
436                    return self.push_format(format, context, None, Some(&text));
437                }
438                let name = self.set_capture(context, &[], s.span())?;
439                text = format!("(?<{name}>{text})");
440            }
441        }
442        self.parse_format.push_hir(to_hir(&text));
443        Ok(())
444    }
445    fn push_format(
446        &mut self,
447        format: &DisplayFormat,
448        context: &DisplayContext,
449        with: Option<&Expr>,
450        regex: Option<&str>,
451    ) -> Result<()> {
452        for p in &format.parts {
453            match p {
454                DisplayFormatPart::Str(s) => self.push_str(s),
455                DisplayFormatPart::EscapedBeginBracket => self.push_str("{"),
456                DisplayFormatPart::EscapedEndBracket => self.push_str("}"),
457                DisplayFormatPart::Var { arg, .. } => {
458                    let keys = FieldKey::from_str_deep(arg);
459                    if let DisplayContext::Variant { variant, style, .. } = context {
460                        if keys.is_empty() {
461                            self.push_str(&style.apply(&variant.ident));
462                            continue;
463                        }
464                    }
465                    if keys.len() == 1 {
466                        self.push_field(context, &keys[0], format.span)?;
467                        continue;
468                    }
469                    let c = self.set_capture(context, &keys, format.span)?;
470                    let mut f = format!("(?<{c}>(?s:.*?))");
471                    if keys.is_empty() {
472                        if let Some(regex) = regex {
473                            f = format!("(?<{c}>(?s:{regex}))");
474                        }
475                        if let DisplayContext::Field { field, key, .. } = context {
476                            if let Some(with_expr) = with {
477                                self.with.push(With::new(c, key, with_expr, &field.ty));
478                            }
479                        }
480                    }
481                    self.parse_format.push_hir(to_hir(&f));
482                }
483            }
484        }
485        Ok(())
486    }
487    fn push_str(&mut self, string: &str) {
488        self.parse_format.push_str(string);
489    }
490    fn push_field(&mut self, context: &DisplayContext, key: &FieldKey, span: Span) -> Result<()> {
491        let e = self.field(key, span)?;
492        let hattrs = e.hattrs.clone();
493        let parent = context;
494        let field = e.source;
495        self.push_attrs(&hattrs, &DisplayContext::Field { parent, key, field })
496    }
497    fn push_attrs(&mut self, hattrs: &HelperAttributes, context: &DisplayContext) -> Result<()> {
498        if !self.try_push_attrs(hattrs, context)? {
499            self.push_format(
500                &context.default_from_str_format()?,
501                context,
502                hattrs.with.as_ref(),
503                None,
504            )?;
505        }
506        Ok(())
507    }
508    fn try_push_attrs(
509        &mut self,
510        hattrs: &HelperAttributes,
511        context: &DisplayContext,
512    ) -> Result<bool> {
513        Ok(if let Some(regex) = &hattrs.regex {
514            self.push_regex(regex, context, &hattrs.format)?;
515            true
516        } else if let Some(format) = &hattrs.format {
517            self.push_format(format, context, hattrs.with.as_ref(), None)?;
518            true
519        } else {
520            false
521        })
522    }
523
524    fn build_from_str_body(&self, crate_path: &Path, constructor: Path) -> Result<TokenStream> {
525        let code = self.build_parse_code(crate_path, constructor)?;
526        Ok(quote! {
527            #code
528            ::core::result::Result::Err(#crate_path::ParseError::new())
529        })
530    }
531    fn build_parse_variant_code(
532        &self,
533        crate_path: &Path,
534        constructor: Path,
535    ) -> Result<ParseVariantCode> {
536        match &self.parse_format {
537            ParseFormat::Hirs(_) => {
538                let fn_ident: Ident = format_ident!("parse_variant");
539                let code = self.build_from_str_body(crate_path, constructor)?;
540                let code = quote! {
541                    let #fn_ident = |s: &str| -> ::core::result::Result<Self, #crate_path::ParseError> {
542                        #code
543                    };
544                    if let ::core::result::Result::Ok(value) = #fn_ident(s) {
545                        return ::core::result::Result::Ok(value);
546                    }
547                };
548                Ok(ParseVariantCode::Statement(code))
549            }
550            ParseFormat::String(s) => {
551                let code = self.build_construct_code(crate_path, constructor)?;
552                let code = quote! { #s  => { #code }};
553                Ok(ParseVariantCode::MatchArm(code))
554            }
555        }
556    }
557
558    fn build_construct_code(&self, crate_path: &Path, constructor: Path) -> Result<TokenStream> {
559        let mut names = HashMap::new();
560        let re;
561        match &self.parse_format {
562            ParseFormat::Hirs(hirs) => {
563                re = Regex::new(&to_regex_string(hirs)).unwrap();
564                for (index, name) in re.capture_names().enumerate() {
565                    if let Some(name) = name {
566                        names.insert(name, index);
567                    }
568                }
569            }
570            ParseFormat::String(_) => {}
571        }
572
573        let code = if let Some(new_expr) = &self.new_expr {
574            let mut code = TokenStream::new();
575            for (key, field) in &self.fields {
576                let expr = field.build_field_init_expr(&names, key, self.span)?;
577                let var = key.new_arg_var();
578                code.extend(quote! { let #var = #expr; });
579            }
580            code.extend(quote! {
581                if let ::core::result::Result::Ok(value) = #crate_path::IntoResult::into_result(#new_expr) {
582                    return ::core::result::Result::Ok(value);
583                }
584            });
585            code
586        } else if self.use_default {
587            let mut setters = Vec::new();
588            for (key, field) in &self.fields {
589                let left_expr = quote! { value . #key };
590                setters.push(field.build_setters(&names, key, left_expr, true));
591            }
592            quote! {
593                let mut value = <Self as ::core::default::Default>::default();
594                #(#setters)*
595                return ::core::result::Result::Ok(value);
596            }
597        } else {
598            let ps = match &self.source {
599                Fields::Named(..) => {
600                    let mut fields_code = Vec::new();
601                    for (key, field) in &self.fields {
602                        let expr = field.build_field_init_expr(&names, key, self.span)?;
603                        fields_code.push(quote! { #key : #expr });
604                    }
605                    quote! { { #(#fields_code,)* } }
606                }
607                Fields::Unnamed(..) => {
608                    let mut fields_code = Vec::new();
609                    for (key, field) in &self.fields {
610                        fields_code.push(field.build_field_init_expr(&names, key, self.span)?);
611                    }
612                    quote! { ( #(#fields_code,)* ) }
613                }
614                Fields::Unit => quote! {},
615            };
616            quote! { return ::core::result::Result::Ok(#constructor #ps); }
617        };
618        Ok(code)
619    }
620    fn build_parse_code(&self, crate_path: &Path, constructor: Path) -> Result<TokenStream> {
621        let code = self.build_construct_code(crate_path, constructor)?;
622        let code = match &self.parse_format {
623            ParseFormat::Hirs(hirs) => {
624                let regex = to_regex_string(hirs);
625                let mut with = Vec::new();
626                let helpers = quote!( #crate_path::helpers );
627                let mut debug_asserts = Vec::new();
628                for (
629                    index,
630                    With {
631                        capture,
632                        key,
633                        ty,
634                        expr,
635                    },
636                ) in self.with.iter().enumerate()
637                {
638                    with.push(quote_spanned! {expr.span()=>
639                        (#capture, #helpers::to_ast::<#ty, _>(&#expr))
640                    });
641                    let msg = format!(
642                        "The regex for the field `{key}` varies depending on the type parameter."
643                    );
644                    debug_asserts.push(quote_spanned! {expr.span()=>
645                        ::core::debug_assert_eq!(&p.ss[#index], &#helpers::to_regex::<#ty, _>(&#expr), #msg);
646                    });
647                }
648                quote! {
649                    static PARSER: ::std::sync::OnceLock<#helpers::Parser> = ::std::sync::OnceLock::new();
650                    #[allow(clippy::trivial_regex)]
651                    let p = PARSER.get_or_init(|| #helpers::Parser::new(#regex, &mut [#(#with,)*]));
652                    #(#debug_asserts)*
653                    if let ::core::option::Option::Some(c) = p.re.captures(&s) {
654                         #code
655                    }
656                }
657            }
658            ParseFormat::String(s) => {
659                quote! {
660                    if s == #s {
661                        #code
662                    }
663                }
664            }
665        };
666        Ok(code)
667    }
668
669    fn build_bounds(&self, generics: &GenericParamSet, bounds: &mut Bounds) {
670        if !bounds.can_extend {
671            return;
672        }
673        for field in self.fields.values() {
674            let mut bounds = bounds.child(field.hattrs.bound_from_str_resolved());
675            if bounds.can_extend && field.capture.is_some() && field.hattrs.with.is_none() {
676                let ty = &field.source.ty;
677                if generics.contains_in_type(ty) {
678                    bounds.ty.push(ty.clone());
679                }
680            }
681        }
682    }
683}
684impl<'a> FieldEntry<'a> {
685    fn new(source: &'a Field, crate_path: &'a Path) -> Result<Self> {
686        let hattrs = HelperAttributes::from(&source.attrs, true)?;
687        let use_default = hattrs.default_self.is_some();
688        Ok(Self {
689            hattrs,
690            deep_captures: BTreeMap::new(),
691            capture: None,
692            use_default,
693            source,
694            crate_path,
695        })
696    }
697    #[allow(clippy::collapsible_else_if)]
698    fn set_capture(&mut self, keys: &[FieldKey], capture_next: &mut usize) -> String {
699        let idx = if keys.is_empty() {
700            if let Some(idx) = self.capture {
701                idx
702            } else {
703                let idx = *capture_next;
704                self.capture = Some(idx);
705                *capture_next += 1;
706                idx
707            }
708        } else {
709            if let Some(&idx) = self.deep_captures.get(keys) {
710                idx
711            } else {
712                let idx = *capture_next;
713                self.deep_captures.insert(keys.to_vec(), idx);
714                *capture_next += 1;
715                idx
716            }
717        };
718        capture_name(idx)
719    }
720    fn capture_index(&self, names: &HashMap<&str, usize>) -> Option<usize> {
721        Some(capture_index(self.capture?, names))
722    }
723    fn build_expr(&self, names: &HashMap<&str, usize>, key: &FieldKey) -> Option<TokenStream> {
724        if let Some(capture_index) = self.capture_index(names) {
725            Some(build_parse_capture_expr(
726                &key.to_string(),
727                capture_index,
728                Some(self),
729                self.crate_path,
730            ))
731        } else if self.use_default {
732            Some(quote! { ::core::default::Default::default() })
733        } else {
734            None
735        }
736    }
737    fn build_setters(
738        &self,
739        names: &HashMap<&str, usize>,
740        key: &FieldKey,
741        left_expr: TokenStream,
742        include_self: bool,
743    ) -> TokenStream {
744        let mut setters = Vec::new();
745        if include_self {
746            if let Some(expr) = self.build_expr(names, key) {
747                setters.push(quote! { #left_expr = #expr; });
748            }
749        }
750        for (keys, idx) in &self.deep_captures {
751            let field_name = key.to_string() + &join(keys, ".");
752            let expr = build_parse_capture_expr(
753                &field_name,
754                capture_index(*idx, names),
755                None,
756                self.crate_path,
757            );
758            setters.push(quote! { #left_expr #(.#keys)* = #expr; });
759        }
760        quote! { #(#setters)* }
761    }
762
763    fn build_field_init_expr(
764        &self,
765        names: &HashMap<&str, usize>,
766        key: &FieldKey,
767        span: Span,
768    ) -> Result<TokenStream> {
769        if let Some(mut expr) = self.build_expr(names, key) {
770            if !self.deep_captures.is_empty() {
771                let setters = self.build_setters(names, key, quote!(field_value), false);
772                let ty = &self.source.ty;
773                expr = quote! {
774                    {
775                        let mut field_value : #ty = #expr;
776                        #setters
777                        field_value
778                    }
779                };
780            }
781            return Ok(expr);
782        }
783        bail!(span, "field `{key}` is not appear in format.");
784    }
785}
786
787fn get_newtype_field(data: &DataStruct) -> Option<String> {
788    let fields: Vec<_> = data.fields.iter().collect();
789    if fields.len() == 1 {
790        if let Some(ident) = &fields[0].ident {
791            Some(ident.to_string())
792        } else {
793            Some("0".into())
794        }
795    } else {
796        None
797    }
798}
799
800#[derive(StructMeta)]
801struct DisplayArgs {
802    #[struct_meta(unnamed)]
803    format: Option<LitStr>,
804    with: Option<Expr>,
805    style: Option<LitStr>,
806    bound: Option<Vec<Quotable<Bound>>>,
807    #[struct_meta(name = "crate")]
808    crate_path: Option<Path>,
809    dump: bool,
810}
811
812#[derive(Clone, ToTokens)]
813struct DefaultField(Member);
814
815impl Parse for DefaultField {
816    fn parse(input: ParseStream) -> Result<Self> {
817        if input.peek(Ident::peek_any) {
818            Ok(Self(Member::Named(Ident::parse_any(input)?)))
819        } else {
820            Ok(Self(input.parse()?))
821        }
822    }
823}
824
825#[derive(StructMeta)]
826struct FromStrArgs {
827    regex: Option<LitStr>,
828    with: Option<Expr>,
829    new: Option<Expr>,
830    bound: Option<Vec<Quotable<Bound>>>,
831    default: Flag,
832    default_fields: Option<Vec<Quotable<DefaultField>>>,
833    ignore: Flag,
834    dump: bool,
835}
836
837#[derive(Clone)]
838struct HelperAttributes {
839    format: Option<DisplayFormat>,
840    with: Option<Expr>,
841    style: Option<DisplayStyle>,
842    bound_display: Option<Vec<Bound>>,
843    bound_from_str: Option<Vec<Bound>>,
844    regex: Option<LitStr>,
845    default_self: Option<Span>,
846    default_fields: Vec<DefaultField>,
847    new_expr: Option<Expr>,
848    ignore: Flag,
849    dump_display: bool,
850    dump_from_str: bool,
851    crate_path: Path,
852}
853impl HelperAttributes {
854    fn from(attrs: &[Attribute], use_from_str: bool) -> Result<Self> {
855        let mut hattrs = Self {
856            format: None,
857            with: None,
858            style: None,
859            bound_display: None,
860            bound_from_str: None,
861            regex: None,
862            new_expr: None,
863            default_self: None,
864            default_fields: Vec::new(),
865            ignore: Flag::NONE,
866            dump_display: false,
867            dump_from_str: false,
868            crate_path: parse_quote!(::parse_display),
869        };
870        for a in attrs {
871            if a.path().is_ident("display") {
872                hattrs.set_display_args(a.parse_args()?)?;
873            }
874            if use_from_str && a.path().is_ident("from_str") {
875                hattrs.set_from_str_args(a.parse_args()?);
876            }
877        }
878        Ok(hattrs)
879    }
880    fn set_display_args(&mut self, args: DisplayArgs) -> Result<()> {
881        if let Some(format) = &args.format {
882            self.format = Some(DisplayFormat::parse_lit_str(format)?);
883        }
884        if let Some(with) = args.with {
885            self.with = Some(with);
886        }
887        if let Some(style) = &args.style {
888            self.style = Some(DisplayStyle::parse_lit_str(style)?);
889        }
890        if let Some(bounds) = args.bound {
891            let list = self.bound_display.get_or_insert(Vec::new());
892            for bound in bounds {
893                for bound in bound.into_iter() {
894                    list.push(bound);
895                }
896            }
897        }
898        if let Some(crate_path) = &args.crate_path {
899            self.crate_path = crate_path.clone();
900        }
901        self.dump_from_str |= args.dump;
902        self.dump_display |= args.dump;
903        Ok(())
904    }
905    fn set_from_str_args(&mut self, args: FromStrArgs) {
906        if let Some(regex) = args.regex {
907            self.regex = Some(regex);
908        }
909        if let Some(with) = args.with {
910            self.with = Some(with);
911        }
912        if let Some(new) = args.new {
913            self.new_expr = Some(new);
914        }
915        if let Some(bound) = args.bound {
916            let list = self.bound_from_str.get_or_insert(Vec::new());
917            for bound in bound {
918                for bound in bound.into_iter() {
919                    list.push(bound);
920                }
921            }
922        }
923        if let Some(span) = args.default.span {
924            self.default_self = Some(span);
925        }
926        if let Some(fields) = args.default_fields {
927            for field in fields {
928                for field in field.into_iter() {
929                    self.default_fields.push(field);
930                }
931            }
932        }
933        if args.ignore.value() {
934            self.ignore = args.ignore;
935        }
936        self.dump_from_str |= args.dump;
937    }
938    fn span_of_from_str_format(&self) -> Option<Span> {
939        if let Some(lit) = &self.regex {
940            return Some(lit.span());
941        }
942        if let Some(format) = &self.format {
943            return Some(format.span);
944        }
945        None
946    }
947    fn bound_from_str_resolved(&self) -> Option<Vec<Bound>> {
948        self.bound_from_str
949            .clone()
950            .or_else(|| self.bound_display.clone())
951    }
952}
953
954#[derive(Copy, Clone)]
955enum DisplayStyle {
956    None,
957    LowerCase,
958    UpperCase,
959    LowerSnakeCase,
960    UpperSnakeCase,
961    LowerCamelCase,
962    UpperCamelCase,
963    LowerKebabCase,
964    UpperKebabCase,
965    TitleCase,
966    TitleCaseHead,
967    TitleCaseLower,
968    TitleCaseUpper,
969}
970
971impl DisplayStyle {
972    fn parse_lit_str(s: &LitStr) -> Result<Self> {
973        const ERROR_MESSAGE: &str = "Invalid display style. \
974        The following values are available: \
975        \"none\", \
976        \"lowercase\", \
977        \"UPPERCASE\", \
978        \"snake_case\", \
979        \"SNAKE_CASE\", \
980        \"camelCase\", \
981        \"CamelCase\", \
982        \"kebab-case\", \
983        \"KEBAB-CASE\", \
984        \"Title Case\", \
985        \"Title case\", \
986        \"title case\", \
987        \"TITLE CASE\"";
988        match Self::parse(&s.value()) {
989            Err(_) => bail!(s.span(), "{ERROR_MESSAGE}"),
990            Ok(value) => Ok(value),
991        }
992    }
993    fn parse(s: &str) -> std::result::Result<Self, ParseDisplayStyleError> {
994        use DisplayStyle::*;
995        Ok(match s {
996            "none" => None,
997            "lowercase" => LowerCase,
998            "UPPERCASE" => UpperCase,
999            "snake_case" => LowerSnakeCase,
1000            "SNAKE_CASE" => UpperSnakeCase,
1001            "camelCase" => LowerCamelCase,
1002            "CamelCase" => UpperCamelCase,
1003            "kebab-case" => LowerKebabCase,
1004            "KEBAB-CASE" => UpperKebabCase,
1005            "Title Case" => TitleCase,
1006            "Title case" => TitleCaseHead,
1007            "title case" => TitleCaseLower,
1008            "TITLE CASE" => TitleCaseUpper,
1009            _ => return Err(ParseDisplayStyleError),
1010        })
1011    }
1012    fn from_helper_attributes(
1013        hattrs_enum: &HelperAttributes,
1014        hattrs_variant: &HelperAttributes,
1015    ) -> Self {
1016        hattrs_variant
1017            .style
1018            .or(hattrs_enum.style)
1019            .unwrap_or(DisplayStyle::None)
1020    }
1021    fn apply(self, ident: &Ident) -> String {
1022        fn convert_case(c: char, to_upper: bool) -> char {
1023            if to_upper {
1024                c.to_ascii_uppercase()
1025            } else {
1026                c.to_ascii_lowercase()
1027            }
1028        }
1029
1030        let s = ident.to_string();
1031        let (line_head, word_head, normal, sep) = match self {
1032            DisplayStyle::None => {
1033                return s;
1034            }
1035            DisplayStyle::LowerCase => (false, false, false, ""),
1036            DisplayStyle::UpperCase => (true, true, true, ""),
1037            DisplayStyle::LowerSnakeCase => (false, false, false, "_"),
1038            DisplayStyle::UpperSnakeCase => (true, true, true, "_"),
1039            DisplayStyle::LowerCamelCase => (false, true, false, ""),
1040            DisplayStyle::UpperCamelCase => (true, true, false, ""),
1041            DisplayStyle::LowerKebabCase => (false, false, false, "-"),
1042            DisplayStyle::UpperKebabCase => (true, true, true, "-"),
1043            DisplayStyle::TitleCase => (true, true, false, " "),
1044            DisplayStyle::TitleCaseUpper => (true, true, true, " "),
1045            DisplayStyle::TitleCaseLower => (false, false, false, " "),
1046            DisplayStyle::TitleCaseHead => (true, false, false, " "),
1047        };
1048        let mut is_line_head = true;
1049        let mut is_word_head = true;
1050        let mut last = '\0';
1051
1052        let mut r = String::new();
1053        for c in s.chars() {
1054            if !c.is_alphanumeric() && !c.is_ascii_digit() {
1055                is_word_head = true;
1056                continue;
1057            }
1058            is_word_head = is_word_head || (!last.is_ascii_uppercase() && c.is_ascii_uppercase());
1059            last = c;
1060            let (to_upper, sep) = match (is_line_head, is_word_head) {
1061                (true, _) => (line_head, ""),
1062                (false, true) => (word_head, sep),
1063                (false, false) => (normal, ""),
1064            };
1065            r.push_str(sep);
1066            r.push(convert_case(c, to_upper));
1067            is_word_head = false;
1068            is_line_head = false;
1069        }
1070        r
1071    }
1072}
1073
1074#[derive(Clone)]
1075struct DisplayFormat {
1076    parts: Vec<DisplayFormatPart>,
1077    span: Span,
1078}
1079impl DisplayFormat {
1080    fn parse_lit_str(s: &LitStr) -> Result<DisplayFormat> {
1081        Self::parse(&s.value(), s.span())
1082    }
1083    fn parse(mut s: &str, span: Span) -> Result<DisplayFormat> {
1084        let regex_str = regex!(r"^[^{}]+");
1085        let regex_var = regex!(r"^\{([^:{}]*)(?::([^}]*))?\}");
1086        let mut parts = Vec::new();
1087        while !s.is_empty() {
1088            if s.starts_with("{{") {
1089                parts.push(DisplayFormatPart::EscapedBeginBracket);
1090                s = &s[2..];
1091                continue;
1092            }
1093            if s.starts_with("}}") {
1094                parts.push(DisplayFormatPart::EscapedEndBracket);
1095                s = &s[2..];
1096                continue;
1097            }
1098            if let Some(m) = regex_str.find(s) {
1099                parts.push(DisplayFormatPart::Str(m.as_str().into()));
1100                s = &s[m.end()..];
1101                continue;
1102            }
1103            if let Some(c) = regex_var.captures(s) {
1104                let arg = c.get(1).unwrap().as_str().into();
1105                let format_spec = c.get(2).map_or("", |x| x.as_str()).into();
1106                parts.push(DisplayFormatPart::Var { arg, format_spec });
1107                s = &s[c.get(0).unwrap().end()..];
1108                continue;
1109            }
1110            bail!(span, "invalid display format.");
1111        }
1112        Ok(Self { parts, span })
1113    }
1114    fn from_newtype_struct(data: &DataStruct) -> Option<Self> {
1115        let p = DisplayFormatPart::Var {
1116            arg: get_newtype_field(data)?,
1117            format_spec: String::new(),
1118        };
1119        Some(Self {
1120            parts: vec![p],
1121            span: data.fields.span(),
1122        })
1123    }
1124    fn from_unit_variant(variant: &Variant) -> Result<Option<Self>> {
1125        Ok(if let Fields::Unit = &variant.fields {
1126            Some(Self::parse("{}", variant.span())?)
1127        } else {
1128            None
1129        })
1130    }
1131
1132    fn format_args(
1133        &self,
1134        context: DisplayContext,
1135        with: &Option<Expr>,
1136        bounds: &mut Bounds,
1137        generics: &GenericParamSet,
1138    ) -> Result<FormatArgs> {
1139        let mut format_str = String::new();
1140        let mut format_args = Vec::new();
1141        for p in &self.parts {
1142            use DisplayFormatPart::*;
1143            match p {
1144                Str(s) => format_str.push_str(s.as_str()),
1145                EscapedBeginBracket => format_str.push_str("{{"),
1146                EscapedEndBracket => format_str.push_str("}}"),
1147                Var { arg, format_spec } => {
1148                    format_str.push('{');
1149                    if !format_spec.is_empty() {
1150                        format_str.push(':');
1151                        format_str.push_str(format_spec);
1152                    }
1153                    format_str.push('}');
1154                    let format_spec = FormatSpec::parse_with_span(format_spec, self.span)?;
1155                    let format_arg =
1156                        context.format_arg(arg, &format_spec, self.span, with, bounds, generics)?;
1157                    let mut expr = quote!(&#format_arg);
1158                    if format_spec.format_type == FormatType::Pointer {
1159                        let crate_path = context.crate_path();
1160                        expr = quote!(#crate_path::helpers::FmtPointer(#expr));
1161                    }
1162                    format_args.push(expr);
1163                }
1164            }
1165        }
1166        Ok(FormatArgs {
1167            format_str,
1168            format_args,
1169            span: self.span,
1170        })
1171    }
1172
1173    fn try_unescape(&self) -> Option<String> {
1174        let mut s = String::new();
1175        for p in &self.parts {
1176            s.push_str(p.try_unescape()?);
1177        }
1178        Some(s)
1179    }
1180}
1181
1182struct FormatArgs {
1183    format_str: String,
1184    format_args: Vec<TokenStream>,
1185    span: Span,
1186}
1187impl FormatArgs {
1188    fn build_write(&self, f: TokenStream) -> Result<TokenStream> {
1189        if self.format_args.is_empty() {
1190            if let Some(s) = DisplayFormat::parse(&self.format_str, self.span)?.try_unescape() {
1191                return Ok(quote! { #f.write_str(#s) });
1192            }
1193        }
1194        Ok(quote! { ::core::write!(#f, #self) })
1195    }
1196}
1197impl ToTokens for FormatArgs {
1198    fn to_tokens(&self, tokens: &mut TokenStream) {
1199        let format_str = LitStr::new(&self.format_str, self.span);
1200        let format_args = &self.format_args;
1201        tokens.extend(quote!(#format_str #(,#format_args)*));
1202    }
1203}
1204
1205#[derive(Clone)]
1206enum DisplayFormatPart {
1207    Str(String),
1208    EscapedBeginBracket,
1209    EscapedEndBracket,
1210    Var { arg: String, format_spec: String },
1211}
1212impl DisplayFormatPart {
1213    fn try_unescape(&self) -> Option<&str> {
1214        match self {
1215            Self::Str(value) => Some(value),
1216            Self::EscapedBeginBracket => Some("{"),
1217            Self::EscapedEndBracket => Some("}"),
1218            Self::Var { .. } => None,
1219        }
1220    }
1221}
1222
1223enum DisplayContext<'a> {
1224    Struct {
1225        data: &'a DataStruct,
1226        crate_path: &'a Path,
1227    },
1228    Variant {
1229        variant: &'a Variant,
1230        style: DisplayStyle,
1231        crate_path: &'a Path,
1232    },
1233    Field {
1234        parent: &'a DisplayContext<'a>,
1235        field: &'a Field,
1236        key: &'a FieldKey,
1237    },
1238}
1239
1240impl<'a> DisplayContext<'a> {
1241    fn format_arg(
1242        &self,
1243        arg: &str,
1244        format_spec: &FormatSpec,
1245        span: Span,
1246        with: &Option<Expr>,
1247        bounds: &mut Bounds,
1248        generics: &GenericParamSet,
1249    ) -> Result<TokenStream> {
1250        let keys = FieldKey::from_str_deep(arg);
1251        if keys.is_empty() {
1252            if matches!(
1253                self,
1254                DisplayContext::Struct { .. } | DisplayContext::Variant { .. }
1255            ) && format_spec.format_type != FormatType::Display
1256            {
1257                return Ok(quote!(self));
1258            }
1259            return Ok(match self {
1260                DisplayContext::Struct { .. } => {
1261                    bail!(span, "{{}} is not allowed in struct format.")
1262                }
1263                DisplayContext::Field { parent, field, key } => parent.format_arg_by_field_expr(
1264                    key,
1265                    field,
1266                    format_spec,
1267                    span,
1268                    with,
1269                    bounds,
1270                    generics,
1271                )?,
1272                DisplayContext::Variant { variant, style, .. } => {
1273                    let s = style.apply(&variant.ident);
1274                    quote! { #s }
1275                }
1276            });
1277        }
1278
1279        if keys.len() == 1 {
1280            if let Some(fields) = self.fields() {
1281                let key = &keys[0];
1282                let m = field_map(fields);
1283                let Some(field) = m.get(key) else {
1284                    bail!(span, "unknown field '{key}'.");
1285                };
1286                return self.format_arg_of_field(key, field, format_spec, span, bounds, generics);
1287            }
1288        }
1289        let mut expr = self.field_expr(&keys[0]);
1290        for key in &keys[1..] {
1291            expr.extend(quote! { .#key });
1292        }
1293        Ok(expr)
1294    }
1295    fn format_arg_of_field(
1296        &self,
1297        key: &FieldKey,
1298        field: &Field,
1299        format_spec: &FormatSpec,
1300        span: Span,
1301        bounds: &mut Bounds,
1302        generics: &GenericParamSet,
1303    ) -> Result<TokenStream> {
1304        let hattrs = HelperAttributes::from(&field.attrs, false)?;
1305        let mut bounds = bounds.child(hattrs.bound_display);
1306        Ok(if let Some(format) = hattrs.format {
1307            let args = format.format_args(
1308                DisplayContext::Field {
1309                    parent: self,
1310                    field,
1311                    key,
1312                },
1313                &hattrs.with,
1314                &mut bounds,
1315                generics,
1316            )?;
1317            quote! { format_args!(#args) }
1318        } else {
1319            self.format_arg_by_field_expr(
1320                key,
1321                field,
1322                format_spec,
1323                span,
1324                &hattrs.with,
1325                &mut bounds,
1326                generics,
1327            )?
1328        })
1329    }
1330    #[allow(clippy::too_many_arguments)]
1331    fn format_arg_by_field_expr(
1332        &self,
1333        key: &FieldKey,
1334        field: &Field,
1335        format_spec: &FormatSpec,
1336        span: Span,
1337        with: &Option<Expr>,
1338        bounds: &mut Bounds,
1339        generics: &GenericParamSet,
1340    ) -> Result<TokenStream> {
1341        let ty = &field.ty;
1342        if with.is_none() && generics.contains_in_type(ty) {
1343            let tr = format_spec.format_type.trait_name();
1344            let tr: Ident = parse_str(tr).unwrap();
1345            if bounds.can_extend {
1346                bounds.pred.push(parse_quote!(#ty : ::core::fmt::#tr));
1347            }
1348        }
1349        let mut expr = self.field_expr(key);
1350        if let Some(with) = with {
1351            if format_spec.format_type != FormatType::Display {
1352                bail!(
1353                    span,
1354                    "Since `with = ...` is specified, the `{}` format cannot be used.",
1355                    format_spec.format_type
1356                );
1357            }
1358            let crate_path = self.crate_path();
1359            let unref_ty = unref_ty(ty);
1360            expr = quote! {
1361                #crate_path::helpers::Formatted::<'_, #unref_ty, _> {
1362                    value : &#expr,
1363                    format : #with,
1364                }
1365            };
1366        }
1367        Ok(expr)
1368    }
1369
1370    fn field_expr(&self, key: &FieldKey) -> TokenStream {
1371        match self {
1372            DisplayContext::Struct { .. } => quote! { self.#key },
1373            DisplayContext::Variant { .. } => {
1374                let var = key.binding_var();
1375                quote! { (*#var) }
1376            }
1377            DisplayContext::Field {
1378                parent,
1379                key: parent_key,
1380                ..
1381            } => {
1382                let expr = parent.field_expr(parent_key);
1383                quote! { #expr.#key }
1384            }
1385        }
1386    }
1387
1388    fn default_from_str_format(&self) -> Result<DisplayFormat> {
1389        const ERROR_MESSAGE_FOR_STRUCT:&str="`#[display(\"format\")]` or `#[from_str(regex = \"regex\")]` is required except newtype pattern.";
1390        const ERROR_MESSAGE_FOR_VARIANT:&str="`#[display(\"format\")]` or `#[from_str(regex = \"regex\")]` is required except unit variant.";
1391        Ok(match self {
1392            DisplayContext::Struct { data, .. } => {
1393                DisplayFormat::from_newtype_struct(data).expect(ERROR_MESSAGE_FOR_STRUCT)
1394            }
1395            DisplayContext::Variant { variant, .. } => {
1396                DisplayFormat::from_unit_variant(variant)?.expect(ERROR_MESSAGE_FOR_VARIANT)
1397            }
1398            DisplayContext::Field { field, .. } => DisplayFormat::parse("{}", field.span())?,
1399        })
1400    }
1401    fn fields(&self) -> Option<&Fields> {
1402        match self {
1403            DisplayContext::Struct { data, .. } => Some(&data.fields),
1404            DisplayContext::Variant { variant, .. } => Some(&variant.fields),
1405            DisplayContext::Field { .. } => None,
1406        }
1407    }
1408    fn crate_path(&self) -> &Path {
1409        match self {
1410            DisplayContext::Struct { crate_path, .. } => crate_path,
1411            DisplayContext::Variant { crate_path, .. } => crate_path,
1412            DisplayContext::Field { parent, .. } => parent.crate_path(),
1413        }
1414    }
1415}
1416
1417#[derive(Debug)]
1418struct ParseDisplayStyleError;
1419impl std::error::Error for ParseDisplayStyleError {}
1420
1421impl Display for ParseDisplayStyleError {
1422    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1423        write!(f, "invalid display style")
1424    }
1425}
1426
1427enum ParseFormat {
1428    Hirs(Vec<Hir>),
1429    String(String),
1430}
1431impl ParseFormat {
1432    fn new() -> Self {
1433        Self::String(String::new())
1434    }
1435    fn as_hirs(&mut self) -> &mut Vec<Hir> {
1436        match self {
1437            Self::Hirs(_) => {}
1438            Self::String(s) => {
1439                let mut hirs = vec![Hir::look(regex_syntax::hir::Look::Start)];
1440                push_str(&mut hirs, s);
1441                std::mem::swap(self, &mut Self::Hirs(hirs));
1442            }
1443        }
1444        if let Self::Hirs(hirs) = self {
1445            hirs
1446        } else {
1447            unreachable!()
1448        }
1449    }
1450    fn push_str(&mut self, string: &str) {
1451        match self {
1452            Self::Hirs(hirs) => push_str(hirs, string),
1453            Self::String(s) => s.push_str(string),
1454        }
1455    }
1456    fn push_hir(&mut self, hir: Hir) {
1457        self.as_hirs().push(hir);
1458    }
1459}
1460
1461enum ParseVariantCode {
1462    MatchArm(TokenStream),
1463    Statement(TokenStream),
1464}
1465
1466#[derive(Clone, ToTokens)]
1467enum Bound {
1468    Type(Type),
1469    Pred(WherePredicate),
1470    Default(Token![..]),
1471}
1472
1473impl Parse for Bound {
1474    fn parse(input: ParseStream) -> Result<Self> {
1475        if input.peek(Token![..]) {
1476            return Ok(Self::Default(input.parse()?));
1477        }
1478        let fork = input.fork();
1479        match fork.parse() {
1480            Ok(p) => {
1481                input.advance_to(&fork);
1482                Ok(Self::Pred(p))
1483            }
1484            Err(e) => {
1485                if let Ok(ty) = input.parse() {
1486                    Ok(Self::Type(ty))
1487                } else {
1488                    Err(e)
1489                }
1490            }
1491        }
1492    }
1493}
1494
1495struct Bounds {
1496    ty: Vec<Type>,
1497    pred: Vec<WherePredicate>,
1498    can_extend: bool,
1499}
1500impl Bounds {
1501    fn new(can_extend: bool) -> Self {
1502        Bounds {
1503            ty: Vec::new(),
1504            pred: Vec::new(),
1505            can_extend,
1506        }
1507    }
1508    fn from_data(bound: Option<Vec<Bound>>) -> Self {
1509        if let Some(bound) = bound {
1510            let mut bs = Self::new(false);
1511            for b in bound {
1512                bs.push(b);
1513            }
1514            bs
1515        } else {
1516            Self::new(true)
1517        }
1518    }
1519    fn push(&mut self, bound: Bound) {
1520        match bound {
1521            Bound::Type(ty) => self.ty.push(ty),
1522            Bound::Pred(pred) => self.pred.push(pred),
1523            Bound::Default(_) => self.can_extend = true,
1524        }
1525    }
1526    fn child(&mut self, bounds: Option<Vec<Bound>>) -> BoundsChild {
1527        let bounds = if self.can_extend {
1528            Self::from_data(bounds)
1529        } else {
1530            Self::new(false)
1531        };
1532        BoundsChild {
1533            owner: self,
1534            bounds,
1535        }
1536    }
1537    fn build_wheres(self, trait_path: &Path) -> Vec<WherePredicate> {
1538        let mut pred = self.pred;
1539        for ty in self.ty {
1540            pred.push(parse_quote!(#ty : #trait_path));
1541        }
1542        pred
1543    }
1544}
1545struct BoundsChild<'a> {
1546    owner: &'a mut Bounds,
1547    bounds: Bounds,
1548}
1549impl<'a> Deref for BoundsChild<'a> {
1550    type Target = Bounds;
1551
1552    fn deref(&self) -> &Self::Target {
1553        &self.bounds
1554    }
1555}
1556impl<'a> DerefMut for BoundsChild<'a> {
1557    fn deref_mut(&mut self) -> &mut Self::Target {
1558        &mut self.bounds
1559    }
1560}
1561impl<'a> Drop for BoundsChild<'a> {
1562    fn drop(&mut self) {
1563        if self.owner.can_extend {
1564            self.owner.ty.append(&mut self.bounds.ty);
1565            self.owner.pred.append(&mut self.bounds.pred);
1566        }
1567    }
1568}
1569
1570#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
1571enum FieldKey {
1572    Named(String),
1573    Unnamed(usize),
1574}
1575
1576impl FieldKey {
1577    fn from_str(s: &str) -> FieldKey {
1578        if let Ok(idx) = s.parse() {
1579            FieldKey::Unnamed(idx)
1580        } else {
1581            FieldKey::Named(trim_raw(s).to_string())
1582        }
1583    }
1584    fn from_string(mut s: String) -> FieldKey {
1585        if let Ok(idx) = s.parse() {
1586            FieldKey::Unnamed(idx)
1587        } else {
1588            if s.starts_with("r#") {
1589                s.drain(0..2);
1590            }
1591            FieldKey::Named(s)
1592        }
1593    }
1594    fn from_ident(ident: &Ident) -> FieldKey {
1595        Self::from_string(ident.to_string())
1596    }
1597    fn from_str_deep(s: &str) -> Vec<FieldKey> {
1598        if s.is_empty() {
1599            Vec::new()
1600        } else {
1601            s.split('.').map(Self::from_str).collect()
1602        }
1603    }
1604    fn from_fields_named(fields: &FieldsNamed) -> impl Iterator<Item = (FieldKey, &Field)> {
1605        fields
1606            .named
1607            .iter()
1608            .map(|field| (Self::from_ident(field.ident.as_ref().unwrap()), field))
1609    }
1610    fn from_fields_unnamed(fields: &FieldsUnnamed) -> impl Iterator<Item = (FieldKey, &Field)> {
1611        fields
1612            .unnamed
1613            .iter()
1614            .enumerate()
1615            .map(|(idx, field)| (FieldKey::Unnamed(idx), field))
1616    }
1617    fn from_member(member: &Member) -> Self {
1618        match member {
1619            Member::Named(ident) => Self::from_ident(ident),
1620            Member::Unnamed(index) => Self::Unnamed(index.index as usize),
1621        }
1622    }
1623
1624    fn to_member(&self) -> Member {
1625        match self {
1626            FieldKey::Named(s) => Member::Named(format_ident!("r#{s}")),
1627            FieldKey::Unnamed(idx) => Member::Unnamed(parse_str(&format!("{idx}")).unwrap()),
1628        }
1629    }
1630    fn binding_var(&self) -> Ident {
1631        parse_str(&format!("_value_{self}")).unwrap()
1632    }
1633    fn new_arg_var(&self) -> Ident {
1634        match self {
1635            Self::Named(s) => parse_str(s),
1636            Self::Unnamed(idx) => parse_str(&format!("_{idx}")),
1637        }
1638        .unwrap()
1639    }
1640}
1641impl std::fmt::Display for FieldKey {
1642    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1643        match self {
1644            FieldKey::Named(s) => write!(f, "{s}"),
1645            FieldKey::Unnamed(idx) => write!(f, "{idx}"),
1646        }
1647    }
1648}
1649impl ToTokens for FieldKey {
1650    fn to_tokens(&self, tokens: &mut TokenStream) {
1651        self.to_member().to_tokens(tokens);
1652    }
1653}
1654
1655fn field_map(fields: &Fields) -> BTreeMap<FieldKey, &Field> {
1656    let mut m = BTreeMap::new();
1657    for (idx, field) in fields.iter().enumerate() {
1658        let key = if let Some(ident) = &field.ident {
1659            FieldKey::from_ident(ident)
1660        } else {
1661            FieldKey::Unnamed(idx)
1662        };
1663        m.insert(key, field);
1664    }
1665    m
1666}
1667
1668fn join<T: std::fmt::Display>(s: impl IntoIterator<Item = T>, sep: &str) -> String {
1669    use std::fmt::Write as _;
1670    let mut sep_current = "";
1671    let mut buf = String::new();
1672    for i in s {
1673        write!(&mut buf, "{sep_current}{i}").unwrap();
1674        sep_current = sep;
1675    }
1676    buf
1677}
1678fn trim_raw(s: &str) -> &str {
1679    if let Some(s) = s.strip_prefix("r#") {
1680        s
1681    } else {
1682        s
1683    }
1684}
1685
1686fn field_of<'a, 'b>(
1687    fields: &'a mut BTreeMap<FieldKey, FieldEntry<'b>>,
1688    key: &FieldKey,
1689    span: Span,
1690) -> Result<&'a mut FieldEntry<'b>> {
1691    if let Some(f) = fields.get_mut(key) {
1692        Ok(f)
1693    } else {
1694        bail!(span, "field `{key}` not found.");
1695    }
1696}
1697
1698const CAPTURE_NAME_EMPTY: &str = "empty";
1699fn capture_name(idx: usize) -> String {
1700    format!("value_{idx}")
1701}
1702fn capture_index(idx: usize, names: &HashMap<&str, usize>) -> usize {
1703    names[capture_name(idx).as_str()]
1704}
1705
1706fn build_parse_capture_expr(
1707    field_name: &str,
1708    capture_index: usize,
1709    field: Option<&FieldEntry>,
1710    crate_path: &Path,
1711) -> TokenStream {
1712    let msg = format!("field `{field_name}` parse failed.");
1713    let expr0 = quote!(c.get(#capture_index).map_or("", |m| m.as_str()));
1714    let mut expr1 = quote!(#expr0.parse());
1715    if let Some(field) = field {
1716        if let Some(with) = &field.hattrs.with {
1717            let ty = &field.source.ty;
1718            expr1 = quote! {
1719                #crate_path::helpers::parse_with::<#ty, _>(#with, #expr0)
1720            };
1721            expr1 = set_span(expr1, with.span());
1722        }
1723    }
1724    quote! {
1725        #expr1.map_err(|e| #crate_path::ParseError::with_message(#msg))?
1726    }
1727}
1728fn set_span(ts: TokenStream, span: Span) -> TokenStream {
1729    ts.into_iter()
1730        .map(|mut ts| {
1731            ts.set_span(span);
1732            ts
1733        })
1734        .collect()
1735}
1736
1737fn unref_ty(ty: &Type) -> Type {
1738    if let Type::Reference(ty) = ty {
1739        unref_ty(&ty.elem)
1740    } else {
1741        ty.clone()
1742    }
1743}