@@ -50,6 +50,9 @@ Version NEXT:
- Support for a post-deserialization callback function call. (!553)
- Support for correctly inheriting `xml:lang` values throughout the
XML document.
+ - `xso::convert_via_fromstr_and_display`, a declarative macro to provide
+ `AsXmlText` and `FromXmlText` implementations based on the standard
+ library's `Display` and `FromStr` traits.
* Changes
- Generated AsXml iterator and FromXml builder types are now
doc(hidden), to not clutter hand-written documentation with auto
@@ -39,10 +39,10 @@ mod rxml_util;
pub mod text;
#[doc(hidden)]
-#[cfg(feature = "macros")]
pub mod exports {
- #[cfg(feature = "minidom")]
+ #[cfg(all(feature = "minidom", feature = "macros"))]
pub use minidom;
+ #[cfg(feature = "macros")]
pub use rxml;
// These re-exports are necessary to support both std and no_std in code
@@ -65,12 +65,14 @@ pub mod exports {
///
/// This is re-exported for use by macros in cases where we cannot rely on
/// people not having done `type bool = str` or some similar shenanigans.
+ #[cfg(feature = "macros")]
pub type CoreBool = bool;
/// The built-in `u8` type.
///
/// This is re-exported for use by macros in cases where we cannot rely on
/// people not having done `type u8 = str` or some similar shenanigans.
+ #[cfg(feature = "macros")]
pub type CoreU8 = u8;
/// Compile-time comparison of two strings.
@@ -78,6 +80,7 @@ pub mod exports {
/// Used by macro-generated code.
///
/// This is necessary because `<str as PartialEq>::eq` is not `const`.
+ #[cfg(feature = "macros")]
pub const fn const_str_eq(a: &'static str, b: &'static str) -> bool {
let a = a.as_bytes();
let b = b.as_bytes();
@@ -97,26 +97,67 @@ use crate::{error::Error, AsXmlText, FromXmlText};
#[cfg(feature = "base64")]
use base64::engine::general_purpose::STANDARD as StandardBase64Engine;
+/// # Generate `AsXmlText` and `FromXmlText` implementations
+///
+/// This macro generates an `AsXmlText` implementation which uses
+/// [`Display`][`core::fmt::Display`] and an `FromXmlText` which uses
+/// [`FromStr`][`core::str::FromStr`] for the types it is called on.
+///
+/// ## Syntax
+///
+/// The macro accepts a comma-separated list of types. Optionally, each type
+/// can be preceded by a `#[cfg(..)]` attribute to make the implementations
+/// conditional on a feature.
+///
+/// ## Example
+///
+#[cfg_attr(
+ not(feature = "macros"),
+ doc = "Because the macros feature was not enabled at doc build time, the example cannot be tested.\n\n```ignore\n"
+)]
+#[cfg_attr(feature = "macros", doc = "\n```\n")]
+/// # use xso::convert_via_fromstr_and_display;
+/// # use core::fmt::{self, Display};
+/// # use core::str::FromStr;
+/// struct Foo;
+///
+/// impl FromStr for Foo {
+/// # type Err = core::convert::Infallible;
+/// #
+/// # fn from_str(s: &str) -> Result<Self, Self::Err> { todo!() }
+/// /* ... */
+/// }
+///
+/// impl Display for Foo {
+/// # fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { todo!() }
+/// /* ... */
+/// }
+///
+/// convert_via_fromstr_and_display!(
+/// Foo,
+/// );
+/// ```
+#[macro_export]
macro_rules! convert_via_fromstr_and_display {
- ($($(#[cfg $cfg:tt])?$t:ty,)+) => {
+ ($($(#[cfg $cfg:tt])?$t:ty),+ $(,)?) => {
$(
$(
#[cfg $cfg]
)?
- impl FromXmlText for $t {
+ impl $crate::FromXmlText for $t {
#[doc = concat!("Parse [`", stringify!($t), "`] from XML text via [`FromStr`][`core::str::FromStr`].")]
- fn from_xml_text(s: String) -> Result<Self, Error> {
- s.parse().map_err(Error::text_parse_error)
+ fn from_xml_text(s: String) -> Result<Self, $crate::error::Error> {
+ s.parse().map_err($crate::error::Error::text_parse_error)
}
}
$(
#[cfg $cfg]
)?
- impl AsXmlText for $t {
+ impl $crate::AsXmlText for $t {
#[doc = concat!("Convert [`", stringify!($t), "`] to XML text via [`Display`][`core::fmt::Display`].\n\nThis implementation never fails.")]
- fn as_xml_text(&self) -> Result<Cow<'_, str>, Error> {
- Ok(Cow::Owned(self.to_string()))
+ fn as_xml_text(&self) -> Result<$crate::exports::alloc::borrow::Cow<'_, str>, $crate::error::Error> {
+ Ok($crate::exports::alloc::borrow::Cow::Owned(self.to_string()))
}
}
)+