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.24.0/")]
24// FIXME: The darling 0.24.0 derives trigger this lint
25#![allow(unused_qualifications)]
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::FnPtr(_)
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 {
391 qself: None,
392 path,
393 attrs: _,
394 }) => {
395 (path.leading_colon.is_none()
396 && path.segments.len() == 1
397 && path.segments[0].ident == "Option")
398 || (path.segments.len() == 3
399 && (path.segments[0].ident == "std" || path.segments[0].ident == "core")
400 && path.segments[1].ident == "option"
401 && path.segments[2].ident == "Option")
402 }
403 _ => false,
404 }
405}
406
407/// Determine if the `field` has an attribute with given `namespace` and `name`
408///
409/// On the example of
410/// `#[serde(skip_serializing_if = "Option::is_none")]`
411///
412/// * `serde` is the outermost path, here namespace
413/// * it contains a `Meta::List`
414/// * which contains in another Meta a `Meta::NameValue`
415/// * with the name being `skip_serializing_if`
416fn field_has_attribute(field: &Field, namespace: &str, name: &str) -> bool {
417 for attr in &field.attrs {
418 if attr.path().is_ident(namespace) {
419 // Ignore non parsable attributes, as these are not important for us
420 if let Meta::List(expr) = &attr.meta {
421 let nested = match Punctuated::<Meta, Token![,]>::parse_terminated
422 .parse2(expr.tokens.clone())
423 {
424 Ok(nested) => nested,
425 Err(_) => continue,
426 };
427 for expr in nested {
428 match expr {
429 Meta::NameValue(expr) => {
430 if let Some(ident) = expr.path.get_ident() {
431 if *ident == name {
432 return true;
433 }
434 }
435 }
436 Meta::Path(expr) => {
437 if let Some(ident) = expr.get_ident() {
438 if *ident == name {
439 return true;
440 }
441 }
442 }
443 _ => (),
444 }
445 }
446 }
447 }
448 }
449 false
450}
451
452/// Convenience macro to use the [`serde_as`] system.
453///
454/// The [`serde_as`] system is designed as a more flexible alternative to serde's `with` annotation.
455/// The `#[serde_as]` attribute must be placed *before* the `#[derive]` attribute.
456/// Each field of a struct or enum can be annotated with `#[serde_as(...)]` to specify which
457/// transformations should be applied. `serde_as` is *not* supported on enum variants.
458/// This is in contrast to `#[serde(with = "...")]`.
459///
460/// # Example
461///
462/// ```rust,ignore
463/// use serde_with::{serde_as, BytesOrString, DisplayFromStr, Map};
464///
465/// #[serde_as]
466/// #[derive(Serialize, Deserialize)]
467/// struct Data {
468/// /// Serialize into number
469/// #[serde_as(as = "_")]
470/// a: u32,
471///
472/// /// Serialize into String, deserialize from Bytes or String
473/// #[serde_as(
474/// serialize_as = "DisplayFromStr",
475/// deserialize_as = "BytesOrString"
476/// )]
477/// b: u32,
478///
479/// /// Serialize into a map from String to String
480/// #[serde_as(as = "Map<DisplayFromStr, _>")]
481/// c: Vec<(u32, String)>,
482/// }
483/// ```
484///
485/// # Alternative path to `serde_with` crate
486///
487/// If `serde_with` is not available at the default path, its path should be specified with the
488/// `crate` argument. See [re-exporting `serde_as`] for more use case information.
489///
490/// ```rust,ignore
491/// #[serde_as(crate = "::some_other_lib::serde_with")]
492/// #[derive(Deserialize)]
493/// struct Data {
494/// #[serde_as(as = "_")]
495/// a: u32,
496/// }
497/// ```
498///
499/// # What this macro does
500///
501/// The `serde_as` macro only serves a convenience function.
502/// All the steps it performs, can easily be done manually, in case the cost of an attribute macro
503/// is deemed too high. The functionality can best be described with an example.
504///
505/// ```rust,ignore
506/// #[serde_as]
507/// #[derive(serde::Serialize)]
508/// struct Foo {
509/// #[serde_as(as = "Vec<_>")]
510/// bar: Vec<u32>,
511///
512/// #[serde_as(as = "Option<DisplayFromStr>")]
513/// baz: Option<u32>,
514/// }
515/// ```
516///
517/// 1. All the placeholder type `_` will be replaced with `::serde_with::Same`.
518/// The placeholder type `_` marks all the places where the type's `Serialize` implementation
519/// should be used. In the example, it means that the `u32` values will serialize with the
520/// `Serialize` implementation of `u32`. The `Same` type implements `SerializeAs` whenever the
521/// underlying type implements `Serialize` and is used to make the two traits compatible.
522///
523/// If you specify a custom path for `serde_with` via the `crate` attribute, the path to the
524/// `Same` type will be altered accordingly.
525///
526/// 2. Wrap the type from the annotation inside a `::serde_with::As`.
527/// In the above example we now have something like `::serde_with::As::<Vec<::serde_with::Same>>`.
528/// The `As` type acts as the opposite of the `Same` type.
529/// It allows using a `SerializeAs` type whenever a `Serialize` is required.
530///
531/// 3. Translate the `*as` attributes into the serde equivalent ones.
532/// `#[serde_as(as = ...)]` will become `#[serde(with = ...)]`.
533/// Similarly, `serialize_as` is translated to `serialize_with`.
534///
535/// The field attributes will be kept on the struct/enum such that other macros can use them
536/// too.
537///
538/// 4. It searches `#[serde_as(as = ...)]` if there is a type named `BorrowCow` under any path.
539/// If `BorrowCow` is found, the attribute `#[serde(borrow)]` is added to the field.
540/// If `#[serde(borrow)]` or `#[serde(borrow = "...")]` is already present, this step will be
541/// skipped.
542///
543/// 5. Restore the ability of accepting missing fields if both the field and the transformation are `Option`.
544///
545/// An `Option` is detected by an exact text match.
546/// Renaming an import or type aliases can cause confusion here.
547/// The following variants are supported.
548/// * `Option`
549/// * `std::option::Option`, with or without leading `::`
550/// * `core::option::Option`, with or without leading `::`
551///
552/// If the field is of type `Option<T>` and the attribute `#[serde_as(as = "Option<S>")]` (also
553/// `deserialize_as`; for any `T`/`S`) then `#[serde(default)]` is applied to the field.
554///
555/// 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).
556/// `#[serde(default)]` is not applied, if it already exists.
557/// It only triggers if both field and transformation are `Option`s.
558/// For example, using `#[serde_as(as = "NoneAsEmptyString")]` on `Option<String>` will not see
559/// any change.
560///
561/// If the automatically applied attribute is undesired, the behavior can be suppressed by adding
562/// `#[serde_as(no_default)]`.
563///
564/// This can be combined like `#[serde_as(as = "Option<S>", no_default)]`.
565///
566/// After all these steps, the code snippet will have transformed into roughly this.
567///
568/// ```rust,ignore
569/// #[derive(serde::Serialize)]
570/// struct Foo {
571/// #[serde_as(as = "Vec<_>")]
572/// #[serde(with = "::serde_with::As::<Vec<::serde_with::Same>>")]
573/// bar: Vec<u32>,
574///
575/// #[serde_as(as = "Option<DisplayFromStr>")]
576/// #[serde(default)]
577/// #[serde(with = "::serde_with::As::<Option<DisplayFromStr>>")]
578/// baz: Option<u32>,
579/// }
580/// ```
581///
582/// # A note on `schemars` integration
583/// When the `schemars_0_8`, `schemars_0_9`, or `schemars_1` features are enabled this macro
584/// will scan for
585/// `#[derive(JsonSchema)]` attributes and, if found, will add
586/// `#[schemars(with = "Schema<T, ...>")]` annotations to any fields with a
587/// `#[serde_as(as = ...)]` annotation. If you wish to override the default
588/// behavior here you can add `#[serde_as(schemars = true)]` or
589/// `#[serde_as(schemars = false)]`.
590///
591/// Note that this macro will check for any of the following derive paths:
592/// * `JsonSchema`
593/// * `schemars::JsonSchema`
594/// * `::schemars::JsonSchema`
595///
596/// It will also work if the relevant derive is behind a `#[cfg_attr]` attribute
597/// and propagate the `#[cfg_attr]` to the various `#[schemars]` field attributes.
598///
599/// [`serde_as`]: https://docs.rs/serde_with/3.24.0/serde_with/guide/index.html
600/// [re-exporting `serde_as`]: https://docs.rs/serde_with/3.24.0/serde_with/guide/serde_as/index.html#re-exporting-serde_as
601#[proc_macro_attribute]
602pub fn serde_as(args: TokenStream, input: TokenStream) -> TokenStream {
603 #[derive(FromMeta)]
604 struct SerdeContainerOptions {
605 #[darling(rename = "crate")]
606 alt_crate_path: Option<Path>,
607 #[darling(rename = "schemars")]
608 enable_schemars_support: Option<bool>,
609 }
610
611 match NestedMeta::parse_meta_list(args.into()) {
612 Ok(list) => {
613 let container_options = match SerdeContainerOptions::from_list(&list) {
614 Ok(v) => v,
615 Err(e) => {
616 return TokenStream::from(e.write_errors());
617 }
618 };
619
620 let serde_with_crate_path = container_options
621 .alt_crate_path
622 .unwrap_or_else(|| syn::parse_quote!(::serde_with));
623
624 let schemars_config = match container_options.enable_schemars_support {
625 _ if cfg!(not(any(
626 feature = "schemars_0_8",
627 feature = "schemars_0_9",
628 feature = "schemars_1"
629 ))) =>
630 {
631 SchemaFieldConfig::False
632 }
633 Some(condition) => condition.into(),
634 None => utils::has_derive_jsonschema(input.clone()).unwrap_or_default(),
635 };
636
637 // Convert any error message into a nice compiler error
638 let res = apply_function_to_struct_and_enum_fields_darling(
639 input,
640 &serde_with_crate_path,
641 |field| serde_as_add_attr_to_field(field, &serde_with_crate_path, &schemars_config),
642 )
643 .unwrap_or_else(darling::Error::write_errors);
644 TokenStream::from(res)
645 }
646 Err(e) => TokenStream::from(DarlingError::from(e).write_errors()),
647 }
648}
649
650/// Inspect the field and convert the `serde_as` attribute into the classical `serde`
651fn serde_as_add_attr_to_field(
652 field: &mut Field,
653 serde_with_crate_path: &Path,
654 schemars_config: &SchemaFieldConfig,
655) -> Result<(), DarlingError> {
656 #[derive(FromField)]
657 #[darling(attributes(serde_as))]
658 struct SerdeAsOptions {
659 /// The original type of the field
660 ty: Type,
661
662 r#as: Option<Type>,
663 deserialize_as: Option<Type>,
664 serialize_as: Option<Type>,
665 no_default: Flag,
666 }
667
668 impl SerdeAsOptions {
669 fn has_any_set(&self) -> bool {
670 self.r#as.is_some() || self.deserialize_as.is_some() || self.serialize_as.is_some()
671 }
672 }
673
674 #[derive(FromField)]
675 #[darling(attributes(serde), allow_unknown_fields)]
676 struct SerdeOptions {
677 with: Option<String>,
678 deserialize_with: Option<String>,
679 serialize_with: Option<String>,
680
681 borrow: Option<Override<String>>,
682 default: Option<Override<String>>,
683 }
684
685 impl SerdeOptions {
686 fn has_any_set(&self) -> bool {
687 self.with.is_some() || self.deserialize_with.is_some() || self.serialize_with.is_some()
688 }
689 }
690
691 /// Emit a `borrow` annotation, if the replacement type requires borrowing.
692 fn emit_borrow_annotation(serde_options: &SerdeOptions, as_type: &Type, field: &mut Field) {
693 let type_borrowcow = &syn::parse_quote!(BorrowCow);
694 // If the field is not borrowed yet, check if we need to borrow it.
695 if serde_options.borrow.is_none() && has_type_embedded(as_type, type_borrowcow) {
696 let attr_borrow = parse_quote!(#[serde(borrow)]);
697 field.attrs.push(attr_borrow);
698 }
699 }
700
701 /// Emit a `default` annotation, if `as_type` and `field` are both `Option`.
702 fn emit_default_annotation(
703 serde_as_options: &SerdeAsOptions,
704 serde_options: &SerdeOptions,
705 as_type: &Type,
706 field: &mut Field,
707 ) {
708 if !serde_as_options.no_default.is_present()
709 && serde_options.default.is_none()
710 && is_std_option(as_type)
711 && is_std_option(&field.ty)
712 {
713 let attr_borrow = parse_quote!(#[serde(default)]);
714 field.attrs.push(attr_borrow);
715 }
716 }
717
718 // syn v2 no longer supports keywords in the path position of an attribute.
719 // That breaks #[serde_as(as = "FooBar")], since `as` is a keyword.
720 // For each attribute, that is named `serde_as`, we replace the `as` keyword with `r#as`.
721 let mut has_serde_as = false;
722 field.attrs.iter_mut().for_each(|attr| {
723 if attr.path().is_ident("serde_as") {
724 // We found a `serde_as` attribute.
725 // Remember that such that we can quick exit otherwise
726 has_serde_as = true;
727
728 if let Meta::List(metalist) = &mut attr.meta {
729 metalist.tokens = std::mem::take(&mut metalist.tokens)
730 .into_iter()
731 .map(|token| {
732 use proc_macro2::{Ident, TokenTree};
733
734 // Replace `as` with `r#as`.
735 match token {
736 TokenTree::Ident(ident) if ident == "as" => {
737 TokenTree::Ident(Ident::new_raw("as", ident.span()))
738 }
739 _ => token,
740 }
741 })
742 .collect();
743 }
744 }
745 });
746 // If there is no `serde_as` attribute, we can exit early.
747 if !has_serde_as {
748 return Ok(());
749 }
750 let serde_as_options = SerdeAsOptions::from_field(field)?;
751 let serde_options = SerdeOptions::from_field(field)?;
752
753 let mut errors = Vec::new();
754 if !serde_as_options.has_any_set() {
755 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."));
756 }
757
758 // Check if there are any conflicting attributes
759 if serde_as_options.has_any_set() && serde_options.has_any_set() {
760 errors.push(DarlingError::custom("Cannot combine `serde_as` with serde's `with`, `deserialize_with`, or `serialize_with`."));
761 }
762
763 if serde_as_options.r#as.is_some() && serde_as_options.deserialize_as.is_some() {
764 errors.push(DarlingError::custom("Cannot combine `as` with `deserialize_as`. Use `serialize_as` to specify different serialization code."));
765 } else if serde_as_options.r#as.is_some() && serde_as_options.serialize_as.is_some() {
766 errors.push(DarlingError::custom("Cannot combine `as` with `serialize_as`. Use `deserialize_as` to specify different deserialization code."));
767 }
768
769 if !errors.is_empty() {
770 return Err(DarlingError::multiple(errors));
771 }
772
773 let type_original = &serde_as_options.ty;
774 let type_same = &syn::parse_quote!(#serde_with_crate_path::Same);
775 if let Some(type_) = &serde_as_options.r#as {
776 emit_borrow_annotation(&serde_options, type_, field);
777 emit_default_annotation(&serde_as_options, &serde_options, type_, field);
778
779 let replacement_type = replace_infer_type_with_type(type_.clone(), type_same);
780 let attr_inner_tokens = quote!(#serde_with_crate_path::As::<#replacement_type>).to_string();
781 let attr = parse_quote!(#[serde(with = #attr_inner_tokens)]);
782 field.attrs.push(attr);
783
784 match schemars_config {
785 SchemaFieldConfig::False => {}
786 lhs => {
787 let rhs = utils::schemars_with_attr_if(
788 &field.attrs,
789 &["with", "serialize_with", "deserialize_with", "schema_with"],
790 )?;
791
792 match lhs & !rhs {
793 SchemaFieldConfig::False => {}
794 condition => {
795 let attr_inner_tokens = quote! {
796 #serde_with_crate_path::Schema::<#type_original, #replacement_type>
797 };
798 let attr_inner_tokens = attr_inner_tokens.to_string();
799 let attr = match condition {
800 SchemaFieldConfig::False => unreachable!(),
801 SchemaFieldConfig::True => {
802 parse_quote! { #[schemars(with = #attr_inner_tokens)] }
803 }
804 SchemaFieldConfig::Lazy(SchemaFieldCondition(condition)) => {
805 parse_quote! {
806 #[cfg_attr(
807 #condition,
808 schemars(with = #attr_inner_tokens))
809 ]
810 }
811 }
812 };
813
814 field.attrs.push(attr);
815 }
816 }
817 }
818 }
819 }
820 if let Some(type_) = &serde_as_options.deserialize_as {
821 emit_borrow_annotation(&serde_options, type_, field);
822 emit_default_annotation(&serde_as_options, &serde_options, type_, field);
823
824 let replacement_type = replace_infer_type_with_type(type_.clone(), type_same);
825 let attr_inner_tokens =
826 quote!(#serde_with_crate_path::As::<#replacement_type>::deserialize).to_string();
827 let attr = parse_quote!(#[serde(deserialize_with = #attr_inner_tokens)]);
828 field.attrs.push(attr);
829 }
830 if let Some(type_) = serde_as_options.serialize_as {
831 let replacement_type = replace_infer_type_with_type(type_.clone(), type_same);
832 let attr_inner_tokens =
833 quote!(#serde_with_crate_path::As::<#replacement_type>::serialize).to_string();
834 let attr = parse_quote!(#[serde(serialize_with = #attr_inner_tokens)]);
835 field.attrs.push(attr);
836 }
837
838 Ok(())
839}
840
841/// Recursively replace all occurrences of `_` with `replacement` in a [Type][]
842///
843/// The [`serde_as`][macro@serde_as] macro allows to use the infer type, i.e., `_`, as shortcut for
844/// `serde_with::As`. This function replaces all occurrences of the infer type with another type.
845fn replace_infer_type_with_type(to_replace: Type, replacement: &Type) -> Type {
846 match to_replace {
847 // Base case
848 // Replace the infer type with the actual replacement type
849 Type::Infer(_) => replacement.clone(),
850
851 // Recursive cases
852 // Iterate through all positions where a type could occur and recursively call this function
853 Type::Array(mut inner) => {
854 *inner.elem = replace_infer_type_with_type(*inner.elem, replacement);
855 Type::Array(inner)
856 }
857 Type::Group(mut inner) => {
858 *inner.elem = replace_infer_type_with_type(*inner.elem, replacement);
859 Type::Group(inner)
860 }
861 Type::Never(inner) => Type::Never(inner),
862 Type::Paren(mut inner) => {
863 *inner.elem = replace_infer_type_with_type(*inner.elem, replacement);
864 Type::Paren(inner)
865 }
866 Type::Path(mut inner) => {
867 if let Some(mut t) = inner.path.segments.pop() {
868 t.arguments = match t.arguments {
869 PathArguments::None => PathArguments::None,
870 PathArguments::AngleBracketed(mut inner) => {
871 // Iterate over the args between the angle brackets
872 inner.args = inner
873 .args
874 .into_iter()
875 .map(|generic_argument| match generic_argument {
876 // replace types within the generics list, but leave other stuff
877 // like lifetimes untouched
878 GenericArgument::Type(type_) => GenericArgument::Type(
879 replace_infer_type_with_type(type_, replacement),
880 ),
881 ga => ga,
882 })
883 .collect();
884 PathArguments::AngleBracketed(inner)
885 }
886 PathArguments::Parenthesized(mut inner) => {
887 inner.inputs.iter_mut().for_each(|named_arg| {
888 named_arg.ty =
889 replace_infer_type_with_type(named_arg.ty.clone(), replacement);
890 });
891 inner.output = match inner.output {
892 ReturnType::Type(arrow, mut type_) => {
893 *type_ = replace_infer_type_with_type(*type_, replacement);
894 ReturnType::Type(arrow, type_)
895 }
896 default => default,
897 };
898 PathArguments::Parenthesized(inner)
899 }
900 };
901 inner.path.segments.push(t);
902 }
903 Type::Path(inner)
904 }
905 Type::Ptr(mut inner) => {
906 *inner.elem = replace_infer_type_with_type(*inner.elem, replacement);
907 Type::Ptr(inner)
908 }
909 Type::Reference(mut inner) => {
910 *inner.elem = replace_infer_type_with_type(*inner.elem, replacement);
911 Type::Reference(inner)
912 }
913 Type::Slice(mut inner) => {
914 *inner.elem = replace_infer_type_with_type(*inner.elem, replacement);
915 Type::Slice(inner)
916 }
917 Type::Tuple(mut inner) => {
918 inner.elems = inner
919 .elems
920 .into_pairs()
921 .map(|pair| match pair {
922 Pair::Punctuated(type_, p) => {
923 Pair::Punctuated(replace_infer_type_with_type(type_, replacement), p)
924 }
925 Pair::End(type_) => Pair::End(replace_infer_type_with_type(type_, replacement)),
926 })
927 .collect();
928 Type::Tuple(inner)
929 }
930
931 // Pass unknown types or non-handleable types (e.g., bare Fn) without performing any
932 // replacements
933 type_ => type_,
934 }
935}
936
937/// Check if a type ending in the `syn::Ident` `embedded_type` is contained in `type_`.
938fn has_type_embedded(type_: &Type, embedded_type: &syn::Ident) -> bool {
939 match type_ {
940 // Base cases
941 Type::Infer(_) => false,
942 Type::Never(_inner) => false,
943
944 // Recursive cases
945 // Iterate through all positions where a type could occur and recursively call this function
946 Type::Array(inner) => has_type_embedded(&inner.elem, embedded_type),
947 Type::Group(inner) => has_type_embedded(&inner.elem, embedded_type),
948 Type::Paren(inner) => has_type_embedded(&inner.elem, embedded_type),
949 Type::Path(inner) => {
950 match inner.path.segments.last() {
951 Some(t) => {
952 if t.ident == *embedded_type {
953 return true;
954 }
955
956 match &t.arguments {
957 PathArguments::None => false,
958 PathArguments::AngleBracketed(inner) => {
959 // Iterate over the args between the angle brackets
960 inner
961 .args
962 .iter()
963 .any(|generic_argument| match generic_argument {
964 // replace types within the generics list, but leave other stuff
965 // like lifetimes untouched
966 GenericArgument::Type(type_) => {
967 has_type_embedded(type_, embedded_type)
968 }
969 _ga => false,
970 })
971 }
972 PathArguments::Parenthesized(inner) => {
973 inner
974 .inputs
975 .iter()
976 .any(|named_arg| has_type_embedded(&named_arg.ty, embedded_type))
977 || match &inner.output {
978 ReturnType::Type(_arrow, type_) => {
979 has_type_embedded(type_, embedded_type)
980 }
981 _default => false,
982 }
983 }
984 }
985 }
986 None => false,
987 }
988 }
989 Type::Ptr(inner) => has_type_embedded(&inner.elem, embedded_type),
990 Type::Reference(inner) => has_type_embedded(&inner.elem, embedded_type),
991 Type::Slice(inner) => has_type_embedded(&inner.elem, embedded_type),
992 Type::Tuple(inner) => inner.elems.pairs().any(|pair| match pair {
993 Pair::Punctuated(type_, _) | Pair::End(type_) => {
994 has_type_embedded(type_, embedded_type)
995 }
996 }),
997
998 // Pass unknown types or non-handleable types (e.g., bare Fn) without performing any
999 // replacements
1000 _type_ => false,
1001 }
1002}
1003
1004/// Deserialize value by using its [`FromStr`] implementation
1005///
1006/// This is an alternative way to implement `Deserialize` for types, which also implement
1007/// [`FromStr`] by deserializing the type from string. Ensure that the struct/enum also implements
1008/// [`FromStr`]. If the implementation is missing, you will get an error message like
1009/// ```text
1010/// error[E0277]: the trait bound `Struct: std::str::FromStr` is not satisfied
1011/// ```
1012/// Additionally, `FromStr::Err` **must** implement [`Display`] as otherwise you will see a rather
1013/// unhelpful error message
1014///
1015/// Serialization with [`Display`] is available with the matching [`SerializeDisplay`] derive.
1016///
1017/// # Attributes
1018///
1019/// Attributes for the derive can be specified via the `#[serde_with(...)]` attribute on the struct
1020/// or enum. Currently, these arguments to the attribute are possible:
1021///
1022/// * **`#[serde_with(crate = "...")]`**: This allows using `DeserializeFromStr` when `serde_with`
1023/// is not available from the crate root. This happens while [renaming dependencies in
1024/// Cargo.toml][cargo-toml-rename] or when re-exporting the macro from a different crate.
1025///
1026/// This argument is analogue to [serde's crate argument][serde-crate] and the [crate argument
1027/// to `serde_as`][serde-as-crate].
1028///
1029/// # Example
1030///
1031/// ```rust,ignore
1032/// use std::str::FromStr;
1033///
1034/// #[derive(DeserializeFromStr)]
1035/// struct A {
1036/// a: u32,
1037/// b: bool,
1038/// }
1039///
1040/// impl FromStr for A {
1041/// type Err = String;
1042///
1043/// /// Parse a value like `123<>true`
1044/// fn from_str(s: &str) -> Result<Self, Self::Err> {
1045/// let mut parts = s.split("<>");
1046/// let number = parts
1047/// .next()
1048/// .ok_or_else(|| "Missing first value".to_string())?
1049/// .parse()
1050/// .map_err(|err: ParseIntError| err.to_string())?;
1051/// let bool = parts
1052/// .next()
1053/// .ok_or_else(|| "Missing second value".to_string())?
1054/// .parse()
1055/// .map_err(|err: ParseBoolError| err.to_string())?;
1056/// Ok(Self { a: number, b: bool })
1057/// }
1058/// }
1059///
1060/// let a: A = serde_json::from_str("\"159<>true\"").unwrap();
1061/// assert_eq!(A { a: 159, b: true }, a);
1062/// ```
1063///
1064/// [`Display`]: std::fmt::Display
1065/// [`FromStr`]: std::str::FromStr
1066/// [cargo-toml-rename]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml
1067/// [serde-as-crate]: https://docs.rs/serde_with/3.24.0/serde_with/guide/serde_as/index.html#re-exporting-serde_as
1068/// [serde-crate]: https://serde.rs/container-attrs.html#crate
1069#[proc_macro_derive(DeserializeFromStr, attributes(serde_with))]
1070pub fn derive_deserialize_fromstr(item: TokenStream) -> TokenStream {
1071 let input: DeriveInput = parse_macro_input!(item);
1072 let derive_options = match DeriveOptions::from_derive_input(&input) {
1073 Ok(opt) => opt,
1074 Err(err) => {
1075 return err;
1076 }
1077 };
1078 TokenStream::from(deserialize_fromstr(
1079 input,
1080 derive_options.get_serde_with_path(),
1081 ))
1082}
1083
1084fn deserialize_fromstr(mut input: DeriveInput, serde_with_crate_path: Path) -> TokenStream2 {
1085 let ident = input.ident;
1086 let where_clause = &mut input.generics.make_where_clause().predicates;
1087 where_clause.push(parse_quote!(Self: #serde_with_crate_path::__private__::FromStr));
1088 where_clause.push(parse_quote!(
1089 <Self as #serde_with_crate_path::__private__::FromStr>::Err: #serde_with_crate_path::__private__::Display
1090 ));
1091 let (de_impl_generics, ty_generics, where_clause) = split_with_de_lifetime(&input.generics);
1092 quote! {
1093 #[automatically_derived]
1094 impl #de_impl_generics #serde_with_crate_path::__private__::Deserialize<'de> for #ident #ty_generics #where_clause {
1095 fn deserialize<__D>(deserializer: __D) -> #serde_with_crate_path::__private__::Result<Self, __D::Error>
1096 where
1097 __D: #serde_with_crate_path::__private__::Deserializer<'de>,
1098 {
1099 struct Helper<__S>(#serde_with_crate_path::__private__::PhantomData<__S>);
1100
1101 impl<'de, __S> #serde_with_crate_path::__private__::Visitor<'de> for Helper<__S>
1102 where
1103 __S: #serde_with_crate_path::__private__::FromStr,
1104 <__S as #serde_with_crate_path::__private__::FromStr>::Err: #serde_with_crate_path::__private__::Display,
1105 {
1106 type Value = __S;
1107
1108 fn expecting(&self, formatter: &mut #serde_with_crate_path::__private__::fmt::Formatter<'_>) -> #serde_with_crate_path::__private__::fmt::Result {
1109 #serde_with_crate_path::__private__::Display::fmt("a string", formatter)
1110 }
1111
1112 fn visit_str<__E>(
1113 self,
1114 value: &str
1115 ) -> #serde_with_crate_path::__private__::Result<Self::Value, __E>
1116 where
1117 __E: #serde_with_crate_path::__private__::DeError,
1118 {
1119 value.parse::<Self::Value>().map_err(#serde_with_crate_path::__private__::DeError::custom)
1120 }
1121
1122 fn visit_bytes<__E>(
1123 self,
1124 value: &[u8]
1125 ) -> #serde_with_crate_path::__private__::Result<Self::Value, __E>
1126 where
1127 __E: #serde_with_crate_path::__private__::DeError,
1128 {
1129 let utf8 = #serde_with_crate_path::__private__::str::from_utf8(value).map_err(#serde_with_crate_path::__private__::DeError::custom)?;
1130 self.visit_str(utf8)
1131 }
1132 }
1133
1134 deserializer.deserialize_str(Helper(#serde_with_crate_path::__private__::PhantomData))
1135 }
1136 }
1137 }
1138}
1139
1140/// Serialize value by using it's [`Display`] implementation
1141///
1142/// This is an alternative way to implement `Serialize` for types, which also implement [`Display`]
1143/// by serializing the type as string. Ensure that the struct/enum also implements [`Display`].
1144/// If the implementation is missing, you will get an error message like
1145/// ```text
1146/// error[E0277]: `Struct` doesn't implement `std::fmt::Display`
1147/// ```
1148///
1149/// Deserialization with [`FromStr`] is available with the matching [`DeserializeFromStr`] derive.
1150///
1151/// # Attributes
1152///
1153/// Attributes for the derive can be specified via the `#[serde_with(...)]` attribute on the struct
1154/// or enum. Currently, these arguments to the attribute are possible:
1155///
1156/// * **`#[serde_with(crate = "...")]`**: This allows using `SerializeDisplay` when `serde_with` is
1157/// not available from the crate root. This happens while [renaming dependencies in
1158/// Cargo.toml][cargo-toml-rename] or when re-exporting the macro from a different crate.
1159///
1160/// This argument is analogue to [serde's crate argument][serde-crate] and the [crate argument
1161/// to `serde_as`][serde-as-crate].
1162///
1163/// # Example
1164///
1165/// ```rust,ignore
1166/// use std::fmt;
1167///
1168/// #[derive(SerializeDisplay)]
1169/// struct A {
1170/// a: u32,
1171/// b: bool,
1172/// }
1173///
1174/// impl fmt::Display for A {
1175/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1176/// write!(f, "{}<>{}", self.a, self.b)
1177/// }
1178/// }
1179///
1180/// let a = A { a: 123, b: false };
1181/// assert_eq!(r#""123<>false""#, serde_json::to_string(&a).unwrap());
1182/// ```
1183///
1184/// [`Display`]: std::fmt::Display
1185/// [`FromStr`]: std::str::FromStr
1186/// [cargo-toml-rename]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml
1187/// [serde-as-crate]: https://docs.rs/serde_with/3.24.0/serde_with/guide/serde_as/index.html#re-exporting-serde_as
1188/// [serde-crate]: https://serde.rs/container-attrs.html#crate
1189#[proc_macro_derive(SerializeDisplay, attributes(serde_with))]
1190pub fn derive_serialize_display(item: TokenStream) -> TokenStream {
1191 let input: DeriveInput = parse_macro_input!(item);
1192 let derive_options = match DeriveOptions::from_derive_input(&input) {
1193 Ok(opt) => opt,
1194 Err(err) => {
1195 return err;
1196 }
1197 };
1198 TokenStream::from(serialize_display(
1199 input,
1200 false,
1201 derive_options.get_serde_with_path(),
1202 ))
1203}
1204
1205/// Serialize value by using its [`Display`] implementation with the “alternate” (`#`) format flag
1206///
1207/// This derive implements `serde::Serialize` for any type that already implements
1208/// [`std::fmt::Display`], emitting its string form using the alternate formatting specifier
1209/// (`{:#}`) instead of the normal `{}`. In other words, rather than calling
1210/// `format!("{}", self)`, it calls `format!("{:#}", self)`.
1211///
1212/// Ensure that your type implements [`Display`], or you will get a compile‐error such as:
1213/// ```text
1214/// error[E0277]: `MyType` doesn't implement `std::fmt::Display`
1215/// ```
1216///
1217/// Deserialization from strings via [`std::str::FromStr`] is handled by the companion
1218/// [`DeserializeFromStr`] derive.
1219///
1220/// # Attributes
1221///
1222/// You may customize which `serde_with` crate is used (for renamed or re-exported crates)
1223/// via the same attribute namespace:
1224///
1225/// * `#[serde_with(crate = "...")]`
1226/// When your workspace renames or re-exports `serde_with`, use this to point at the correct path.
1227/// For example:
1228/// ```rust,ignore
1229/// #[derive(SerializeDisplayAlt)]
1230/// #[serde_with(crate = "my_forked_serde_with")]
1231/// pub struct Foo(/* … */);
1232/// ```
1233///
1234/// # Example
1235///
1236/// ```rust,ignore
1237/// use std::fmt;
1238/// use serde_with::{SerializeDisplayAlt, DeserializeFromStr};
1239///
1240/// #[derive(Debug, Clone, SerializeDisplayAlt, DeserializeFromStr)]
1241/// pub struct MyType(u32);
1242///
1243/// impl fmt::Display for MyType {
1244/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1245/// if f.alternate() {
1246/// // Alternate formatting: hex with 0x prefix
1247/// write!(f, "0x{:X}", self.0)
1248/// } else {
1249/// // Standard formatting: decimal
1250/// write!(f, "{}", self.0)
1251/// }
1252/// }
1253/// }
1254///
1255/// let v = MyType(15);
1256/// // SerializeDisplayAlt always uses `{:#}`, so this yields `"0xF"`
1257/// assert_eq!(r#""0xF""#, serde_json::to_string(&v).unwrap());
1258/// ```
1259///
1260/// [`Display`]: std::fmt::Display
1261/// [`FromStr`]: std::str::FromStr
1262/// [`DeserializeFromStr`]: crate::DeserializeFromStr
1263#[proc_macro_derive(SerializeDisplayAlt, attributes(serde_with))]
1264pub fn derive_serialize_display_alt(item: TokenStream) -> TokenStream {
1265 let input: DeriveInput = parse_macro_input!(item);
1266 let derive_options = match DeriveOptions::from_derive_input(&input) {
1267 Ok(opt) => opt,
1268 Err(err) => {
1269 return err;
1270 }
1271 };
1272 TokenStream::from(serialize_display(
1273 input,
1274 true,
1275 derive_options.get_serde_with_path(),
1276 ))
1277}
1278
1279fn serialize_display(
1280 mut input: DeriveInput,
1281 alternate: bool,
1282 serde_with_crate_path: Path,
1283) -> TokenStream2 {
1284 let ident = input.ident;
1285 input
1286 .generics
1287 .make_where_clause()
1288 .predicates
1289 .push(parse_quote!(Self: #serde_with_crate_path::__private__::Display));
1290 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
1291
1292 let collect_str_param = if alternate {
1293 quote! { &format_args!("{self:#}") }
1294 } else {
1295 quote! { &self }
1296 };
1297
1298 quote! {
1299 #[automatically_derived]
1300 impl #impl_generics #serde_with_crate_path::__private__::Serialize for #ident #ty_generics #where_clause {
1301 fn serialize<__S>(
1302 &self,
1303 serializer: __S
1304 ) -> #serde_with_crate_path::__private__::Result<__S::Ok, __S::Error>
1305 where
1306 __S: #serde_with_crate_path::__private__::Serializer,
1307 {
1308 serializer.collect_str(#collect_str_param)
1309 }
1310 }
1311 }
1312}
1313
1314#[doc(hidden)]
1315/// Private function. Not part of the public API
1316///
1317/// The only task of this derive macro is to consume any `serde_as` attributes and turn them into
1318/// inert attributes. This allows the serde_as macro to keep the field attributes without causing
1319/// compiler errors. The intend is that keeping the field attributes allows downstream crates to
1320/// consume and act on them without causing an ordering dependency to the serde_as macro.
1321///
1322/// Otherwise, downstream proc-macros would need to be placed *in front of* the main `#[serde_as]`
1323/// attribute, since otherwise the field attributes would already be stripped off.
1324///
1325/// More details about the use-cases in the GitHub discussion: <https://github.com/jonasbb/serde_with/discussions/260>.
1326#[proc_macro_derive(
1327 __private_consume_serde_as_attributes,
1328 attributes(serde_as, serde_with)
1329)]
1330pub fn __private_consume_serde_as_attributes(_: TokenStream) -> TokenStream {
1331 TokenStream::new()
1332}
1333
1334/// Apply attributes to all fields with matching types
1335///
1336/// Whenever you experience the need to apply the same attributes to multiple fields, you can use
1337/// this macro. It allows you to specify a list of types and a list of attributes.
1338/// Each field with a "matching" type will then get the attributes applied.
1339/// The `apply` attribute must be placed *before* any consuming attributes, such as `derive` or
1340/// `serde_as`, because Rust expands all attributes in order.
1341///
1342/// For example, if your struct or enum contains many `Option<T>` fields, but you do not want to
1343/// serialize `None` values, you can use this macro to apply the `#[serde(skip_serializing_if =
1344/// "Option::is_none")]` attribute to all fields of type `Option<T>`.
1345///
1346/// ```rust
1347/// # use serde_with_macros as serde_with;
1348/// #[serde_with::apply(
1349/// # crate="serde_with",
1350/// Option => #[serde(skip_serializing_if = "Option::is_none")],
1351/// )]
1352/// #[derive(serde::Serialize)]
1353/// # #[derive(Default)]
1354/// struct Data {
1355/// a: Option<String>,
1356/// b: Option<u64>,
1357/// c: Option<String>,
1358/// d: Option<bool>,
1359/// }
1360/// #
1361/// # assert_eq!("{}", serde_json::to_string(&Data::default()).unwrap());
1362/// ```
1363///
1364/// Each rule starts with a type pattern, specifying which fields to match and a list of attributes
1365/// to apply. Multiple rules can be provided in a single `apply` attribute.
1366///
1367/// ```rust
1368/// # use serde_with_macros as serde_with;
1369/// #[serde_with::apply(
1370/// # crate="serde_with",
1371/// Option => #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")],
1372/// Option<bool> => #[serde(rename = "bool")],
1373/// )]
1374/// # #[derive(serde::Serialize)]
1375/// # #[derive(Default)]
1376/// # struct Data {
1377/// # a: Option<String>,
1378/// # b: Option<u64>,
1379/// # c: Option<String>,
1380/// # d: Option<bool>,
1381/// # }
1382/// #
1383/// # assert_eq!("{}", serde_json::to_string(&Data::default()).unwrap());
1384/// ```
1385///
1386/// ## Type Patterns
1387///
1388/// The type pattern left of the `=>` specifies which fields to match.
1389///
1390/// | Type Pattern | Matching Types | Notes |
1391/// | :---------------------- | ---------------------------------------------------: | :------------------------------------------------------------------------------ |
1392/// | `_` | `Option<bool>`<br>`BTreeMap<&'static str, Vec<u32>>` | `_` matches all fields. |
1393/// | `Option` | `Option<bool>`<br>`Option<String>` | A missing generic is compatible with any generic arguments. |
1394/// | `Option<bool>` | `Option<bool>` | A fully specified type only matches exactly. |
1395/// | `BTreeMap<String, u32>` | `BTreeMap<String, u32>` | A fully specified type only matches exactly. |
1396/// | `BTreeMap<String, _>` | `BTreeMap<String, u32>`<br>`BTreeMap<String, bool>` | Any `String` key `BTreeMap` matches, as the value is using the `_` placeholder. |
1397/// | `[u8; _]` | `[u8; 1]`<br>`[u8; N]` | `_` also works as a placeholder for any array length. |
1398///
1399/// ## Opt-out for Individual Fields
1400///
1401/// The `apply` attribute will find all fields with a compatible type.
1402/// This can be overly eager and a different set of attributes might be required for a specific
1403/// field. You can opt-out of the `apply` attribute by adding the `#[serde_with(skip_apply)]`
1404/// attribute to the field. This will prevent any `apply` to apply to this field.
1405/// If two rules apply to the same field, it is impossible to opt-out of only a single one.
1406/// In this case the attributes must be applied to the field manually.
1407///
1408/// ```rust
1409/// # use serde_json::json;
1410/// # use serde_with_macros as serde_with;
1411/// #[serde_with::apply(
1412/// # crate="serde_with",
1413/// Option => #[serde(skip_serializing_if = "Option::is_none")],
1414/// )]
1415/// #[derive(serde::Serialize)]
1416/// struct Data {
1417/// a: Option<String>,
1418/// #[serde_with(skip_apply)]
1419/// always_serialize_this_field: Option<u64>,
1420/// c: Option<String>,
1421/// d: Option<bool>,
1422/// }
1423///
1424/// let data = Data {
1425/// a: None,
1426/// always_serialize_this_field: None,
1427/// c: None,
1428/// d: None,
1429/// };
1430///
1431/// // serializes into this JSON:
1432/// # assert_eq!(json!(
1433/// {
1434/// "always_serialize_this_field": null
1435/// }
1436/// # ), serde_json::to_value(data).unwrap());
1437/// ```
1438///
1439/// # Alternative path to `serde_with` crate
1440///
1441/// If `serde_with` is not available at the default path, its path should be specified with the
1442/// `crate` argument. See [re-exporting `serde_as`] for more use case information.
1443///
1444/// ```rust,ignore
1445/// #[serde_with::apply(
1446/// crate = "::some_other_lib::serde_with"
1447/// Option => #[serde(skip_serializing_if = "Option::is_none")],
1448/// )]
1449/// #[derive(serde::Serialize)]
1450/// struct Data {
1451/// a: Option<String>,
1452/// b: Option<u64>,
1453/// c: Option<String>,
1454/// d: Option<bool>,
1455/// }
1456/// ```
1457#[proc_macro_attribute]
1458pub fn apply(args: TokenStream, input: TokenStream) -> TokenStream {
1459 apply::apply(args, input)
1460}