use serde::de::DeserializeOwned;
use serde::{Deserializer, Serialize, Serializer};
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
where
T: Serialize,
S: Serializer,
{
use serde::ser::SerializeMap;
let yaml_value = crate::to_value(value).map_err(serde::ser::Error::custom)?;
match yaml_value {
crate::Value::Mapping(map) => {
let mut ser_map = serializer.serialize_map(Some(map.len()))?;
for (k, v) in map {
ser_map.serialize_entry(&k, &v)?;
}
ser_map.end()
}
crate::Value::String(s) => {
let mut ser_map = serializer.serialize_map(Some(1))?;
ser_map.serialize_entry(&s, &())?;
ser_map.end()
}
other => {
other.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 TestEnum {
Unit,
Newtype(i32),
Struct { value: String },
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Container {
name: String,
#[serde(with = "crate::with::singleton_map")]
item: TestEnum,
}
#[test]
fn test_singleton_map_unit_variant() {
let container = Container {
name: "test".to_string(),
item: TestEnum::Unit,
};
let yaml = crate::to_string(&container).unwrap();
assert!(yaml.contains("Unit"));
let parsed: Container = crate::from_str(&yaml).unwrap();
assert_eq!(parsed, container);
}
#[test]
fn test_singleton_map_struct_variant() {
let container = Container {
name: "test".to_string(),
item: TestEnum::Struct {
value: "hello".to_string(),
},
};
let yaml = crate::to_string(&container).unwrap();
assert!(yaml.contains("Struct"));
assert!(yaml.contains("value: hello"));
let parsed: Container = crate::from_str(&yaml).unwrap();
assert_eq!(parsed, container);
}
#[test]
fn test_singleton_map_fallback_sequence() {
#[derive(Debug, Serialize)]
struct SeqContainer {
#[serde(with = "crate::with::singleton_map")]
items: Vec<i32>,
}
let container = SeqContainer {
items: vec![1, 2, 3],
};
let yaml = crate::to_string(&container).unwrap();
assert!(yaml.contains("1"));
assert!(yaml.contains("2"));
assert!(yaml.contains("3"));
}
#[test]
fn test_singleton_map_fallback_integer() {
#[derive(Debug, Serialize)]
struct NumContainer {
#[serde(with = "crate::with::singleton_map")]
value: i32,
}
let container = NumContainer { value: 42 };
let yaml = crate::to_string(&container).unwrap();
assert!(yaml.contains("42"));
}
}