1use proc_macro2::Span;
2use syn::{parse_quote, spanned::Spanned};
3
4use crate::ast::NestedMeta;
5use crate::{Error, FromMeta, Result};
6
7mod core;
8mod forward_attrs;
9mod from_attributes;
10mod from_derive;
11mod from_field;
12mod from_meta;
13mod from_type_param;
14mod from_variant;
15mod input_field;
16mod input_variant;
17mod outer_from;
18mod shape;
19
20pub use self::core::Core;
21pub use self::forward_attrs::ForwardAttrs;
22pub use self::from_attributes::FromAttributesOptions;
23pub use self::from_derive::FdiOptions;
24pub use self::from_field::FromFieldOptions;
25pub use self::from_meta::FromMetaOptions;
26pub use self::from_type_param::FromTypeParamOptions;
27pub use self::from_variant::FromVariantOptions;
28pub use self::input_field::InputField;
29pub use self::input_variant::InputVariant;
30pub use self::outer_from::OuterFrom;
31pub use self::shape::{DataShape, DeriveInputShapeSet};
32
33/// A default/fallback expression encountered in attributes during parsing.
34#[derive(Debug, Clone)]
35pub enum DefaultExpression {
36 /// The value should be taken from the `default` instance of the containing struct.
37 /// This is not valid in container options.
38 Inherit,
39 Explicit(syn::Path),
40 Trait {
41 /// The input span that is responsible for the use of `Default::default`.
42 span: Span,
43 },
44}
45
46#[doc(hidden)]
47impl FromMeta for DefaultExpression {
48 // Note: This cannot use `from_word` as it needs to capture the span
49 // in the `Meta::Path` case.
50 fn from_meta(item: &syn::Meta) -> Result<Self> {
51 match item {
52 syn::Meta::Path(_) => Ok(DefaultExpression::Trait { span: item.span() }),
53 syn::Meta::List(nm: &MetaList) => Err(Error::unsupported_format("list").with_span(node:nm)),
54 syn::Meta::NameValue(nv: &MetaNameValue) => Self::from_expr(&nv.value),
55 }
56 }
57
58 fn from_value(value: &syn::Lit) -> Result<Self> {
59 syn::Path::from_value(value).map(op:DefaultExpression::Explicit)
60 }
61}
62
63/// Middleware for extracting attribute values. Implementers are expected to override
64/// `parse_nested` so they can apply individual items to themselves, while `parse_attributes`
65/// is responsible for looping through distinct outer attributes and collecting errors.
66pub trait ParseAttribute: Sized {
67 fn parse_attributes(mut self, attrs: &[syn::Attribute]) -> Result<Self> {
68 let mut errors: Accumulator = Error::accumulator();
69 for attr: &Attribute in attrs {
70 if attr.meta.path() == &parse_quote!(darling) {
71 errors.handle(result:parse_attr(attr, &mut self));
72 }
73 }
74
75 errors.finish_with(self)
76 }
77
78 /// Read a meta-item, and apply its values to the current instance.
79 fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()>;
80}
81
82fn parse_attr<T: ParseAttribute>(attr: &syn::Attribute, target: &mut T) -> Result<()> {
83 let mut errors: Accumulator = Error::accumulator();
84 match &attr.meta {
85 syn::Meta::List(data: &MetaList) => {
86 for item: NestedMeta in NestedMeta::parse_meta_list(tokens:data.tokens.clone())? {
87 if let NestedMeta::Meta(ref mi: &Meta) = item {
88 errors.handle(result:target.parse_nested(mi));
89 } else {
90 panic!("Wasn't able to parse: `{:?}`", item);
91 }
92 }
93
94 errors.finish()
95 }
96 item: &Meta => panic!("Wasn't able to parse: `{:?}`", item),
97 }
98}
99
100/// Middleware for extracting values from the body of the derive input. Implementers are
101/// expected to override `parse_field` or `parse_variant` as appropriate for their use-case,
102/// while `parse_body` dispatches to the appropriate methods and handles error collection.
103pub trait ParseData: Sized {
104 fn parse_body(mut self, body: &syn::Data) -> Result<Self> {
105 use syn::{Data, Fields};
106
107 let mut errors = Error::accumulator();
108
109 match *body {
110 Data::Struct(ref data) => match data.fields {
111 Fields::Unit => {}
112 Fields::Named(ref fields) => {
113 for field in &fields.named {
114 errors.handle(self.parse_field(field));
115 }
116 }
117 Fields::Unnamed(ref fields) => {
118 for field in &fields.unnamed {
119 errors.handle(self.parse_field(field));
120 }
121 }
122 },
123 Data::Enum(ref data) => {
124 for variant in &data.variants {
125 errors.handle(self.parse_variant(variant));
126 }
127 }
128 Data::Union(_) => unreachable!(),
129 };
130
131 errors.finish_with(self)
132 }
133
134 /// Apply the next found variant to the object, returning an error
135 /// if parsing goes wrong.
136 fn parse_variant(&mut self, variant: &syn::Variant) -> Result<()> {
137 Err(Error::unsupported_format("enum variant").with_span(variant))
138 }
139
140 /// Apply the next found struct field to the object, returning an error
141 /// if parsing goes wrong.
142 fn parse_field(&mut self, field: &syn::Field) -> Result<()> {
143 Err(Error::unsupported_format("struct field").with_span(field))
144 }
145}
146