1#![cfg_attr(not(feature = "default"), allow(dead_code), allow(unused_mut))]
2
3use crate::syn_compat::{AttributeExt as _, NestedMeta, ParsedMeta};
4use proc_macro2::{Span, TokenStream};
5use quote::{quote, ToTokens};
6use syn::{
7 parse_quote, punctuated::Punctuated, spanned::Spanned, Attribute, Data,
8 DeriveInput, Error, Field, Fields, FieldsNamed, FieldsUnnamed, GenericParam,
9 Generics, Ident, ImplGenerics, Index, Result, Token, Type, TypeGenerics,
10 TypeParamBound, Variant, WhereClause,
11};
12
13#[derive(Clone, Copy, Default)]
14pub struct DeterministicState;
15
16impl std::hash::BuildHasher for DeterministicState {
17 type Hasher = std::collections::hash_map::DefaultHasher;
18
19 fn build_hasher(&self) -> Self::Hasher {
20 Self::Hasher::default()
21 }
22}
23
24pub type HashMap<K, V> = std::collections::HashMap<K, V, DeterministicState>;
25pub type HashSet<K> = std::collections::HashSet<K, DeterministicState>;
26
27#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
28pub enum RefType {
29 No,
30 Ref,
31 Mut,
32}
33
34impl RefType {
35 pub fn lifetime(self) -> TokenStream {
36 match self {
37 RefType::No => quote!(),
38 _ => quote!('__deriveMoreLifetime),
39 }
40 }
41
42 pub fn reference(self) -> TokenStream {
43 match self {
44 RefType::No => quote!(),
45 RefType::Ref => quote!(&),
46 RefType::Mut => quote!(&mut),
47 }
48 }
49
50 pub fn mutability(self) -> TokenStream {
51 match self {
52 RefType::Mut => quote!(mut),
53 _ => quote!(),
54 }
55 }
56
57 pub fn pattern_ref(self) -> TokenStream {
58 match self {
59 RefType::Ref => quote!(ref),
60 RefType::Mut => quote!(ref mut),
61 RefType::No => quote!(),
62 }
63 }
64
65 pub fn reference_with_lifetime(self) -> TokenStream {
66 if !self.is_ref() {
67 return quote!();
68 }
69 let lifetime = self.lifetime();
70 let mutability = self.mutability();
71 quote!(&#lifetime #mutability)
72 }
73
74 pub fn is_ref(self) -> bool {
75 match self {
76 RefType::No => false,
77 _ => true,
78 }
79 }
80
81 pub fn from_attr_name(name: &str) -> Self {
82 match name {
83 "owned" => RefType::No,
84 "ref" => RefType::Ref,
85 "ref_mut" => RefType::Mut,
86 _ => panic!("'{}' is not a RefType", name),
87 }
88 }
89}
90
91pub fn numbered_vars(count: usize, prefix: &str) -> Vec<Ident> {
92 (0..count)
93 .map(|i| Ident::new(&format!("__{}{}", prefix, i), Span::call_site()))
94 .collect()
95}
96
97pub fn field_idents<'a>(fields: &'a [&'a Field]) -> Vec<&'a Ident> {
98 fields
99 .iter()
100 .map(|f| {
101 f.ident
102 .as_ref()
103 .expect("Tried to get field names of a tuple struct")
104 })
105 .collect()
106}
107
108pub fn get_field_types_iter<'a>(
109 fields: &'a [&'a Field],
110) -> Box<dyn Iterator<Item = &'a Type> + 'a> {
111 Box::new(fields.iter().map(|f| &f.ty))
112}
113
114pub fn get_field_types<'a>(fields: &'a [&'a Field]) -> Vec<&'a Type> {
115 get_field_types_iter(fields).collect()
116}
117
118pub fn add_extra_type_param_bound_op_output<'a>(
119 generics: &'a Generics,
120 trait_ident: &'a Ident,
121) -> Generics {
122 let mut generics = generics.clone();
123 for type_param in &mut generics.type_params_mut() {
124 let type_ident = &type_param.ident;
125 let bound: TypeParamBound = parse_quote! {
126 ::core::ops::#trait_ident<Output=#type_ident>
127 };
128 type_param.bounds.push(bound)
129 }
130
131 generics
132}
133
134pub fn add_extra_ty_param_bound_op<'a>(
135 generics: &'a Generics,
136 trait_ident: &'a Ident,
137) -> Generics {
138 add_extra_ty_param_bound(generics, "e!(::core::ops::#trait_ident))
139}
140
141pub fn add_extra_ty_param_bound<'a>(
142 generics: &'a Generics,
143 bound: &'a TokenStream,
144) -> Generics {
145 let mut generics = generics.clone();
146 let bound: TypeParamBound = parse_quote! { #bound };
147 for type_param in &mut generics.type_params_mut() {
148 type_param.bounds.push(bound.clone())
149 }
150
151 generics
152}
153
154pub fn add_extra_ty_param_bound_ref<'a>(
155 generics: &'a Generics,
156 bound: &'a TokenStream,
157 ref_type: RefType,
158) -> Generics {
159 match ref_type {
160 RefType::No => add_extra_ty_param_bound(generics, bound),
161 _ => {
162 let generics = generics.clone();
163 let idents = generics.type_params().map(|x| &x.ident);
164 let ref_with_lifetime = ref_type.reference_with_lifetime();
165 add_extra_where_clauses(
166 &generics,
167 quote!(
168 where #(#ref_with_lifetime #idents: #bound),*
169 ),
170 )
171 }
172 }
173}
174
175pub fn add_extra_generic_param(
176 generics: &Generics,
177 generic_param: TokenStream,
178) -> Generics {
179 let generic_param: GenericParam = parse_quote! { #generic_param };
180 let mut generics = generics.clone();
181 generics.params.push(generic_param);
182
183 generics
184}
185
186pub fn add_extra_generic_type_param(
187 generics: &Generics,
188 generic_param: TokenStream,
189) -> Generics {
190 let generic_param: GenericParam = parse_quote! { #generic_param };
191 let lifetimes: Vec<GenericParam> =
192 generics.lifetimes().map(|x| x.clone().into()).collect();
193 let type_params: Vec<GenericParam> =
194 generics.type_params().map(|x| x.clone().into()).collect();
195 let const_params: Vec<GenericParam> =
196 generics.const_params().map(|x| x.clone().into()).collect();
197 let mut generics = generics.clone();
198 generics.params = Default::default();
199 generics.params.extend(lifetimes);
200 generics.params.extend(type_params);
201 generics.params.push(generic_param);
202 generics.params.extend(const_params);
203
204 generics
205}
206
207pub fn add_extra_where_clauses(
208 generics: &Generics,
209 type_where_clauses: TokenStream,
210) -> Generics {
211 let mut type_where_clauses: WhereClause = parse_quote! { #type_where_clauses };
212 let mut new_generics = generics.clone();
213 if let Some(old_where) = new_generics.where_clause {
214 type_where_clauses.predicates.extend(old_where.predicates)
215 }
216 new_generics.where_clause = Some(type_where_clauses);
217
218 new_generics
219}
220
221pub fn add_where_clauses_for_new_ident<'a>(
222 generics: &'a Generics,
223 fields: &[&'a Field],
224 type_ident: &Ident,
225 type_where_clauses: TokenStream,
226 sized: bool,
227) -> Generics {
228 let generic_param = if fields.len() > 1 {
229 quote!(#type_ident: ::core::marker::Copy)
230 } else if sized {
231 quote!(#type_ident)
232 } else {
233 quote!(#type_ident: ?::core::marker::Sized)
234 };
235
236 let generics = add_extra_where_clauses(generics, type_where_clauses);
237 add_extra_generic_type_param(&generics, generic_param)
238}
239
240pub fn unnamed_to_vec(fields: &FieldsUnnamed) -> Vec<&Field> {
241 fields.unnamed.iter().collect()
242}
243
244pub fn named_to_vec(fields: &FieldsNamed) -> Vec<&Field> {
245 fields.named.iter().collect()
246}
247
248fn panic_one_field(trait_name: &str, trait_attr: &str) -> ! {
249 panic!(
250 "derive({}) only works when forwarding to a single field. Try putting #[{}] or #[{}(ignore)] on the fields in the struct",
251 trait_name, trait_attr, trait_attr,
252 )
253}
254
255#[derive(Copy, Clone, Debug, PartialEq, Eq)]
256pub enum DeriveType {
257 Unnamed,
258 Named,
259 Enum,
260}
261
262pub struct State<'input> {
263 pub input: &'input DeriveInput,
264 pub trait_name: &'static str,
265 pub method_ident: Ident,
266 pub trait_module: TokenStream,
267 pub trait_path: TokenStream,
268 pub trait_path_params: Vec<TokenStream>,
269 pub trait_attr: String,
270 pub derive_type: DeriveType,
271 pub fields: Vec<&'input Field>,
272 pub variants: Vec<&'input Variant>,
273 pub variant_states: Vec<State<'input>>,
274 pub variant: Option<&'input Variant>,
275 pub generics: Generics,
276 pub default_info: FullMetaInfo,
277 full_meta_infos: Vec<FullMetaInfo>,
278}
279
280#[derive(Default, Clone)]
281pub struct AttrParams {
282 pub enum_: Vec<&'static str>,
283 pub variant: Vec<&'static str>,
284 pub struct_: Vec<&'static str>,
285 pub field: Vec<&'static str>,
286}
287
288impl AttrParams {
289 pub fn new(params: Vec<&'static str>) -> AttrParams {
290 AttrParams {
291 enum_: params.clone(),
292 struct_: params.clone(),
293 variant: params.clone(),
294 field: params,
295 }
296 }
297 pub fn struct_(params: Vec<&'static str>) -> AttrParams {
298 AttrParams {
299 enum_: vec![],
300 struct_: params,
301 variant: vec![],
302 field: vec![],
303 }
304 }
305
306 pub fn ignore_and_forward() -> AttrParams {
307 AttrParams::new(vec!["ignore", "forward"])
308 }
309}
310
311impl<'input> State<'input> {
312 pub fn new<'arg_input>(
313 input: &'arg_input DeriveInput,
314 trait_name: &'static str,
315 trait_module: TokenStream,
316 trait_attr: String,
317 ) -> Result<State<'arg_input>> {
318 State::new_impl(
319 input,
320 trait_name,
321 trait_module,
322 trait_attr,
323 AttrParams::default(),
324 true,
325 )
326 }
327
328 pub fn with_field_ignore<'arg_input>(
329 input: &'arg_input DeriveInput,
330 trait_name: &'static str,
331 trait_module: TokenStream,
332 trait_attr: String,
333 ) -> Result<State<'arg_input>> {
334 State::new_impl(
335 input,
336 trait_name,
337 trait_module,
338 trait_attr,
339 AttrParams::new(vec!["ignore"]),
340 true,
341 )
342 }
343
344 pub fn with_field_ignore_and_forward<'arg_input>(
345 input: &'arg_input DeriveInput,
346 trait_name: &'static str,
347 trait_module: TokenStream,
348 trait_attr: String,
349 ) -> Result<State<'arg_input>> {
350 State::new_impl(
351 input,
352 trait_name,
353 trait_module,
354 trait_attr,
355 AttrParams::new(vec!["ignore", "forward"]),
356 true,
357 )
358 }
359
360 pub fn with_field_ignore_and_refs<'arg_input>(
361 input: &'arg_input DeriveInput,
362 trait_name: &'static str,
363 trait_module: TokenStream,
364 trait_attr: String,
365 ) -> Result<State<'arg_input>> {
366 State::new_impl(
367 input,
368 trait_name,
369 trait_module,
370 trait_attr,
371 AttrParams::new(vec!["ignore", "owned", "ref", "ref_mut"]),
372 true,
373 )
374 }
375
376 pub fn with_attr_params<'arg_input>(
377 input: &'arg_input DeriveInput,
378 trait_name: &'static str,
379 trait_module: TokenStream,
380 trait_attr: String,
381 allowed_attr_params: AttrParams,
382 ) -> Result<State<'arg_input>> {
383 State::new_impl(
384 input,
385 trait_name,
386 trait_module,
387 trait_attr,
388 allowed_attr_params,
389 true,
390 )
391 }
392
393 pub fn with_type_bound<'arg_input>(
394 input: &'arg_input DeriveInput,
395 trait_name: &'static str,
396 trait_module: TokenStream,
397 trait_attr: String,
398 allowed_attr_params: AttrParams,
399 add_type_bound: bool,
400 ) -> Result<State<'arg_input>> {
401 Self::new_impl(
402 input,
403 trait_name,
404 trait_module,
405 trait_attr,
406 allowed_attr_params,
407 add_type_bound,
408 )
409 }
410
411 fn new_impl<'arg_input>(
412 input: &'arg_input DeriveInput,
413 trait_name: &'static str,
414 trait_module: TokenStream,
415 trait_attr: String,
416 allowed_attr_params: AttrParams,
417 add_type_bound: bool,
418 ) -> Result<State<'arg_input>> {
419 let trait_name = trait_name.trim_end_matches("ToInner");
420 let trait_ident = Ident::new(trait_name, Span::call_site());
421 let method_ident = Ident::new(&trait_attr, Span::call_site());
422 let trait_path = quote!(#trait_module::#trait_ident);
423 let (derive_type, fields, variants): (_, Vec<_>, Vec<_>) = match input.data {
424 Data::Struct(ref data_struct) => match data_struct.fields {
425 Fields::Unnamed(ref fields) => {
426 (DeriveType::Unnamed, unnamed_to_vec(fields), vec![])
427 }
428
429 Fields::Named(ref fields) => {
430 (DeriveType::Named, named_to_vec(fields), vec![])
431 }
432 Fields::Unit => (DeriveType::Named, vec![], vec![]),
433 },
434 Data::Enum(ref data_enum) => (
435 DeriveType::Enum,
436 vec![],
437 data_enum.variants.iter().collect(),
438 ),
439 Data::Union(_) => {
440 panic!("cannot derive({}) for union", trait_name)
441 }
442 };
443 let attrs: Vec<_> = if derive_type == DeriveType::Enum {
444 variants.iter().map(|v| &v.attrs).collect()
445 } else {
446 fields.iter().map(|f| &f.attrs).collect()
447 };
448
449 let (allowed_attr_params_outer, allowed_attr_params_inner) =
450 if derive_type == DeriveType::Enum {
451 (&allowed_attr_params.enum_, &allowed_attr_params.variant)
452 } else {
453 (&allowed_attr_params.struct_, &allowed_attr_params.field)
454 };
455
456 let struct_meta_info =
457 get_meta_info(&trait_attr, &input.attrs, allowed_attr_params_outer)?;
458 let meta_infos: Result<Vec<_>> = attrs
459 .iter()
460 .map(|attrs| get_meta_info(&trait_attr, attrs, allowed_attr_params_inner))
461 .collect();
462 let meta_infos = meta_infos?;
463 let first_match = meta_infos
464 .iter()
465 .filter_map(|info| info.enabled.map(|_| info))
466 .next();
467
468 let default_enabled = if trait_name == "Error" {
483 true
484 } else {
485 first_match.map_or(true, |info| !info.enabled.unwrap())
486 };
487
488 let defaults = struct_meta_info.into_full(FullMetaInfo {
489 enabled: default_enabled,
490 forward: false,
491 owned: first_match.map_or(true, |info| {
497 info.owned.is_none() && info.ref_.is_none() || info.ref_mut.is_none()
498 }),
499 ref_: false,
500 ref_mut: false,
501 info: MetaInfo::default(),
502 });
503
504 let full_meta_infos: Vec<_> = meta_infos
505 .into_iter()
506 .map(|info| info.into_full(defaults.clone()))
507 .collect();
508
509 let variant_states: Result<Vec<_>> = if derive_type == DeriveType::Enum {
510 variants
511 .iter()
512 .zip(full_meta_infos.iter().cloned())
513 .map(|(variant, info)| {
514 State::from_variant(
515 input,
516 trait_name,
517 trait_module.clone(),
518 trait_attr.clone(),
519 allowed_attr_params.clone(),
520 variant,
521 info,
522 )
523 })
524 .collect()
525 } else {
526 Ok(vec![])
527 };
528
529 let generics = if add_type_bound {
530 add_extra_ty_param_bound(&input.generics, &trait_path)
531 } else {
532 input.generics.clone()
533 };
534
535 Ok(State {
536 input,
537 trait_name,
538 method_ident,
539 trait_module,
540 trait_path,
541 trait_path_params: vec![],
542 trait_attr,
543 fields,
545 variants,
546 variant_states: variant_states?,
547 variant: None,
548 derive_type,
549 generics,
550 full_meta_infos,
551 default_info: defaults,
552 })
553 }
554
555 pub fn from_variant<'arg_input>(
556 input: &'arg_input DeriveInput,
557 trait_name: &'static str,
558 trait_module: TokenStream,
559 trait_attr: String,
560 allowed_attr_params: AttrParams,
561 variant: &'arg_input Variant,
562 default_info: FullMetaInfo,
563 ) -> Result<State<'arg_input>> {
564 let trait_name = trait_name.trim_end_matches("ToInner");
565 let trait_ident = Ident::new(trait_name, Span::call_site());
566 let method_ident = Ident::new(&trait_attr, Span::call_site());
567 let trait_path = quote!(#trait_module::#trait_ident);
568 let (derive_type, fields): (_, Vec<_>) = match variant.fields {
569 Fields::Unnamed(ref fields) => {
570 (DeriveType::Unnamed, unnamed_to_vec(fields))
571 }
572
573 Fields::Named(ref fields) => (DeriveType::Named, named_to_vec(fields)),
574 Fields::Unit => (DeriveType::Named, vec![]),
575 };
576
577 let meta_infos: Result<Vec<_>> = fields
578 .iter()
579 .map(|f| &f.attrs)
580 .map(|attrs| get_meta_info(&trait_attr, attrs, &allowed_attr_params.field))
581 .collect();
582 let meta_infos = meta_infos?;
583 let full_meta_infos: Vec<_> = meta_infos
584 .into_iter()
585 .map(|info| info.into_full(default_info.clone()))
586 .collect();
587
588 let generics = add_extra_ty_param_bound(&input.generics, &trait_path);
589
590 Ok(State {
591 input,
592 trait_name,
593 trait_module,
594 trait_path,
595 trait_path_params: vec![],
596 trait_attr,
597 method_ident,
598 fields,
600 variants: vec![],
601 variant_states: vec![],
602 variant: Some(variant),
603 derive_type,
604 generics,
605 full_meta_infos,
606 default_info,
607 })
608 }
609 pub fn add_trait_path_type_param(&mut self, param: TokenStream) {
610 self.trait_path_params.push(param);
611 }
612
613 pub fn assert_single_enabled_field<'state>(
614 &'state self,
615 ) -> SingleFieldData<'input, 'state> {
616 if self.derive_type == DeriveType::Enum {
617 panic_one_field(self.trait_name, &self.trait_attr);
618 }
619 let data = self.enabled_fields_data();
620 if data.fields.len() != 1 {
621 panic_one_field(self.trait_name, &self.trait_attr);
622 };
623 SingleFieldData {
624 input_type: data.input_type,
625 field: data.fields[0],
626 field_type: data.field_types[0],
627 member: data.members[0].clone(),
628 info: data.infos[0].clone(),
629 trait_path: data.trait_path,
630 trait_path_with_params: data.trait_path_with_params.clone(),
631 casted_trait: data.casted_traits[0].clone(),
632 impl_generics: data.impl_generics.clone(),
633 ty_generics: data.ty_generics.clone(),
634 where_clause: data.where_clause,
635 multi_field_data: data,
636 }
637 }
638
639 pub fn enabled_fields_data<'state>(&'state self) -> MultiFieldData<'input, 'state> {
640 if self.derive_type == DeriveType::Enum {
641 panic!("cannot derive({}) for enum", self.trait_name)
642 }
643 let fields = self.enabled_fields();
644 let field_idents = self.enabled_fields_idents();
645 let field_indexes = self.enabled_fields_indexes();
646 let field_types: Vec<_> = fields.iter().map(|f| &f.ty).collect();
647 let members: Vec<_> = field_idents
648 .iter()
649 .map(|ident| quote!(self.#ident))
650 .collect();
651 let trait_path = &self.trait_path;
652 let trait_path_with_params = if !self.trait_path_params.is_empty() {
653 let params = self.trait_path_params.iter();
654 quote!(#trait_path<#(#params),*>)
655 } else {
656 self.trait_path.clone()
657 };
658
659 let casted_traits: Vec<_> = field_types
660 .iter()
661 .map(|field_type| quote!(<#field_type as #trait_path_with_params>))
662 .collect();
663 let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl();
664 let input_type = &self.input.ident;
665 let (variant_name, variant_type) = self.variant.map_or_else(
666 || (None, quote!(#input_type)),
667 |v| {
668 let variant_name = &v.ident;
669 (Some(variant_name), quote!(#input_type::#variant_name))
670 },
671 );
672 MultiFieldData {
673 input_type,
674 variant_type,
675 variant_name,
676 variant_info: self.default_info.clone(),
677 fields,
678 field_types,
679 field_indexes,
680 members,
681 infos: self.enabled_infos(),
682 field_idents,
683 method_ident: &self.method_ident,
684 trait_path,
685 trait_path_with_params,
686 casted_traits,
687 impl_generics,
688 ty_generics,
689 where_clause,
690 state: self,
691 }
692 }
693
694 pub fn enabled_variant_data<'state>(
695 &'state self,
696 ) -> MultiVariantData<'input, 'state> {
697 if self.derive_type != DeriveType::Enum {
698 panic!("can only derive({}) for enum", self.trait_name)
699 }
700 let variants = self.enabled_variants();
701 MultiVariantData {
702 variants,
703 variant_states: self.enabled_variant_states(),
704 }
705 }
706
707 fn enabled_variants(&self) -> Vec<&'input Variant> {
708 self.variants
709 .iter()
710 .zip(self.full_meta_infos.iter().map(|info| info.enabled))
711 .filter(|(_, ig)| *ig)
712 .map(|(v, _)| *v)
713 .collect()
714 }
715
716 fn enabled_variant_states(&self) -> Vec<&State<'input>> {
717 self.variant_states
718 .iter()
719 .zip(self.full_meta_infos.iter().map(|info| info.enabled))
720 .filter(|(_, ig)| *ig)
721 .map(|(v, _)| v)
722 .collect()
723 }
724
725 pub fn enabled_fields(&self) -> Vec<&'input Field> {
726 self.fields
727 .iter()
728 .zip(self.full_meta_infos.iter().map(|info| info.enabled))
729 .filter(|(_, ig)| *ig)
730 .map(|(f, _)| *f)
731 .collect()
732 }
733
734 fn field_idents(&self) -> Vec<TokenStream> {
735 if self.derive_type == DeriveType::Named {
736 self.fields
737 .iter()
738 .map(|f| {
739 f.ident
740 .as_ref()
741 .expect("Tried to get field names of a tuple struct")
742 .to_token_stream()
743 })
744 .collect()
745 } else {
746 let count = self.fields.len();
747 (0..count)
748 .map(|i| Index::from(i).to_token_stream())
749 .collect()
750 }
751 }
752
753 fn enabled_fields_idents(&self) -> Vec<TokenStream> {
754 self.field_idents()
755 .into_iter()
756 .zip(self.full_meta_infos.iter().map(|info| info.enabled))
757 .filter(|(_, ig)| *ig)
758 .map(|(f, _)| f)
759 .collect()
760 }
761
762 fn enabled_fields_indexes(&self) -> Vec<usize> {
763 self.full_meta_infos
764 .iter()
765 .map(|info| info.enabled)
766 .enumerate()
767 .filter(|(_, ig)| *ig)
768 .map(|(i, _)| i)
769 .collect()
770 }
771 fn enabled_infos(&self) -> Vec<FullMetaInfo> {
772 self.full_meta_infos
773 .iter()
774 .filter(|info| info.enabled)
775 .cloned()
776 .collect()
777 }
778}
779
780#[derive(Clone)]
781pub struct SingleFieldData<'input, 'state> {
782 pub input_type: &'input Ident,
783 pub field: &'input Field,
784 pub field_type: &'input Type,
785 pub member: TokenStream,
786 pub info: FullMetaInfo,
787 pub trait_path: &'state TokenStream,
788 pub trait_path_with_params: TokenStream,
789 pub casted_trait: TokenStream,
790 pub impl_generics: ImplGenerics<'state>,
791 pub ty_generics: TypeGenerics<'state>,
792 pub where_clause: Option<&'state WhereClause>,
793 multi_field_data: MultiFieldData<'input, 'state>,
794}
795
796#[derive(Clone)]
797pub struct MultiFieldData<'input, 'state> {
798 pub input_type: &'input Ident,
799 pub variant_type: TokenStream,
800 pub variant_name: Option<&'input Ident>,
801 pub variant_info: FullMetaInfo,
802 pub fields: Vec<&'input Field>,
803 pub field_types: Vec<&'input Type>,
804 pub field_idents: Vec<TokenStream>,
805 pub field_indexes: Vec<usize>,
806 pub members: Vec<TokenStream>,
807 pub infos: Vec<FullMetaInfo>,
808 pub method_ident: &'state Ident,
809 pub trait_path: &'state TokenStream,
810 pub trait_path_with_params: TokenStream,
811 pub casted_traits: Vec<TokenStream>,
812 pub impl_generics: ImplGenerics<'state>,
813 pub ty_generics: TypeGenerics<'state>,
814 pub where_clause: Option<&'state WhereClause>,
815 pub state: &'state State<'input>,
816}
817
818pub struct MultiVariantData<'input, 'state> {
819 pub variants: Vec<&'input Variant>,
820 pub variant_states: Vec<&'state State<'input>>,
821}
822
823impl<'input, 'state> MultiFieldData<'input, 'state> {
824 pub fn initializer<T: ToTokens>(&self, initializers: &[T]) -> TokenStream {
825 let MultiFieldData {
826 variant_type,
827 field_idents,
828 ..
829 } = self;
830 if self.state.derive_type == DeriveType::Named {
831 quote!(#variant_type{#(#field_idents: #initializers),*})
832 } else {
833 quote!(#variant_type(#(#initializers),*))
834 }
835 }
836 pub fn matcher<T: ToTokens>(
837 &self,
838 indexes: &[usize],
839 bindings: &[T],
840 ) -> TokenStream {
841 let MultiFieldData { variant_type, .. } = self;
842 let full_bindings = (0..self.state.fields.len()).map(|i| {
843 indexes.iter().position(|index| i == *index).map_or_else(
844 || quote!(_),
845 |found_index| bindings[found_index].to_token_stream(),
846 )
847 });
848 if self.state.derive_type == DeriveType::Named {
849 let field_idents = self.state.field_idents();
850 quote!(#variant_type{#(#field_idents: #full_bindings),*})
851 } else {
852 quote!(#variant_type(#(#full_bindings),*))
853 }
854 }
855}
856
857impl<'input, 'state> SingleFieldData<'input, 'state> {
858 pub fn initializer<T: ToTokens>(&self, initializers: &[T]) -> TokenStream {
859 self.multi_field_data.initializer(initializers)
860 }
861}
862
863fn get_meta_info(
864 trait_attr: &str,
865 attrs: &[Attribute],
866 allowed_attr_params: &[&str],
867) -> Result<MetaInfo> {
868 let mut it = attrs
869 .iter()
870 .filter_map(|m| m.parse_meta().ok())
871 .filter(|m| {
872 m.path()
873 .segments
874 .first()
875 .map(|p| p.ident == trait_attr)
876 .unwrap_or_default()
877 });
878
879 let mut info = MetaInfo::default();
880
881 let meta = if let Some(meta) = it.next() {
882 meta
883 } else {
884 return Ok(info);
885 };
886
887 if allowed_attr_params.is_empty() {
888 return Err(Error::new(meta.span(), "Attribute is not allowed here"));
889 }
890
891 info.enabled = Some(true);
892
893 if let Some(another_meta) = it.next() {
894 return Err(Error::new(
895 another_meta.span(),
896 "Only a single attribute is allowed",
897 ));
898 }
899
900 let list = match meta.clone() {
901 ParsedMeta::Path(_) => {
902 if allowed_attr_params.contains(&"ignore") {
903 return Ok(info);
904 } else {
905 return Err(Error::new(
906 meta.span(),
907 format!(
908 "Empty attribute is not allowed, add one of the following parameters: {}",
909 allowed_attr_params.join(", "),
910 ),
911 ));
912 }
913 }
914 ParsedMeta::List(list) => list,
915 ParsedMeta::NameValue(val) => {
916 return Err(Error::new(
917 val.span(),
918 "Attribute doesn't support name-value format here",
919 ));
920 }
921 };
922
923 parse_punctuated_nested_meta(&mut info, &list.nested, allowed_attr_params, None)?;
924
925 Ok(info)
926}
927
928fn parse_punctuated_nested_meta(
929 info: &mut MetaInfo,
930 meta: &Punctuated<NestedMeta, Token![,]>,
931 allowed_attr_params: &[&str],
932 wrapper_name: Option<&str>,
933) -> Result<()> {
934 for meta in meta.iter() {
935 let meta = match meta {
936 NestedMeta::Meta(meta) => meta,
937 NestedMeta::Lit(lit) => {
938 return Err(Error::new(
939 lit.span(),
940 "Attribute doesn't support literals here",
941 ))
942 }
943 };
944
945 match meta {
946 ParsedMeta::List(list) if list.path.is_ident("not") => {
947 if wrapper_name.is_some() {
948 return Err(Error::new(
950 list.span(),
951 "Attribute doesn't support multiple multiple or nested `not` parameters",
952 ));
953 }
954 parse_punctuated_nested_meta(
955 info,
956 &list.nested,
957 allowed_attr_params,
958 Some("not"),
959 )?;
960 }
961
962 ParsedMeta::List(list) => {
963 let path = &list.path;
964 if !allowed_attr_params.iter().any(|param| path.is_ident(param)) {
965 return Err(Error::new(
966 meta.span(),
967 format!(
968 "Attribute nested parameter not supported. \
969 Supported attribute parameters are: {}",
970 allowed_attr_params.join(", "),
971 ),
972 ));
973 }
974
975 let mut parse_nested = true;
976
977 let attr_name = path.get_ident().unwrap().to_string();
978 match (wrapper_name, attr_name.as_str()) {
979 (None, "owned") => info.owned = Some(true),
980 (None, "ref") => info.ref_ = Some(true),
981 (None, "ref_mut") => info.ref_mut = Some(true),
982
983 #[cfg(any(feature = "from", feature = "into"))]
984 (None, "types")
985 | (Some("owned"), "types")
986 | (Some("ref"), "types")
987 | (Some("ref_mut"), "types") => {
988 parse_nested = false;
989 for meta in &list.nested {
990 let typ: syn::Type = match meta {
991 NestedMeta::Meta(meta) => {
992 let path = if let ParsedMeta::Path(p) = meta {
993 p
994 } else {
995 return Err(Error::new(
996 meta.span(),
997 format!(
998 "Attribute doesn't support type {}",
999 quote! { #meta },
1000 ),
1001 ));
1002 };
1003 syn::TypePath {
1004 qself: None,
1005 path: path.clone(),
1006 }
1007 .into()
1008 }
1009 NestedMeta::Lit(syn::Lit::Str(s)) => s.parse()?,
1010 NestedMeta::Lit(lit) => return Err(Error::new(
1011 lit.span(),
1012 "Attribute doesn't support nested literals here",
1013 )),
1014 };
1015
1016 for ref_type in wrapper_name
1017 .map(|n| vec![RefType::from_attr_name(n)])
1018 .unwrap_or_else(|| {
1019 vec![RefType::No, RefType::Ref, RefType::Mut]
1020 })
1021 {
1022 if info
1023 .types
1024 .entry(ref_type)
1025 .or_default()
1026 .replace(typ.clone())
1027 .is_some()
1028 {
1029 return Err(Error::new(
1030 typ.span(),
1031 format!(
1032 "Duplicate type `{}` specified",
1033 quote! { #path },
1034 ),
1035 ));
1036 }
1037 }
1038 }
1039 }
1040
1041 _ => {
1042 return Err(Error::new(
1043 list.span(),
1044 format!(
1045 "Attribute doesn't support nested parameter `{}` here",
1046 quote! { #path },
1047 ),
1048 ))
1049 }
1050 };
1051
1052 if parse_nested {
1053 parse_punctuated_nested_meta(
1054 info,
1055 &list.nested,
1056 allowed_attr_params,
1057 Some(&attr_name),
1058 )?;
1059 }
1060 }
1061
1062 ParsedMeta::Path(path) => {
1063 if !allowed_attr_params.iter().any(|param| path.is_ident(param)) {
1064 return Err(Error::new(
1065 meta.span(),
1066 format!(
1067 "Attribute parameter not supported. \
1068 Supported attribute parameters are: {}",
1069 allowed_attr_params.join(", "),
1070 ),
1071 ));
1072 }
1073
1074 let attr_name = path.get_ident().unwrap().to_string();
1075 match (wrapper_name, attr_name.as_str()) {
1076 (None, "ignore") => info.enabled = Some(false),
1077 (None, "forward") => info.forward = Some(true),
1078 (Some("not"), "forward") => info.forward = Some(false),
1079 (None, "owned") => info.owned = Some(true),
1080 (None, "ref") => info.ref_ = Some(true),
1081 (None, "ref_mut") => info.ref_mut = Some(true),
1082 (None, "source") => info.source = Some(true),
1083 (Some("not"), "source") => info.source = Some(false),
1084 (None, "backtrace") => info.backtrace = Some(true),
1085 (Some("not"), "backtrace") => info.backtrace = Some(false),
1086 _ => {
1087 return Err(Error::new(
1088 path.span(),
1089 format!(
1090 "Attribute doesn't support parameter `{}` here",
1091 quote! { #path }
1092 ),
1093 ))
1094 }
1095 }
1096 }
1097
1098 ParsedMeta::NameValue(val) => {
1099 return Err(Error::new(
1100 val.span(),
1101 "Attribute doesn't support name-value parameters here",
1102 ))
1103 }
1104 }
1105 }
1106
1107 Ok(())
1108}
1109
1110#[derive(Clone, Debug, Default)]
1111pub struct FullMetaInfo {
1112 pub enabled: bool,
1113 pub forward: bool,
1114 pub owned: bool,
1115 pub ref_: bool,
1116 pub ref_mut: bool,
1117 pub info: MetaInfo,
1118}
1119
1120#[derive(Clone, Debug, Default)]
1121pub struct MetaInfo {
1122 pub enabled: Option<bool>,
1123 pub forward: Option<bool>,
1124 pub owned: Option<bool>,
1125 pub ref_: Option<bool>,
1126 pub ref_mut: Option<bool>,
1127 pub source: Option<bool>,
1128 pub backtrace: Option<bool>,
1129 #[cfg(any(feature = "from", feature = "into"))]
1130 pub types: HashMap<RefType, HashSet<syn::Type>>,
1131}
1132
1133impl MetaInfo {
1134 fn into_full(self, defaults: FullMetaInfo) -> FullMetaInfo {
1135 FullMetaInfo {
1136 enabled: self.enabled.unwrap_or(defaults.enabled),
1137 forward: self.forward.unwrap_or(defaults.forward),
1138 owned: self.owned.unwrap_or(defaults.owned),
1139 ref_: self.ref_.unwrap_or(defaults.ref_),
1140 ref_mut: self.ref_mut.unwrap_or(defaults.ref_mut),
1141 info: self,
1142 }
1143 }
1144}
1145
1146impl FullMetaInfo {
1147 pub fn ref_types(&self) -> Vec<RefType> {
1148 let mut ref_types = vec![];
1149 if self.owned {
1150 ref_types.push(RefType::No);
1151 }
1152 if self.ref_ {
1153 ref_types.push(RefType::Ref);
1154 }
1155 if self.ref_mut {
1156 ref_types.push(RefType::Mut);
1157 }
1158 ref_types
1159 }
1160
1161 #[cfg(any(feature = "from", feature = "into"))]
1162 pub fn additional_types(&self, ref_type: RefType) -> HashSet<syn::Type> {
1163 self.info.types.get(&ref_type).cloned().unwrap_or_default()
1164 }
1165}
1166
1167pub fn get_if_type_parameter_used_in_type(
1168 type_parameters: &HashSet<syn::Ident>,
1169 ty: &syn::Type,
1170) -> Option<syn::Type> {
1171 if is_type_parameter_used_in_type(type_parameters, ty) {
1172 match ty {
1173 syn::Type::Reference(syn::TypeReference { elem: ty, .. }) => {
1174 Some((**ty).clone())
1175 }
1176 ty => Some(ty.clone()),
1177 }
1178 } else {
1179 None
1180 }
1181}
1182
1183pub fn is_type_parameter_used_in_type(
1184 type_parameters: &HashSet<syn::Ident>,
1185 ty: &syn::Type,
1186) -> bool {
1187 match ty {
1188 syn::Type::Path(ty) => {
1189 if let Some(qself) = &ty.qself {
1190 if is_type_parameter_used_in_type(type_parameters, &qself.ty) {
1191 return true;
1192 }
1193 }
1194
1195 if let Some(segment) = ty.path.segments.first() {
1196 if type_parameters.contains(&segment.ident) {
1197 return true;
1198 }
1199 }
1200
1201 ty.path.segments.iter().any(|segment| {
1202 if let syn::PathArguments::AngleBracketed(arguments) =
1203 &segment.arguments
1204 {
1205 arguments.args.iter().any(|argument| match argument {
1206 syn::GenericArgument::Type(ty) => {
1207 is_type_parameter_used_in_type(type_parameters, ty)
1208 }
1209 syn::GenericArgument::Constraint(constraint) => {
1210 type_parameters.contains(&constraint.ident)
1211 }
1212 _ => false,
1213 })
1214 } else {
1215 false
1216 }
1217 })
1218 }
1219
1220 syn::Type::Reference(ty) => {
1221 is_type_parameter_used_in_type(type_parameters, &ty.elem)
1222 }
1223
1224 _ => false,
1225 }
1226}