1#![recursion_limit = "128"]
2#![allow(clippy::large_enum_variant)]
3
4extern 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}