1#![cfg_attr(not(feature = "default"), allow(dead_code), allow(unused_mut))]
2
3use proc_macro2::{Span, TokenStream};
4use quote::{quote, ToTokens};
5use syn::{
6 parse_quote, punctuated::Punctuated, spanned::Spanned, Attribute, Data,
7 DeriveInput, Error, Field, Fields, FieldsNamed, FieldsUnnamed, GenericParam,
8 Generics, Ident, ImplGenerics, Index, Meta, NestedMeta, Result, Token, Type,
9 TypeGenerics, TypeParamBound, Variant, WhereClause,
10};
11
12#[derive(Clone, Copy, Default)]
13pub struct DeterministicState;
14
15impl std::hash::BuildHasher for DeterministicState {
16 type Hasher = std::collections::hash_map::DefaultHasher;
17
18 fn build_hasher(&self) -> Self::Hasher {
19 Self::Hasher::default()
20 }
21}
22
23pub type HashMap<K, V> = std::collections::HashMap<K, V, DeterministicState>;
24pub type HashSet<K> = std::collections::HashSet<K, DeterministicState>;
25
26#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
27pub enum RefType {
28 No,
29 Ref,
30 Mut,
31}
32
33impl RefType {
34 pub fn lifetime(self) -> TokenStream {
35 match self {
36 RefType::No => quote!(),
37 _ => quote!('__deriveMoreLifetime),
38 }
39 }
40
41 pub fn reference(self) -> TokenStream {
42 match self {
43 RefType::No => quote!(),
44 RefType::Ref => quote!(&),
45 RefType::Mut => quote!(&mut),
46 }
47 }
48
49 pub fn mutability(self) -> TokenStream {
50 match self {
51 RefType::Mut => quote!(mut),
52 _ => quote!(),
53 }
54 }
55
56 pub fn pattern_ref(self) -> TokenStream {
57 match self {
58 RefType::Ref => quote!(ref),
59 RefType::Mut => quote!(ref mut),
60 RefType::No => quote!(),
61 }
62 }
63
64 pub fn reference_with_lifetime(self) -> TokenStream {
65 if !self.is_ref() {
66 return quote!();
67 }
68 let lifetime = self.lifetime();
69 let mutability = self.mutability();
70 quote!(&#lifetime #mutability)
71 }
72
73 pub fn is_ref(self) -> bool {
74 match self {
75 RefType::No => false,
76 _ => true,
77 }
78 }
79
80 pub fn from_attr_name(name: &str) -> Self {
81 match name {
82 "owned" => RefType::No,
83 "ref" => RefType::Ref,
84 "ref_mut" => RefType::Mut,
85 _ => panic!("'{}' is not a RefType", name),
86 }
87 }
88}
89
90pub fn numbered_vars(count: usize, prefix: &str) -> Vec<Ident> {
91 (0..count)
92 .map(|i: usize| Ident::new(&format!("__{}{}", prefix, i), Span::call_site()))
93 .collect()
94}
95
96pub fn field_idents<'a>(fields: &'a [&'a Field]) -> Vec<&'a Ident> {
97 fieldsimpl Iterator
98 .iter()
99 .map(|f: &&Field| {
100 f.ident
101 .as_ref()
102 .expect(msg:"Tried to get field names of a tuple struct")
103 })
104 .collect()
105}
106
107pub fn get_field_types_iter<'a>(
108 fields: &'a [&'a Field],
109) -> Box<dyn Iterator<Item = &'a Type> + 'a> {
110 Box::new(fields.iter().map(|f: &&Field| &f.ty))
111}
112
113pub fn get_field_types<'a>(fields: &'a [&'a Field]) -> Vec<&'a Type> {
114 get_field_types_iter(fields).collect()
115}
116
117pub fn add_extra_type_param_bound_op_output<'a>(
118 generics: &'a Generics,
119 trait_ident: &'a Ident,
120) -> Generics {
121 let mut generics: Generics = generics.clone();
122 for type_param: &mut TypeParam in &mut generics.type_params_mut() {
123 let type_ident: &Ident = &type_param.ident;
124 let bound: TypeParamBound = parse_quote! {
125 ::core::ops::#trait_ident<Output=#type_ident>
126 };
127 type_param.bounds.push(bound)
128 }
129
130 generics
131}
132
133pub fn add_extra_ty_param_bound_op<'a>(
134 generics: &'a Generics,
135 trait_ident: &'a Ident,
136) -> Generics {
137 add_extra_ty_param_bound(generics, &quote!(::core::ops::#trait_ident))
138}
139
140pub fn add_extra_ty_param_bound<'a>(
141 generics: &'a Generics,
142 bound: &'a TokenStream,
143) -> Generics {
144 let mut generics: Generics = generics.clone();
145 let bound: TypeParamBound = parse_quote! { #bound };
146 for type_param: &mut TypeParam in &mut generics.type_params_mut() {
147 type_param.bounds.push(bound.clone())
148 }
149
150 generics
151}
152
153pub fn add_extra_ty_param_bound_ref<'a>(
154 generics: &'a Generics,
155 bound: &'a TokenStream,
156 ref_type: RefType,
157) -> Generics {
158 match ref_type {
159 RefType::No => add_extra_ty_param_bound(generics, bound),
160 _ => {
161 let generics: Generics = generics.clone();
162 let idents: impl Iterator = generics.type_params().map(|x: &TypeParam| &x.ident);
163 let ref_with_lifetime: TokenStream = ref_type.reference_with_lifetime();
164 add_extra_where_clauses(
165 &generics,
166 type_where_clauses:quote!(
167 where #(#ref_with_lifetime #idents: #bound),*
168 ),
169 )
170 }
171 }
172}
173
174pub fn add_extra_generic_param(
175 generics: &Generics,
176 generic_param: TokenStream,
177) -> Generics {
178 let generic_param: GenericParam = parse_quote! { #generic_param };
179 let mut generics: Generics = generics.clone();
180 generics.params.push(generic_param);
181
182 generics
183}
184
185pub fn add_extra_generic_type_param(
186 generics: &Generics,
187 generic_param: TokenStream,
188) -> Generics {
189 let generic_param: GenericParam = parse_quote! { #generic_param };
190 let lifetimes: Vec<GenericParam> =
191 generics.lifetimes().map(|x: &LifetimeDef| x.clone().into()).collect();
192 let type_params: Vec<GenericParam> =
193 generics.type_params().map(|x: &TypeParam| x.clone().into()).collect();
194 let const_params: Vec<GenericParam> =
195 generics.const_params().map(|x: &ConstParam| x.clone().into()).collect();
196 let mut generics: Generics = generics.clone();
197 generics.params = Default::default();
198 generics.params.extend(iter:lifetimes);
199 generics.params.extend(iter:type_params);
200 generics.params.push(generic_param);
201 generics.params.extend(iter:const_params);
202
203 generics
204}
205
206pub fn add_extra_where_clauses(
207 generics: &Generics,
208 type_where_clauses: TokenStream,
209) -> Generics {
210 let mut type_where_clauses: WhereClause = parse_quote! { #type_where_clauses };
211 let mut new_generics: Generics = generics.clone();
212 if let Some(old_where: WhereClause) = new_generics.where_clause {
213 type_where_clauses.predicates.extend(iter:old_where.predicates)
214 }
215 new_generics.where_clause = Some(type_where_clauses);
216
217 new_generics
218}
219
220pub fn add_where_clauses_for_new_ident<'a>(
221 generics: &'a Generics,
222 fields: &[&'a Field],
223 type_ident: &Ident,
224 type_where_clauses: TokenStream,
225 sized: bool,
226) -> Generics {
227 let generic_param: TokenStream = if fields.len() > 1 {
228 quote!(#type_ident: ::core::marker::Copy)
229 } else if sized {
230 quote!(#type_ident)
231 } else {
232 quote!(#type_ident: ?::core::marker::Sized)
233 };
234
235 let generics: Generics = add_extra_where_clauses(generics, type_where_clauses);
236 add_extra_generic_type_param(&generics, generic_param)
237}
238
239pub fn unnamed_to_vec(fields: &FieldsUnnamed) -> Vec<&Field> {
240 fields.unnamed.iter().collect()
241}
242
243pub fn named_to_vec(fields: &FieldsNamed) -> Vec<&Field> {
244 fields.named.iter().collect()
245}
246
247fn panic_one_field(trait_name: &str, trait_attr: &str) -> ! {
248 panic!(
249 "derive({}) only works when forwarding to a single field. Try putting #[{}] or #[{}(ignore)] on the fields in the struct",
250 trait_name, trait_attr, trait_attr,
251 )
252}
253
254#[derive(Copy, Clone, Debug, PartialEq, Eq)]
255pub enum DeriveType {
256 Unnamed,
257 Named,
258 Enum,
259}
260
261pub struct State<'input> {
262 pub input: &'input DeriveInput,
263 pub trait_name: &'static str,
264 pub trait_ident: Ident,
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(params: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 // Default to enabled true, except when first attribute has explicit
469 // enabling.
470 //
471 // Except for derive Error.
472 //
473 // The way `else` case works is that if any field have any valid
474 // attribute specified, then all fields without any attributes
475 // specified are filtered out from `State::enabled_fields`.
476 //
477 // However, derive Error *infers* fields and there are cases when
478 // one of the fields may have an attribute specified, but another field
479 // would be inferred. So, for derive Error macro we default enabled
480 // to true unconditionally (i.e., even if some fields have attributes
481 // specified).
482 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 // Default to owned true, except when first attribute has one of owned,
492 // ref or ref_mut
493 // - not a single attribute means default true
494 // - an attribute, but non of owned, ref or ref_mut means default true
495 // - an attribute, and owned, ref or ref_mut means default false
496 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 trait_ident,
539 method_ident,
540 trait_module,
541 trait_path,
542 trait_path_params: vec![],
543 trait_attr,
544 // input,
545 fields,
546 variants,
547 variant_states: variant_states?,
548 variant: None,
549 derive_type,
550 generics,
551 full_meta_infos,
552 default_info: defaults,
553 })
554 }
555
556 pub fn from_variant<'arg_input>(
557 input: &'arg_input DeriveInput,
558 trait_name: &'static str,
559 trait_module: TokenStream,
560 trait_attr: String,
561 allowed_attr_params: AttrParams,
562 variant: &'arg_input Variant,
563 default_info: FullMetaInfo,
564 ) -> Result<State<'arg_input>> {
565 let trait_name = trait_name.trim_end_matches("ToInner");
566 let trait_ident = Ident::new(trait_name, Span::call_site());
567 let method_ident = Ident::new(&trait_attr, Span::call_site());
568 let trait_path = quote!(#trait_module::#trait_ident);
569 let (derive_type, fields): (_, Vec<_>) = match variant.fields {
570 Fields::Unnamed(ref fields) => {
571 (DeriveType::Unnamed, unnamed_to_vec(fields))
572 }
573
574 Fields::Named(ref fields) => (DeriveType::Named, named_to_vec(fields)),
575 Fields::Unit => (DeriveType::Named, vec![]),
576 };
577
578 let meta_infos: Result<Vec<_>> = fields
579 .iter()
580 .map(|f| &f.attrs)
581 .map(|attrs| get_meta_info(&trait_attr, attrs, &allowed_attr_params.field))
582 .collect();
583 let meta_infos = meta_infos?;
584 let full_meta_infos: Vec<_> = meta_infos
585 .into_iter()
586 .map(|info| info.into_full(default_info.clone()))
587 .collect();
588
589 let generics = add_extra_ty_param_bound(&input.generics, &trait_path);
590
591 Ok(State {
592 input,
593 trait_name,
594 trait_module,
595 trait_path,
596 trait_path_params: vec![],
597 trait_attr,
598 trait_ident,
599 method_ident,
600 // input,
601 fields,
602 variants: vec![],
603 variant_states: vec![],
604 variant: Some(variant),
605 derive_type,
606 generics,
607 full_meta_infos,
608 default_info,
609 })
610 }
611 pub fn add_trait_path_type_param(&mut self, param: TokenStream) {
612 self.trait_path_params.push(param);
613 }
614
615 pub fn assert_single_enabled_field<'state>(
616 &'state self,
617 ) -> SingleFieldData<'input, 'state> {
618 if self.derive_type == DeriveType::Enum {
619 panic_one_field(self.trait_name, &self.trait_attr);
620 }
621 let data = self.enabled_fields_data();
622 if data.fields.len() != 1 {
623 panic_one_field(self.trait_name, &self.trait_attr);
624 };
625 SingleFieldData {
626 input_type: data.input_type,
627 field: data.fields[0],
628 field_type: data.field_types[0],
629 member: data.members[0].clone(),
630 info: data.infos[0].clone(),
631 field_ident: data.field_idents[0].clone(),
632 trait_path: data.trait_path,
633 trait_path_with_params: data.trait_path_with_params.clone(),
634 casted_trait: data.casted_traits[0].clone(),
635 impl_generics: data.impl_generics.clone(),
636 ty_generics: data.ty_generics.clone(),
637 where_clause: data.where_clause,
638 multi_field_data: data,
639 }
640 }
641
642 pub fn enabled_fields_data<'state>(&'state self) -> MultiFieldData<'input, 'state> {
643 if self.derive_type == DeriveType::Enum {
644 panic!("cannot derive({}) for enum", self.trait_name)
645 }
646 let fields = self.enabled_fields();
647 let field_idents = self.enabled_fields_idents();
648 let field_indexes = self.enabled_fields_indexes();
649 let field_types: Vec<_> = fields.iter().map(|f| &f.ty).collect();
650 let members: Vec<_> = field_idents
651 .iter()
652 .map(|ident| quote!(self.#ident))
653 .collect();
654 let trait_path = &self.trait_path;
655 let trait_path_with_params = if !self.trait_path_params.is_empty() {
656 let params = self.trait_path_params.iter();
657 quote!(#trait_path<#(#params),*>)
658 } else {
659 self.trait_path.clone()
660 };
661
662 let casted_traits: Vec<_> = field_types
663 .iter()
664 .map(|field_type| quote!(<#field_type as #trait_path_with_params>))
665 .collect();
666 let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl();
667 let input_type = &self.input.ident;
668 let (variant_name, variant_type) = self.variant.map_or_else(
669 || (None, quote!(#input_type)),
670 |v| {
671 let variant_name = &v.ident;
672 (Some(variant_name), quote!(#input_type::#variant_name))
673 },
674 );
675 MultiFieldData {
676 input_type,
677 variant_type,
678 variant_name,
679 variant_info: self.default_info.clone(),
680 fields,
681 field_types,
682 field_indexes,
683 members,
684 infos: self.enabled_infos(),
685 field_idents,
686 method_ident: &self.method_ident,
687 trait_path,
688 trait_path_with_params,
689 casted_traits,
690 impl_generics,
691 ty_generics,
692 where_clause,
693 state: self,
694 }
695 }
696
697 pub fn enabled_variant_data<'state>(
698 &'state self,
699 ) -> MultiVariantData<'input, 'state> {
700 if self.derive_type != DeriveType::Enum {
701 panic!("can only derive({}) for enum", self.trait_name)
702 }
703 let variants = self.enabled_variants();
704 let trait_path = &self.trait_path;
705 let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl();
706 MultiVariantData {
707 input_type: &self.input.ident,
708 variants,
709 variant_states: self.enabled_variant_states(),
710 infos: self.enabled_infos(),
711 trait_path,
712 impl_generics,
713 ty_generics,
714 where_clause,
715 }
716 }
717
718 fn enabled_variants(&self) -> Vec<&'input Variant> {
719 self.variants
720 .iter()
721 .zip(self.full_meta_infos.iter().map(|info| info.enabled))
722 .filter(|(_, ig)| *ig)
723 .map(|(v, _)| *v)
724 .collect()
725 }
726
727 fn enabled_variant_states(&self) -> Vec<&State<'input>> {
728 self.variant_states
729 .iter()
730 .zip(self.full_meta_infos.iter().map(|info| info.enabled))
731 .filter(|(_, ig)| *ig)
732 .map(|(v, _)| v)
733 .collect()
734 }
735
736 pub fn enabled_fields(&self) -> Vec<&'input Field> {
737 self.fields
738 .iter()
739 .zip(self.full_meta_infos.iter().map(|info| info.enabled))
740 .filter(|(_, ig)| *ig)
741 .map(|(f, _)| *f)
742 .collect()
743 }
744
745 fn field_idents(&self) -> Vec<TokenStream> {
746 if self.derive_type == DeriveType::Named {
747 self.fields
748 .iter()
749 .map(|f| {
750 f.ident
751 .as_ref()
752 .expect("Tried to get field names of a tuple struct")
753 .to_token_stream()
754 })
755 .collect()
756 } else {
757 let count = self.fields.len();
758 (0..count)
759 .map(|i| Index::from(i).to_token_stream())
760 .collect()
761 }
762 }
763
764 fn enabled_fields_idents(&self) -> Vec<TokenStream> {
765 self.field_idents()
766 .into_iter()
767 .zip(self.full_meta_infos.iter().map(|info| info.enabled))
768 .filter(|(_, ig)| *ig)
769 .map(|(f, _)| f)
770 .collect()
771 }
772
773 fn enabled_fields_indexes(&self) -> Vec<usize> {
774 self.full_meta_infos
775 .iter()
776 .map(|info| info.enabled)
777 .enumerate()
778 .filter(|(_, ig)| *ig)
779 .map(|(i, _)| i)
780 .collect()
781 }
782 fn enabled_infos(&self) -> Vec<FullMetaInfo> {
783 self.full_meta_infos
784 .iter()
785 .filter(|info| info.enabled)
786 .cloned()
787 .collect()
788 }
789}
790
791#[derive(Clone)]
792pub struct SingleFieldData<'input, 'state> {
793 pub input_type: &'input Ident,
794 pub field: &'input Field,
795 pub field_type: &'input Type,
796 pub field_ident: TokenStream,
797 pub member: TokenStream,
798 pub info: FullMetaInfo,
799 pub trait_path: &'state TokenStream,
800 pub trait_path_with_params: TokenStream,
801 pub casted_trait: TokenStream,
802 pub impl_generics: ImplGenerics<'state>,
803 pub ty_generics: TypeGenerics<'state>,
804 pub where_clause: Option<&'state WhereClause>,
805 multi_field_data: MultiFieldData<'input, 'state>,
806}
807
808#[derive(Clone)]
809pub struct MultiFieldData<'input, 'state> {
810 pub input_type: &'input Ident,
811 pub variant_type: TokenStream,
812 pub variant_name: Option<&'input Ident>,
813 pub variant_info: FullMetaInfo,
814 pub fields: Vec<&'input Field>,
815 pub field_types: Vec<&'input Type>,
816 pub field_idents: Vec<TokenStream>,
817 pub field_indexes: Vec<usize>,
818 pub members: Vec<TokenStream>,
819 pub infos: Vec<FullMetaInfo>,
820 pub method_ident: &'state Ident,
821 pub trait_path: &'state TokenStream,
822 pub trait_path_with_params: TokenStream,
823 pub casted_traits: Vec<TokenStream>,
824 pub impl_generics: ImplGenerics<'state>,
825 pub ty_generics: TypeGenerics<'state>,
826 pub where_clause: Option<&'state WhereClause>,
827 pub state: &'state State<'input>,
828}
829
830pub struct MultiVariantData<'input, 'state> {
831 pub input_type: &'input Ident,
832 pub variants: Vec<&'input Variant>,
833 pub variant_states: Vec<&'state State<'input>>,
834 pub infos: Vec<FullMetaInfo>,
835 pub trait_path: &'state TokenStream,
836 pub impl_generics: ImplGenerics<'state>,
837 pub ty_generics: TypeGenerics<'state>,
838 pub where_clause: Option<&'state WhereClause>,
839}
840
841impl<'input, 'state> MultiFieldData<'input, 'state> {
842 pub fn initializer<T: ToTokens>(&self, initializers: &[T]) -> TokenStream {
843 let MultiFieldData {
844 variant_type,
845 field_idents,
846 ..
847 } = self;
848 if self.state.derive_type == DeriveType::Named {
849 quote!(#variant_type{#(#field_idents: #initializers),*})
850 } else {
851 quote!(#variant_type(#(#initializers),*))
852 }
853 }
854 pub fn matcher<T: ToTokens>(
855 &self,
856 indexes: &[usize],
857 bindings: &[T],
858 ) -> TokenStream {
859 let MultiFieldData { variant_type, .. } = self;
860 let full_bindings = (0..self.state.fields.len()).map(|i| {
861 indexes.iter().position(|index| i == *index).map_or_else(
862 || quote!(_),
863 |found_index| bindings[found_index].to_token_stream(),
864 )
865 });
866 if self.state.derive_type == DeriveType::Named {
867 let field_idents = self.state.field_idents();
868 quote!(#variant_type{#(#field_idents: #full_bindings),*})
869 } else {
870 quote!(#variant_type(#(#full_bindings),*))
871 }
872 }
873}
874
875impl<'input, 'state> SingleFieldData<'input, 'state> {
876 pub fn initializer<T: ToTokens>(&self, initializers: &[T]) -> TokenStream {
877 self.multi_field_data.initializer(initializers)
878 }
879}
880
881fn get_meta_info(
882 trait_attr: &str,
883 attrs: &[Attribute],
884 allowed_attr_params: &[&str],
885) -> Result<MetaInfo> {
886 let mut it = attrs
887 .iter()
888 .filter_map(|m| m.parse_meta().ok())
889 .filter(|m| {
890 m.path()
891 .segments
892 .first()
893 .map(|p| p.ident == trait_attr)
894 .unwrap_or_default()
895 });
896
897 let mut info = MetaInfo::default();
898
899 let meta = if let Some(meta) = it.next() {
900 meta
901 } else {
902 return Ok(info);
903 };
904
905 if allowed_attr_params.is_empty() {
906 return Err(Error::new(meta.span(), "Attribute is not allowed here"));
907 }
908
909 info.enabled = Some(true);
910
911 if let Some(another_meta) = it.next() {
912 return Err(Error::new(
913 another_meta.span(),
914 "Only a single attribute is allowed",
915 ));
916 }
917
918 let list = match meta.clone() {
919 Meta::Path(_) => {
920 if allowed_attr_params.contains(&"ignore") {
921 return Ok(info);
922 } else {
923 return Err(Error::new(
924 meta.span(),
925 format!(
926 "Empty attribute is not allowed, add one of the following parameters: {}",
927 allowed_attr_params.join(", "),
928 ),
929 ));
930 }
931 }
932 Meta::List(list) => list,
933 Meta::NameValue(val) => {
934 return Err(Error::new(
935 val.span(),
936 "Attribute doesn't support name-value format here",
937 ));
938 }
939 };
940
941 parse_punctuated_nested_meta(&mut info, &list.nested, allowed_attr_params, None)?;
942
943 Ok(info)
944}
945
946fn parse_punctuated_nested_meta(
947 info: &mut MetaInfo,
948 meta: &Punctuated<NestedMeta, Token![,]>,
949 allowed_attr_params: &[&str],
950 wrapper_name: Option<&str>,
951) -> Result<()> {
952 for meta in meta.iter() {
953 let meta = match meta {
954 NestedMeta::Meta(meta) => meta,
955 NestedMeta::Lit(lit) => {
956 return Err(Error::new(
957 lit.span(),
958 "Attribute doesn't support literals here",
959 ))
960 }
961 };
962
963 match meta {
964 Meta::List(list) if list.path.is_ident("not") => {
965 if wrapper_name.is_some() {
966 // Only single top-level `not` attribute is allowed.
967 return Err(Error::new(
968 list.span(),
969 "Attribute doesn't support multiple multiple or nested `not` parameters",
970 ));
971 }
972 parse_punctuated_nested_meta(
973 info,
974 &list.nested,
975 allowed_attr_params,
976 Some("not"),
977 )?;
978 }
979
980 Meta::List(list) => {
981 let path = &list.path;
982 if !allowed_attr_params.iter().any(|param| path.is_ident(param)) {
983 return Err(Error::new(
984 meta.span(),
985 format!(
986 "Attribute nested parameter not supported. \
987 Supported attribute parameters are: {}",
988 allowed_attr_params.join(", "),
989 ),
990 ));
991 }
992
993 let mut parse_nested = true;
994
995 let attr_name = path.get_ident().unwrap().to_string();
996 match (wrapper_name, attr_name.as_str()) {
997 (None, "owned") => info.owned = Some(true),
998 (None, "ref") => info.ref_ = Some(true),
999 (None, "ref_mut") => info.ref_mut = Some(true),
1000
1001 #[cfg(any(feature = "from", feature = "into"))]
1002 (None, "types")
1003 | (Some("owned"), "types")
1004 | (Some("ref"), "types")
1005 | (Some("ref_mut"), "types") => {
1006 parse_nested = false;
1007 for meta in &list.nested {
1008 let typ: syn::Type = match meta {
1009 NestedMeta::Meta(meta) => {
1010 let path = if let Meta::Path(p) = meta {
1011 p
1012 } else {
1013 return Err(Error::new(
1014 meta.span(),
1015 format!(
1016 "Attribute doesn't support type {}",
1017 quote! { #meta },
1018 ),
1019 ));
1020 };
1021 syn::TypePath {
1022 qself: None,
1023 path: path.clone(),
1024 }
1025 .into()
1026 }
1027 NestedMeta::Lit(syn::Lit::Str(s)) => s.parse()?,
1028 NestedMeta::Lit(lit) => return Err(Error::new(
1029 lit.span(),
1030 "Attribute doesn't support nested literals here",
1031 )),
1032 };
1033
1034 for ref_type in wrapper_name
1035 .map(|n| vec![RefType::from_attr_name(n)])
1036 .unwrap_or_else(|| {
1037 vec![RefType::No, RefType::Ref, RefType::Mut]
1038 })
1039 {
1040 if info
1041 .types
1042 .entry(ref_type)
1043 .or_default()
1044 .replace(typ.clone())
1045 .is_some()
1046 {
1047 return Err(Error::new(
1048 typ.span(),
1049 format!(
1050 "Duplicate type `{}` specified",
1051 quote! { #path },
1052 ),
1053 ));
1054 }
1055 }
1056 }
1057 }
1058
1059 _ => {
1060 return Err(Error::new(
1061 list.span(),
1062 format!(
1063 "Attribute doesn't support nested parameter `{}` here",
1064 quote! { #path },
1065 ),
1066 ))
1067 }
1068 };
1069
1070 if parse_nested {
1071 parse_punctuated_nested_meta(
1072 info,
1073 &list.nested,
1074 allowed_attr_params,
1075 Some(&attr_name),
1076 )?;
1077 }
1078 }
1079
1080 Meta::Path(path) => {
1081 if !allowed_attr_params.iter().any(|param| path.is_ident(param)) {
1082 return Err(Error::new(
1083 meta.span(),
1084 format!(
1085 "Attribute parameter not supported. \
1086 Supported attribute parameters are: {}",
1087 allowed_attr_params.join(", "),
1088 ),
1089 ));
1090 }
1091
1092 let attr_name = path.get_ident().unwrap().to_string();
1093 match (wrapper_name, attr_name.as_str()) {
1094 (None, "ignore") => info.enabled = Some(false),
1095 (None, "forward") => info.forward = Some(true),
1096 (Some("not"), "forward") => info.forward = Some(false),
1097 (None, "owned") => info.owned = Some(true),
1098 (None, "ref") => info.ref_ = Some(true),
1099 (None, "ref_mut") => info.ref_mut = Some(true),
1100 (None, "source") => info.source = Some(true),
1101 (Some("not"), "source") => info.source = Some(false),
1102 (None, "backtrace") => info.backtrace = Some(true),
1103 (Some("not"), "backtrace") => info.backtrace = Some(false),
1104 _ => {
1105 return Err(Error::new(
1106 path.span(),
1107 format!(
1108 "Attribute doesn't support parameter `{}` here",
1109 quote! { #path }
1110 ),
1111 ))
1112 }
1113 }
1114 }
1115
1116 Meta::NameValue(val) => {
1117 return Err(Error::new(
1118 val.span(),
1119 "Attribute doesn't support name-value parameters here",
1120 ))
1121 }
1122 }
1123 }
1124
1125 Ok(())
1126}
1127
1128#[derive(Clone, Debug, Default)]
1129pub struct FullMetaInfo {
1130 pub enabled: bool,
1131 pub forward: bool,
1132 pub owned: bool,
1133 pub ref_: bool,
1134 pub ref_mut: bool,
1135 pub info: MetaInfo,
1136}
1137
1138#[derive(Clone, Debug, Default)]
1139pub struct MetaInfo {
1140 pub enabled: Option<bool>,
1141 pub forward: Option<bool>,
1142 pub owned: Option<bool>,
1143 pub ref_: Option<bool>,
1144 pub ref_mut: Option<bool>,
1145 pub source: Option<bool>,
1146 pub backtrace: Option<bool>,
1147 #[cfg(any(feature = "from", feature = "into"))]
1148 pub types: HashMap<RefType, HashSet<syn::Type>>,
1149}
1150
1151impl MetaInfo {
1152 fn into_full(self, defaults: FullMetaInfo) -> FullMetaInfo {
1153 FullMetaInfo {
1154 enabled: self.enabled.unwrap_or(default:defaults.enabled),
1155 forward: self.forward.unwrap_or(default:defaults.forward),
1156 owned: self.owned.unwrap_or(default:defaults.owned),
1157 ref_: self.ref_.unwrap_or(default:defaults.ref_),
1158 ref_mut: self.ref_mut.unwrap_or(default:defaults.ref_mut),
1159 info: self,
1160 }
1161 }
1162}
1163
1164impl FullMetaInfo {
1165 pub fn ref_types(&self) -> Vec<RefType> {
1166 let mut ref_types: Vec = vec![];
1167 if self.owned {
1168 ref_types.push(RefType::No);
1169 }
1170 if self.ref_ {
1171 ref_types.push(RefType::Ref);
1172 }
1173 if self.ref_mut {
1174 ref_types.push(RefType::Mut);
1175 }
1176 ref_types
1177 }
1178
1179 #[cfg(any(feature = "from", feature = "into"))]
1180 pub fn additional_types(&self, ref_type: RefType) -> HashSet<syn::Type> {
1181 self.info.types.get(&ref_type).cloned().unwrap_or_default()
1182 }
1183}
1184
1185pub fn get_if_type_parameter_used_in_type(
1186 type_parameters: &HashSet<syn::Ident>,
1187 ty: &syn::Type,
1188) -> Option<syn::Type> {
1189 if is_type_parameter_used_in_type(type_parameters, ty) {
1190 match ty {
1191 syn::Type::Reference(syn::TypeReference { elem: ty: &Box, .. }) => {
1192 Some((&**ty).clone())
1193 }
1194 ty: &Type => Some(ty.clone()),
1195 }
1196 } else {
1197 None
1198 }
1199}
1200
1201pub fn is_type_parameter_used_in_type(
1202 type_parameters: &HashSet<syn::Ident>,
1203 ty: &syn::Type,
1204) -> bool {
1205 match ty {
1206 syn::Type::Path(ty) => {
1207 if let Some(qself) = &ty.qself {
1208 if is_type_parameter_used_in_type(type_parameters, &qself.ty) {
1209 return true;
1210 }
1211 }
1212
1213 if let Some(segment) = ty.path.segments.first() {
1214 if type_parameters.contains(&segment.ident) {
1215 return true;
1216 }
1217 }
1218
1219 ty.path.segments.iter().any(|segment| {
1220 if let syn::PathArguments::AngleBracketed(arguments) =
1221 &segment.arguments
1222 {
1223 arguments.args.iter().any(|argument| match argument {
1224 syn::GenericArgument::Type(ty) => {
1225 is_type_parameter_used_in_type(type_parameters, ty)
1226 }
1227 syn::GenericArgument::Constraint(constraint) => {
1228 type_parameters.contains(&constraint.ident)
1229 }
1230 _ => false,
1231 })
1232 } else {
1233 false
1234 }
1235 })
1236 }
1237
1238 syn::Type::Reference(ty) => {
1239 is_type_parameter_used_in_type(type_parameters, &ty.elem)
1240 }
1241
1242 _ => false,
1243 }
1244}
1245