Skip to main content

serde_with_macros/
lib.rs

1// Cleanup when workspace lints can be overridden
2// https://github.com/rust-lang/cargo/issues/13157
3#![forbid(unsafe_code)]
4#![warn(missing_copy_implementations, missing_debug_implementations)]
5#![doc(test(attr(
6    // Problematic handling for foreign From<T> impls in tests
7    // https://github.com/rust-lang/rust/issues/121621
8    allow(unknown_lints, non_local_definitions),
9    deny(
10        missing_debug_implementations,
11        rust_2018_idioms,
12        trivial_casts,
13        trivial_numeric_casts,
14        unused_extern_crates,
15        unused_import_braces,
16        unused_qualifications,
17        warnings,
18    ),
19    forbid(unsafe_code),
20)))]
21// Not needed for 2018 edition and conflicts with `rust_2018_idioms`
22#![doc(test(no_crate_inject))]
23#![doc(html_root_url = "https://docs.rs/serde_with_macros/3.22.0/")]
24// Tarpaulin does not work well with proc macros and marks most of the lines as uncovered.
25#![cfg(not(tarpaulin_include))]
26
27//! proc-macro extensions for [`serde_with`].
28//!
29//! This crate should **NEVER** be used alone.
30//! All macros **MUST** be used via the re-exports in the [`serde_with`] crate.
31//!
32//! [`serde_with`]: https://crates.io/crates/serde_with/
33
34mod apply;
35mod lazy_bool;
36mod utils;
37
38use crate::utils::{
39    split_with_de_lifetime, DeriveOptions, IteratorExt as _, SchemaFieldCondition,
40    SchemaFieldConfig,
41};
42use darling::{
43    ast::NestedMeta,
44    util::{Flag, Override},
45    Error as DarlingError, FromField, FromMeta,
46};
47use proc_macro::TokenStream;
48use proc_macro2::{Span, TokenStream as TokenStream2};
49use quote::quote;
50use syn::{
51    parse::Parser,
52    parse_macro_input, parse_quote,
53    punctuated::{Pair, Punctuated},
54    spanned::Spanned,
55    DeriveInput, Error, Field, Fields, GenericArgument, ItemEnum, ItemStruct, Meta, Path,
56    PathArguments, ReturnType, Token, Type,
57};
58
59/// Apply function on every field of structs or enums
60fn apply_function_to_struct_and_enum_fields<F>(
61    input: TokenStream,
62    function: F,
63) -> Result<TokenStream2, Error>
64where
65    F: Copy,
66    F: Fn(&mut Field) -> Result<(), String>,
67{
68    /// Handle a single struct or a single enum variant
69    fn apply_on_fields<F>(fields: &mut Fields, function: F) -> Result<(), Error>
70    where
71        F: Fn(&mut Field) -> Result<(), String>,
72    {
73        match fields {
74            // simple, no fields, do nothing
75            Fields::Unit => Ok(()),
76            Fields::Named(fields) => fields
77                .named
78                .iter_mut()
79                .map(|field| function(field).map_err(|err| Error::new(field.span(), err)))
80                .collect_error(),
81            Fields::Unnamed(fields) => fields
82                .unnamed
83                .iter_mut()
84                .map(|field| function(field).map_err(|err| Error::new(field.span(), err)))
85                .collect_error(),
86        }
87    }
88
89    // For each field in the struct given by `input`, add the `skip_serializing_if` attribute,
90    // if and only if, it is of type `Option`
91    if let Ok(mut input) = syn::parse::<ItemStruct>(input.clone()) {
92        apply_on_fields(&mut input.fields, function)?;
93        Ok(quote!(#input))
94    } else if let Ok(mut input) = syn::parse::<ItemEnum>(input) {
95        input
96            .variants
97            .iter_mut()
98            .map(|variant| apply_on_fields(&mut variant.fields, function))
99            .collect_error()?;
100        Ok(quote!(#input))
101    } else {
102        Err(Error::new(
103            Span::call_site(),
104            "The attribute can only be applied to struct or enum definitions.",
105        ))
106    }
107}
108
109/// Like [`apply_function_to_struct_and_enum_fields`] but for darling errors
110fn apply_function_to_struct_and_enum_fields_darling<F>(
111    input: TokenStream,
112    serde_with_crate_path: &Path,
113    function: F,
114) -> Result<TokenStream2, DarlingError>
115where
116    F: Copy,
117    F: Fn(&mut Field) -> Result<(), DarlingError>,
118{
119    /// Handle a single struct or a single enum variant
120    fn apply_on_fields<F>(fields: &mut Fields, function: F) -> Result<(), DarlingError>
121    where
122        F: Fn(&mut Field) -> Result<(), DarlingError>,
123    {
124        match fields {
125            // simple, no fields, do nothing
126            Fields::Unit => Ok(()),
127            Fields::Named(ref mut fields) => {
128                let errors: Vec<DarlingError> = fields
129                    .named
130                    .iter_mut()
131                    .map(|field| function(field).map_err(|err| err.with_span(&field)))
132                    // turn the Err variant into the Some, such that we only collect errors
133                    .filter_map(Result::err)
134                    .collect();
135                if errors.is_empty() {
136                    Ok(())
137                } else {
138                    Err(DarlingError::multiple(errors))
139                }
140            }
141            Fields::Unnamed(fields) => {
142                let errors: Vec<DarlingError> = fields
143                    .unnamed
144                    .iter_mut()
145                    .map(|field| function(field).map_err(|err| err.with_span(&field)))
146                    // turn the Err variant into the Some, such that we only collect errors
147                    .filter_map(Result::err)
148                    .collect();
149                if errors.is_empty() {
150                    Ok(())
151                } else {
152                    Err(DarlingError::multiple(errors))
153                }
154            }
155        }
156    }
157
158    // Add a dummy derive macro which consumes (makes inert) all field attributes
159    let consume_serde_as_attribute = parse_quote!(
160        #[derive(#serde_with_crate_path::__private_consume_serde_as_attributes)]
161    );
162
163    // For each field in the struct given by `input`, add the `skip_serializing_if` attribute,
164    // if and only if, it is of type `Option`
165    if let Ok(mut input) = syn::parse::<ItemStruct>(input.clone()) {
166        apply_on_fields(&mut input.fields, function)?;
167        input.attrs.push(consume_serde_as_attribute);
168        Ok(quote!(#input))
169    } else if let Ok(mut input) = syn::parse::<ItemEnum>(input) {
170        // Prevent serde_as on enum variants
171        let mut errors: Vec<DarlingError> = input
172            .variants
173            .iter()
174            .flat_map(|variant| {
175                variant.attrs.iter().filter_map(|attr| {
176                    if attr.path().is_ident("serde_as") {
177                        Some(
178                            DarlingError::custom(
179                                "serde_as attribute is not allowed on enum variants",
180                            )
181                            .with_span(&attr),
182                        )
183                    } else {
184                        None
185                    }
186                })
187            })
188            .collect();
189        // Process serde_as on all fields
190        errors.extend(
191            input
192                .variants
193                .iter_mut()
194                .map(|variant| apply_on_fields(&mut variant.fields, function))
195                // turn the Err variant into the Some, such that we only collect errors
196                .filter_map(Result::err),
197        );
198
199        if errors.is_empty() {
200            input.attrs.push(consume_serde_as_attribute);
201            Ok(quote!(#input))
202        } else {
203            Err(DarlingError::multiple(errors))
204        }
205    } else {
206        Err(DarlingError::custom(
207            "The attribute can only be applied to struct or enum definitions.",
208        )
209        .with_span(&Span::call_site()))
210    }
211}
212
213/// Add `skip_serializing_if` annotations to [`Option`] fields.
214///
215/// The attribute can be added to structs and enums.
216/// The `#[skip_serializing_none]` attribute must be placed *before* the `#[derive]` attribute.
217///
218/// # Example
219///
220/// JSON APIs sometimes have many optional values.
221/// Missing values should not be serialized, to keep the serialized format smaller.
222/// Such a data type might look like:
223///
224/// ```rust
225/// # use serde::Serialize;
226/// #
227/// # #[allow(dead_code)]
228/// #[derive(Serialize)]
229/// struct Data {
230///     #[serde(skip_serializing_if = "Option::is_none")]
231///     a: Option<String>,
232///     #[serde(skip_serializing_if = "Option::is_none")]
233///     b: Option<u64>,
234///     #[serde(skip_serializing_if = "Option::is_none")]
235///     c: Option<String>,
236///     #[serde(skip_serializing_if = "Option::is_none")]
237///     d: Option<bool>,
238/// }
239/// ```
240///
241/// The `skip_serializing_if` annotation is repetitive and harms readability.
242/// Instead, the same struct can be written as:
243///
244/// ```rust
245/// # use serde::Serialize;
246/// # use serde_with_macros::skip_serializing_none;
247/// #
248/// # #[allow(dead_code)]
249/// #[skip_serializing_none]
250/// #[derive(Serialize)]
251/// struct Data {
252///     a: Option<String>,
253///     b: Option<u64>,
254///     c: Option<String>,
255///     // Always serialize field d even if None
256///     #[serialize_always]
257///     d: Option<bool>,
258/// }
259/// ```
260///
261/// Existing `skip_serializing_if` annotations will not be altered.
262///
263/// If some values should always be serialized, then `serialize_always` can be used.
264///
265/// # Limitations
266///
267/// The `serialize_always` cannot be used together with a manual `skip_serializing_if` annotations,
268/// as these conflict in their meaning. A compile error will be generated if this occurs.
269///
270/// The `skip_serializing_none` only works if the type is called `Option`,
271/// `std::option::Option`, or `core::option::Option`. Type aliasing an [`Option`] and giving it
272/// another name, will cause this field to be ignored. This cannot be supported, as proc-macros run
273/// before type checking, thus it is not possible to determine if a type alias refers to an
274/// [`Option`].
275///
276/// ```rust
277/// # use serde::Serialize;
278/// # use serde_with_macros::skip_serializing_none;
279/// # #[allow(dead_code)]
280/// type MyOption<T> = Option<T>;
281///
282/// # #[allow(dead_code)]
283/// #[skip_serializing_none]
284/// #[derive(Serialize)]
285/// struct Data {
286///     a: MyOption<String>, // This field will not be skipped
287/// }
288/// ```
289///
290/// Likewise, if you import a type and name it `Option`, the `skip_serializing_if` attributes will
291/// be added and compile errors will occur, if `Option::is_none` is not a valid function.
292/// Here the function `Vec::is_none` does not exist, and therefore the example fails to compile.
293///
294/// ```rust,compile_fail
295/// # use serde::Serialize;
296/// # use serde_with_macros::skip_serializing_none;
297/// use std::vec::Vec as Option;
298///
299/// #[skip_serializing_none]
300/// #[derive(Serialize)]
301/// struct Data {
302///     a: Option<String>,
303/// }
304/// ```
305#[proc_macro_attribute]
306pub fn skip_serializing_none(_args: TokenStream, input: TokenStream) -> TokenStream {
307    let res =
308        apply_function_to_struct_and_enum_fields(input, skip_serializing_none_add_attr_to_field)
309            .unwrap_or_else(|err| err.to_compile_error());
310    TokenStream::from(res)
311}
312
313/// Add the `skip_serializing_if` annotation to each field of the struct
314fn skip_serializing_none_add_attr_to_field(field: &mut Field) -> Result<(), String> {
315    if is_std_option(&field.ty) {
316        let has_skip_serializing_if = field_has_attribute(field, "serde", "skip_serializing_if");
317
318        // Remove the `serialize_always` attribute
319        let mut has_always_attr = false;
320        field.attrs.retain(|attr| {
321            let has_attr = attr.path().is_ident("serialize_always");
322            has_always_attr |= has_attr;
323            !has_attr
324        });
325
326        // Error on conflicting attributes
327        if has_always_attr && has_skip_serializing_if {
328            let mut msg = r#"The attributes `serialize_always` and `serde(skip_serializing_if = "...")` cannot be used on the same field"#.to_string();
329            if let Some(ident) = &field.ident {
330                msg += ": `";
331                msg += &ident.to_string();
332                msg += "`";
333            }
334            msg += ".";
335            return Err(msg);
336        }
337
338        // Do nothing if `skip_serializing_if` or `serialize_always` is already present
339        if has_skip_serializing_if || has_always_attr {
340            return Ok(());
341        }
342
343        // Add the `skip_serializing_if` attribute
344        let attr = parse_quote!(
345            #[serde(skip_serializing_if = "Option::is_none")]
346        );
347        field.attrs.push(attr);
348    } else {
349        // Warn on use of `serialize_always` on non-Option fields
350        let has_attr = field
351            .attrs
352            .iter()
353            .any(|attr| attr.path().is_ident("serialize_always"));
354        if has_attr {
355            return Err("`serialize_always` may only be used on fields of type `Option`.".into());
356        }
357    }
358    Ok(())
359}
360
361/// Return `true`, if the type path refers to `std::option::Option`
362///
363/// Accepts
364///
365/// * `Option`
366/// * `std::option::Option`, with or without leading `::`
367/// * `core::option::Option`, with or without leading `::`
368fn is_std_option(type_: &Type) -> bool {
369    match type_ {
370        Type::Array(_)
371        | Type::BareFn(_)
372        | Type::ImplTrait(_)
373        | Type::Infer(_)
374        | Type::Macro(_)
375        | Type::Never(_)
376        | Type::Ptr(_)
377        | Type::Reference(_)
378        | Type::Slice(_)
379        | Type::TraitObject(_)
380        | Type::Tuple(_)
381        | Type::Verbatim(_) => false,
382
383        Type::Group(syn::TypeGroup { elem, .. })
384        | Type::Paren(syn::TypeParen { elem, .. })
385        | Type::Path(syn::TypePath {
386            qself: Some(syn::QSelf { ty: elem, .. }),
387            ..
388        }) => is_std_option(elem),
389
390        Type::Path(syn::TypePath { qself: None, path }) => {
391            (path.leading_colon.is_none()
392                && path.segments.len() == 1
393                && path.segments[0].ident == "Option")
394                || (path.segments.len() == 3
395                    && (path.segments[0].ident == "std" || path.segments[0].ident == "core")
396                    && path.segments[1].ident == "option"
397                    && path.segments[2].ident == "Option")
398        }
399        _ => false,
400    }
401}
402
403/// Determine if the `field` has an attribute with given `namespace` and `name`
404///
405/// On the example of
406/// `#[serde(skip_serializing_if = "Option::is_none")]`
407///
408/// * `serde` is the outermost path, here namespace
409/// * it contains a `Meta::List`
410/// * which contains in another Meta a `Meta::NameValue`
411/// * with the name being `skip_serializing_if`
412fn field_has_attribute(field: &Field, namespace: &str, name: &str) -> bool {
413    for attr in &field.attrs {
414        if attr.path().is_ident(namespace) {
415            // Ignore non parsable attributes, as these are not important for us
416            if let Meta::List(expr) = &attr.meta {
417                let nested = match Punctuated::<Meta, Token![,]>::parse_terminated
418                    .parse2(expr.tokens.clone())
419                {
420                    Ok(nested) => nested,
421                    Err(_) => continue,
422                };
423                for expr in nested {
424                    match expr {
425                        Meta::NameValue(expr) => {
426                            if let Some(ident) = expr.path.get_ident() {
427                                if *ident == name {
428                                    return true;
429                                }
430                            }
431                        }
432                        Meta::Path(expr) => {
433                            if let Some(ident) = expr.get_ident() {
434                                if *ident == name {
435                                    return true;
436                                }
437                            }
438                        }
439                        _ => (),
440                    }
441                }
442            }
443        }
444    }
445    false
446}
447
448/// Convenience macro to use the [`serde_as`] system.
449///
450/// The [`serde_as`] system is designed as a more flexible alternative to serde's `with` annotation.
451/// The `#[serde_as]` attribute must be placed *before* the `#[derive]` attribute.
452/// Each field of a struct or enum can be annotated with `#[serde_as(...)]` to specify which
453/// transformations should be applied. `serde_as` is *not* supported on enum variants.
454/// This is in contrast to `#[serde(with = "...")]`.
455///
456/// # Example
457///
458/// ```rust,ignore
459/// use serde_with::{serde_as, BytesOrString, DisplayFromStr, Map};
460///
461/// #[serde_as]
462/// #[derive(Serialize, Deserialize)]
463/// struct Data {
464///     /// Serialize into number
465///     #[serde_as(as = "_")]
466///     a: u32,
467///
468///     /// Serialize into String, deserialize from Bytes or String
469///     #[serde_as(
470///         serialize_as = "DisplayFromStr",
471///         deserialize_as = "BytesOrString"
472///     )]
473///     b: u32,
474///
475///     /// Serialize into a map from String to String
476///     #[serde_as(as = "Map<DisplayFromStr, _>")]
477///     c: Vec<(u32, String)>,
478/// }
479/// ```
480///
481/// # Alternative path to `serde_with` crate
482///
483/// If `serde_with` is not available at the default path, its path should be specified with the
484/// `crate` argument. See [re-exporting `serde_as`] for more use case information.
485///
486/// ```rust,ignore
487/// #[serde_as(crate = "::some_other_lib::serde_with")]
488/// #[derive(Deserialize)]
489/// struct Data {
490///     #[serde_as(as = "_")]
491///     a: u32,
492/// }
493/// ```
494///
495/// # What this macro does
496///
497/// The `serde_as` macro only serves a convenience function.
498/// All the steps it performs, can easily be done manually, in case the cost of an attribute macro
499/// is deemed too high. The functionality can best be described with an example.
500///
501/// ```rust,ignore
502/// #[serde_as]
503/// #[derive(serde::Serialize)]
504/// struct Foo {
505///     #[serde_as(as = "Vec<_>")]
506///     bar: Vec<u32>,
507///
508///     #[serde_as(as = "Option<DisplayFromStr>")]
509///     baz: Option<u32>,
510/// }
511/// ```
512///
513/// 1. All the placeholder type `_` will be replaced with `::serde_with::Same`.
514///    The placeholder type `_` marks all the places where the type's `Serialize` implementation
515///    should be used. In the example, it means that the `u32` values will serialize with the
516///    `Serialize` implementation of `u32`. The `Same` type implements `SerializeAs` whenever the
517///    underlying type implements `Serialize` and is used to make the two traits compatible.
518///
519///    If you specify a custom path for `serde_with` via the `crate` attribute, the path to the
520///    `Same` type will be altered accordingly.
521///
522/// 2. Wrap the type from the annotation inside a `::serde_with::As`.
523///    In the above example we now have something like `::serde_with::As::<Vec<::serde_with::Same>>`.
524///    The `As` type acts as the opposite of the `Same` type.
525///    It allows using a `SerializeAs` type whenever a `Serialize` is required.
526///
527/// 3. Translate the `*as` attributes into the serde equivalent ones.
528///    `#[serde_as(as = ...)]` will become `#[serde(with = ...)]`.
529///    Similarly, `serialize_as` is translated to `serialize_with`.
530///
531///    The field attributes will be kept on the struct/enum such that other macros can use them
532///    too.
533///
534/// 4. It searches `#[serde_as(as = ...)]` if there is a type named `BorrowCow` under any path.
535///    If `BorrowCow` is found, the attribute `#[serde(borrow)]` is added to the field.
536///    If `#[serde(borrow)]` or `#[serde(borrow = "...")]` is already present, this step will be
537///    skipped.
538///
539/// 5. Restore the ability of accepting missing fields if both the field and the transformation are `Option`.
540///
541///    An `Option` is detected by an exact text match.
542///    Renaming an import or type aliases can cause confusion here.
543///    The following variants are supported.
544///    * `Option`
545///    * `std::option::Option`, with or without leading `::`
546///    * `core::option::Option`, with or without leading `::`
547///
548///    If the field is of type `Option<T>` and the attribute `#[serde_as(as = "Option<S>")]` (also
549///    `deserialize_as`; for any `T`/`S`) then `#[serde(default)]` is applied to the field.
550///
551///    This restores the ability of accepting missing fields, which otherwise often leads to confusing [serde_with#185](https://github.com/jonasbb/serde_with/issues/185).
552///    `#[serde(default)]` is not applied, if it already exists.
553///    It only triggers if both field and transformation are `Option`s.
554///    For example, using `#[serde_as(as = "NoneAsEmptyString")]` on `Option<String>` will not see
555///    any change.
556///
557///    If the automatically applied attribute is undesired, the behavior can be suppressed by adding
558///    `#[serde_as(no_default)]`.
559///
560///     This can be combined like `#[serde_as(as = "Option<S>", no_default)]`.
561///
562/// After all these steps, the code snippet will have transformed into roughly this.
563///
564/// ```rust,ignore
565/// #[derive(serde::Serialize)]
566/// struct Foo {
567///     #[serde_as(as = "Vec<_>")]
568///     #[serde(with = "::serde_with::As::<Vec<::serde_with::Same>>")]
569///     bar: Vec<u32>,
570///
571///     #[serde_as(as = "Option<DisplayFromStr>")]
572///     #[serde(default)]
573///     #[serde(with = "::serde_with::As::<Option<DisplayFromStr>>")]
574///     baz: Option<u32>,
575/// }
576/// ```
577///
578/// # A note on `schemars` integration
579/// When the `schemars_0_8`, `schemars_0_9`, or `schemars_1` features are enabled this macro
580/// will scan for
581/// `#[derive(JsonSchema)]` attributes and, if found, will add
582/// `#[schemars(with = "Schema<T, ...>")]` annotations to any fields with a
583/// `#[serde_as(as = ...)]` annotation. If you wish to override the default
584/// behavior here you can add `#[serde_as(schemars = true)]` or
585/// `#[serde_as(schemars = false)]`.
586///
587/// Note that this macro will check for any of the following derive paths:
588/// * `JsonSchema`
589/// * `schemars::JsonSchema`
590/// * `::schemars::JsonSchema`
591///
592/// It will also work if the relevant derive is behind a `#[cfg_attr]` attribute
593/// and propagate the `#[cfg_attr]` to the various `#[schemars]` field attributes.
594///
595/// [`serde_as`]: https://docs.rs/serde_with/3.22.0/serde_with/guide/index.html
596/// [re-exporting `serde_as`]: https://docs.rs/serde_with/3.22.0/serde_with/guide/serde_as/index.html#re-exporting-serde_as
597#[proc_macro_attribute]
598pub fn serde_as(args: TokenStream, input: TokenStream) -> TokenStream {
599    #[derive(FromMeta)]
600    struct SerdeContainerOptions {
601        #[darling(rename = "crate")]
602        alt_crate_path: Option<Path>,
603        #[darling(rename = "schemars")]
604        enable_schemars_support: Option<bool>,
605    }
606
607    match NestedMeta::parse_meta_list(args.into()) {
608        Ok(list) => {
609            let container_options = match SerdeContainerOptions::from_list(&list) {
610                Ok(v) => v,
611                Err(e) => {
612                    return TokenStream::from(e.write_errors());
613                }
614            };
615
616            let serde_with_crate_path = container_options
617                .alt_crate_path
618                .unwrap_or_else(|| syn::parse_quote!(::serde_with));
619
620            let schemars_config = match container_options.enable_schemars_support {
621                _ if cfg!(not(any(
622                    feature = "schemars_0_8",
623                    feature = "schemars_0_9",
624                    feature = "schemars_1"
625                ))) =>
626                {
627                    SchemaFieldConfig::False
628                }
629                Some(condition) => condition.into(),
630                None => utils::has_derive_jsonschema(input.clone()).unwrap_or_default(),
631            };
632
633            // Convert any error message into a nice compiler error
634            let res = apply_function_to_struct_and_enum_fields_darling(
635                input,
636                &serde_with_crate_path,
637                |field| serde_as_add_attr_to_field(field, &serde_with_crate_path, &schemars_config),
638            )
639            .unwrap_or_else(darling::Error::write_errors);
640            TokenStream::from(res)
641        }
642        Err(e) => TokenStream::from(DarlingError::from(e).write_errors()),
643    }
644}
645
646/// Inspect the field and convert the `serde_as` attribute into the classical `serde`
647fn serde_as_add_attr_to_field(
648    field: &mut Field,
649    serde_with_crate_path: &Path,
650    schemars_config: &SchemaFieldConfig,
651) -> Result<(), DarlingError> {
652    #[derive(FromField)]
653    #[darling(attributes(serde_as))]
654    struct SerdeAsOptions {
655        /// The original type of the field
656        ty: Type,
657
658        r#as: Option<Type>,
659        deserialize_as: Option<Type>,
660        serialize_as: Option<Type>,
661        no_default: Flag,
662    }
663
664    impl SerdeAsOptions {
665        fn has_any_set(&self) -> bool {
666            self.r#as.is_some() || self.deserialize_as.is_some() || self.serialize_as.is_some()
667        }
668    }
669
670    #[derive(FromField)]
671    #[darling(attributes(serde), allow_unknown_fields)]
672    struct SerdeOptions {
673        with: Option<String>,
674        deserialize_with: Option<String>,
675        serialize_with: Option<String>,
676
677        borrow: Option<Override<String>>,
678        default: Option<Override<String>>,
679    }
680
681    impl SerdeOptions {
682        fn has_any_set(&self) -> bool {
683            self.with.is_some() || self.deserialize_with.is_some() || self.serialize_with.is_some()
684        }
685    }
686
687    /// Emit a `borrow` annotation, if the replacement type requires borrowing.
688    fn emit_borrow_annotation(serde_options: &SerdeOptions, as_type: &Type, field: &mut Field) {
689        let type_borrowcow = &syn::parse_quote!(BorrowCow);
690        // If the field is not borrowed yet, check if we need to borrow it.
691        if serde_options.borrow.is_none() && has_type_embedded(as_type, type_borrowcow) {
692            let attr_borrow = parse_quote!(#[serde(borrow)]);
693            field.attrs.push(attr_borrow);
694        }
695    }
696
697    /// Emit a `default` annotation, if `as_type` and `field` are both `Option`.
698    fn emit_default_annotation(
699        serde_as_options: &SerdeAsOptions,
700        serde_options: &SerdeOptions,
701        as_type: &Type,
702        field: &mut Field,
703    ) {
704        if !serde_as_options.no_default.is_present()
705            && serde_options.default.is_none()
706            && is_std_option(as_type)
707            && is_std_option(&field.ty)
708        {
709            let attr_borrow = parse_quote!(#[serde(default)]);
710            field.attrs.push(attr_borrow);
711        }
712    }
713
714    // syn v2 no longer supports keywords in the path position of an attribute.
715    // That breaks #[serde_as(as = "FooBar")], since `as` is a keyword.
716    // For each attribute, that is named `serde_as`, we replace the `as` keyword with `r#as`.
717    let mut has_serde_as = false;
718    field.attrs.iter_mut().for_each(|attr| {
719        if attr.path().is_ident("serde_as") {
720            // We found a `serde_as` attribute.
721            // Remember that such that we can quick exit otherwise
722            has_serde_as = true;
723
724            if let Meta::List(metalist) = &mut attr.meta {
725                metalist.tokens = std::mem::take(&mut metalist.tokens)
726                    .into_iter()
727                    .map(|token| {
728                        use proc_macro2::{Ident, TokenTree};
729
730                        // Replace `as` with `r#as`.
731                        match token {
732                            TokenTree::Ident(ident) if ident == "as" => {
733                                TokenTree::Ident(Ident::new_raw("as", ident.span()))
734                            }
735                            _ => token,
736                        }
737                    })
738                    .collect();
739            }
740        }
741    });
742    // If there is no `serde_as` attribute, we can exit early.
743    if !has_serde_as {
744        return Ok(());
745    }
746    let serde_as_options = SerdeAsOptions::from_field(field)?;
747    let serde_options = SerdeOptions::from_field(field)?;
748
749    let mut errors = Vec::new();
750    if !serde_as_options.has_any_set() {
751        errors.push(DarlingError::custom("An empty `serde_as` attribute on a field has no effect. You are missing an `as`, `serialize_as`, or `deserialize_as` parameter."));
752    }
753
754    // Check if there are any conflicting attributes
755    if serde_as_options.has_any_set() && serde_options.has_any_set() {
756        errors.push(DarlingError::custom("Cannot combine `serde_as` with serde's `with`, `deserialize_with`, or `serialize_with`."));
757    }
758
759    if serde_as_options.r#as.is_some() && serde_as_options.deserialize_as.is_some() {
760        errors.push(DarlingError::custom("Cannot combine `as` with `deserialize_as`. Use `serialize_as` to specify different serialization code."));
761    } else if serde_as_options.r#as.is_some() && serde_as_options.serialize_as.is_some() {
762        errors.push(DarlingError::custom("Cannot combine `as` with `serialize_as`. Use `deserialize_as` to specify different deserialization code."));
763    }
764
765    if !errors.is_empty() {
766        return Err(DarlingError::multiple(errors));
767    }
768
769    let type_original = &serde_as_options.ty;
770    let type_same = &syn::parse_quote!(#serde_with_crate_path::Same);
771    if let Some(type_) = &serde_as_options.r#as {
772        emit_borrow_annotation(&serde_options, type_, field);
773        emit_default_annotation(&serde_as_options, &serde_options, type_, field);
774
775        let replacement_type = replace_infer_type_with_type(type_.clone(), type_same);
776        let attr_inner_tokens = quote!(#serde_with_crate_path::As::<#replacement_type>).to_string();
777        let attr = parse_quote!(#[serde(with = #attr_inner_tokens)]);
778        field.attrs.push(attr);
779
780        match schemars_config {
781            SchemaFieldConfig::False => {}
782            lhs => {
783                let rhs = utils::schemars_with_attr_if(
784                    &field.attrs,
785                    &["with", "serialize_with", "deserialize_with", "schema_with"],
786                )?;
787
788                match lhs & !rhs {
789                    SchemaFieldConfig::False => {}
790                    condition => {
791                        let attr_inner_tokens = quote! {
792                            #serde_with_crate_path::Schema::<#type_original, #replacement_type>
793                        };
794                        let attr_inner_tokens = attr_inner_tokens.to_string();
795                        let attr = match condition {
796                            SchemaFieldConfig::False => unreachable!(),
797                            SchemaFieldConfig::True => {
798                                parse_quote! { #[schemars(with = #attr_inner_tokens)] }
799                            }
800                            SchemaFieldConfig::Lazy(SchemaFieldCondition(condition)) => {
801                                parse_quote! {
802                                    #[cfg_attr(
803                                        #condition,
804                                        schemars(with = #attr_inner_tokens))
805                                    ]
806                                }
807                            }
808                        };
809
810                        field.attrs.push(attr);
811                    }
812                }
813            }
814        }
815    }
816    if let Some(type_) = &serde_as_options.deserialize_as {
817        emit_borrow_annotation(&serde_options, type_, field);
818        emit_default_annotation(&serde_as_options, &serde_options, type_, field);
819
820        let replacement_type = replace_infer_type_with_type(type_.clone(), type_same);
821        let attr_inner_tokens =
822            quote!(#serde_with_crate_path::As::<#replacement_type>::deserialize).to_string();
823        let attr = parse_quote!(#[serde(deserialize_with = #attr_inner_tokens)]);
824        field.attrs.push(attr);
825    }
826    if let Some(type_) = serde_as_options.serialize_as {
827        let replacement_type = replace_infer_type_with_type(type_.clone(), type_same);
828        let attr_inner_tokens =
829            quote!(#serde_with_crate_path::As::<#replacement_type>::serialize).to_string();
830        let attr = parse_quote!(#[serde(serialize_with = #attr_inner_tokens)]);
831        field.attrs.push(attr);
832    }
833
834    Ok(())
835}
836
837/// Recursively replace all occurrences of `_` with `replacement` in a [Type][]
838///
839/// The [`serde_as`][macro@serde_as] macro allows to use the infer type, i.e., `_`, as shortcut for
840/// `serde_with::As`. This function replaces all occurrences of the infer type with another type.
841fn replace_infer_type_with_type(to_replace: Type, replacement: &Type) -> Type {
842    match to_replace {
843        // Base case
844        // Replace the infer type with the actual replacement type
845        Type::Infer(_) => replacement.clone(),
846
847        // Recursive cases
848        // Iterate through all positions where a type could occur and recursively call this function
849        Type::Array(mut inner) => {
850            *inner.elem = replace_infer_type_with_type(*inner.elem, replacement);
851            Type::Array(inner)
852        }
853        Type::Group(mut inner) => {
854            *inner.elem = replace_infer_type_with_type(*inner.elem, replacement);
855            Type::Group(inner)
856        }
857        Type::Never(inner) => Type::Never(inner),
858        Type::Paren(mut inner) => {
859            *inner.elem = replace_infer_type_with_type(*inner.elem, replacement);
860            Type::Paren(inner)
861        }
862        Type::Path(mut inner) => {
863            if let Some(Pair::End(mut t)) | Some(Pair::Punctuated(mut t, _)) =
864                inner.path.segments.pop()
865            {
866                t.arguments = match t.arguments {
867                    PathArguments::None => PathArguments::None,
868                    PathArguments::AngleBracketed(mut inner) => {
869                        // Iterate over the args between the angle brackets
870                        inner.args = inner
871                            .args
872                            .into_iter()
873                            .map(|generic_argument| match generic_argument {
874                                // replace types within the generics list, but leave other stuff
875                                // like lifetimes untouched
876                                GenericArgument::Type(type_) => GenericArgument::Type(
877                                    replace_infer_type_with_type(type_, replacement),
878                                ),
879                                ga => ga,
880                            })
881                            .collect();
882                        PathArguments::AngleBracketed(inner)
883                    }
884                    PathArguments::Parenthesized(mut inner) => {
885                        inner.inputs = inner
886                            .inputs
887                            .into_iter()
888                            .map(|type_| replace_infer_type_with_type(type_, replacement))
889                            .collect();
890                        inner.output = match inner.output {
891                            ReturnType::Type(arrow, mut type_) => {
892                                *type_ = replace_infer_type_with_type(*type_, replacement);
893                                ReturnType::Type(arrow, type_)
894                            }
895                            default => default,
896                        };
897                        PathArguments::Parenthesized(inner)
898                    }
899                };
900                inner.path.segments.push(t);
901            }
902            Type::Path(inner)
903        }
904        Type::Ptr(mut inner) => {
905            *inner.elem = replace_infer_type_with_type(*inner.elem, replacement);
906            Type::Ptr(inner)
907        }
908        Type::Reference(mut inner) => {
909            *inner.elem = replace_infer_type_with_type(*inner.elem, replacement);
910            Type::Reference(inner)
911        }
912        Type::Slice(mut inner) => {
913            *inner.elem = replace_infer_type_with_type(*inner.elem, replacement);
914            Type::Slice(inner)
915        }
916        Type::Tuple(mut inner) => {
917            inner.elems = inner
918                .elems
919                .into_pairs()
920                .map(|pair| match pair {
921                    Pair::Punctuated(type_, p) => {
922                        Pair::Punctuated(replace_infer_type_with_type(type_, replacement), p)
923                    }
924                    Pair::End(type_) => Pair::End(replace_infer_type_with_type(type_, replacement)),
925                })
926                .collect();
927            Type::Tuple(inner)
928        }
929
930        // Pass unknown types or non-handleable types (e.g., bare Fn) without performing any
931        // replacements
932        type_ => type_,
933    }
934}
935
936/// Check if a type ending in the `syn::Ident` `embedded_type` is contained in `type_`.
937fn has_type_embedded(type_: &Type, embedded_type: &syn::Ident) -> bool {
938    match type_ {
939        // Base cases
940        Type::Infer(_) => false,
941        Type::Never(_inner) => false,
942
943        // Recursive cases
944        // Iterate through all positions where a type could occur and recursively call this function
945        Type::Array(inner) => has_type_embedded(&inner.elem, embedded_type),
946        Type::Group(inner) => has_type_embedded(&inner.elem, embedded_type),
947        Type::Paren(inner) => has_type_embedded(&inner.elem, embedded_type),
948        Type::Path(inner) => {
949            match inner.path.segments.last() {
950                Some(t) => {
951                    if t.ident == *embedded_type {
952                        return true;
953                    }
954
955                    match &t.arguments {
956                        PathArguments::None => false,
957                        PathArguments::AngleBracketed(inner) => {
958                            // Iterate over the args between the angle brackets
959                            inner
960                                .args
961                                .iter()
962                                .any(|generic_argument| match generic_argument {
963                                    // replace types within the generics list, but leave other stuff
964                                    // like lifetimes untouched
965                                    GenericArgument::Type(type_) => {
966                                        has_type_embedded(type_, embedded_type)
967                                    }
968                                    _ga => false,
969                                })
970                        }
971                        PathArguments::Parenthesized(inner) => {
972                            inner
973                                .inputs
974                                .iter()
975                                .any(|type_| has_type_embedded(type_, embedded_type))
976                                || match &inner.output {
977                                    ReturnType::Type(_arrow, type_) => {
978                                        has_type_embedded(type_, embedded_type)
979                                    }
980                                    _default => false,
981                                }
982                        }
983                    }
984                }
985                None => false,
986            }
987        }
988        Type::Ptr(inner) => has_type_embedded(&inner.elem, embedded_type),
989        Type::Reference(inner) => has_type_embedded(&inner.elem, embedded_type),
990        Type::Slice(inner) => has_type_embedded(&inner.elem, embedded_type),
991        Type::Tuple(inner) => inner.elems.pairs().any(|pair| match pair {
992            Pair::Punctuated(type_, _) | Pair::End(type_) => {
993                has_type_embedded(type_, embedded_type)
994            }
995        }),
996
997        // Pass unknown types or non-handleable types (e.g., bare Fn) without performing any
998        // replacements
999        _type_ => false,
1000    }
1001}
1002
1003/// Deserialize value by using its [`FromStr`] implementation
1004///
1005/// This is an alternative way to implement `Deserialize` for types, which also implement
1006/// [`FromStr`] by deserializing the type from string. Ensure that the struct/enum also implements
1007/// [`FromStr`]. If the implementation is missing, you will get an error message like
1008/// ```text
1009/// error[E0277]: the trait bound `Struct: std::str::FromStr` is not satisfied
1010/// ```
1011/// Additionally, `FromStr::Err` **must** implement [`Display`] as otherwise you will see a rather
1012/// unhelpful error message
1013///
1014/// Serialization with [`Display`] is available with the matching [`SerializeDisplay`] derive.
1015///
1016/// # Attributes
1017///
1018/// Attributes for the derive can be specified via the `#[serde_with(...)]` attribute on the struct
1019/// or enum. Currently, these arguments to the attribute are possible:
1020///
1021/// * **`#[serde_with(crate = "...")]`**: This allows using `DeserializeFromStr` when `serde_with`
1022///   is not available from the crate root. This happens while [renaming dependencies in
1023///   Cargo.toml][cargo-toml-rename] or when re-exporting the macro from a different crate.
1024///
1025///   This argument is analogue to [serde's crate argument][serde-crate] and the [crate argument
1026///   to `serde_as`][serde-as-crate].
1027///
1028/// # Example
1029///
1030/// ```rust,ignore
1031/// use std::str::FromStr;
1032///
1033/// #[derive(DeserializeFromStr)]
1034/// struct A {
1035///     a: u32,
1036///     b: bool,
1037/// }
1038///
1039/// impl FromStr for A {
1040///     type Err = String;
1041///
1042///     /// Parse a value like `123<>true`
1043///     fn from_str(s: &str) -> Result<Self, Self::Err> {
1044///         let mut parts = s.split("<>");
1045///         let number = parts
1046///             .next()
1047///             .ok_or_else(|| "Missing first value".to_string())?
1048///             .parse()
1049///             .map_err(|err: ParseIntError| err.to_string())?;
1050///         let bool = parts
1051///             .next()
1052///             .ok_or_else(|| "Missing second value".to_string())?
1053///             .parse()
1054///             .map_err(|err: ParseBoolError| err.to_string())?;
1055///         Ok(Self { a: number, b: bool })
1056///     }
1057/// }
1058///
1059/// let a: A = serde_json::from_str("\"159<>true\"").unwrap();
1060/// assert_eq!(A { a: 159, b: true }, a);
1061/// ```
1062///
1063/// [`Display`]: std::fmt::Display
1064/// [`FromStr`]: std::str::FromStr
1065/// [cargo-toml-rename]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml
1066/// [serde-as-crate]: https://docs.rs/serde_with/3.22.0/serde_with/guide/serde_as/index.html#re-exporting-serde_as
1067/// [serde-crate]: https://serde.rs/container-attrs.html#crate
1068#[proc_macro_derive(DeserializeFromStr, attributes(serde_with))]
1069pub fn derive_deserialize_fromstr(item: TokenStream) -> TokenStream {
1070    let input: DeriveInput = parse_macro_input!(item);
1071    let derive_options = match DeriveOptions::from_derive_input(&input) {
1072        Ok(opt) => opt,
1073        Err(err) => {
1074            return err;
1075        }
1076    };
1077    TokenStream::from(deserialize_fromstr(
1078        input,
1079        derive_options.get_serde_with_path(),
1080    ))
1081}
1082
1083fn deserialize_fromstr(mut input: DeriveInput, serde_with_crate_path: Path) -> TokenStream2 {
1084    let ident = input.ident;
1085    let where_clause = &mut input.generics.make_where_clause().predicates;
1086    where_clause.push(parse_quote!(Self: #serde_with_crate_path::__private__::FromStr));
1087    where_clause.push(parse_quote!(
1088        <Self as #serde_with_crate_path::__private__::FromStr>::Err: #serde_with_crate_path::__private__::Display
1089    ));
1090    let (de_impl_generics, ty_generics, where_clause) = split_with_de_lifetime(&input.generics);
1091    quote! {
1092        #[automatically_derived]
1093        impl #de_impl_generics #serde_with_crate_path::__private__::Deserialize<'de> for #ident #ty_generics #where_clause {
1094            fn deserialize<__D>(deserializer: __D) -> #serde_with_crate_path::__private__::Result<Self, __D::Error>
1095            where
1096                __D: #serde_with_crate_path::__private__::Deserializer<'de>,
1097            {
1098                struct Helper<__S>(#serde_with_crate_path::__private__::PhantomData<__S>);
1099
1100                impl<'de, __S> #serde_with_crate_path::__private__::Visitor<'de> for Helper<__S>
1101                where
1102                    __S: #serde_with_crate_path::__private__::FromStr,
1103                    <__S as #serde_with_crate_path::__private__::FromStr>::Err: #serde_with_crate_path::__private__::Display,
1104                {
1105                    type Value = __S;
1106
1107                    fn expecting(&self, formatter: &mut #serde_with_crate_path::__private__::fmt::Formatter<'_>) -> #serde_with_crate_path::__private__::fmt::Result {
1108                        #serde_with_crate_path::__private__::Display::fmt("a string", formatter)
1109                    }
1110
1111                    fn visit_str<__E>(
1112                        self,
1113                        value: &str
1114                    ) -> #serde_with_crate_path::__private__::Result<Self::Value, __E>
1115                    where
1116                        __E: #serde_with_crate_path::__private__::DeError,
1117                    {
1118                        value.parse::<Self::Value>().map_err(#serde_with_crate_path::__private__::DeError::custom)
1119                    }
1120
1121                    fn visit_bytes<__E>(
1122                        self,
1123                        value: &[u8]
1124                    ) -> #serde_with_crate_path::__private__::Result<Self::Value, __E>
1125                    where
1126                        __E: #serde_with_crate_path::__private__::DeError,
1127                    {
1128                        let utf8 = #serde_with_crate_path::__private__::str::from_utf8(value).map_err(#serde_with_crate_path::__private__::DeError::custom)?;
1129                        self.visit_str(utf8)
1130                    }
1131                }
1132
1133                deserializer.deserialize_str(Helper(#serde_with_crate_path::__private__::PhantomData))
1134            }
1135        }
1136    }
1137}
1138
1139/// Serialize value by using it's [`Display`] implementation
1140///
1141/// This is an alternative way to implement `Serialize` for types, which also implement [`Display`]
1142/// by serializing the type as string. Ensure that the struct/enum also implements [`Display`].
1143/// If the implementation is missing, you will get an error message like
1144/// ```text
1145/// error[E0277]: `Struct` doesn't implement `std::fmt::Display`
1146/// ```
1147///
1148/// Deserialization with [`FromStr`] is available with the matching [`DeserializeFromStr`] derive.
1149///
1150/// # Attributes
1151///
1152/// Attributes for the derive can be specified via the `#[serde_with(...)]` attribute on the struct
1153/// or enum. Currently, these arguments to the attribute are possible:
1154///
1155/// * **`#[serde_with(crate = "...")]`**: This allows using `SerializeDisplay` when `serde_with` is
1156///   not available from the crate root. This happens while [renaming dependencies in
1157///   Cargo.toml][cargo-toml-rename] or when re-exporting the macro from a different crate.
1158///
1159///   This argument is analogue to [serde's crate argument][serde-crate] and the [crate argument
1160///   to `serde_as`][serde-as-crate].
1161///
1162/// # Example
1163///
1164/// ```rust,ignore
1165/// use std::fmt;
1166///
1167/// #[derive(SerializeDisplay)]
1168/// struct A {
1169///     a: u32,
1170///     b: bool,
1171/// }
1172///
1173/// impl fmt::Display for A {
1174///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1175///         write!(f, "{}<>{}", self.a, self.b)
1176///     }
1177/// }
1178///
1179/// let a = A { a: 123, b: false };
1180/// assert_eq!(r#""123<>false""#, serde_json::to_string(&a).unwrap());
1181/// ```
1182///
1183/// [`Display`]: std::fmt::Display
1184/// [`FromStr`]: std::str::FromStr
1185/// [cargo-toml-rename]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml
1186/// [serde-as-crate]: https://docs.rs/serde_with/3.22.0/serde_with/guide/serde_as/index.html#re-exporting-serde_as
1187/// [serde-crate]: https://serde.rs/container-attrs.html#crate
1188#[proc_macro_derive(SerializeDisplay, attributes(serde_with))]
1189pub fn derive_serialize_display(item: TokenStream) -> TokenStream {
1190    let input: DeriveInput = parse_macro_input!(item);
1191    let derive_options = match DeriveOptions::from_derive_input(&input) {
1192        Ok(opt) => opt,
1193        Err(err) => {
1194            return err;
1195        }
1196    };
1197    TokenStream::from(serialize_display(
1198        input,
1199        false,
1200        derive_options.get_serde_with_path(),
1201    ))
1202}
1203
1204/// Serialize value by using its [`Display`] implementation with the “alternate” (`#`) format flag
1205///
1206/// This derive implements `serde::Serialize` for any type that already implements
1207/// [`std::fmt::Display`], emitting its string form using the alternate formatting specifier
1208/// (`{:#}`) instead of the normal `{}`.  In other words, rather than calling
1209/// `format!("{}", self)`, it calls `format!("{:#}", self)`.
1210///
1211/// Ensure that your type implements [`Display`], or you will get a compile‐error such as:
1212/// ```text
1213/// error[E0277]: `MyType` doesn't implement `std::fmt::Display`
1214/// ```
1215///
1216/// Deserialization from strings via [`std::str::FromStr`] is handled by the companion
1217/// [`DeserializeFromStr`] derive.
1218///
1219/// # Attributes
1220///
1221/// You may customize which `serde_with` crate is used (for renamed or re-exported crates)
1222/// via the same attribute namespace:
1223///
1224/// * `#[serde_with(crate = "...")]`
1225///   When your workspace renames or re-exports `serde_with`, use this to point at the correct path.
1226///   For example:
1227///   ```rust,ignore
1228///   #[derive(SerializeDisplayAlt)]
1229///   #[serde_with(crate = "my_forked_serde_with")]
1230///   pub struct Foo(/* … */);
1231///   ```
1232///
1233/// # Example
1234///
1235/// ```rust,ignore
1236/// use std::fmt;
1237/// use serde_with::{SerializeDisplayAlt, DeserializeFromStr};
1238///
1239/// #[derive(Debug, Clone, SerializeDisplayAlt, DeserializeFromStr)]
1240/// pub struct MyType(u32);
1241///
1242/// impl fmt::Display for MyType {
1243///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1244///         if f.alternate() {
1245///             // Alternate formatting: hex with 0x prefix
1246///             write!(f, "0x{:X}", self.0)
1247///         } else {
1248///             // Standard formatting: decimal
1249///             write!(f, "{}", self.0)
1250///         }
1251///     }
1252/// }
1253///
1254/// let v = MyType(15);
1255/// // SerializeDisplayAlt always uses `{:#}`, so this yields `"0xF"`
1256/// assert_eq!(r#""0xF""#, serde_json::to_string(&v).unwrap());
1257/// ```
1258///
1259/// [`Display`]: std::fmt::Display
1260/// [`FromStr`]: std::str::FromStr
1261/// [`DeserializeFromStr`]: crate::DeserializeFromStr
1262#[proc_macro_derive(SerializeDisplayAlt, attributes(serde_with))]
1263pub fn derive_serialize_display_alt(item: TokenStream) -> TokenStream {
1264    let input: DeriveInput = parse_macro_input!(item);
1265    let derive_options = match DeriveOptions::from_derive_input(&input) {
1266        Ok(opt) => opt,
1267        Err(err) => {
1268            return err;
1269        }
1270    };
1271    TokenStream::from(serialize_display(
1272        input,
1273        true,
1274        derive_options.get_serde_with_path(),
1275    ))
1276}
1277
1278fn serialize_display(
1279    mut input: DeriveInput,
1280    alternate: bool,
1281    serde_with_crate_path: Path,
1282) -> TokenStream2 {
1283    let ident = input.ident;
1284    input
1285        .generics
1286        .make_where_clause()
1287        .predicates
1288        .push(parse_quote!(Self: #serde_with_crate_path::__private__::Display));
1289    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
1290
1291    let collect_str_param = if alternate {
1292        quote! { &format_args!("{self:#}") }
1293    } else {
1294        quote! { &self }
1295    };
1296
1297    quote! {
1298        #[automatically_derived]
1299        impl #impl_generics #serde_with_crate_path::__private__::Serialize for #ident #ty_generics #where_clause {
1300            fn serialize<__S>(
1301                &self,
1302                serializer: __S
1303            ) -> #serde_with_crate_path::__private__::Result<__S::Ok, __S::Error>
1304            where
1305                __S: #serde_with_crate_path::__private__::Serializer,
1306            {
1307                serializer.collect_str(#collect_str_param)
1308            }
1309        }
1310    }
1311}
1312
1313#[doc(hidden)]
1314/// Private function. Not part of the public API
1315///
1316/// The only task of this derive macro is to consume any `serde_as` attributes and turn them into
1317/// inert attributes. This allows the serde_as macro to keep the field attributes without causing
1318/// compiler errors. The intend is that keeping the field attributes allows downstream crates to
1319/// consume and act on them without causing an ordering dependency to the serde_as macro.
1320///
1321/// Otherwise, downstream proc-macros would need to be placed *in front of* the main `#[serde_as]`
1322/// attribute, since otherwise the field attributes would already be stripped off.
1323///
1324/// More details about the use-cases in the GitHub discussion: <https://github.com/jonasbb/serde_with/discussions/260>.
1325#[proc_macro_derive(
1326    __private_consume_serde_as_attributes,
1327    attributes(serde_as, serde_with)
1328)]
1329pub fn __private_consume_serde_as_attributes(_: TokenStream) -> TokenStream {
1330    TokenStream::new()
1331}
1332
1333/// Apply attributes to all fields with matching types
1334///
1335/// Whenever you experience the need to apply the same attributes to multiple fields, you can use
1336/// this macro. It allows you to specify a list of types and a list of attributes.
1337/// Each field with a "matching" type will then get the attributes applied.
1338/// The `apply` attribute must be placed *before* any consuming attributes, such as `derive` or
1339/// `serde_as`, because Rust expands all attributes in order.
1340///
1341/// For example, if your struct or enum contains many `Option<T>` fields, but you do not want to
1342/// serialize `None` values, you can use this macro to apply the `#[serde(skip_serializing_if =
1343/// "Option::is_none")]` attribute to all fields of type `Option<T>`.
1344///
1345/// ```rust
1346/// # use serde_with_macros as serde_with;
1347/// #[serde_with::apply(
1348/// #   crate="serde_with",
1349///     Option => #[serde(skip_serializing_if = "Option::is_none")],
1350/// )]
1351/// #[derive(serde::Serialize)]
1352/// # #[derive(Default)]
1353/// struct Data {
1354///     a: Option<String>,
1355///     b: Option<u64>,
1356///     c: Option<String>,
1357///     d: Option<bool>,
1358/// }
1359/// #
1360/// # assert_eq!("{}", serde_json::to_string(&Data::default()).unwrap());
1361/// ```
1362///
1363/// Each rule starts with a type pattern, specifying which fields to match and a list of attributes
1364/// to apply. Multiple rules can be provided in a single `apply` attribute.
1365///
1366/// ```rust
1367/// # use serde_with_macros as serde_with;
1368/// #[serde_with::apply(
1369/// #   crate="serde_with",
1370///     Option => #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")],
1371///     Option<bool> => #[serde(rename = "bool")],
1372/// )]
1373/// # #[derive(serde::Serialize)]
1374/// # #[derive(Default)]
1375/// # struct Data {
1376/// #     a: Option<String>,
1377/// #     b: Option<u64>,
1378/// #     c: Option<String>,
1379/// #     d: Option<bool>,
1380/// # }
1381/// #
1382/// # assert_eq!("{}", serde_json::to_string(&Data::default()).unwrap());
1383/// ```
1384///
1385/// ## Type Patterns
1386///
1387/// The type pattern left of the `=>` specifies which fields to match.
1388///
1389/// | Type Pattern            |                                       Matching Types | Notes                                                                           |
1390/// | :---------------------- | ---------------------------------------------------: | :------------------------------------------------------------------------------ |
1391/// | `_`                     | `Option<bool>`<br>`BTreeMap<&'static str, Vec<u32>>` | `_` matches all fields.                                                         |
1392/// | `Option`                |                   `Option<bool>`<br>`Option<String>` | A missing generic is compatible with any generic arguments.                     |
1393/// | `Option<bool>`          |                                       `Option<bool>` | A fully specified type only matches exactly.                                    |
1394/// | `BTreeMap<String, u32>` |                              `BTreeMap<String, u32>` | A fully specified type only matches exactly.                                    |
1395/// | `BTreeMap<String, _>`   |  `BTreeMap<String, u32>`<br>`BTreeMap<String, bool>` | Any `String` key `BTreeMap` matches, as the value is using the `_` placeholder. |
1396/// | `[u8; _]`               |                               `[u8; 1]`<br>`[u8; N]` | `_` also works as a placeholder for any array length.                           |
1397///
1398/// ## Opt-out for Individual Fields
1399///
1400/// The `apply` attribute will find all fields with a compatible type.
1401/// This can be overly eager and a different set of attributes might be required for a specific
1402/// field. You can opt-out of the `apply` attribute by adding the `#[serde_with(skip_apply)]`
1403/// attribute to the field. This will prevent any `apply` to apply to this field.
1404/// If two rules apply to the same field, it is impossible to opt-out of only a single one.
1405/// In this case the attributes must be applied to the field manually.
1406///
1407/// ```rust
1408/// # use serde_json::json;
1409/// # use serde_with_macros as serde_with;
1410/// #[serde_with::apply(
1411/// #   crate="serde_with",
1412///     Option => #[serde(skip_serializing_if = "Option::is_none")],
1413/// )]
1414/// #[derive(serde::Serialize)]
1415/// struct Data {
1416///     a: Option<String>,
1417///     #[serde_with(skip_apply)]
1418///     always_serialize_this_field: Option<u64>,
1419///     c: Option<String>,
1420///     d: Option<bool>,
1421/// }
1422///
1423/// let data = Data {
1424///     a: None,
1425///     always_serialize_this_field: None,
1426///     c: None,
1427///     d: None,
1428/// };
1429///
1430/// // serializes into this JSON:
1431/// # assert_eq!(json!(
1432/// {
1433///     "always_serialize_this_field": null
1434/// }
1435/// # ), serde_json::to_value(data).unwrap());
1436/// ```
1437///
1438/// # Alternative path to `serde_with` crate
1439///
1440/// If `serde_with` is not available at the default path, its path should be specified with the
1441/// `crate` argument. See [re-exporting `serde_as`] for more use case information.
1442///
1443/// ```rust,ignore
1444/// #[serde_with::apply(
1445///     crate = "::some_other_lib::serde_with"
1446///     Option => #[serde(skip_serializing_if = "Option::is_none")],
1447/// )]
1448/// #[derive(serde::Serialize)]
1449/// struct Data {
1450///     a: Option<String>,
1451///     b: Option<u64>,
1452///     c: Option<String>,
1453///     d: Option<bool>,
1454/// }
1455/// ```
1456#[proc_macro_attribute]
1457pub fn apply(args: TokenStream, input: TokenStream) -> TokenStream {
1458    apply::apply(args, input)
1459}