use crate::prelude::*;
use serde::de::DeserializeOwned;
use serde::{Deserializer, Serialize, Serializer};
fn transform_to_singleton_map(value: crate::Value) -> crate::Value {
match value {
crate::Value::Sequence(seq) => {
crate::Value::Sequence(seq.into_iter().map(transform_to_singleton_map).collect())
}
crate::Value::Mapping(map) => {
let transformed: crate::Mapping = map
.into_iter()
.map(|(k, v)| (k, transform_to_singleton_map(v)))
.collect();
crate::Value::Mapping(transformed)
}
crate::Value::Tagged(tagged) => {
let (tag, value) = tagged.into_parts();
let inner = transform_to_singleton_map(value);
crate::Value::Tagged(Box::new(crate::TaggedValue::new(tag, inner)))
}
other => other,
}
}
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
where
T: Serialize,
S: Serializer,
{
let yaml_value = crate::to_value(value).map_err(serde::ser::Error::custom)?;
let transformed = transform_to_singleton_map(yaml_value);
transformed.serialize(serializer)
}
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
T: DeserializeOwned + 'static,
D: Deserializer<'de>,
{
use serde::Deserialize;
let value = crate::Value::deserialize(deserializer)?;
crate::from_value(&value).map_err(serde::de::Error::custom)
}
#[cfg(test)]
mod tests {
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, PartialEq)]
enum Inner {
A,
B { value: i32 },
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Container {
name: String,
#[serde(with = "crate::with::singleton_map_recursive")]
items: Vec<Inner>,
}
#[test]
fn test_recursive_vec_of_enums() {
let container = Container {
name: "test".to_string(),
items: vec![Inner::A, Inner::B { value: 42 }],
};
let yaml = crate::to_string(&container).unwrap();
let parsed: Container = crate::from_str(&yaml).unwrap();
assert_eq!(parsed, container);
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Nested {
#[serde(with = "crate::with::singleton_map_recursive")]
data: std::collections::BTreeMap<String, Inner>,
}
#[test]
fn test_recursive_map_of_enums() {
let mut data = std::collections::BTreeMap::new();
let _ = data.insert("first".to_string(), Inner::A);
let _ = data.insert("second".to_string(), Inner::B { value: 100 });
let container = Nested { data };
let yaml = crate::to_string(&container).unwrap();
let parsed: Nested = crate::from_str(&yaml).unwrap();
assert_eq!(parsed, container);
}
}