xso-proc: add support for text codecs

Text codecs allow to customize the conversion of data from/to XML,
in particular in two scenarios:

1. When the type for which the behaviour is to be defined comes from a
   foreign crate, preventing the implementation of
   FromXmlText/IntoXmlText.

2. When there is not one obvious, or more than one sensible, way to
   convert a value to XML text and back.
This commit is contained in:
Jonas Schäfer 2024-06-26 18:26:13 +02:00
commit c83ff286e0
8 changed files with 258 additions and 26 deletions

View file

@ -312,7 +312,10 @@ pub(crate) enum XmlFieldMeta {
},
/// `#[xml(text)]`
Text,
Text {
/// The path to the optional codec type.
codec: Option<Type>,
},
}
impl XmlFieldMeta {
@ -393,8 +396,28 @@ impl XmlFieldMeta {
}
/// Parse a `#[xml(text)]` meta.
fn text_from_meta(_: ParseNestedMeta<'_>) -> Result<Self> {
Ok(Self::Text)
fn text_from_meta(meta: ParseNestedMeta<'_>) -> Result<Self> {
let mut codec: Option<Type> = None;
if meta.input.peek(Token![=]) {
Ok(Self::Text {
codec: Some(meta.value()?.parse()?),
})
} else if meta.input.peek(syn::token::Paren) {
meta.parse_nested_meta(|meta| {
if meta.path.is_ident("codec") {
if codec.is_some() {
return Err(Error::new_spanned(meta.path, "duplicate `codec` key"));
}
codec = Some(meta.value()?.parse()?);
Ok(())
} else {
Err(Error::new_spanned(meta.path, "unsupported key"))
}
})?;
Ok(Self::Text { codec })
} else {
Ok(Self::Text { codec: None })
}
}
/// Parse [`Self`] from a nestd meta, switching on the identifier