deluxe_macros/lib.rs
1//! # Deluxe Macros
2//!
3//! Procedural derive macros for [deluxe](https://docs.rs/deluxe). See the documentation of that
4//! crate for an overview.
5
6#![deny(missing_docs)]
7#![deny(unsafe_code)]
8
9#[macro_use]
10mod util;
11mod parse_attributes;
12mod parse_meta_item;
13mod types;
14use util::*;
15
16use deluxe_core::Errors;
17use proc_macro::TokenStream;
18
19/// Generates [`ExtractAttributes`](deluxe_core::ExtractAttributes) for a struct or enum.
20///
21/// This macro is identical to [`ParseAttributes`], except for the following differences:
22/// - The generated [`extract_attributes`](deluxe_core::ExtractAttributes::extract_attributes)
23/// function will remove any attributes matching the paths listed in
24/// [`#[deluxe(attributes(...))]`](ParseAttributes#deluxeattributes).
25///
26/// - Reference types for [`#[deluxe(container)]`](ParseAttributes#deluxecontainer) fields will not
27/// work. The container type must be an owned type or an [`Option`], and the container will
28/// always be [`clone`](Clone::clone)d into the field. The cloning will happen after the
29/// attributes have been extracted. Using the `lifetime` parameter for custom container types
30/// will also not work.
31///
32/// See the [`ParseAttributes`] and [`ParseMetaItem`] documentation for all other details.
33#[proc_macro_derive(ExtractAttributes, attributes(deluxe))]
34pub fn derive_extract_attributes(item: TokenStream) -> TokenStream {
35 let errors = Errors::new();
36 let mut tokens = util::parse::<syn::DeriveInput>(item, &errors)
37 .map(|input| {
38 parse_attributes::impl_parse_attributes(input, &errors, parse_attributes::Mode::Extract)
39 })
40 .unwrap_or_default();
41 tokens.extend(errors.into_compile_errors());
42 tokens.into()
43}
44
45/// Generates [`ParseAttributes`](deluxe_core::ParseAttributes) for a struct or enum.
46///
47/// Supported attributes are the same as in [`ParseMetaItem`]. Additionally, some extra attributes
48/// are supported.
49///
50/// ### Extra Container Attributes
51///
52/// The following extra attributes are supported on structs and enums:
53///
54/// - ##### `#[deluxe(attributes(...))]`
55///
56/// Provides a list of paths to match attribute names against. These paths will be checked inside
57/// the [`ParseAttributes::path_matches`](deluxe_core::ParseAttributes::path_matches) function to
58/// see if a path matches. This attribute can be specified multiple times to append more paths to
59/// the list of matching paths.
60///
61/// Omitting this attribute will cause *all* paths to match. This can be useful when doing your
62/// own filtering on an attribute list before parsing.
63///
64/// ### Extra Field Attributes
65///
66/// The following extra attributes are supported on struct fields and enum fields:
67///
68/// - ##### `#[deluxe(container)]`
69///
70/// Specifies that this field should store the current `obj` being parsed by
71/// [`parse_attributes`](deluxe_core::ParseAttributes::parse_attributes). The field can be a
72/// value type, an [`Option`], or a reference type. If the field is not a reference type, the
73/// container will be [`clone`](Clone::clone)d into the field.
74///
75/// If the type of the container contains a lifetime, Deluxe will try to use it for a lifetime
76/// bound for [`ParseAttributes`](deluxe_core::ParseAttributes). If the container type is a
77/// reference, it will try to infer it from the lietime of the reference. Otherwise, it will try
78/// to take the first lifetime parameter used by the type if one is present. If no lifetimes can
79/// be inferred, a new lifetime parameter will be generated. See
80/// [`container(lifetime = ...)`](#deluxecontainerlifetime--t-ty--pathmytype) for instructions on
81/// how to specify a lifetime parameter manually.
82///
83/// If the struct/enum also derives [`ParseMetaItem`], then
84/// [`#[deluxe(default)]`](ParseMetaItem#deluxedefault-1) is implied on any container fields. In
85/// that case, a common pattern is to use an [`Option`] as the container field. It will be set to
86/// [`None`] when calling [`parse_meta_item`](deluxe_core::ParseMetaItem::parse_meta_item), but
87/// will be [`Some`] when calling
88/// [`parse_attributes`](deluxe_core::ParseAttributes::parse_attributes).
89///
90/// If used within an enum, only the first container field will supply the trait bounds. Any
91/// other container fields in other variants must have a compatible type and lifetime.
92///
93/// Fields with this attribute can safely be added to a struct or variant using
94/// [`#[deluxe(transparent)]`](ParseMetaItem#deluxetransparent). Container fields do not count as
95/// a parseable field, as they are never parsed from tokens.
96///
97/// - ##### `#[deluxe(container(lifetime = 't, ty = path::MyType)]`
98///
99/// Specifies that this field should store the current `obj` being parsed by
100/// [`parse_attributes`](deluxe_core::ParseAttributes::parse_attributes), with a custom lifetime
101/// and type bound used for the [`ParseAttributes`](deluxe_core::ParseAttributes) trait
102/// implementation.
103///
104/// Normally the `lifetime` and `ty` are not needed when using
105/// [`#[deluxe(container)]`](#deluxecontainer) because the macro can infer the lifetime and type
106/// from the field itself. If Deluxe is unable to infer them, these attributes can be supplied to
107/// manually provide the lifetime and type. `lifetime` can be omitted if the container is an
108/// owning type.
109///
110/// This attribute is implemented by calling methods on the
111/// [`ContainerFrom`](deluxe_core::ContainerFrom) trait. Other container types besides references
112/// and [`Option`] will also need to provide an implementation for that trait.
113#[proc_macro_derive(ParseAttributes, attributes(deluxe))]
114pub fn derive_parse_attributes(item: TokenStream) -> TokenStream {
115 let errors = Errors::new();
116 let mut tokens = util::parse::<syn::DeriveInput>(item, &errors)
117 .map(|input| {
118 parse_attributes::impl_parse_attributes(input, &errors, parse_attributes::Mode::Parse)
119 })
120 .unwrap_or_default();
121 tokens.extend(errors.into_compile_errors());
122 tokens.into()
123}
124
125/// Generates [`ParseMetaItem`](deluxe_core::ParseMetaItem) for a struct or enum.
126///
127/// ### Container Attributes
128///
129/// The following attributes are supported on structs and enums:
130///
131/// - ##### `#[deluxe(default)]`
132///
133/// Initializes the container with [`Default::default`] before parsing.
134///
135/// - ##### `#[deluxe(default = expr)]`
136///
137/// Initializes the container with the value of `expr` before parsing. The expression will
138/// be evaluated every time it is needed to construct the field, and must evaluate to a value of
139/// the same type as the field.
140///
141/// - ##### `#[deluxe(transparent)]`
142///
143/// Parses a struct with one field as if it were the field. Can only be used on a struct with a
144/// single parseable field. Analogous to `#[repr(transparent)]`. The struct can still contain
145/// fields that are [`skip`](#deluxeskip-1), as those will be ignored by `transparent`.
146///
147/// - ##### `#[deluxe(transparent(flatten_named)]`
148///
149/// `#[deluxe(transparent(flatten_unnamed)]`
150///
151/// `#[deluxe(transparent(flatten_unnamed, append)]`
152///
153/// `#[deluxe(transparent(rest)]`
154///
155/// Parses a struct with one field as if it were the field, additionally implementing the traits
156/// required to use `flatten`, `rest`, or `append`. Can only be used on a struct with a
157/// single parseable field.
158///
159/// Currently, it is required to provide these additional attributes to generate the trait
160/// definitions to use [`flatten`](#deluxeflatten-1), [`append`](#deluxeappend) or
161/// [`rest`](#deluxerest) on this type.
162///
163/// - ##### `#[deluxe(and_then = expr)]`
164///
165/// Executes an additional function ater parsing to perform additional transformations or
166/// validation on the input.
167///
168/// This attribute is a simple wrapper around
169/// [`Result::and_then`](deluxe_core::Result::and_then). The function returned by `expr` must
170/// conform to the signature <code>fn(T) -> [deluxe::Result](deluxe_core::Result)<T></code>
171/// where `T` is the type of the struct/enum being parsed. Returning
172/// [`Err`](deluxe_core::Result::Err) will cause the entire parse to fail.
173///
174/// This attribute can be specified multiple times. When multiple `and_then` attributes are
175/// present, Deluxe will chain each function in the order the attributes were specified.
176///
177/// ##### Example
178///
179/// ```ignore
180/// #[derive(deluxe::ParseMetaItem)]
181/// #[deluxe(and_then = Self::validate)]
182/// struct Data(i32);
183/// impl Data {
184/// fn validate(self) -> deluxe::Result<Self> {
185/// // ... perform some checks here ...
186/// Ok(self)
187/// }
188/// }
189/// ```
190///
191/// - ##### `#[deluxe(allow_unknown_fields)]`
192///
193/// Ignore any tokens and do not generate an error when an unknown field is encountered.
194///
195/// - ##### `#[deluxe(crate = path)]`
196///
197/// Specifies `path` as a custom path to the `deluxe` crate. Useful if `proc_macro_crate` is
198/// unable to find the `deluxe` crate, for instance if the crate is only re-exported inside
199/// another dependency.
200///
201/// ### Variant Attributes
202///
203/// The following attributes are supported on variants:
204///
205/// - ##### `#[deluxe(rename = ident)]`
206///
207/// Parse the variant with the given `ident` instead of its Rust name.
208///
209/// - ##### `#[deluxe(alias = ident)]`
210///
211/// Parse the variant with the given `ident`, or its Rust name. Can be repeated multiple times to
212/// provide additional aliases.
213///
214/// - ##### `#[deluxe(transparent)]`
215///
216/// Parses a variant with one field as if it were the field. Can only be used on a variant with a
217/// single parseable field. Analogous to `#[repr(transparent)]`. The variant can still contain
218/// fields that are [`skip`](#deluxeskip-1), as those will be ignored by `transparent`.
219///
220/// - ##### `#[deluxe(flatten)]`
221///
222/// Flattens the variant so that its unique fields are used as the key for this variant instead
223/// of its name. Can be used on multiple variants as long as they each have a unique set of
224/// parseable fields that can be used to identify the variant. Fields with
225/// [`flatten`](#deluxeflatten-1), [`append`](#deluxeappend) or [`rest`](#deluxerest) are not
226/// counted as unique fields as their field names are ignored.
227///
228/// A single variant with no parseable fields can also be flattened. In that case, that variant
229/// will always be parsed as the default variant. Setting a default variant in this way is
230/// mutually exclusive with using [`#[deluxe(default)]`](#deluxedefault) on the enum.
231///
232/// - ##### `#[deluxe(skip)]`
233///
234/// Skips this variant from parsing entirely.
235///
236/// - ##### `#[deluxe(allow_unknown_fields)]`
237///
238/// Ignore any tokens and do not generate an error when an unknown field is encountered in this
239/// variant.
240///
241/// ### Field Attributes
242///
243/// The following attributes are supported on struct fields and enum fields:
244///
245/// - ##### `#[deluxe(rename = ident)]`
246///
247/// Parse the field with the given `ident` instead of its Rust name.
248///
249/// - ##### `#[deluxe(alias = ident)]`
250///
251/// Parse the field with the given `ident`, or its Rust name. Can be repeated multiple times to
252/// provide additional aliases.
253///
254/// - ##### `#[deluxe(default)]`
255///
256/// Initializes the field with the value of [`Default::default`] if the field is omitted.
257///
258/// It is not necessary to use this on fields of type [`Option`] or [`Flag`](deluxe_core::Flag),
259/// or any other type that has a top-level [`#[deluxe(default)]`](#deluxedefault) on the type
260/// itself.
261///
262/// - ##### `#[deluxe(default = expr)]`
263///
264/// Initializes the field with the value of `expr` if the field is omitted. The expression will
265/// be evaluated every time it is needed to construct the field, and must evaluate to a value of
266/// the same type as the field.
267///
268/// - ##### `#[deluxe(flatten)]`
269///
270/// Flattens the field so that its fields are parsed inline as part of the current struct or enum
271/// variant.
272///
273/// When the container uses named fields, only enums or other structs with named fields can be
274/// flattened. The fields from the flattened field can be freely interspersed with the fields
275/// from the containing struct or variant. This has the effect of making it so the order of
276/// flattened fields does not matter when using named fields.
277///
278/// When the container uses unnamed fields, only unnamed structs, tuples, and collections/arrays
279/// can be flattened. The order of flattened unnamed fields is important. The fields of the
280/// flattened structure will be consumed starting from the position of the field in the
281/// containing tuple. Flattening a collection into a tuple struct/variant without a finite size
282/// will consume all fields from that position until the end.
283///
284/// This attribute is implemented by either calling
285/// [`ParseMetaFlatUnnamed::parse_meta_flat_unnamed`](deluxe_core::ParseMetaFlatUnnamed::parse_meta_flat_unnamed)
286/// or
287/// [`ParseMetaFlatNamed::parse_meta_flat_named`](deluxe_core::ParseMetaFlatNamed::parse_meta_flat_named)
288/// depending on the type of the containing structure. The appropriate trait will be
289/// automatically implemented when deriving [`ParseMetaItem`], but some implementations are
290/// provided for common collection types. Custom container types can support flattening by
291/// providing implementations of those traits.
292///
293/// - ##### `#[deluxe(flatten(prefix = path)])`
294///
295/// Flattens the field so that its fields are parsed inline as part of the current struct or enum
296/// variant, only accepting fields that are prefixed with `path`. This can be used if the
297/// flattened structure contains field names that conflict with the fields in the containing
298/// structure.
299///
300/// For all other details on this attribute, refer to [`flatten`](#deluxeflatten-1).
301///
302/// - ##### `#[deluxe(append)]`
303///
304/// Allows duplicates of this field. Additional fields parsed with the same name will be appended
305/// on to the previous value. This attribute is only allowed on named fields.
306///
307/// This attribute is implemented by calling
308/// [`ParseMetaAppend::parse_meta_append`](deluxe_core::ParseMetaAppend::parse_meta_append). Some
309/// implementations are provided for common collection types. Custom container types can support
310/// appending by providing an implementation of that trait.
311///
312/// - ##### `#[deluxe(rest)]`
313///
314/// Inserts all unknown fields into this field. Typically, this field will be a map type with
315/// [`syn::Path`] as the key. This attribute is only allowed on named fields.
316///
317/// This attribute is implemented by calling
318/// [`ParseMetaRest::parse_meta_rest`](deluxe_core::ParseMetaRest::parse_meta_rest). Some
319/// implementations are provided for common collection types. Custom map types can be allowed as
320/// a rest field by providing an implementation of that trait.
321///
322/// - ##### `#[deluxe(map = expr)]`
323///
324/// `#[deluxe(and_then = expr)]`
325///
326/// Executes additional functions ater parsing to perform additional transformations or
327/// validation on the input.
328///
329/// These attributes are simple wrappers around [`Result::map`](deluxe_core::Result::map) and
330/// [`Result::and_then`](deluxe_core::Result::and_then). These attributes can be specified
331/// multiple times. When multiple are present, Deluxe will chain each function in the order the
332/// attributes were specified.
333///
334/// For `map`, the function returned by `expr` must conform to the signature `fn(T) -> U`. For
335/// `and_then`, the function returned by `expr` must conform to the signature <code>fn(T) ->
336/// [deluxe::Result](deluxe_core::Result)<U></code>. Returning
337/// [`Err`](deluxe_core::Result::Err) will cause the entire parse to fail. Arbitrary types can be
338/// used for `T` and `U` as long as the following constraints hold:
339///
340/// - The first function must have a fully specified type for `T`, which will have its
341/// [`ParseMetaItem`](deluxe_core::ParseMetaItem) implementation used.
342/// - The `U from any function in the chain matches the `T` for the following function.
343/// - The last function must have a type for `U` that matches the type of the field.
344///
345/// ##### Example
346///
347/// ```ignore
348/// #[derive(deluxe::ParseMetaItem)]
349/// struct Data {
350/// // parses as an Ident but stored as a string
351/// #[deluxe(map = |i: syn::Ident| i.to_string())]
352/// ident_string: String,
353/// // converts an Ident to a string and does a validation
354/// #[deluxe(and_then = Self::check_ident)]
355/// valid_ident_string: String,
356/// }
357///
358/// impl Data {
359/// fn check_ident(i: syn::Ident) -> deluxe::Result<String> {
360/// let s = i.to_string();
361/// if s == "invalid" {
362/// Err(syn::Error::new(i.span(), "`invalid` not allowed"))
363/// } else {
364/// Ok(s)
365/// }
366/// }
367/// }
368/// ```
369///
370/// - ##### `#[deluxe(with = module)]`
371///
372/// When parsing, call functions from the path `module` instead of attempting to call
373/// [`ParseMetaItem`](deluxe_core::ParseMetaItem) functions. The path can be a module path or a
374/// path to a type containing associated functions.
375///
376/// The functions will be called as `module::parse_meta_item`, `module::parse_meta_item_inline`,
377/// `module::parse_meta_item_flag`, `module::parse_meta_item_named`, and
378/// `module::missing_meta_item`. All five functions must be implemented, even if just to return
379/// an error. The signatures of these functions should match the equivalent functions in
380/// [`ParseMetaItem`](crate::ParseMetaItem), although they can be generic over the return type.
381/// Fields using this attribute are not required to implement
382/// [`ParseMetaItem`](crate::ParseMetaItem).
383///
384/// `parse_meta_item_inline` implementations can call
385/// [`parse_first`](deluxe_core::parse_helpers::parse_first) to simply delegate the impementation
386/// to `parse_meta_item`. `parse_meta_item_flag` implementations can call
387/// [`flag_disallowed_error`](deluxe_core::parse_helpers::flag_disallowed_error) for a standard
388/// error if flags are not supported by the target type. `parse_meta_item_named` implementations
389/// can call [`parse_named_meta_item_with!`](deluxe_core::parse_named_meta_item_with) using
390/// `self` as the last parameter for the standard behavior.
391///
392/// Some common parsers are available in the [`with`](deluxe_core::with) module.
393///
394/// - ##### `#[deluxe(skip)]`
395///
396/// Skips this field from parsing entirely. The field still must receive a default value through
397/// a `default` attribute either on the struct or the field, so the parse function can still
398/// construct the object. If not used in a struct with [`default`](#deluxedefault), then this
399/// implies [`default`](#deluxedefault-1) on the field if it is omitted.
400#[proc_macro_derive(ParseMetaItem, attributes(deluxe))]
401pub fn derive_parse_meta_item(item: TokenStream) -> TokenStream {
402 let errors = Errors::new();
403 let mut tokens = util::parse::<syn::DeriveInput>(item, &errors)
404 .map(|input| parse_meta_item::impl_parse_meta_item(input, &errors))
405 .unwrap_or_default();
406 tokens.extend(errors.into_compile_errors());
407 tokens.into()
408}