From b1c50d530f7a25cea5082c0ba0a0fff934b5258e Mon Sep 17 00:00:00 2001 From: Ryosuke Yasuoka Date: Mon, 16 Dec 2024 19:11:28 +0900 Subject: [PATCH] Support Option in plain String serializer Signed-off-by: Ryosuke Yasuoka --- src/ser/map.rs | 10 ++++++---- src/ser/plain.rs | 27 ++++++++++++++++++--------- tests/datatypes.rs | 11 +++++++++++ 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/ser/map.rs b/src/ser/map.rs index b0793e6..bf4ca3a 100644 --- a/src/ser/map.rs +++ b/src/ser/map.rs @@ -26,7 +26,7 @@ impl<'ser, W: Write> serde::ser::SerializeMap for MapSerializer<'ser, W> { where T: ?Sized + Serialize, { - self.ser.open_tag(&to_plain_string(key)?)?; + self.ser.open_tag(&to_plain_string(key)?.unwrap())?; Ok(()) } @@ -65,20 +65,22 @@ impl<'ser, W: 'ser + Write> StructSerializer<'ser, W> { { if key.starts_with("@") { debug!("attribute {}", key); - self.ser.add_attr(&key[1..], to_plain_string(value)?) + if let Some(string_value) = to_plain_string(value)? { + self.ser.add_attr(&key[1..], string_value)? + } + // key was not present } else if key == "$value" { self.ser.build_start_tag()?; debug!("body"); value.serialize(&mut *self.ser)?; - Ok(()) } else { self.ser.build_start_tag()?; self.ser.open_tag(key)?; debug!("field {}", key); value.serialize(&mut *self.ser)?; debug!("end field"); - Ok(()) } + Ok(()) } fn after_fields(self) -> Result<()> { diff --git a/src/ser/plain.rs b/src/ser/plain.rs index 49e2964..c76b995 100644 --- a/src/ser/plain.rs +++ b/src/ser/plain.rs @@ -4,24 +4,32 @@ use serde::ser::{Impossible, Serialize}; use crate::error::{Error, Result}; -pub fn to_plain_string(value: &T) -> Result +pub fn to_plain_string(value: &T) -> Result> where T: ?Sized + Serialize, { let mut writer = Vec::with_capacity(128); - value.serialize(&mut PlainStringSerializer::new(&mut writer))?; + let mut pss = PlainStringSerializer::new(&mut writer); + value.serialize(&mut pss)?; - let string = String::from_utf8(writer)?; - Ok(string) + if !pss.present { + // String does not present + return Ok(None); + } + Ok(Some(String::from_utf8(writer)?)) } struct PlainStringSerializer { writer: W, + present: bool, } impl PlainStringSerializer { fn new(writer: W) -> Self { - PlainStringSerializer { writer } + PlainStringSerializer { + writer, + present: true, + } } fn characters(&mut self, s: &str) -> Result<()> { @@ -99,18 +107,19 @@ impl<'ser, W: 'ser + Write> serde::ser::Serializer for &'ser mut PlainStringSeri } fn serialize_none(self) -> Result { - unimplemented!() + self.serialize_unit() } - fn serialize_some(self, _value: &T) -> Result + fn serialize_some(self, value: &T) -> Result where T: Serialize, { - unimplemented!() + value.serialize(self) } fn serialize_unit(self) -> Result { - unimplemented!() + self.present = false; + Ok(()) } fn serialize_unit_struct(self, _name: &'static str) -> Result { diff --git a/tests/datatypes.rs b/tests/datatypes.rs index 60410c4..70bb454 100644 --- a/tests/datatypes.rs +++ b/tests/datatypes.rs @@ -136,6 +136,7 @@ mod ser { #[case::string(r#""#, "".to_string())] #[case::bool(r#""#, true)] #[case::bool(r#""#, false)] + #[case::option(r#""#, Some("apple".to_string()))] fn attribute_ok(_logger: (), #[case] expected: &str, #[case] value: T) where T: Serialize + Debug, @@ -146,4 +147,14 @@ mod ser { format!(r#"{}"#, expected) ); } + + #[rstest] + #[case::option(r#""#, None)] + fn attribute_none_ok(_logger: (), #[case] expected: &str, #[case] value: Option) { + let actual = to_string(&DummyAttribute { value }).unwrap(); + assert_eq!( + actual, + format!(r#"{}"#, expected) + ); + } }