Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Describe how the serde_as macro works on a high level #303

Merged
merged 1 commit into from
Apr 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Describe how the serde_as macro works on a high level
Closed #297
  • Loading branch information
jonasbb committed Apr 21, 2021
commit d97f0fa89a139f66cb55e707ca9fd46d0c918a5b
6 changes: 6 additions & 0 deletions serde_with_macros/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## Unreleased

### Fixed

* Describe how the `serde_as` macro works on a high level.

## [1.4.1] - 2021-02-16

### Fixed
Expand Down
42 changes: 42 additions & 0 deletions serde_with_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,48 @@ fn field_has_attribute(field: &Field, namespace: &str, name: &str) -> bool {
/// }
/// ```
///
/// # What this macro does
///
/// The `serde_as` macro only serves a convenience function.
/// All the steps it takes can easily applied manually, in case the cost of an attribute macro is deemed to high.
/// The functionality can best be described with an example.
///
/// ```rust,ignore
/// #[serde_as]
/// #[derive(serde::Serialize)]
/// struct Foo {
/// #[serde_as(as = "Vec<_>")]
/// bar: Vec<u32>,
/// }
/// ```
///
/// 1. All the placeholder type `_` will be replaced with `::serde_with::Same`.
/// The placeholder type `_` marks all the places where the types `Serialize` implementation should be used.
/// In the example it means that the u32 values will be serialize by the `Serialize` implementation of u32.
/// The `Same` type implements `SerializeAs` whenever the underlying type implements `Serialize` and is used to make the two traits compatible.
///
/// If you specify a custom path for `serde_with` via the `crate` attribute the path to the `Same` type will be altered accordingly.
/// 2. Wrap the type from the annotation inside a `::serde_with::As`.
/// In the above example we know have something like `::serde_with::As::<Vec<::serde_with::Same>>`.
/// The `As` type acts as the opposite of the `Same` type.
/// It allows using a `SerializeAs` type whenever a `Serialize` is required.
/// 3. Translate the `*as` attributes into the serde equivalent ones.
/// `#[serde_as(as = ...)]` will become `#[serde(with = ...)]`.
/// Similarly, `serialize_as` is translated to `serialize_with`.
///
/// The field attributes will be kept on the struct/enum such that other macros can use them too.
///
/// After all these steps, the code snippet will have transformed into roughly this.
///
/// ```rust,ignore
/// #[derive(serde::Serialize)]
/// struct Foo {
/// #[serde_as(as = "Vec<_>")]
/// #[serde(with = "::serde_with::As::<Vec<::serde_with::Same>>")]
/// bar: Vec<u32>,
/// }
/// ```
///
/// [`serde_as`]: https://docs.rs/serde_with/1.8.1/serde_with/guide/index.html
/// [re-exporting `serde_as`]: https://docs.rs/serde_with/1.8.1/serde_with/guide/serde_as/index.html#re-exporting-serde_as
#[proc_macro_attribute]
Expand Down