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

Macro generated serde helpers for designspace fields #314

Merged
merged 2 commits into from
Aug 3, 2023
Merged
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
194 changes: 86 additions & 108 deletions src/designspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,117 +184,95 @@ impl DesignSpaceDocument {
}

mod serde_impls {

use super::{Axis, Dimension, Instance, Source};
use serde::{Deserialize, Deserializer, Serialize, Serializer};

pub(super) mod location {
use super::*;

pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Vec<Dimension>, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
struct Helper {
dimension: Vec<Dimension>,
}
Helper::deserialize(deserializer).map(|x| x.dimension)
}

pub(crate) fn serialize<S>(location: &[Dimension], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
#[derive(Serialize)]
struct Helper<'a> {
dimension: &'a [Dimension],
}
let helper = Helper { dimension: location };
helper.serialize(serializer)
}
}

pub(super) mod instances {
use super::*;

pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Vec<Instance>, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
struct Helper {
instance: Vec<Instance>,
}
Helper::deserialize(deserializer).map(|x| x.instance)
}

pub(crate) fn serialize<S>(instances: &[Instance], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
#[derive(Serialize)]
struct Helper<'a> {
instance: &'a [Instance],
}
let helper = Helper { instance: instances };
helper.serialize(serializer)
}
}

pub(super) mod axes {
use super::*;

pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Vec<Axis>, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
struct Helper {
axis: Vec<Axis>,
}
Helper::deserialize(deserializer).map(|x| x.axis)
}

pub(crate) fn serialize<S>(axes: &[Axis], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
#[derive(Serialize)]
struct Helper<'a> {
axis: &'a [Axis],
/// Produces a self-contained module to (de)serialise an XML list of a given type
///
/// Example usage:
/// ```ignore
/// # use serde::{Serialize, Deserialize};
///
/// // In XML, the locations are referred to as <dimension/>
/// serde_from_field!(locations, dimension, Dimension);
///
/// #[derive(Serialize, Deserialize)]
/// struct DesignSpaceDocument {
/// #[serde(with = "locations")]
/// location: Vec<Dimension>,
/// }
///
/// #[derive(Serialize, Deserialize)]
/// struct Dimension;
/// ```
///
/// the generated code is approximately:
/// ```ignore
/// pub(super) mod locations {
/// # use serde::{Deserialize, Deserializer, Serializer, Serialize};
/// # use norad::designspace::Dimension;
/// pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Vec<Dimension>, D::Error>
/// where
/// D: Deserializer<'de>,
/// {
/// #[derive(Deserialize)]
/// struct Helper {
/// dimension: Vec<Dimension>,
/// }
/// Helper::deserialize(deserializer).map(|x| x.dimension)
/// }
///
/// pub(crate) fn serialize<S>(
/// dimension: &[Dimension],
/// serializer: S,
/// ) -> Result<S::Ok, S::Error>
/// where
/// S: Serializer,
/// {
/// #[derive(Serialize)]
/// struct Helper<'a> {
/// dimension: &'a [Dimension],
/// }
/// let helper = Helper { dimension };
/// helper.serialize(serializer)
/// }
/// }
/// ```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😆

macro_rules! serde_from_field {
($mod_name:ident, $field_name:ident, $inner:path) => {
pub(super) mod $mod_name {
pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Vec<$inner>, D::Error>
where
D: ::serde::Deserializer<'de>,
{
use ::serde::Deserialize as _;
#[derive(::serde::Deserialize)]
struct Helper {
$field_name: Vec<$inner>,
}
Helper::deserialize(deserializer).map(|x| x.$field_name)
}

pub(crate) fn serialize<S>(
$field_name: &[$inner],
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: ::serde::Serializer,
{
use ::serde::Serialize as _;
#[derive(::serde::Serialize)]
struct Helper<'a> {
$field_name: &'a [$inner],
}
let helper = Helper { $field_name };
helper.serialize(serializer)
}
}
let helper = Helper { axis: axes };
helper.serialize(serializer)
}
};
}

pub(super) mod sources {
use super::*;

pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Vec<Source>, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
struct Helper {
source: Vec<Source>,
}
Helper::deserialize(deserializer).map(|x| x.source)
}

pub(crate) fn serialize<S>(sources: &[Source], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
#[derive(Serialize)]
struct Helper<'a> {
source: &'a [Source],
}
let helper = Helper { source: sources };
helper.serialize(serializer)
}
}
serde_from_field!(location, dimension, crate::designspace::Dimension);
serde_from_field!(instances, instance, crate::designspace::Instance);
serde_from_field!(axes, axis, crate::designspace::Axis);
serde_from_field!(sources, source, crate::designspace::Source);
}

#[cfg(test)]
Expand Down