use serde::{Deserialize, Deserializer};
use std::fmt;
use std::result;
pub(super) fn deserialize_abstract_text<'de, D>(deserializer: D) -> result::Result<String, D::Error>
where
D: Deserializer<'de>,
{
use serde::de::{self, IgnoredAny, MapAccess, Visitor};
struct AbstractTextVisitor;
impl<'de> Visitor<'de> for AbstractTextVisitor {
type Value = String;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("abstract text content")
}
fn visit_str<E>(self, value: &str) -> result::Result<String, E>
where
E: de::Error,
{
Ok(value.to_string())
}
fn visit_string<E>(self, value: String) -> result::Result<String, E>
where
E: de::Error,
{
Ok(value)
}
fn visit_map<M>(self, mut map: M) -> result::Result<String, M::Error>
where
M: MapAccess<'de>,
{
let mut text_parts = Vec::new();
while let Some(key) = map.next_key::<String>()? {
if key == "$text" || key == "$value" {
let value: String = map.next_value()?;
text_parts.push(value);
} else {
let _: IgnoredAny = map.next_value()?;
}
}
Ok(text_parts.join(""))
}
}
deserializer.deserialize_any(AbstractTextVisitor)
}
pub(super) fn deserialize_bool_yn<'de, D>(deserializer: D) -> result::Result<bool, D::Error>
where
D: Deserializer<'de>,
{
let s: Option<String> = Option::deserialize(deserializer)?;
Ok(s.is_some_and(|s| s == "Y"))
}
#[cfg(test)]
mod tests {
use super::*;
use quick_xml::de::from_str;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct TestBoolYN {
#[serde(rename = "@value", default, deserialize_with = "deserialize_bool_yn")]
value: bool,
}
#[test]
fn test_deserialize_bool_yn() {
let xml = r#"<TestBoolYN value="Y" />"#;
let result: TestBoolYN = from_str(xml).unwrap();
assert!(result.value);
let xml = r#"<TestBoolYN value="N" />"#;
let result: TestBoolYN = from_str(xml).unwrap();
assert!(!result.value);
let xml = r#"<TestBoolYN />"#;
let result: TestBoolYN = from_str(xml).unwrap();
assert!(!result.value);
}
}