xso: add text conversion traits for AsXml
This commit is contained in:
parent
569b6e327d
commit
4910b01244
2 changed files with 107 additions and 1 deletions
|
@ -285,6 +285,90 @@ impl<T: IntoOptionalXmlText> IntoOptionalXmlText for Option<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trait to convert a value to an XML text string.
|
||||||
|
///
|
||||||
|
/// This trait is implemented for many standard library types implementing
|
||||||
|
/// [`std::fmt::Display`]. In addition, the following feature flags can enable
|
||||||
|
/// more implementations:
|
||||||
|
///
|
||||||
|
/// - `jid`: `jid::Jid`, `jid::BareJid`, `jid::FullJid`
|
||||||
|
/// - `uuid`: `uuid::Uuid`
|
||||||
|
///
|
||||||
|
/// Because of the unfortunate situation as described in [`FromXmlText`], we
|
||||||
|
/// are **extremely liberal** with accepting optional dependencies for this
|
||||||
|
/// purpose. You are very welcome to make merge requests against this crate
|
||||||
|
/// adding support for parsing third-party crates.
|
||||||
|
pub trait AsXmlText {
|
||||||
|
/// Convert the value to an XML string in a context where an absent value
|
||||||
|
/// cannot be represented.
|
||||||
|
fn as_xml_text(&self) -> Result<Cow<'_, str>, self::error::Error>;
|
||||||
|
|
||||||
|
/// Convert the value to an XML string in a context where an absent value
|
||||||
|
/// can be represented.
|
||||||
|
///
|
||||||
|
/// The provided implementation will always return the result of
|
||||||
|
/// [`Self::as_xml_text`] wrapped into `Some(.)`. By re-implementing
|
||||||
|
/// this method, implementors can customize the behaviour for certain
|
||||||
|
/// values.
|
||||||
|
fn as_optional_xml_text(&self) -> Result<Option<Cow<'_, str>>, self::error::Error> {
|
||||||
|
Ok(Some(self.as_xml_text()?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsXmlText for String {
|
||||||
|
fn as_xml_text(&self) -> Result<Cow<'_, str>, self::error::Error> {
|
||||||
|
Ok(Cow::Borrowed(self.as_str()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsXmlText for &str {
|
||||||
|
fn as_xml_text(&self) -> Result<Cow<'_, str>, self::error::Error> {
|
||||||
|
Ok(Cow::Borrowed(&**self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: AsXmlText> AsXmlText for Box<T> {
|
||||||
|
fn as_xml_text(&self) -> Result<Cow<'_, str>, self::error::Error> {
|
||||||
|
T::as_xml_text(&*self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B: AsXmlText + ToOwned> AsXmlText for Cow<'_, B> {
|
||||||
|
fn as_xml_text(&self) -> Result<Cow<'_, str>, self::error::Error> {
|
||||||
|
B::as_xml_text(self.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Specialized variant of [`AsXmlText`].
|
||||||
|
///
|
||||||
|
/// Do **not** implement this unless you cannot implement [`AsXmlText`]:
|
||||||
|
/// implementing [`AsXmlText`] is more versatile and an
|
||||||
|
/// [`AsOptionalXmlText`] implementation is automatically provided.
|
||||||
|
///
|
||||||
|
/// If you need to customize the behaviour of the [`AsOptionalXmlText`]
|
||||||
|
/// blanket implementation, implement a custom
|
||||||
|
/// [`AsXmlText::as_optional_xml_text`] instead.
|
||||||
|
pub trait AsOptionalXmlText {
|
||||||
|
/// Convert the value to an XML string in a context where an absent value
|
||||||
|
/// can be represented.
|
||||||
|
fn as_optional_xml_text(&self) -> Result<Option<Cow<'_, str>>, self::error::Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: AsXmlText> AsOptionalXmlText for T {
|
||||||
|
fn as_optional_xml_text(&self) -> Result<Option<Cow<'_, str>>, self::error::Error> {
|
||||||
|
<Self as AsXmlText>::as_optional_xml_text(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: AsXmlText> AsOptionalXmlText for Option<T> {
|
||||||
|
fn as_optional_xml_text(&self) -> Result<Option<Cow<'_, str>>, self::error::Error> {
|
||||||
|
self.as_ref()
|
||||||
|
.map(T::as_optional_xml_text)
|
||||||
|
.transpose()
|
||||||
|
.map(Option::flatten)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Attempt to transform a type implementing [`IntoXml`] into another
|
/// Attempt to transform a type implementing [`IntoXml`] into another
|
||||||
/// type which implements [`FromXml`].
|
/// type which implements [`FromXml`].
|
||||||
pub fn transform<T: FromXml, F: IntoXml>(from: F) -> Result<T, self::error::Error> {
|
pub fn transform<T: FromXml, F: IntoXml>(from: F) -> Result<T, self::error::Error> {
|
||||||
|
|
|
@ -9,7 +9,9 @@
|
||||||
#[cfg(feature = "base64")]
|
#[cfg(feature = "base64")]
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use crate::{error::Error, FromXmlText, IntoXmlText};
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
use crate::{error::Error, AsXmlText, FromXmlText, IntoXmlText};
|
||||||
|
|
||||||
#[cfg(feature = "base64")]
|
#[cfg(feature = "base64")]
|
||||||
use base64::engine::{general_purpose::STANDARD as StandardBase64Engine, Engine as _};
|
use base64::engine::{general_purpose::STANDARD as StandardBase64Engine, Engine as _};
|
||||||
|
@ -40,6 +42,16 @@ macro_rules! convert_via_fromstr_and_display {
|
||||||
Ok(self.to_string())
|
Ok(self.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(
|
||||||
|
#[cfg(feature = $feature)]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = $feature)))]
|
||||||
|
)?
|
||||||
|
impl AsXmlText for $t {
|
||||||
|
fn as_xml_text(&self) -> Result<Cow<'_, str>, Error> {
|
||||||
|
Ok(Cow::Owned(self.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
)+
|
)+
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,6 +76,16 @@ impl IntoXmlText for bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This provides an implementation compliant with xsd::bool.
|
||||||
|
impl AsXmlText for bool {
|
||||||
|
fn as_xml_text(&self) -> Result<Cow<'_, str>, Error> {
|
||||||
|
match self {
|
||||||
|
true => Ok(Cow::Borrowed("true")),
|
||||||
|
false => Ok(Cow::Borrowed("false")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
convert_via_fromstr_and_display! {
|
convert_via_fromstr_and_display! {
|
||||||
u8,
|
u8,
|
||||||
u16,
|
u16,
|
||||||
|
|
Loading…
Reference in a new issue