1#![cfg_attr(
2 not(all(feature = "add", feature = "mul")),
3 allow(dead_code, unused_mut)
4)]
5
6use proc_macro2::TokenStream;
7use quote::{format_ident, quote, ToTokens};
8use syn::{
9 parse_quote, punctuated::Punctuated, spanned::Spanned, Attribute, Data,
10 DeriveInput, Error, Field, Fields, FieldsNamed, FieldsUnnamed, GenericParam,
11 Generics, Ident, Index, Result, Token, Type, TypeGenerics, TypeParamBound, Variant,
12 WhereClause,
13};
14
15#[cfg(any(
16 feature = "add",
17 feature = "add_assign",
18 feature = "as_ref",
19 feature = "debug",
20 feature = "display",
21 feature = "eq",
22 feature = "from",
23 feature = "from_str",
24 feature = "into",
25 feature = "mul",
26 feature = "mul_assign",
27 feature = "try_from",
28 feature = "try_into",
29))]
30pub(crate) use self::either::Either;
31#[cfg(any(feature = "from", feature = "into"))]
32pub(crate) use self::fields_ext::FieldsExt;
33#[cfg(any(
34 feature = "add",
35 feature = "add_assign",
36 feature = "as_ref",
37 feature = "eq",
38 feature = "from_str",
39 feature = "mul",
40 feature = "mul_assign",
41))]
42pub(crate) use self::generics_search::GenericsSearch;
43#[cfg(any(
44 feature = "add",
45 feature = "add_assign",
46 feature = "as_ref",
47 feature = "debug",
48 feature = "display",
49 feature = "eq",
50 feature = "from",
51 feature = "from_str",
52 feature = "into",
53 feature = "mul",
54 feature = "mul_assign",
55 feature = "try_from",
56 feature = "try_into",
57))]
58pub(crate) use self::spanning::Spanning;
59
60#[derive(Clone, Copy, Default)]
61pub struct DeterministicState;
62
63impl std::hash::BuildHasher for DeterministicState {
64 type Hasher = std::collections::hash_map::DefaultHasher;
65
66 fn build_hasher(&self) -> Self::Hasher {
67 Self::Hasher::default()
68 }
69}
70
71pub type HashMap<K, V> = std::collections::HashMap<K, V, DeterministicState>;
72pub type HashSet<K> = std::collections::HashSet<K, DeterministicState>;
73
74#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
75pub enum RefType {
76 No,
77 Ref,
78 Mut,
79}
80
81impl RefType {
82 pub fn lifetime(self) -> TokenStream {
83 match self {
84 RefType::No => quote! {},
85 _ => quote! { '__deriveMoreLifetime },
86 }
87 }
88
89 pub fn reference(self) -> TokenStream {
90 match self {
91 RefType::No => quote! {},
92 RefType::Ref => quote! { & },
93 RefType::Mut => quote! { &mut },
94 }
95 }
96
97 pub fn mutability(self) -> TokenStream {
98 match self {
99 RefType::Mut => quote! { mut },
100 _ => quote! {},
101 }
102 }
103
104 pub fn pattern_ref(self) -> TokenStream {
105 match self {
106 RefType::Ref => quote! { ref },
107 RefType::Mut => quote! { ref mut },
108 RefType::No => quote! {},
109 }
110 }
111
112 pub fn reference_with_lifetime(self) -> TokenStream {
113 if !self.is_ref() {
114 return quote! {};
115 }
116 let lifetime = self.lifetime();
117 let mutability = self.mutability();
118 quote! { &#lifetime #mutability }
119 }
120
121 pub fn is_ref(self) -> bool {
122 !matches!(self, RefType::No)
123 }
124
125 pub fn from_attr_name(name: &str) -> Self {
126 match name {
127 "owned" => RefType::No,
128 "ref" => RefType::Ref,
129 "ref_mut" => RefType::Mut,
130 _ => panic!("`{name}` is not a `RefType`"),
131 }
132 }
133}
134
135pub fn numbered_vars(count: usize, prefix: &str) -> Vec<Ident> {
136 (0..count).map(|i| format_ident!("__{prefix}{i}")).collect()
137}
138
139pub fn field_idents<'a>(fields: &'a [&'a Field]) -> Vec<&'a Ident> {
140 fields
141 .iter()
142 .map(|f| {
143 f.ident
144 .as_ref()
145 .expect("Tried to get field names of a tuple struct")
146 })
147 .collect()
148}
149
150pub fn get_field_types_iter<'a>(
151 fields: &'a [&'a Field],
152) -> Box<dyn Iterator<Item = &'a Type> + 'a> {
153 Box::new(fields.iter().map(|f| &f.ty))
154}
155
156pub fn get_field_types<'a>(fields: &'a [&'a Field]) -> Vec<&'a Type> {
157 get_field_types_iter(fields).collect()
158}
159
160pub fn add_extra_type_param_bound_op_output<'a>(
161 generics: &'a Generics,
162 trait_ident: &'a Ident,
163) -> Generics {
164 let mut generics = generics.clone();
165 for type_param in &mut generics.type_params_mut() {
166 let type_ident = &type_param.ident;
167 let bound: TypeParamBound = parse_quote! {
168 derive_more::core::ops::#trait_ident<Output = #type_ident>
169 };
170 type_param.bounds.push(bound)
171 }
172
173 generics
174}
175
176pub fn add_extra_ty_param_bound<'a>(
177 generics: &'a Generics,
178 bound: &'a TokenStream,
179) -> Generics {
180 let mut generics = generics.clone();
181 let bound: TypeParamBound = parse_quote! { #bound };
182 for type_param in &mut generics.type_params_mut() {
183 type_param.bounds.push(bound.clone())
184 }
185
186 generics
187}
188
189pub fn add_extra_generic_param(
190 generics: &Generics,
191 generic_param: TokenStream,
192) -> Generics {
193 let generic_param: GenericParam = parse_quote! { #generic_param };
194 let mut generics = generics.clone();
195 generics.params.push(generic_param);
196
197 generics
198}
199
200pub fn add_extra_generic_type_param(
201 generics: &Generics,
202 generic_param: TokenStream,
203) -> Generics {
204 let generic_param: GenericParam = parse_quote! { #generic_param };
205 let lifetimes: Vec<GenericParam> =
206 generics.lifetimes().map(|x| x.clone().into()).collect();
207 let type_params: Vec<GenericParam> =
208 generics.type_params().map(|x| x.clone().into()).collect();
209 let const_params: Vec<GenericParam> =
210 generics.const_params().map(|x| x.clone().into()).collect();
211 let mut generics = generics.clone();
212 generics.params = Default::default();
213 generics.params.extend(lifetimes);
214 generics.params.extend(type_params);
215 generics.params.push(generic_param);
216 generics.params.extend(const_params);
217
218 generics
219}
220
221pub fn add_extra_where_clauses(
222 generics: &Generics,
223 type_where_clauses: TokenStream,
224) -> Generics {
225 let mut type_where_clauses: WhereClause = parse_quote! { #type_where_clauses };
226 let mut new_generics = generics.clone();
227 if let Some(old_where) = new_generics.where_clause {
228 type_where_clauses.predicates.extend(old_where.predicates)
229 }
230 new_generics.where_clause = Some(type_where_clauses);
231
232 new_generics
233}
234
235pub fn add_where_clauses_for_new_ident<'a>(
236 generics: &'a Generics,
237 fields: &[&'a Field],
238 type_ident: &Ident,
239 type_where_clauses: TokenStream,
240 sized: bool,
241) -> Generics {
242 let generic_param = if fields.len() > 1 {
243 quote! { #type_ident: derive_more::core::marker::Copy }
244 } else if sized {
245 quote! { #type_ident }
246 } else {
247 quote! { #type_ident: ?derive_more::core::marker::Sized }
248 };
249
250 let generics = add_extra_where_clauses(generics, type_where_clauses);
251 add_extra_generic_type_param(&generics, generic_param)
252}
253
254pub fn unnamed_to_vec(fields: &FieldsUnnamed) -> Vec<&Field> {
255 fields.unnamed.iter().collect()
256}
257
258pub fn named_to_vec(fields: &FieldsNamed) -> Vec<&Field> {
259 fields.named.iter().collect()
260}
261
262pub(crate) fn panic_one_field(trait_name: &str, trait_attr: &str) -> ! {
263 panic!(
264 "derive({trait_name}) only works when forwarding to a single field. \
265 Try putting #[{trait_attr}] or #[{trait_attr}(ignore)] on the fields in the struct",
266 )
267}
268
269#[derive(Copy, Clone, Debug, PartialEq, Eq)]
270pub enum DeriveType {
271 Unnamed,
272 Named,
273 Enum,
274}
275
276pub struct State<'input> {
277 pub input: &'input DeriveInput,
278 pub trait_name: &'static str,
279 pub method_ident: Ident,
280 pub trait_path: TokenStream,
281 pub trait_path_params: Vec<TokenStream>,
282 pub trait_attr: String,
283 pub derive_type: DeriveType,
284 pub fields: Vec<&'input Field>,
285 pub variants: Vec<&'input Variant>,
286 pub variant_states: Vec<State<'input>>,
287 pub variant: Option<&'input Variant>,
288 pub generics: Generics,
289 pub default_info: FullMetaInfo,
290 full_meta_infos: Vec<FullMetaInfo>,
291}
292
293#[derive(Default, Clone)]
294pub struct AttrParams {
295 pub enum_: Vec<&'static str>,
296 pub variant: Vec<&'static str>,
297 pub struct_: Vec<&'static str>,
298 pub field: Vec<&'static str>,
299}
300
301impl AttrParams {
302 pub fn new(params: Vec<&'static str>) -> AttrParams {
303 AttrParams {
304 enum_: params.clone(),
305 struct_: params.clone(),
306 variant: params.clone(),
307 field: params,
308 }
309 }
310}
311
312impl<'input> State<'input> {
313 pub fn new<'arg_input>(
314 input: &'arg_input DeriveInput,
315 trait_name: &'static str,
316 trait_attr: String,
317 ) -> Result<State<'arg_input>> {
318 State::new_impl(input, trait_name, trait_attr, AttrParams::default(), true)
319 }
320
321 pub fn with_field_ignore<'arg_input>(
322 input: &'arg_input DeriveInput,
323 trait_name: &'static str,
324 trait_attr: String,
325 ) -> Result<State<'arg_input>> {
326 State::new_impl(
327 input,
328 trait_name,
329 trait_attr,
330 AttrParams::new(vec!["ignore"]),
331 true,
332 )
333 }
334
335 pub fn with_field_ignore_and_forward<'arg_input>(
336 input: &'arg_input DeriveInput,
337 trait_name: &'static str,
338 trait_attr: String,
339 ) -> Result<State<'arg_input>> {
340 State::new_impl(
341 input,
342 trait_name,
343 trait_attr,
344 AttrParams::new(vec!["ignore", "forward"]),
345 true,
346 )
347 }
348
349 pub fn with_field_ignore_and_refs<'arg_input>(
350 input: &'arg_input DeriveInput,
351 trait_name: &'static str,
352 trait_attr: String,
353 ) -> Result<State<'arg_input>> {
354 State::new_impl(
355 input,
356 trait_name,
357 trait_attr,
358 AttrParams::new(vec!["ignore", "owned", "ref", "ref_mut"]),
359 true,
360 )
361 }
362
363 pub fn with_attr_params<'arg_input>(
364 input: &'arg_input DeriveInput,
365 trait_name: &'static str,
366 trait_attr: String,
367 allowed_attr_params: AttrParams,
368 ) -> Result<State<'arg_input>> {
369 State::new_impl(input, trait_name, trait_attr, allowed_attr_params, true)
370 }
371
372 fn new_impl<'arg_input>(
373 input: &'arg_input DeriveInput,
374 trait_name: &'static str,
375 trait_attr: String,
376 allowed_attr_params: AttrParams,
377 add_type_bound: bool,
378 ) -> Result<State<'arg_input>> {
379 let trait_name = trait_name.trim_end_matches("ToInner");
380 let trait_ident = format_ident!("{trait_name}");
381 let method_ident = format_ident!("{trait_attr}");
382 let trait_path = quote! { derive_more::with_trait::#trait_ident };
383 let (derive_type, fields, variants): (_, Vec<_>, Vec<_>) = match input.data {
384 Data::Struct(ref data_struct) => match data_struct.fields {
385 Fields::Unnamed(ref fields) => {
386 (DeriveType::Unnamed, unnamed_to_vec(fields), vec![])
387 }
388
389 Fields::Named(ref fields) => {
390 (DeriveType::Named, named_to_vec(fields), vec![])
391 }
392 Fields::Unit => (DeriveType::Named, vec![], vec![]),
393 },
394 Data::Enum(ref data_enum) => (
395 DeriveType::Enum,
396 vec![],
397 data_enum.variants.iter().collect(),
398 ),
399 Data::Union(_) => {
400 panic!("cannot derive({trait_name}) for union")
401 }
402 };
403 let attrs: Vec<_> = if derive_type == DeriveType::Enum {
404 variants.iter().map(|v| &v.attrs).collect()
405 } else {
406 fields.iter().map(|f| &f.attrs).collect()
407 };
408
409 let (allowed_attr_params_outer, allowed_attr_params_inner) =
410 if derive_type == DeriveType::Enum {
411 (&allowed_attr_params.enum_, &allowed_attr_params.variant)
412 } else {
413 (&allowed_attr_params.struct_, &allowed_attr_params.field)
414 };
415
416 let struct_meta_info =
417 get_meta_info(&trait_attr, &input.attrs, allowed_attr_params_outer)?;
418 let meta_infos: Result<Vec<_>> = attrs
419 .iter()
420 .map(|attrs| get_meta_info(&trait_attr, attrs, allowed_attr_params_inner))
421 .collect();
422 let meta_infos = meta_infos?;
423 let first_match = meta_infos
424 .iter()
425 .find_map(|info| info.enabled.map(|_| info));
426
427 let default_enabled = if trait_name == "Error" {
442 true
443 } else {
444 first_match.map_or(true, |info| !info.enabled.unwrap())
445 };
446
447 let defaults = struct_meta_info.into_full(FullMetaInfo {
448 enabled: default_enabled,
449 forward: false,
450 owned: first_match.map_or(true, |info| {
456 info.owned.is_none() && info.ref_.is_none() || info.ref_mut.is_none()
457 }),
458 ref_: false,
459 ref_mut: false,
460 info: MetaInfo::default(),
461 });
462
463 let full_meta_infos: Vec<_> = meta_infos
464 .into_iter()
465 .map(|info| info.into_full(defaults.clone()))
466 .collect();
467
468 let variant_states: Result<Vec<_>> = if derive_type == DeriveType::Enum {
469 variants
470 .iter()
471 .zip(full_meta_infos.iter().cloned())
472 .map(|(variant, info)| {
473 State::from_variant(
474 input,
475 trait_name,
476 trait_attr.clone(),
477 allowed_attr_params.clone(),
478 variant,
479 info,
480 )
481 })
482 .collect()
483 } else {
484 Ok(vec![])
485 };
486
487 let generics = if add_type_bound {
488 add_extra_ty_param_bound(&input.generics, &trait_path)
489 } else {
490 input.generics.clone()
491 };
492
493 Ok(State {
494 input,
495 trait_name,
496 method_ident,
497 trait_path,
498 trait_path_params: vec![],
499 trait_attr,
500 fields,
502 variants,
503 variant_states: variant_states?,
504 variant: None,
505 derive_type,
506 generics,
507 full_meta_infos,
508 default_info: defaults,
509 })
510 }
511
512 pub fn from_variant<'arg_input>(
513 input: &'arg_input DeriveInput,
514 trait_name: &'static str,
515 trait_attr: String,
516 allowed_attr_params: AttrParams,
517 variant: &'arg_input Variant,
518 default_info: FullMetaInfo,
519 ) -> Result<State<'arg_input>> {
520 let trait_name = trait_name.trim_end_matches("ToInner");
521 let trait_ident = format_ident!("{trait_name}");
522 let method_ident = format_ident!("{trait_attr}");
523 let trait_path = quote! { derive_more::with_trait::#trait_ident };
524 let (derive_type, fields): (_, Vec<_>) = match variant.fields {
525 Fields::Unnamed(ref fields) => {
526 (DeriveType::Unnamed, unnamed_to_vec(fields))
527 }
528
529 Fields::Named(ref fields) => (DeriveType::Named, named_to_vec(fields)),
530 Fields::Unit => (DeriveType::Named, vec![]),
531 };
532
533 let meta_infos: Result<Vec<_>> = fields
534 .iter()
535 .map(|f| &f.attrs)
536 .map(|attrs| get_meta_info(&trait_attr, attrs, &allowed_attr_params.field))
537 .collect();
538 let meta_infos = meta_infos?;
539
540 let first_match = meta_infos
541 .iter()
542 .find_map(|info| info.enabled.map(|_| info));
543
544 let default_enabled = if trait_name == "Error" {
545 true
546 } else {
547 first_match.map_or(true, |info| !info.enabled.unwrap())
548 };
549
550 let default_info = FullMetaInfo {
551 enabled: default_enabled,
552 ..default_info.clone()
553 };
554
555 let full_meta_infos: Vec<_> = meta_infos
556 .into_iter()
557 .map(|info| info.into_full(default_info.clone()))
558 .collect();
559
560 let generics = add_extra_ty_param_bound(&input.generics, &trait_path);
561
562 Ok(State {
563 input,
564 trait_name,
565 trait_path,
566 trait_path_params: vec![],
567 trait_attr,
568 method_ident,
569 fields,
571 variants: vec![],
572 variant_states: vec![],
573 variant: Some(variant),
574 derive_type,
575 generics,
576 full_meta_infos,
577 default_info,
578 })
579 }
580 pub fn add_trait_path_type_param(&mut self, param: TokenStream) {
581 self.trait_path_params.push(param);
582 }
583
584 pub fn assert_single_enabled_field<'state>(
585 &'state self,
586 ) -> SingleFieldData<'input, 'state> {
587 if self.derive_type == DeriveType::Enum {
588 panic_one_field(self.trait_name, &self.trait_attr);
589 }
590 let data = self.enabled_fields_data();
591 if data.fields.len() != 1 {
592 panic_one_field(self.trait_name, &self.trait_attr);
593 };
594 SingleFieldData {
595 input_type: data.input_type,
596 field: data.fields[0],
597 field_type: data.field_types[0],
598 member: data.members[0].clone(),
599 info: data.infos[0].clone(),
600 trait_path: data.trait_path,
601 trait_path_with_params: data.trait_path_with_params.clone(),
602 casted_trait: data.casted_traits[0].clone(),
603 ty_generics: data.ty_generics.clone(),
604 }
605 }
606
607 pub fn enabled_fields_data<'state>(&'state self) -> MultiFieldData<'input, 'state> {
608 if self.derive_type == DeriveType::Enum {
609 panic!("cannot derive({}) for enum", self.trait_name)
610 }
611 let fields = self.enabled_fields();
612 let field_idents = self.enabled_fields_idents();
613 let field_indexes = self.enabled_fields_indexes();
614 let field_types: Vec<_> = fields.iter().map(|f| &f.ty).collect();
615 let members: Vec<_> = field_idents
616 .iter()
617 .map(|ident| quote! { self.#ident })
618 .collect();
619 let trait_path = &self.trait_path;
620 let trait_path_with_params = if !self.trait_path_params.is_empty() {
621 let params = self.trait_path_params.iter();
622 quote! { #trait_path<#(#params),*> }
623 } else {
624 self.trait_path.clone()
625 };
626
627 let casted_traits: Vec<_> = field_types
628 .iter()
629 .map(|field_type| quote! { <#field_type as #trait_path_with_params> })
630 .collect();
631 let (_, ty_generics, _) = self.generics.split_for_impl();
632 let input_type = &self.input.ident;
633 let (variant_name, variant_type) = self.variant.map_or_else(
634 || (None, quote! { #input_type }),
635 |v| {
636 let variant_name = &v.ident;
637 (Some(variant_name), quote! { #input_type::#variant_name })
638 },
639 );
640 MultiFieldData {
641 input_type,
642 variant_type,
643 variant_name,
644 variant_info: self.default_info.clone(),
645 fields,
646 field_types,
647 field_indexes,
648 members,
649 infos: self.enabled_infos(),
650 field_idents,
651 method_ident: &self.method_ident,
652 trait_path,
653 trait_path_with_params,
654 casted_traits,
655 ty_generics,
656 state: self,
657 }
658 }
659
660 pub fn enabled_variant_data<'state>(
661 &'state self,
662 ) -> MultiVariantData<'input, 'state> {
663 if self.derive_type != DeriveType::Enum {
664 panic!("can only derive({}) for enum", self.trait_name)
665 }
666 let variants = self.enabled_variants();
667 MultiVariantData {
668 variants,
669 variant_states: self.enabled_variant_states(),
670 infos: self.enabled_infos(),
671 }
672 }
673
674 fn enabled_variants(&self) -> Vec<&'input Variant> {
675 self.variants
676 .iter()
677 .zip(self.full_meta_infos.iter().map(|info| info.enabled))
678 .filter(|(_, ig)| *ig)
679 .map(|(v, _)| *v)
680 .collect()
681 }
682
683 fn enabled_variant_states(&self) -> Vec<&State<'input>> {
684 self.variant_states
685 .iter()
686 .zip(self.full_meta_infos.iter().map(|info| info.enabled))
687 .filter(|(_, ig)| *ig)
688 .map(|(v, _)| v)
689 .collect()
690 }
691
692 pub fn enabled_fields(&self) -> Vec<&'input Field> {
693 self.fields
694 .iter()
695 .zip(self.full_meta_infos.iter().map(|info| info.enabled))
696 .filter(|(_, ig)| *ig)
697 .map(|(f, _)| *f)
698 .collect()
699 }
700
701 fn field_idents(&self) -> Vec<TokenStream> {
702 if self.derive_type == DeriveType::Named {
703 self.fields
704 .iter()
705 .map(|f| {
706 f.ident
707 .as_ref()
708 .expect("Tried to get field names of a tuple struct")
709 .to_token_stream()
710 })
711 .collect()
712 } else {
713 let count = self.fields.len();
714 (0..count)
715 .map(|i| Index::from(i).to_token_stream())
716 .collect()
717 }
718 }
719
720 fn enabled_fields_idents(&self) -> Vec<TokenStream> {
721 self.field_idents()
722 .into_iter()
723 .zip(self.full_meta_infos.iter().map(|info| info.enabled))
724 .filter(|(_, ig)| *ig)
725 .map(|(f, _)| f)
726 .collect()
727 }
728
729 fn enabled_fields_indexes(&self) -> Vec<usize> {
730 self.full_meta_infos
731 .iter()
732 .map(|info| info.enabled)
733 .enumerate()
734 .filter(|(_, ig)| *ig)
735 .map(|(i, _)| i)
736 .collect()
737 }
738 fn enabled_infos(&self) -> Vec<FullMetaInfo> {
739 self.full_meta_infos
740 .iter()
741 .filter(|info| info.enabled)
742 .cloned()
743 .collect()
744 }
745}
746
747#[derive(Clone)]
748pub struct SingleFieldData<'input, 'state> {
749 pub input_type: &'input Ident,
750 pub field: &'input Field,
751 pub field_type: &'input Type,
752 pub member: TokenStream,
753 pub info: FullMetaInfo,
754 pub trait_path: &'state TokenStream,
755 pub trait_path_with_params: TokenStream,
756 pub casted_trait: TokenStream,
757 pub ty_generics: TypeGenerics<'state>,
758}
759
760#[derive(Clone)]
761pub struct MultiFieldData<'input, 'state> {
762 pub input_type: &'input Ident,
763 pub variant_type: TokenStream,
764 pub variant_name: Option<&'input Ident>,
765 pub variant_info: FullMetaInfo,
766 pub fields: Vec<&'input Field>,
767 pub field_types: Vec<&'input Type>,
768 pub field_idents: Vec<TokenStream>,
769 pub field_indexes: Vec<usize>,
770 pub members: Vec<TokenStream>,
771 pub infos: Vec<FullMetaInfo>,
772 pub method_ident: &'state Ident,
773 pub trait_path: &'state TokenStream,
774 pub trait_path_with_params: TokenStream,
775 pub casted_traits: Vec<TokenStream>,
776 pub ty_generics: TypeGenerics<'state>,
777 pub state: &'state State<'input>,
778}
779
780pub struct MultiVariantData<'input, 'state> {
781 pub variants: Vec<&'input Variant>,
782 pub variant_states: Vec<&'state State<'input>>,
783 pub infos: Vec<FullMetaInfo>,
784}
785
786impl MultiFieldData<'_, '_> {
787 pub fn initializer<T: ToTokens>(&self, initializers: &[T]) -> TokenStream {
788 let MultiFieldData {
789 variant_type,
790 field_idents,
791 ..
792 } = self;
793 if self.state.derive_type == DeriveType::Named {
794 quote! { #variant_type{#(#field_idents: #initializers),*} }
795 } else {
796 quote! { #variant_type(#(#initializers),*) }
797 }
798 }
799 pub fn matcher<T: ToTokens>(
800 &self,
801 indexes: &[usize],
802 bindings: &[T],
803 ) -> TokenStream {
804 let MultiFieldData { variant_type, .. } = self;
805 let full_bindings = (0..self.state.fields.len()).map(|i| {
806 indexes.iter().position(|index| i == *index).map_or_else(
807 || quote! { _ },
808 |found_index| bindings[found_index].to_token_stream(),
809 )
810 });
811 if self.state.derive_type == DeriveType::Named {
812 let field_idents = self.state.field_idents();
813 quote! { #variant_type{#(#field_idents: #full_bindings),*} }
814 } else {
815 quote! { #variant_type(#(#full_bindings),*) }
816 }
817 }
818}
819
820fn get_meta_info(
821 trait_attr: &str,
822 attrs: &[Attribute],
823 allowed_attr_params: &[&str],
824) -> Result<MetaInfo> {
825 let mut it = attrs.iter().filter(|a| {
826 a.meta
827 .path()
828 .segments
829 .first()
830 .map(|p| p.ident == trait_attr)
831 .unwrap_or_default()
832 });
833
834 let mut info = MetaInfo::default();
835
836 let Some(attr) = it.next() else {
837 return Ok(info);
838 };
839
840 if allowed_attr_params.is_empty() {
841 return Err(Error::new(attr.span(), "Attribute is not allowed here"));
842 }
843
844 info.enabled = Some(true);
845
846 if let Some(another_attr) = it.next() {
847 return Err(Error::new(
848 another_attr.span(),
849 "Only a single attribute is allowed",
850 ));
851 }
852
853 let list = match &attr.meta {
854 syn::Meta::Path(_) => {
855 if allowed_attr_params.contains(&"ignore") {
856 return Ok(info);
857 } else {
858 return Err(Error::new(
859 attr.span(),
860 format!(
861 "Empty attribute is not allowed, add one of the following parameters: {}",
862 allowed_attr_params.join(", "),
863 ),
864 ));
865 }
866 }
867 syn::Meta::List(list) => list,
868 syn::Meta::NameValue(val) => {
869 return Err(Error::new(
870 val.span(),
871 "Attribute doesn't support name-value format here",
872 ));
873 }
874 };
875
876 parse_punctuated_nested_meta(
877 &mut info,
878 &list.parse_args_with(Punctuated::parse_terminated)?,
879 allowed_attr_params,
880 None,
881 )?;
882
883 Ok(info)
884}
885
886fn parse_punctuated_nested_meta(
887 info: &mut MetaInfo,
888 meta: &Punctuated<polyfill::Meta, Token![,]>,
889 allowed_attr_params: &[&str],
890 wrapper_name: Option<&str>,
891) -> Result<()> {
892 for meta in meta.iter() {
893 match meta {
894 polyfill::Meta::List(list) if list.path.is_ident("not") => {
895 if wrapper_name.is_some() {
896 return Err(Error::new(
898 list.span(),
899 "Attribute doesn't support multiple multiple or nested `not` parameters",
900 ));
901 }
902 parse_punctuated_nested_meta(
903 info,
904 &list.parse_args_with(Punctuated::parse_terminated)?,
905 allowed_attr_params,
906 Some("not"),
907 )?;
908 }
909
910 polyfill::Meta::List(list) => {
911 let path = &list.path;
912 if !allowed_attr_params.iter().any(|param| path.is_ident(param)) {
913 return Err(Error::new(
914 meta.span(),
915 format!(
916 "Attribute nested parameter not supported. \
917 Supported attribute parameters are: {}",
918 allowed_attr_params.join(", "),
919 ),
920 ));
921 }
922
923 let mut parse_nested = true;
924
925 let attr_name = path.get_ident().unwrap().to_string();
926 match (wrapper_name, attr_name.as_str()) {
927 (None, "owned") => info.owned = Some(true),
928 (None, "ref") => info.ref_ = Some(true),
929 (None, "ref_mut") => info.ref_mut = Some(true),
930
931 (None, "source") => info.source = Some(true),
932
933 #[cfg(any(feature = "from", feature = "into"))]
934 (None, "types")
935 | (Some("owned"), "types")
936 | (Some("ref"), "types")
937 | (Some("ref_mut"), "types") => {
938 parse_nested = false;
939 for meta in &list.parse_args_with(
940 Punctuated::<polyfill::NestedMeta, syn::token::Comma>::parse_terminated,
941 )? {
942 let typ: syn::Type = match meta {
943 polyfill::NestedMeta::Meta(meta) => {
944 let polyfill::Meta::Path(path) = meta else {
945 return Err(Error::new(
946 meta.span(),
947 format!(
948 "Attribute doesn't support type {}",
949 quote! { #meta },
950 ),
951 ));
952 };
953 syn::TypePath {
954 qself: None,
955 path: path.clone().into(),
956 }
957 .into()
958 }
959 polyfill::NestedMeta::Lit(syn::Lit::Str(s)) => s.parse()?,
960 polyfill::NestedMeta::Lit(lit) => return Err(Error::new(
961 lit.span(),
962 "Attribute doesn't support nested literals here",
963 )),
964 };
965
966 for ref_type in wrapper_name
967 .map(|n| vec![RefType::from_attr_name(n)])
968 .unwrap_or_else(|| {
969 vec![RefType::No, RefType::Ref, RefType::Mut]
970 })
971 {
972 if info
973 .types
974 .entry(ref_type)
975 .or_default()
976 .replace(typ.clone())
977 .is_some()
978 {
979 return Err(Error::new(
980 typ.span(),
981 format!(
982 "Duplicate type `{}` specified",
983 quote! { #path },
984 ),
985 ));
986 }
987 }
988 }
989 }
990
991 _ => {
992 return Err(Error::new(
993 list.span(),
994 format!(
995 "Attribute doesn't support nested parameter `{}` here",
996 quote! { #path },
997 ),
998 ))
999 }
1000 };
1001
1002 if parse_nested {
1003 parse_punctuated_nested_meta(
1004 info,
1005 &list.parse_args_with(Punctuated::parse_terminated)?,
1006 allowed_attr_params,
1007 Some(&attr_name),
1008 )?;
1009 }
1010 }
1011
1012 polyfill::Meta::Path(path) => {
1013 if !allowed_attr_params.iter().any(|param| path.is_ident(param)) {
1014 return Err(Error::new(
1015 meta.span(),
1016 format!(
1017 "Attribute parameter not supported. \
1018 Supported attribute parameters are: {}",
1019 allowed_attr_params.join(", "),
1020 ),
1021 ));
1022 }
1023
1024 let attr_name = path.get_ident().unwrap().to_string();
1025 match (wrapper_name, attr_name.as_str()) {
1026 (None, "ignore") => info.enabled = Some(false),
1027 (None, "forward") => info.forward = Some(true),
1028 (Some("not"), "forward") => info.forward = Some(false),
1029 (None, "owned") => info.owned = Some(true),
1030 (None, "ref") => info.ref_ = Some(true),
1031 (None, "ref_mut") => info.ref_mut = Some(true),
1032 (None, "source") => info.source = Some(true),
1033 (Some("not"), "source") => info.source = Some(false),
1034 (Some("source"), "optional") => info.source_optional = Some(true),
1035 (None, "backtrace") => info.backtrace = Some(true),
1036 (Some("not"), "backtrace") => info.backtrace = Some(false),
1037 _ => {
1038 return Err(Error::new(
1039 path.span(),
1040 format!(
1041 "Attribute doesn't support parameter `{}` here",
1042 quote! { #path }
1043 ),
1044 ))
1045 }
1046 }
1047 }
1048 }
1049 }
1050
1051 Ok(())
1052}
1053
1054pub(crate) mod polyfill {
1058 use proc_macro2::TokenStream;
1059 use quote::ToTokens;
1060 use syn::{
1061 ext::IdentExt as _,
1062 parse::{Parse, ParseStream, Parser},
1063 token, Token,
1064 };
1065
1066 #[derive(Clone)]
1067 pub(crate) enum PathOrKeyword {
1068 Path(syn::Path),
1069 Keyword(syn::Ident),
1070 }
1071
1072 impl Parse for PathOrKeyword {
1073 fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
1074 if input.fork().parse::<syn::Path>().is_ok() {
1075 return input.parse().map(Self::Path);
1076 }
1077 syn::Ident::parse_any(input).map(Self::Keyword)
1078 }
1079 }
1080
1081 impl ToTokens for PathOrKeyword {
1082 fn to_tokens(&self, tokens: &mut TokenStream) {
1083 match self {
1084 Self::Path(p) => p.to_tokens(tokens),
1085 Self::Keyword(i) => i.to_tokens(tokens),
1086 }
1087 }
1088 }
1089
1090 impl PathOrKeyword {
1091 pub(crate) fn is_ident<I: ?Sized>(&self, ident: &I) -> bool
1092 where
1093 syn::Ident: PartialEq<I>,
1094 {
1095 match self {
1096 Self::Path(p) => p.is_ident(ident),
1097 Self::Keyword(i) => i == ident,
1098 }
1099 }
1100
1101 pub fn get_ident(&self) -> Option<&syn::Ident> {
1102 match self {
1103 Self::Path(p) => p.get_ident(),
1104 Self::Keyword(i) => Some(i),
1105 }
1106 }
1107 }
1108
1109 impl From<PathOrKeyword> for syn::Path {
1110 fn from(p: PathOrKeyword) -> Self {
1111 match p {
1112 PathOrKeyword::Path(p) => p,
1113 PathOrKeyword::Keyword(i) => i.into(),
1114 }
1115 }
1116 }
1117
1118 #[derive(Clone)]
1119 pub(crate) struct MetaList {
1120 pub(crate) path: PathOrKeyword,
1121 pub(crate) tokens: TokenStream,
1122 }
1123
1124 impl Parse for MetaList {
1125 fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
1126 let path = input.parse::<PathOrKeyword>()?;
1127 let tokens;
1128 _ = syn::parenthesized!(tokens in input);
1129 Ok(Self {
1130 path,
1131 tokens: tokens.parse()?,
1132 })
1133 }
1134 }
1135
1136 impl ToTokens for MetaList {
1137 fn to_tokens(&self, tokens: &mut TokenStream) {
1138 self.path.to_tokens(tokens);
1139 token::Paren::default()
1140 .surround(tokens, |tokens| self.tokens.to_tokens(tokens))
1141 }
1142 }
1143
1144 impl MetaList {
1145 pub fn parse_args_with<F: Parser>(&self, parser: F) -> syn::Result<F::Output> {
1146 parser.parse2(self.tokens.clone())
1147 }
1148 }
1149
1150 #[derive(Clone)]
1151 pub(crate) enum Meta {
1152 Path(PathOrKeyword),
1153 List(MetaList),
1154 }
1155
1156 impl Parse for Meta {
1157 fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
1158 let path = input.parse::<PathOrKeyword>()?;
1159 Ok(if input.peek(token::Paren) {
1160 let tokens;
1161 _ = syn::parenthesized!(tokens in input);
1162 Self::List(MetaList {
1163 path,
1164 tokens: tokens.parse()?,
1165 })
1166 } else {
1167 Self::Path(path)
1168 })
1169 }
1170 }
1171
1172 impl ToTokens for Meta {
1173 fn to_tokens(&self, tokens: &mut TokenStream) {
1174 match self {
1175 Self::Path(p) => p.to_tokens(tokens),
1176 Self::List(l) => l.to_tokens(tokens),
1177 }
1178 }
1179 }
1180
1181 #[derive(Clone)]
1182 pub(crate) enum NestedMeta {
1183 Meta(Meta),
1184 Lit(syn::Lit),
1185 }
1186
1187 impl Parse for NestedMeta {
1188 fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
1189 if input.peek(syn::Lit)
1190 && !(input.peek(syn::LitBool) && input.peek2(Token![=]))
1191 {
1192 input.parse().map(Self::Lit)
1193 } else if input.peek(syn::Ident::peek_any)
1194 || input.peek(Token![::]) && input.peek3(syn::Ident::peek_any)
1195 {
1196 input.parse().map(Self::Meta)
1197 } else {
1198 Err(input.error("expected identifier or literal"))
1199 }
1200 }
1201 }
1202
1203 impl ToTokens for NestedMeta {
1204 fn to_tokens(&self, tokens: &mut TokenStream) {
1205 match self {
1206 Self::Meta(m) => m.to_tokens(tokens),
1207 Self::Lit(l) => l.to_tokens(tokens),
1208 }
1209 }
1210 }
1211}
1212
1213#[derive(Clone, Debug, Default)]
1214pub struct FullMetaInfo {
1215 pub enabled: bool,
1216 pub forward: bool,
1217 pub owned: bool,
1218 pub ref_: bool,
1219 pub ref_mut: bool,
1220 pub info: MetaInfo,
1221}
1222
1223#[derive(Clone, Debug, Default)]
1224pub struct MetaInfo {
1225 pub enabled: Option<bool>,
1226 pub forward: Option<bool>,
1227 pub owned: Option<bool>,
1228 pub ref_: Option<bool>,
1229 pub ref_mut: Option<bool>,
1230 pub source: Option<bool>,
1231 pub source_optional: Option<bool>,
1232 pub backtrace: Option<bool>,
1233 #[cfg(any(feature = "from", feature = "into"))]
1234 pub types: HashMap<RefType, HashSet<syn::Type>>,
1235}
1236
1237impl MetaInfo {
1238 fn into_full(self, defaults: FullMetaInfo) -> FullMetaInfo {
1239 FullMetaInfo {
1240 enabled: self.enabled.unwrap_or(defaults.enabled),
1241 forward: self.forward.unwrap_or(defaults.forward),
1242 owned: self.owned.unwrap_or(defaults.owned),
1243 ref_: self.ref_.unwrap_or(defaults.ref_),
1244 ref_mut: self.ref_mut.unwrap_or(defaults.ref_mut),
1245 info: self,
1246 }
1247 }
1248}
1249
1250impl FullMetaInfo {
1251 pub fn ref_types(&self) -> Vec<RefType> {
1252 let mut ref_types = vec![];
1253 if self.owned {
1254 ref_types.push(RefType::No);
1255 }
1256 if self.ref_ {
1257 ref_types.push(RefType::Ref);
1258 }
1259 if self.ref_mut {
1260 ref_types.push(RefType::Mut);
1261 }
1262 ref_types
1263 }
1264}
1265
1266pub fn get_if_type_parameter_used_in_type(
1267 type_parameters: &HashSet<syn::Ident>,
1268 ty: &syn::Type,
1269) -> Option<syn::Type> {
1270 is_type_parameter_used_in_type(type_parameters, ty).then(|| match ty {
1271 syn::Type::Reference(syn::TypeReference { elem: ty, .. }) => (**ty).clone(),
1272 ty => ty.clone(),
1273 })
1274}
1275
1276pub fn is_type_parameter_used_in_type(
1277 type_parameters: &HashSet<syn::Ident>,
1278 ty: &syn::Type,
1279) -> bool {
1280 match ty {
1281 syn::Type::Path(ty) => {
1282 if let Some(qself) = &ty.qself {
1283 if is_type_parameter_used_in_type(type_parameters, &qself.ty) {
1284 return true;
1285 }
1286 }
1287
1288 if let Some(segment) = ty.path.segments.first() {
1289 if type_parameters.contains(&segment.ident) {
1290 return true;
1291 }
1292 }
1293
1294 ty.path.segments.iter().any(|segment| {
1295 if let syn::PathArguments::AngleBracketed(arguments) =
1296 &segment.arguments
1297 {
1298 arguments.args.iter().any(|argument| match argument {
1299 syn::GenericArgument::Type(ty) => {
1300 is_type_parameter_used_in_type(type_parameters, ty)
1301 }
1302 syn::GenericArgument::Constraint(constraint) => {
1303 type_parameters.contains(&constraint.ident)
1304 }
1305 _ => false,
1306 })
1307 } else {
1308 false
1309 }
1310 })
1311 }
1312
1313 syn::Type::Reference(ty) => {
1314 is_type_parameter_used_in_type(type_parameters, &ty.elem)
1315 }
1316
1317 _ => false,
1318 }
1319}
1320
1321#[cfg(any(
1322 feature = "add",
1323 feature = "add_assign",
1324 feature = "as_ref",
1325 feature = "debug",
1326 feature = "display",
1327 feature = "eq",
1328 feature = "from",
1329 feature = "from_str",
1330 feature = "into",
1331 feature = "mul",
1332 feature = "mul_assign",
1333 feature = "try_from",
1334 feature = "try_into",
1335))]
1336mod either {
1337 use proc_macro2::TokenStream;
1338 use quote::ToTokens;
1339 use syn::parse::{discouraged::Speculative as _, Parse, ParseStream};
1340
1341 #[derive(Clone, Copy, Debug)]
1346 pub(crate) enum Either<L, R> {
1347 Left(L),
1349
1350 Right(R),
1352 }
1353
1354 impl<L, R> Parse for Either<L, R>
1355 where
1356 L: Parse,
1357 R: Parse,
1358 {
1359 fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
1360 let ahead = input.fork();
1361 if let Ok(left) = ahead.parse::<L>() {
1362 input.advance_to(&ahead);
1363 Ok(Self::Left(left))
1364 } else {
1365 input.parse::<R>().map(Self::Right)
1366 }
1367 }
1368 }
1369
1370 impl<L, R, T> Iterator for Either<L, R>
1371 where
1372 L: Iterator<Item = T>,
1373 R: Iterator<Item = T>,
1374 {
1375 type Item = T;
1376
1377 fn next(&mut self) -> Option<Self::Item> {
1378 match self {
1379 Self::Left(left) => left.next(),
1380 Self::Right(right) => right.next(),
1381 }
1382 }
1383 }
1384
1385 impl<L, R> ToTokens for Either<L, R>
1386 where
1387 L: ToTokens,
1388 R: ToTokens,
1389 {
1390 fn to_tokens(&self, tokens: &mut TokenStream) {
1391 match self {
1392 Self::Left(l) => l.to_tokens(tokens),
1393 Self::Right(r) => r.to_tokens(tokens),
1394 }
1395 }
1396 }
1397}
1398
1399#[cfg(any(
1400 feature = "add",
1401 feature = "add_assign",
1402 feature = "as_ref",
1403 feature = "debug",
1404 feature = "display",
1405 feature = "eq",
1406 feature = "from",
1407 feature = "from_str",
1408 feature = "into",
1409 feature = "mul",
1410 feature = "mul_assign",
1411 feature = "try_from",
1412 feature = "try_into",
1413))]
1414mod spanning {
1415 use std::ops::{Deref, DerefMut};
1416
1417 use proc_macro2::Span;
1418
1419 #[derive(Clone, Copy, Debug)]
1423 pub(crate) struct Spanning<T: ?Sized> {
1424 pub(crate) span: Span,
1426
1427 pub(crate) item: T,
1429 }
1430
1431 impl<T: ?Sized> Spanning<T> {
1432 pub(crate) const fn new(item: T, span: Span) -> Self
1434 where
1435 T: Sized,
1436 {
1437 Self { span, item }
1438 }
1439
1440 pub fn into_inner(self) -> T
1442 where
1443 T: Sized,
1444 {
1445 self.item
1446 }
1447
1448 pub(crate) const fn span(&self) -> Span {
1450 self.span
1451 }
1452
1453 pub(crate) const fn as_ref(&self) -> Spanning<&T> {
1455 Spanning {
1456 span: self.span,
1457 item: &self.item,
1458 }
1459 }
1460
1461 pub(crate) fn map<U>(self, f: impl FnOnce(T) -> U) -> Spanning<U>
1463 where
1464 T: Sized,
1465 {
1466 Spanning {
1467 span: self.span,
1468 item: f(self.item),
1469 }
1470 }
1471 }
1472
1473 #[cfg(feature = "into")]
1474 impl<T> Spanning<Option<T>> {
1475 pub(crate) fn transpose(self) -> Option<Spanning<T>> {
1476 match self.item {
1477 Some(item) => Some(Spanning {
1478 item,
1479 span: self.span,
1480 }),
1481 None => None,
1482 }
1483 }
1484 }
1485
1486 impl<T: ?Sized> Deref for Spanning<T> {
1487 type Target = T;
1488
1489 fn deref(&self) -> &Self::Target {
1490 &self.item
1491 }
1492 }
1493
1494 impl<T: ?Sized> DerefMut for Spanning<T> {
1495 fn deref_mut(&mut self) -> &mut Self::Target {
1496 &mut self.item
1497 }
1498 }
1499}
1500
1501#[cfg(any(
1502 feature = "add",
1503 feature = "add_assign",
1504 feature = "as_ref",
1505 feature = "debug",
1506 feature = "display",
1507 feature = "eq",
1508 feature = "from",
1509 feature = "from_str",
1510 feature = "into",
1511 feature = "mul",
1512 feature = "mul_assign",
1513 feature = "try_from",
1514 feature = "try_into",
1515))]
1516pub(crate) mod attr {
1517 use std::any::Any;
1518
1519 use syn::{
1520 parse::{Parse, ParseStream},
1521 spanned::Spanned as _,
1522 };
1523
1524 use super::{Either, Spanning};
1525
1526 #[cfg(any(
1527 feature = "as_ref",
1528 feature = "from",
1529 feature = "into",
1530 feature = "try_from"
1531 ))]
1532 pub(crate) use self::empty::Empty;
1533 #[cfg(any(feature = "from_str", feature = "try_into"))]
1534 pub(crate) use self::error::Error;
1535 #[cfg(any(
1536 feature = "as_ref",
1537 feature = "from",
1538 feature = "mul",
1539 feature = "mul_assign",
1540 ))]
1541 pub(crate) use self::forward::Forward;
1542 #[cfg(any(feature = "display", feature = "from_str"))]
1543 pub(crate) use self::rename_all::RenameAll;
1544 #[cfg(any(
1545 feature = "add",
1546 feature = "add_assign",
1547 feature = "as_ref",
1548 feature = "debug",
1549 feature = "eq",
1550 feature = "from",
1551 feature = "into",
1552 feature = "mul",
1553 feature = "mul_assign",
1554 ))]
1555 pub(crate) use self::skip::Skip;
1556 #[cfg(any(feature = "as_ref", feature = "from", feature = "try_from"))]
1557 pub(crate) use self::types::Types;
1558 #[cfg(any(feature = "as_ref", feature = "from"))]
1559 pub(crate) use self::{conversion::Conversion, field_conversion::FieldConversion};
1560 #[cfg(feature = "try_from")]
1561 pub(crate) use self::{repr_conversion::ReprConversion, repr_int::ReprInt};
1562
1563 pub(crate) trait Parser {
1565 fn parse<T: Parse + Any>(&self, input: ParseStream<'_>) -> syn::Result<T> {
1569 T::parse(input)
1570 }
1571 }
1572
1573 impl Parser for () {}
1574
1575 pub(crate) trait ParseMultiple: Parse + Sized + 'static {
1577 fn parse_attr_with<P: Parser>(
1585 attr: &syn::Attribute,
1586 parser: &P,
1587 ) -> syn::Result<Self> {
1588 attr.parse_args_with(|ps: ParseStream<'_>| parser.parse(ps))
1589 }
1590
1591 fn merge_attrs(
1595 _prev: Spanning<Self>,
1596 new: Spanning<Self>,
1597 name: &syn::Ident,
1598 ) -> syn::Result<Spanning<Self>> {
1599 Err(syn::Error::new(
1600 new.span,
1601 format!("only single `#[{name}(...)]` attribute is allowed here"),
1602 ))
1603 }
1604
1605 fn merge_opt_attrs(
1610 prev: Option<Spanning<Self>>,
1611 new: Option<Spanning<Self>>,
1612 name: &syn::Ident,
1613 ) -> syn::Result<Option<Spanning<Self>>> {
1614 Ok(match (prev, new) {
1615 (Some(p), Some(n)) => Some(Self::merge_attrs(p, n, name)?),
1616 (Some(p), None) => Some(p),
1617 (None, Some(n)) => Some(n),
1618 (None, None) => None,
1619 })
1620 }
1621
1622 fn parse_attrs_with<P: Parser>(
1627 attrs: impl AsRef<[syn::Attribute]>,
1628 name: &syn::Ident,
1629 parser: &P,
1630 ) -> syn::Result<Option<Spanning<Self>>> {
1631 attrs
1632 .as_ref()
1633 .iter()
1634 .filter(|attr| attr.path().is_ident(name))
1635 .try_fold(None, |merged, attr| {
1636 let parsed = Spanning::new(
1637 Self::parse_attr_with(attr, parser)?,
1638 attr.span(),
1639 );
1640 if let Some(prev) = merged {
1641 Self::merge_attrs(prev, parsed, name).map(Some)
1642 } else {
1643 Ok(Some(parsed))
1644 }
1645 })
1646 }
1647
1648 fn parse_attrs(
1653 attrs: impl AsRef<[syn::Attribute]>,
1654 name: &syn::Ident,
1655 ) -> syn::Result<Option<Spanning<Self>>> {
1656 Self::parse_attrs_with(attrs, name, &())
1657 }
1658 }
1659
1660 impl<L: ParseMultiple, R: ParseMultiple> ParseMultiple for Either<L, R> {
1661 fn parse_attr_with<P: Parser>(
1662 attr: &syn::Attribute,
1663 parser: &P,
1664 ) -> syn::Result<Self> {
1665 L::parse_attr_with(attr, parser)
1666 .map(Self::Left)
1667 .or_else(|_| R::parse_attr_with(attr, parser).map(Self::Right))
1668 }
1669
1670 fn merge_attrs(
1671 prev: Spanning<Self>,
1672 new: Spanning<Self>,
1673 name: &syn::Ident,
1674 ) -> syn::Result<Spanning<Self>> {
1675 Ok(match (prev.item, new.item) {
1676 (Self::Left(p), Self::Left(n)) => {
1677 L::merge_attrs(Spanning::new(p, prev.span), Spanning::new(n, new.span), name)?
1678 .map(Self::Left)
1679 },
1680 (Self::Right(p), Self::Right(n)) => {
1681 R::merge_attrs(Spanning::new(p, prev.span), Spanning::new(n, new.span), name)?
1682 .map(Self::Right)
1683 },
1684 _ => return Err(syn::Error::new(
1685 new.span,
1686 format!("only single kind of `#[{name}(...)]` attribute is allowed here"),
1687 ))
1688 })
1689 }
1690 }
1691
1692 #[cfg(any(
1693 feature = "as_ref",
1694 feature = "from",
1695 feature = "into",
1696 feature = "try_from"
1697 ))]
1698 mod empty {
1699 use syn::{
1700 parse::{Parse, ParseStream},
1701 spanned::Spanned as _,
1702 };
1703
1704 use super::{ParseMultiple, Parser, Spanning};
1705
1706 #[derive(Clone, Copy, Debug)]
1712 pub(crate) struct Empty;
1713
1714 impl Parse for Empty {
1715 fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
1716 if input.is_empty() {
1717 Ok(Self)
1718 } else {
1719 Err(syn::Error::new(
1720 input.span(),
1721 "no attribute arguments allowed here",
1722 ))
1723 }
1724 }
1725 }
1726
1727 impl ParseMultiple for Empty {
1728 fn parse_attr_with<P: Parser>(
1729 attr: &syn::Attribute,
1730 _: &P,
1731 ) -> syn::Result<Self> {
1732 if matches!(attr.meta, syn::Meta::Path(_)) {
1733 Ok(Self)
1734 } else {
1735 Err(syn::Error::new(
1736 attr.span(),
1737 "no attribute arguments allowed here",
1738 ))
1739 }
1740 }
1741
1742 fn merge_attrs(
1743 _prev: Spanning<Self>,
1744 new: Spanning<Self>,
1745 name: &syn::Ident,
1746 ) -> syn::Result<Spanning<Self>> {
1747 Err(syn::Error::new(
1748 new.span,
1749 format!("only single `#[{name}]` attribute is allowed here"),
1750 ))
1751 }
1752 }
1753 }
1754
1755 #[cfg(any(
1756 feature = "as_ref",
1757 feature = "from",
1758 feature = "mul",
1759 feature = "mul_assign",
1760 ))]
1761 mod forward {
1762 use syn::{
1763 parse::{Parse, ParseStream},
1764 spanned::Spanned as _,
1765 };
1766
1767 use super::ParseMultiple;
1768
1769 #[derive(Clone, Copy, Debug)]
1775 pub(crate) struct Forward;
1776
1777 impl Parse for Forward {
1778 fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
1779 match input.parse::<syn::Path>()? {
1780 p if p.is_ident("forward") => Ok(Self),
1781 p => Err(syn::Error::new(p.span(), "only `forward` allowed here")),
1782 }
1783 }
1784 }
1785
1786 impl ParseMultiple for Forward {}
1787 }
1788
1789 #[cfg(feature = "try_from")]
1790 mod repr_int {
1791 use proc_macro2::Span;
1792 use syn::parse::{Parse, ParseStream};
1793
1794 use super::{ParseMultiple, Parser, Spanning};
1795
1796 #[derive(Default)]
1806 pub(crate) struct ReprInt(Option<syn::Ident>);
1807
1808 impl ReprInt {
1809 pub(crate) fn ty(&self) -> syn::Ident {
1818 self.0
1819 .as_ref()
1820 .cloned()
1821 .unwrap_or_else(|| syn::Ident::new("isize", Span::call_site()))
1822 }
1823 }
1824
1825 impl Parse for ReprInt {
1826 fn parse(_: ParseStream<'_>) -> syn::Result<Self> {
1827 unreachable!("call `attr::ParseMultiple::parse_attr_with()` instead")
1828 }
1829 }
1830
1831 impl ParseMultiple for ReprInt {
1832 fn parse_attr_with<P: Parser>(
1833 attr: &syn::Attribute,
1834 _: &P,
1835 ) -> syn::Result<Self> {
1836 let mut repr = None;
1837 attr.parse_nested_meta(|meta| {
1838 if let Some(ident) = meta.path.get_ident() {
1839 if matches!(
1840 ident.to_string().as_str(),
1841 "u8" | "u16"
1842 | "u32"
1843 | "u64"
1844 | "u128"
1845 | "usize"
1846 | "i8"
1847 | "i16"
1848 | "i32"
1849 | "i64"
1850 | "i128"
1851 | "isize"
1852 ) {
1853 repr = Some(ident.clone());
1854 return Ok(());
1855 }
1856 }
1857 _ = meta.input.parse::<proc_macro2::Group>();
1859 Ok(())
1860 })?;
1861 Ok(Self(repr))
1862 }
1863
1864 fn merge_attrs(
1865 prev: Spanning<Self>,
1866 new: Spanning<Self>,
1867 name: &syn::Ident,
1868 ) -> syn::Result<Spanning<Self>> {
1869 match (&prev.item.0, &new.item.0) {
1870 (Some(_), None) | (None, None) => Ok(prev),
1871 (None, Some(_)) => Ok(new),
1872 (Some(_), Some(_)) => Err(syn::Error::new(
1873 new.span,
1874 format!(
1875 "only single `#[{name}(u/i*)]` attribute is expected here",
1876 ),
1877 )),
1878 }
1879 }
1880 }
1881 }
1882
1883 #[cfg(any(
1884 feature = "add",
1885 feature = "add_assign",
1886 feature = "as_ref",
1887 feature = "debug",
1888 feature = "display",
1889 feature = "eq",
1890 feature = "from",
1891 feature = "into",
1892 feature = "mul",
1893 feature = "mul_assign",
1894 ))]
1895 mod skip {
1896 use syn::{
1897 parse::{Parse, ParseStream},
1898 spanned::Spanned as _,
1899 };
1900
1901 use super::{ParseMultiple, Spanning};
1902
1903 #[derive(Clone, Copy, Debug)]
1910 pub(crate) struct Skip(&'static str);
1911
1912 impl Parse for Skip {
1913 fn parse(content: ParseStream<'_>) -> syn::Result<Self> {
1914 match content.parse::<syn::Path>()? {
1915 p if p.is_ident("skip") => Ok(Self("skip")),
1916 p if p.is_ident("ignore") => Ok(Self("ignore")),
1917 p => Err(syn::Error::new(
1918 p.span(),
1919 "only `skip`/`ignore` allowed here",
1920 )),
1921 }
1922 }
1923 }
1924
1925 impl Skip {
1926 pub(crate) const fn name(&self) -> &'static str {
1928 self.0
1929 }
1930 }
1931
1932 impl ParseMultiple for Skip {
1933 fn merge_attrs(
1934 _: Spanning<Self>,
1935 new: Spanning<Self>,
1936 name: &syn::Ident,
1937 ) -> syn::Result<Spanning<Self>> {
1938 Err(syn::Error::new(
1939 new.span,
1940 format!(
1941 "only single `#[{name}(skip)]`/`#[{name}(ignore)]` attribute is allowed \
1942 here",
1943 ),
1944 ))
1945 }
1946 }
1947 }
1948
1949 #[cfg(any(feature = "as_ref", feature = "from", feature = "try_from"))]
1950 mod types {
1951 use syn::{
1952 parse::{Parse, ParseStream},
1953 punctuated::Punctuated,
1954 Token,
1955 };
1956
1957 use super::{ParseMultiple, Spanning};
1958
1959 pub(crate) struct Types(pub(crate) Punctuated<syn::Type, Token![,]>);
1965
1966 impl Parse for Types {
1967 fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
1968 input
1969 .parse_terminated(syn::Type::parse, Token![,])
1970 .map(Self)
1971 }
1972 }
1973
1974 impl ParseMultiple for Types {
1975 fn merge_attrs(
1976 mut prev: Spanning<Self>,
1977 new: Spanning<Self>,
1978 _: &syn::Ident,
1979 ) -> syn::Result<Spanning<Self>> {
1980 prev.item.0.extend(new.item.0);
1981 Ok(Spanning::new(
1982 prev.item,
1983 prev.span.join(new.span).unwrap_or(prev.span),
1984 ))
1985 }
1986 }
1987 }
1988
1989 #[cfg(any(feature = "as_ref", feature = "from"))]
1990 mod conversion {
1991 use syn::parse::{Parse, ParseStream};
1992
1993 use crate::utils::attr;
1994
1995 use super::{Either, ParseMultiple, Spanning};
1996
1997 type Untyped = Either<attr::Forward, attr::Types>;
2001
2002 pub(crate) enum Conversion {
2010 Forward(attr::Forward),
2011 Types(attr::Types),
2012 }
2013
2014 impl From<Untyped> for Conversion {
2015 fn from(v: Untyped) -> Self {
2016 match v {
2017 Untyped::Left(f) => Self::Forward(f),
2018 Untyped::Right(t) => Self::Types(t),
2019 }
2020 }
2021 }
2022 impl From<Conversion> for Untyped {
2023 fn from(v: Conversion) -> Self {
2024 match v {
2025 Conversion::Forward(f) => Self::Left(f),
2026 Conversion::Types(t) => Self::Right(t),
2027 }
2028 }
2029 }
2030
2031 impl Parse for Conversion {
2032 fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
2033 Untyped::parse(input).map(Self::from)
2034 }
2035 }
2036
2037 impl ParseMultiple for Conversion {
2038 fn parse_attr_with<P: attr::Parser>(
2039 attr: &syn::Attribute,
2040 parser: &P,
2041 ) -> syn::Result<Self> {
2042 Untyped::parse_attr_with(attr, parser).map(Self::from)
2043 }
2044
2045 fn merge_attrs(
2046 prev: Spanning<Self>,
2047 new: Spanning<Self>,
2048 name: &syn::Ident,
2049 ) -> syn::Result<Spanning<Self>> {
2050 Untyped::merge_attrs(prev.map(Into::into), new.map(Into::into), name)
2051 .map(|v| v.map(Self::from))
2052 }
2053 }
2054 }
2055
2056 #[cfg(any(feature = "as_ref", feature = "from"))]
2057 mod field_conversion {
2058 use syn::parse::{Parse, ParseStream};
2059
2060 use crate::utils::attr;
2061
2062 use super::{Either, ParseMultiple, Spanning};
2063
2064 type Untyped =
2068 Either<attr::Empty, Either<attr::Skip, Either<attr::Forward, attr::Types>>>;
2069
2070 pub(crate) enum FieldConversion {
2080 Empty(attr::Empty),
2081 Skip(attr::Skip),
2082 Forward(attr::Forward),
2083 Types(attr::Types),
2084 }
2085
2086 impl From<Untyped> for FieldConversion {
2087 fn from(v: Untyped) -> Self {
2088 match v {
2089 Untyped::Left(e) => Self::Empty(e),
2090 Untyped::Right(Either::Left(s)) => Self::Skip(s),
2091 Untyped::Right(Either::Right(Either::Left(f))) => Self::Forward(f),
2092 Untyped::Right(Either::Right(Either::Right(t))) => Self::Types(t),
2093 }
2094 }
2095 }
2096
2097 impl From<FieldConversion> for Untyped {
2098 fn from(v: FieldConversion) -> Self {
2099 match v {
2100 FieldConversion::Empty(e) => Self::Left(e),
2101 FieldConversion::Skip(s) => Self::Right(Either::Left(s)),
2102 FieldConversion::Forward(f) => {
2103 Self::Right(Either::Right(Either::Left(f)))
2104 }
2105 FieldConversion::Types(t) => {
2106 Self::Right(Either::Right(Either::Right(t)))
2107 }
2108 }
2109 }
2110 }
2111
2112 impl From<attr::Conversion> for FieldConversion {
2113 fn from(v: attr::Conversion) -> Self {
2114 match v {
2115 attr::Conversion::Forward(f) => Self::Forward(f),
2116 attr::Conversion::Types(t) => Self::Types(t),
2117 }
2118 }
2119 }
2120
2121 impl From<FieldConversion> for Option<attr::Conversion> {
2122 fn from(v: FieldConversion) -> Self {
2123 match v {
2124 FieldConversion::Forward(f) => Some(attr::Conversion::Forward(f)),
2125 FieldConversion::Types(t) => Some(attr::Conversion::Types(t)),
2126 FieldConversion::Empty(_) | FieldConversion::Skip(_) => None,
2127 }
2128 }
2129 }
2130
2131 impl Parse for FieldConversion {
2132 fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
2133 Untyped::parse(input).map(Self::from)
2134 }
2135 }
2136
2137 impl ParseMultiple for FieldConversion {
2138 fn parse_attr_with<P: attr::Parser>(
2139 attr: &syn::Attribute,
2140 parser: &P,
2141 ) -> syn::Result<Self> {
2142 Untyped::parse_attr_with(attr, parser).map(Self::from)
2143 }
2144
2145 fn merge_attrs(
2146 prev: Spanning<Self>,
2147 new: Spanning<Self>,
2148 name: &syn::Ident,
2149 ) -> syn::Result<Spanning<Self>> {
2150 Untyped::merge_attrs(prev.map(Into::into), new.map(Into::into), name)
2151 .map(|v| v.map(Self::from))
2152 }
2153 }
2154 }
2155
2156 #[cfg(any(feature = "from_str", feature = "try_into"))]
2157 pub(crate) mod error {
2158 use syn::parse::{Parse, ParseStream};
2159
2160 use super::{Either, ParseMultiple};
2161
2162 pub(crate) struct Error {
2170 pub(crate) ty: syn::TypePath,
2172
2173 pub(crate) conv: Option<Conversion>,
2177 }
2178
2179 impl Parse for Error {
2180 fn parse(input: ParseStream) -> syn::Result<Self> {
2181 let prefix = syn::Ident::parse(input)?;
2182 if prefix != "error" {
2183 return Err(syn::Error::new(
2184 prefix.span(),
2185 "expected `error` argument here",
2186 ));
2187 }
2188
2189 let inner;
2190 syn::parenthesized!(inner in input);
2191
2192 let ty = syn::TypePath::parse(&inner)?;
2193 if inner.is_empty() {
2194 return Ok(Self { ty, conv: None });
2195 }
2196
2197 _ = syn::token::Comma::parse(&inner)?;
2198
2199 let conv = Conversion::parse(&inner)?;
2200 if inner.is_empty() {
2201 Ok(Self {
2202 ty,
2203 conv: Some(conv),
2204 })
2205 } else {
2206 Err(syn::Error::new(
2207 inner.span(),
2208 "no more arguments allowed here",
2209 ))
2210 }
2211 }
2212 }
2213
2214 impl ParseMultiple for Error {}
2215
2216 pub(crate) type Conversion =
2220 Either<syn::ExprCall, Either<syn::Path, syn::ExprClosure>>;
2221 }
2222
2223 #[cfg(feature = "try_from")]
2224 mod repr_conversion {
2225 use syn::parse::{Parse, ParseStream};
2226
2227 use crate::utils::attr;
2228
2229 use super::{ParseMultiple, Spanning};
2230
2231 pub(crate) enum ReprConversion {
2240 Discriminant(attr::Empty),
2241 Types(attr::Types),
2242 }
2243
2244 impl Parse for ReprConversion {
2245 fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
2246 let prefix = syn::Ident::parse(input)?;
2247 if prefix != "repr" {
2248 return Err(syn::Error::new(
2249 prefix.span(),
2250 "expected `repr` argument here",
2251 ));
2252 }
2253 if input.is_empty() {
2254 Ok(Self::Discriminant(attr::Empty))
2255 } else {
2256 let inner;
2257 syn::parenthesized!(inner in input);
2258 Ok(Self::Types(attr::Types::parse(&inner)?))
2259 }
2260 }
2261 }
2262
2263 impl ParseMultiple for ReprConversion {
2264 fn merge_attrs(
2265 prev: Spanning<Self>,
2266 new: Spanning<Self>,
2267 name: &syn::Ident,
2268 ) -> syn::Result<Spanning<Self>> {
2269 Ok(match (prev.item, new.item) {
2270 (Self::Discriminant(_), Self::Discriminant(_)) => {
2271 return Err(syn::Error::new(
2272 new.span,
2273 format!("only single `#[{name}(repr)]` attribute is allowed here"),
2274 ))
2275 },
2276 (Self::Types(p), Self::Types(n)) => {
2277 attr::Types::merge_attrs(
2278 Spanning::new(p, prev.span),
2279 Spanning::new(n, new.span),
2280 name,
2281 )?.map(Self::Types)
2282 },
2283 _ => return Err(syn::Error::new(
2284 new.span,
2285 format!(
2286 "only single kind of `#[{name}(repr(...))]` attribute is allowed here",
2287 ),
2288 ))
2289 })
2290 }
2291 }
2292 }
2293
2294 #[cfg(any(feature = "display", feature = "from_str"))]
2295 mod rename_all {
2296 use syn::{
2297 parse::{Parse, ParseStream},
2298 spanned::Spanned as _,
2299 token,
2300 };
2301
2302 use super::ParseMultiple;
2303
2304 #[derive(Clone, Copy, Debug)]
2320 pub(crate) enum RenameAll {
2321 Lower,
2322 Upper,
2323 Pascal,
2324 Camel,
2325 Snake,
2326 ScreamingSnake,
2327 Kebab,
2328 ScreamingKebab,
2329 }
2330
2331 impl RenameAll {
2332 pub(crate) fn convert_case(&self, name: &str) -> String {
2334 use convert_case::Casing as _;
2335
2336 let case = match self {
2337 Self::Lower => convert_case::Case::Flat,
2338 Self::Upper => convert_case::Case::UpperFlat,
2339 Self::Pascal => convert_case::Case::Pascal,
2340 Self::Camel => convert_case::Case::Camel,
2341 Self::Snake => convert_case::Case::Snake,
2342 Self::ScreamingSnake => convert_case::Case::UpperSnake,
2343 Self::Kebab => convert_case::Case::Kebab,
2344 Self::ScreamingKebab => convert_case::Case::UpperKebab,
2345 };
2346 name.to_case(case)
2347 }
2348 }
2349
2350 impl Parse for RenameAll {
2351 fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
2352 let _ = input.parse::<syn::Path>().and_then(|p| {
2353 if p.is_ident("rename_all") {
2354 Ok(p)
2355 } else {
2356 Err(syn::Error::new(
2357 p.span(),
2358 "unknown attribute argument, expected `rename_all = \"...\"`",
2359 ))
2360 }
2361 })?;
2362
2363 input.parse::<token::Eq>()?;
2364
2365 let lit: syn::LitStr = input.parse()?;
2366 Ok(
2367 match lit.value().replace(['-', '_'], "").to_lowercase().as_str() {
2368 "lowercase" => Self::Lower,
2369 "uppercase" => Self::Upper,
2370 "pascalcase" => Self::Pascal,
2371 "camelcase" => Self::Camel,
2372 "snakecase" => Self::Snake,
2373 "screamingsnakecase" => Self::ScreamingSnake,
2374 "kebabcase" => Self::Kebab,
2375 "screamingkebabcase" => Self::ScreamingKebab,
2376 _ => {
2377 return Err(syn::Error::new_spanned(
2378 lit,
2379 "unexpected casing expected one of: \
2380 \"lowercase\", \"UPPERCASE\", \"PascalCase\", \"camelCase\", \
2381 \"snake_case\", \"SCREAMING_SNAKE_CASE\", \"kebab-case\", or \
2382 \"SCREAMING-KEBAB-CASE\"",
2383 ))
2384 }
2385 },
2386 )
2387 }
2388 }
2389
2390 impl ParseMultiple for RenameAll {}
2391 }
2392}
2393
2394#[cfg(any(feature = "from", feature = "into"))]
2395mod fields_ext {
2396 use std::{cmp, iter};
2397
2398 use quote::ToTokens as _;
2399 use syn::{punctuated, spanned::Spanned as _};
2400
2401 use super::Either;
2402
2403 pub(crate) trait Len {
2405 fn len(&self) -> usize;
2407 }
2408
2409 impl Len for syn::Fields {
2410 fn len(&self) -> usize {
2411 self.len()
2412 }
2413 }
2414
2415 impl<T> Len for [T] {
2416 fn len(&self) -> usize {
2417 self.len()
2418 }
2419 }
2420
2421 pub(crate) trait FieldsExt: Len {
2423 fn validate_type<'t>(
2425 &self,
2426 ty: &'t syn::Type,
2427 ) -> syn::Result<
2428 Either<punctuated::Iter<'t, syn::Type>, iter::Once<&'t syn::Type>>,
2429 > {
2430 match ty {
2431 syn::Type::Tuple(syn::TypeTuple { elems, .. }) if self.len() > 1 => {
2432 match self.len().cmp(&elems.len()) {
2433 cmp::Ordering::Greater => {
2434 return Err(syn::Error::new(
2435 ty.span(),
2436 format!(
2437 "wrong tuple length: expected {}, found {}. \
2438 Consider adding {} more type{}: `({})`",
2439 self.len(),
2440 elems.len(),
2441 self.len() - elems.len(),
2442 if self.len() - elems.len() > 1 {
2443 "s"
2444 } else {
2445 ""
2446 },
2447 elems
2448 .iter()
2449 .map(|ty| ty.into_token_stream().to_string())
2450 .chain(
2451 (0..(self.len() - elems.len()))
2452 .map(|_| "_".to_string())
2453 )
2454 .collect::<Vec<_>>()
2455 .join(", "),
2456 ),
2457 ));
2458 }
2459 cmp::Ordering::Less => {
2460 return Err(syn::Error::new(
2461 ty.span(),
2462 format!(
2463 "wrong tuple length: expected {}, found {}. \
2464 Consider removing last {} type{}: `({})`",
2465 self.len(),
2466 elems.len(),
2467 elems.len() - self.len(),
2468 if elems.len() - self.len() > 1 {
2469 "s"
2470 } else {
2471 ""
2472 },
2473 elems
2474 .iter()
2475 .take(self.len())
2476 .map(|ty| ty.into_token_stream().to_string())
2477 .collect::<Vec<_>>()
2478 .join(", "),
2479 ),
2480 ));
2481 }
2482 cmp::Ordering::Equal => {}
2483 }
2484 }
2485 other if self.len() > 1 => {
2486 return Err(syn::Error::new(
2487 other.span(),
2488 format!(
2489 "expected tuple: `({}, {})`",
2490 other.into_token_stream(),
2491 (0..(self.len() - 1))
2492 .map(|_| "_")
2493 .collect::<Vec<_>>()
2494 .join(", "),
2495 ),
2496 ));
2497 }
2498 _ => {}
2499 }
2500 Ok(match ty {
2501 syn::Type::Tuple(syn::TypeTuple { elems, .. }) => {
2502 Either::Left(elems.iter())
2503 }
2504 other => Either::Right(iter::once(other)),
2505 })
2506 }
2507 }
2508
2509 impl<T: Len + ?Sized> FieldsExt for T {}
2510}
2511
2512#[cfg(any(
2513 feature = "add",
2514 feature = "add_assign",
2515 feature = "as_ref",
2516 feature = "eq",
2517 feature = "from_str",
2518 feature = "mul",
2519 feature = "mul_assign",
2520))]
2521mod generics_search {
2522 use syn::visit::Visit;
2523
2524 pub(crate) struct GenericsSearch<'s> {
2527 pub(crate) types: Vec<&'s syn::Ident>,
2529
2530 pub(crate) lifetimes: Vec<&'s syn::Ident>,
2532
2533 pub(crate) consts: Vec<&'s syn::Ident>,
2535 }
2536
2537 impl<'s> From<&'s syn::Generics> for GenericsSearch<'s> {
2538 fn from(value: &'s syn::Generics) -> Self {
2539 Self {
2540 types: value.type_params().map(|p| &p.ident).collect(),
2541 lifetimes: value.lifetimes().map(|p| &p.lifetime.ident).collect(),
2542 consts: value.const_params().map(|p| &p.ident).collect(),
2543 }
2544 }
2545 }
2546
2547 impl GenericsSearch<'_> {
2548 pub(crate) fn any_in(&self, ty: &syn::Type) -> bool {
2550 let mut visitor = Visitor {
2551 search: self,
2552 found: false,
2553 };
2554 visitor.visit_type(ty);
2555 visitor.found
2556 }
2557 }
2558
2559 struct Visitor<'s> {
2561 search: &'s GenericsSearch<'s>,
2563
2564 found: bool,
2566 }
2567
2568 impl<'ast> Visit<'ast> for Visitor<'_> {
2569 fn visit_expr_path(&mut self, ep: &'ast syn::ExprPath) {
2570 self.found |= ep
2571 .path
2572 .get_ident()
2573 .is_some_and(|ident| self.search.consts.contains(&ident));
2574
2575 if !self.found {
2576 syn::visit::visit_expr_path(self, ep);
2577 }
2578 }
2579
2580 fn visit_lifetime(&mut self, lf: &'ast syn::Lifetime) {
2581 self.found |= self.search.lifetimes.contains(&&lf.ident);
2582
2583 if !self.found {
2584 syn::visit::visit_lifetime(self, lf);
2585 }
2586 }
2587
2588 fn visit_type_path(&mut self, tp: &'ast syn::TypePath) {
2589 self.found |= tp.path.get_ident().is_some_and(|ident| {
2590 self.search.types.contains(&ident)
2591 || self.search.consts.contains(&ident)
2592 });
2593
2594 if !self.found {
2595 self.found |= tp.path.segments.first().is_some_and(|segment| {
2597 matches!(segment.arguments, syn::PathArguments::None)
2598 && self.search.types.contains(&&segment.ident)
2599 });
2600 }
2601
2602 if !self.found {
2603 syn::visit::visit_type_path(self, tp)
2604 }
2605 }
2606 }
2607
2608 #[cfg(test)]
2609 mod spec {
2610 use quote::ToTokens as _;
2611 use syn::parse_quote;
2612
2613 use super::GenericsSearch;
2614
2615 #[test]
2616 fn types() {
2617 let generics: syn::Generics = parse_quote! { <T> };
2618 let search = GenericsSearch::from(&generics);
2619
2620 for input in [
2621 parse_quote! { T },
2622 parse_quote! { &T },
2623 parse_quote! { &'a T },
2624 parse_quote! { &&'a T },
2625 parse_quote! { Type<'a, T> },
2626 parse_quote! { path::Type<T, 'a> },
2627 parse_quote! { path::<'a, T>::Type },
2628 parse_quote! { <Self as Trait<'a, T>>::Type },
2629 parse_quote! { <Self as Trait>::Type<T, 'a> },
2630 parse_quote! { T::Type },
2631 parse_quote! { <T as Trait>::Type },
2632 parse_quote! { [T] },
2633 parse_quote! { [T; 3] },
2634 parse_quote! { [T; _] },
2635 parse_quote! { (T) },
2636 parse_quote! { (T,) },
2637 parse_quote! { (T, u8) },
2638 parse_quote! { (u8, T) },
2639 parse_quote! { fn(T) },
2640 parse_quote! { fn(u8, T) },
2641 parse_quote! { fn(_) -> T },
2642 parse_quote! { fn(_) -> (u8, T) },
2643 ] {
2644 assert!(
2645 search.any_in(&input),
2646 "cannot find type parameter `T` in type `{}`",
2647 input.into_token_stream(),
2648 );
2649 }
2650 }
2651
2652 #[test]
2653 fn lifetimes() {
2654 let generics: syn::Generics = parse_quote! { <'a> };
2655 let search = GenericsSearch::from(&generics);
2656
2657 for input in [
2658 parse_quote! { &'a T },
2659 parse_quote! { &&'a T },
2660 parse_quote! { Type<'a> },
2661 parse_quote! { path::Type<'a> },
2662 parse_quote! { path::<'a>::Type },
2663 parse_quote! { <Self as Trait<'a>>::Type },
2664 parse_quote! { <Self as Trait>::Type<'a> },
2665 ] {
2666 assert!(
2667 search.any_in(&input),
2668 "cannot find lifetime parameter `'a` in type `{}`",
2669 input.into_token_stream(),
2670 );
2671 }
2672 }
2673
2674 #[test]
2675 fn consts() {
2676 let generics: syn::Generics = parse_quote! { <const N: usize> };
2677 let search = GenericsSearch::from(&generics);
2678
2679 for input in [
2680 parse_quote! { [_; N] },
2681 parse_quote! { Type<N> },
2682 #[cfg(feature = "testing-helpers")] parse_quote! { Type<{ N }> },
2684 parse_quote! { path::Type<N> },
2685 #[cfg(feature = "testing-helpers")] parse_quote! { path::Type<{ N }> },
2687 parse_quote! { path::<N>::Type },
2688 #[cfg(feature = "testing-helpers")] parse_quote! { path::<{ N }>::Type },
2690 parse_quote! { <Self as Trait<N>>::Type },
2691 #[cfg(feature = "testing-helpers")] parse_quote! { <Self as Trait<{ N }>>::Type },
2693 parse_quote! { <Self as Trait>::Type<N> },
2694 #[cfg(feature = "testing-helpers")] parse_quote! { <Self as Trait>::Type<{ N }> },
2696 ] {
2697 assert!(
2698 search.any_in(&input),
2699 "cannot find const parameter `N` in type `{}`",
2700 input.into_token_stream(),
2701 );
2702 }
2703 }
2704 }
2705}
2706
2707#[cfg(any(feature = "into", feature = "try_into"))]
2708pub(crate) mod replace_self {
2709 use syn::{parse_quote, visit_mut::VisitMut};
2710
2711 pub(crate) trait DeriveInputExt {
2713 fn replace_self_type(&self) -> Self;
2715 }
2716
2717 impl DeriveInputExt for syn::DeriveInput {
2718 fn replace_self_type(&self) -> Self {
2719 let mut input = self.clone();
2720 Visitor::new(&input).visit_derive_input_mut(&mut input);
2721 input
2722 }
2723 }
2724
2725 struct Visitor {
2730 self_ty: syn::PathSegment,
2732 }
2733
2734 impl Visitor {
2735 fn new(input: &syn::DeriveInput) -> Self {
2737 let ident = &input.ident;
2738 let (_, ty_generics, _) = input.generics.split_for_impl();
2739 Self {
2740 self_ty: parse_quote! { #ident #ty_generics },
2741 }
2742 }
2743 }
2744
2745 impl VisitMut for Visitor {
2746 fn visit_derive_input_mut(&mut self, i: &mut syn::DeriveInput) {
2747 self.visit_generics_mut(&mut i.generics);
2748 self.visit_data_mut(&mut i.data);
2749 }
2750
2751 fn visit_field_mut(&mut self, i: &mut syn::Field) {
2752 self.visit_type_mut(&mut i.ty);
2753 }
2754
2755 fn visit_path_segment_mut(&mut self, i: &mut syn::PathSegment) {
2756 if i.ident == "Self" {
2757 *i = self.self_ty.clone();
2758 } else {
2759 self.visit_path_arguments_mut(&mut i.arguments);
2760 }
2761 }
2762
2763 fn visit_variant_mut(&mut self, i: &mut syn::Variant) {
2764 self.visit_fields_mut(&mut i.fields);
2765 }
2766 }
2767
2768 #[cfg(test)]
2769 mod spec {
2770 use syn::{parse_quote, DeriveInput};
2771
2772 use super::DeriveInputExt as _;
2773
2774 #[test]
2775 fn replaces_generics() {
2776 let input: DeriveInput = parse_quote! {
2777 struct Foo<T, U: Sub<Self>>
2778 where
2779 U: Add<Self>,
2780 Self: X,
2781 <U as Add<Self>>::Output: X,
2782 T: IntoIterator<Item = Self>,
2783 [Self; 5]: SomeTrait,
2784 <Self as OtherTrait>::Type: Copy;
2785 };
2786
2787 let actual = input.replace_self_type();
2788
2789 let expected: DeriveInput = parse_quote! {
2790 struct Foo<T, U: Sub<Foo<T, U>>>
2791 where
2792 U: Add<Foo<T, U>>,
2793 Foo<T, U>: X,
2794 <U as Add<Foo<T, U>>>::Output: X,
2795 T: IntoIterator<Item = Foo<T, U>>,
2796 [Foo<T, U>; 5]: SomeTrait,
2797 <Foo<T, U> as OtherTrait>::Type: Copy;
2798 };
2799
2800 assert_eq!(actual, expected);
2801 }
2802
2803 #[test]
2804 fn replaces_struct_named_fields() {
2805 let input: DeriveInput = parse_quote! {
2806 struct Foo {
2807 a: AddType<Self>,
2808 b: <Self as OtherTrait>::Type,
2809 }
2810 };
2811
2812 let actual = input.replace_self_type();
2813
2814 let expected: DeriveInput = parse_quote! {
2815 struct Foo {
2816 a: AddType<Foo>,
2817 b: <Foo as OtherTrait>::Type,
2818 }
2819 };
2820
2821 assert_eq!(actual, expected);
2822 }
2823
2824 #[test]
2825 fn replaces_struct_unnamed_fields() {
2826 let input: DeriveInput = parse_quote! {
2827 struct Bar([Self; 5], <Foo as Add<Self>>::Output);
2828 };
2829
2830 let actual = input.replace_self_type();
2831
2832 let expected: DeriveInput = parse_quote! {
2833 struct Bar([Bar; 5], <Foo as Add<Bar>>::Output);
2834 };
2835
2836 assert_eq!(actual, expected);
2837 }
2838
2839 #[test]
2840 fn replaces_enum_fields() {
2841 let input: DeriveInput = parse_quote! {
2842 enum E {
2843 Foo {
2844 a: AddType<Self>,
2845 b: <Self as OtherTrait>::Type,
2846 },
2847 Bar([Self; 5], <Foo as Add<Self>>::Output),
2848 }
2849 };
2850
2851 let actual = input.replace_self_type();
2852
2853 let expected: DeriveInput = parse_quote! {
2854 enum E {
2855 Foo {
2856 a: AddType<E>,
2857 b: <E as OtherTrait>::Type,
2858 },
2859 Bar([E; 5], <Foo as Add<E>>::Output),
2860 }
2861 };
2862
2863 assert_eq!(actual, expected);
2864 }
2865 }
2866}
2867
2868#[cfg(any(
2869 feature = "add",
2870 feature = "add_assign",
2871 feature = "eq",
2872 feature = "mul",
2873 feature = "mul_assign",
2874))]
2875pub(crate) mod structural_inclusion {
2876 pub(crate) trait TypeExt {
2881 fn contains_type_structurally(&self, needle: &syn::Type) -> bool;
2890 }
2891
2892 impl TypeExt for syn::Type {
2893 fn contains_type_structurally(&self, needle: &Self) -> bool {
2894 if self == needle {
2895 return true;
2896 }
2897 match self {
2898 syn::Type::Array(syn::TypeArray { elem, .. })
2899 | syn::Type::Group(syn::TypeGroup { elem, .. })
2900 | syn::Type::Paren(syn::TypeParen { elem, .. })
2901 | syn::Type::Ptr(syn::TypePtr { elem, .. })
2902 | syn::Type::Reference(syn::TypeReference { elem, .. })
2903 | syn::Type::Slice(syn::TypeSlice { elem, .. }) => {
2904 elem.contains_type_structurally(needle)
2905 }
2906 syn::Type::Tuple(syn::TypeTuple { elems, .. }) => {
2907 elems.iter().any(|elem| elem.contains_type_structurally(needle))
2908 }
2909 syn::Type::Path(syn::TypePath { path, .. }) => path
2910 .segments
2911 .iter()
2912 .filter_map(|seg| {
2913 if let syn::PathArguments::AngleBracketed(args) = &seg.arguments {
2914 Some(&args.args)
2915 } else {
2916 None
2917 }
2918 })
2919 .flatten()
2920 .any(|generic_arg| {
2921 matches!(
2922 generic_arg,
2923 syn::GenericArgument::Type(ty) if ty.contains_type_structurally(needle),
2924 )
2925 }),
2926 syn::Type::BareFn(_)
2927 | syn::Type::ImplTrait(_)
2928 | syn::Type::Infer(_)
2929 | syn::Type::Macro(_)
2930 | syn::Type::Never(_)
2931 | syn::Type::TraitObject(_)
2932 | syn::Type::Verbatim(_) => false,
2933 _ => unimplemented!(
2934 "syntax is not supported by `derive_more`, please report a bug",
2935 ),
2936 }
2937 }
2938 }
2939
2940 #[cfg(test)]
2941 mod type_ext_spec {
2942 use quote::ToTokens as _;
2943 use syn::parse_quote;
2944
2945 use super::TypeExt as _;
2946
2947 #[test]
2948 fn contains() {
2949 for (input, container) in [
2950 (parse_quote! { Self }, parse_quote! { Self }),
2951 (parse_quote! { Self }, parse_quote! { (Self) }),
2952 (parse_quote! { Self }, parse_quote! { (Self,) }),
2953 (parse_quote! { Self }, parse_quote! { (Self, Foo) }),
2954 (
2955 parse_quote! { Self },
2956 parse_quote! { (Foo, Bar, Baz, Self) },
2957 ),
2958 (parse_quote! { Self }, parse_quote! { [Self] }),
2959 (parse_quote! { Self }, parse_quote! { [Self; N] }),
2960 (parse_quote! { Self }, parse_quote! { *const Self }),
2961 (parse_quote! { Self }, parse_quote! { *mut Self }),
2962 (parse_quote! { Self }, parse_quote! { &'a Self }),
2963 (parse_quote! { Self }, parse_quote! { &'a mut Self }),
2964 (parse_quote! { Self }, parse_quote! { Box<Self> }),
2965 (parse_quote! { Self }, parse_quote! { PhantomData<Self> }),
2966 (parse_quote! { Self }, parse_quote! { Arc<Mutex<Self>> }),
2967 (
2968 parse_quote! { Self },
2969 parse_quote! { [*const (&'a [Arc<Mutex<Self>>],); 0] },
2970 ),
2971 ] {
2972 let container: syn::Type = container; assert!(
2974 container.contains_type_structurally(&input),
2975 "cannot find type `{}` in type `{}`",
2976 input.into_token_stream(),
2977 container.into_token_stream(),
2978 );
2979 }
2980 }
2981
2982 #[test]
2983 fn not_contains() {
2984 for (input, container) in [
2985 (parse_quote! { Self }, parse_quote! { Foo }),
2986 (parse_quote! { Self }, parse_quote! { (Foo) }),
2987 (parse_quote! { Self }, parse_quote! { (Foo,) }),
2988 (parse_quote! { Self }, parse_quote! { (Foo, Bar, Baz) }),
2989 (parse_quote! { Self }, parse_quote! { [Foo] }),
2990 (parse_quote! { Self }, parse_quote! { [Foo; N] }),
2991 (parse_quote! { Self }, parse_quote! { *const Foo }),
2992 (parse_quote! { Self }, parse_quote! { *mut Foo }),
2993 (parse_quote! { Self }, parse_quote! { &'a Foo }),
2994 (parse_quote! { Self }, parse_quote! { &'a mut Foo }),
2995 (parse_quote! { Self }, parse_quote! { Box<Foo> }),
2996 (parse_quote! { Self }, parse_quote! { PhantomData<Foo> }),
2997 (parse_quote! { Self }, parse_quote! { Arc<Mutex<Foo>> }),
2998 (
2999 parse_quote! { Self },
3000 parse_quote! { [*const (&'a [Arc<Mutex<Foo>>],); 0] },
3001 ),
3002 (parse_quote! { Self }, parse_quote! { fn(Self) -> Foo }),
3003 (parse_quote! { Self }, parse_quote! { fn(Foo) -> Self }),
3004 (parse_quote! { Self }, parse_quote! { impl Foo<Self> }),
3005 (
3006 parse_quote! { Self },
3007 parse_quote! { impl Foo<Type = Self> },
3008 ),
3009 (parse_quote! { Self }, parse_quote! { dyn Foo<Self> }),
3010 (
3011 parse_quote! { Self },
3012 parse_quote! { dyn Sync + Foo<Type = Self> },
3013 ),
3014 ] {
3015 let container: syn::Type = container; assert!(
3017 !container.contains_type_structurally(&input),
3018 "found type `{}` in type `{}`",
3019 input.into_token_stream(),
3020 container.into_token_stream(),
3021 );
3022 }
3023 }
3024 }
3025}
3026
3027#[cfg(any(
3028 feature = "add",
3029 feature = "add_assign",
3030 feature = "eq",
3031 feature = "mul",
3032 feature = "mul_assign",
3033))]
3034pub(crate) mod pattern_matching {
3035 use proc_macro2::TokenStream;
3038 use quote::{format_ident, quote};
3039
3040 #[cfg(any(feature = "add_assign", feature = "eq", feature = "mul_assign"))]
3041 use crate::utils::HashSet;
3042
3043 pub(crate) trait FieldsExt {
3045 #[cfg(any(feature = "add_assign", feature = "eq", feature = "mul_assign"))]
3046 fn non_exhaustive_arm_pattern(
3051 &self,
3052 prefix: &str,
3053 skipped_indices: &HashSet<usize>,
3054 ) -> TokenStream;
3055
3056 #[cfg(any(feature = "add", feature = "mul"))]
3057 fn exhaustive_arm_pattern(&self, prefix: &str) -> TokenStream;
3062 }
3063
3064 impl FieldsExt for syn::Fields {
3065 #[cfg(any(feature = "add_assign", feature = "eq", feature = "mul_assign"))]
3066 fn non_exhaustive_arm_pattern(
3067 &self,
3068 prefix: &str,
3069 skipped_indices: &HashSet<usize>,
3070 ) -> TokenStream {
3071 match self {
3072 Self::Named(fields) => {
3073 let fields = fields
3074 .named
3075 .iter()
3076 .enumerate()
3077 .filter(|(num, _)| !skipped_indices.contains(num))
3078 .map(|(num, field)| {
3079 let name = &field.ident;
3080 let binding = format_ident!("{prefix}{num}");
3081 quote! { #name: #binding }
3082 });
3083 let wildcard =
3084 (!skipped_indices.is_empty()).then(syn::token::DotDot::default);
3085 quote! {{ #( #fields , )* #wildcard }}
3086 }
3087 Self::Unnamed(fields) => {
3088 let fields = (0..fields.unnamed.len()).map(|num| {
3089 if skipped_indices.contains(&num) {
3090 quote! { _ }
3091 } else {
3092 let binding = format_ident!("{prefix}{num}");
3093 quote! { #binding }
3094 }
3095 });
3096 quote! {( #( #fields , )* )}
3097 }
3098 Self::Unit => quote! {},
3099 }
3100 }
3101
3102 #[cfg(any(feature = "add", feature = "mul"))]
3103 fn exhaustive_arm_pattern(&self, prefix: &str) -> TokenStream {
3104 match self {
3105 Self::Named(fields) => {
3106 let fields = fields.named.iter().enumerate().map(|(num, field)| {
3107 let name = &field.ident;
3108 let binding = format_ident!("{prefix}{num}");
3109 quote! { #name: #binding }
3110 });
3111 quote! {{ #( #fields , )* }}
3112 }
3113 Self::Unnamed(fields) => {
3114 let fields = (0..fields.unnamed.len())
3115 .map(|num| format_ident!("{prefix}{num}"));
3116 quote! {( #( #fields , )* )}
3117 }
3118 Self::Unit => quote! {},
3119 }
3120 }
3121 }
3122}