xso: Allow any T: FromXmlText + AsXmlText in EmptyAsNone

This text codec was previously implemented only for Option<String>, this
extends it to all types implementing those two traits, such as numbers
or JIDs.
This commit is contained in:
Emmanuel Gil Peyrot 2024-08-03 13:35:41 +02:00
commit 7f5b6fec7f

View file

@ -123,7 +123,7 @@ convert_via_fromstr_and_display! {
/// Represent a way to encode/decode text data into a Rust type. /// Represent a way to encode/decode text data into a Rust type.
/// ///
/// This trait can be used in scenarios where implementing [`FromXmlText`] /// This trait can be used in scenarios where implementing [`FromXmlText`]
/// and/or [`AsXmlText`] on a type is not feasible or sensible, such as the /// and/or [`AsXmlText`] on a type is not feasible or sensible, such as the
/// following: /// following:
/// ///
@ -202,23 +202,32 @@ impl TextCodec<String> for Plain {
} }
} }
/// Text codec which returns None instead of the empty string. /// Text codec which returns `None` if the input to decode is the empty string, instead of
/// attempting to decode it.
///
/// Particularly useful when parsing `Option<T>` on `#[xml(text)]`, which does not support
/// `Option<_>` otherwise.
pub struct EmptyAsNone; pub struct EmptyAsNone;
impl TextCodec<Option<String>> for EmptyAsNone { impl<T> TextCodec<Option<T>> for EmptyAsNone
fn decode(&self, s: String) -> Result<Option<String>, Error> { where
T: FromXmlText + AsXmlText,
{
fn decode(&self, s: String) -> Result<Option<T>, Error> {
if s.is_empty() { if s.is_empty() {
Ok(None) Ok(None)
} else { } else {
Ok(Some(s)) Some(T::from_xml_text(s)).transpose()
} }
} }
fn encode<'x>(&self, value: &'x Option<String>) -> Result<Option<Cow<'x, str>>, Error> { fn encode<'x>(&self, value: &'x Option<T>) -> Result<Option<Cow<'x, str>>, Error> {
Ok(match value.as_ref() { Ok(value
Some(v) if !v.is_empty() => Some(Cow::Borrowed(v.as_str())), .as_ref()
Some(_) | None => None, .map(AsXmlText::as_xml_text)
}) .transpose()?
.map(|v| (!v.is_empty()).then_some(v))
.flatten())
} }
} }