107 lines
2.2 KiB
Rust
107 lines
2.2 KiB
Rust
// build adapter with custom serialization names / grouping of (flattened) optional entries
|
|
macro_rules! adapter {
|
|
(
|
|
$adapter:ident => Option<$base:ident> {
|
|
$(
|
|
$(#[$field_meta:meta])*
|
|
$field:ident: $field_ty:ty,
|
|
)*
|
|
}
|
|
) => {
|
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
|
pub struct $adapter {
|
|
$(
|
|
$(#[$field_meta])*
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
$field: Option<$field_ty>,
|
|
)*
|
|
}
|
|
|
|
impl $adapter {
|
|
pub fn serialize<S>(value: &Option<$base>, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: serde::Serializer,
|
|
{
|
|
Self::from(value.clone()).serialize(serializer)
|
|
}
|
|
|
|
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<$base>, D::Error>
|
|
where
|
|
D: serde::Deserializer<'de>,
|
|
{
|
|
<$adapter as serde::Deserialize>::deserialize(deserializer).map(Option::<$base>::from)
|
|
}
|
|
}
|
|
|
|
impl From<Option<$base>> for $adapter {
|
|
fn from(base: Option<$base>) -> Self {
|
|
if let Some(base) = base {
|
|
Self {
|
|
$($field: Some(base.$field),)*
|
|
}
|
|
} else {
|
|
Self {
|
|
$($field: None,)*
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<$adapter> for Option<$base> {
|
|
fn from(adapter: $adapter) -> Self {
|
|
Option::Some($base {
|
|
$($field: adapter.$field?,)*
|
|
})
|
|
}
|
|
}
|
|
};
|
|
(
|
|
$adapter:ident => $base:ident {
|
|
$(
|
|
$(#[$field_meta:meta])*
|
|
$field:ident: $field_ty:ty,
|
|
)*
|
|
}
|
|
) => {
|
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
|
pub struct $adapter {
|
|
$(
|
|
$(#[$field_meta])*
|
|
$field: $field_ty,
|
|
)*
|
|
}
|
|
|
|
impl $adapter {
|
|
pub fn serialize<S>(value: &$base, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: serde::Serializer,
|
|
{
|
|
Self::from(value.clone()).serialize(serializer)
|
|
}
|
|
|
|
pub fn deserialize<'de, D>(deserializer: D) -> Result<$base, D::Error>
|
|
where
|
|
D: serde::Deserializer<'de>,
|
|
{
|
|
<$adapter as serde::Deserialize>::deserialize(deserializer).map($base::from)
|
|
}
|
|
}
|
|
|
|
impl From<$base> for $adapter {
|
|
fn from(base: $base) -> Self {
|
|
Self {
|
|
$($field: base.$field,)*
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<$adapter> for $base {
|
|
fn from(adapter: $adapter) -> Self {
|
|
Self {
|
|
$($field: adapter.$field,)*
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|