From 8c7b503f122f2a9709e76367d06081b7a587b101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Sch=C3=A4fer?= Date: Thu, 1 May 2025 16:35:42 +0200 Subject: [PATCH] xso: reorganise the code a little The main lib.rs is getting a bit cluttered, so I'm trying to bring some order into the chaos by moving some things into other modules. skip-changelog, because there are no user-facing changes (names which have been moved are doc(inline)'d and pub use'd in the main lib, and other things (trait implementations) aren't addressable by users). --- xso/src/fromxml.rs | 39 +++++++++++++- xso/src/lib.rs | 131 ++------------------------------------------- xso/src/text.rs | 90 ++++++++++++++++++++++++++++++- 3 files changed, 130 insertions(+), 130 deletions(-) diff --git a/xso/src/fromxml.rs b/xso/src/fromxml.rs index 6964019aa217827453b13702d9deb967d124ac54..9ecc94b5e510449d76010e2d47ce39e2802a4fa0 100644 --- a/xso/src/fromxml.rs +++ b/xso/src/fromxml.rs @@ -15,7 +15,44 @@ use alloc::boxed::Box; use crate::error::{Error, FromEventsError}; -use crate::{Context, FromEventsBuilder, FromXml}; +use crate::{FromEventsBuilder, FromXml}; + +/// # Parsing context for [`FromEventsBuilder`] +/// +/// For the most part, [`FromEventsBuilder`] implementations can work with +/// only the information inside the [`rxml::Event`] which is delivered to +/// them (and any information they may have stored from previous events). +/// +/// However, there is (currently) one special case: the `xml:lang` attribute. +/// That attribute is inherited across the entire document tree hierarchy. If +/// the parsed element is not the top-level element, there may be an implicit +/// value for `xml:lang`. +#[derive(Debug)] +#[doc(hidden)] +pub struct Context<'x> { + language: Option<&'x str>, +} + +impl<'x> Context<'x> { + /// A context suitable for the beginning of the document. + /// + /// `xml:lang` is assumed to be unset. + pub fn empty() -> Self { + Self { language: None } + } + + /// Set the effective `xml:lang` value on the context and return it. + pub fn with_language(mut self, language: Option<&'x str>) -> Self { + self.language = language; + self + } + + /// Return the `xml:lang` value in effect at the end of the event which + /// is currently being processed. + pub fn language(&self) -> Option<&str> { + self.language.as_deref() + } +} /// Helper struct to construct an `Option` from XML events. pub struct OptionBuilder(T); diff --git a/xso/src/lib.rs b/xso/src/lib.rs index d1caa406ec20309eadc5f6ac2bffac19a5b92f5b..04365d3895eb364557d592a29003933c3f6d4681 100644 --- a/xso/src/lib.rs +++ b/xso/src/lib.rs @@ -100,12 +100,10 @@ pub mod exports { } } -use alloc::{ - borrow::{Cow, ToOwned}, - boxed::Box, - string::String, - vec::Vec, -}; +use alloc::{borrow::Cow, string::String, vec::Vec}; + +#[doc(inline)] +pub use fromxml::Context; pub use text::TextCodec; @@ -154,42 +152,6 @@ pub trait AsXml { fn as_xml_iter(&self) -> Result, self::error::Error>; } -/// # Parsing context for [`FromEventsBuilder`] -/// -/// For the most part, [`FromEventsBuilder`] implementations can work with -/// only the information inside the [`rxml::Event`] which is delivered to -/// them (and any information they may have stored from previous events). -/// -/// However, there is (currently) one special case: the `xml:lang` attribute. -/// That attribute is inherited across the entire document tree hierarchy. If -/// the parsed element is not the top-level element, there may be an implicit -/// value for `xml:lang`. -#[derive(Debug)] -pub struct Context<'x> { - language: Option<&'x str>, -} - -impl<'x> Context<'x> { - /// A context suitable for the beginning of the document. - /// - /// `xml:lang` is assumed to be unset. - pub fn empty() -> Self { - Self { language: None } - } - - /// Set the effective `xml:lang` value on the context and return it. - pub fn with_language(mut self, language: Option<&'x str>) -> Self { - self.language = language; - self - } - - /// Return the `xml:lang` value in effect at the end of the event which - /// is currently being processed. - pub fn language(&self) -> Option<&str> { - self.language.as_deref() - } -} - /// Trait for a temporary object allowing to construct a struct from /// [`rxml::Event`] items. /// @@ -277,34 +239,6 @@ pub trait FromXmlText: Sized { fn from_xml_text(data: String) -> Result; } -impl FromXmlText for String { - /// Return the string unchanged. - fn from_xml_text(data: String) -> Result { - Ok(data) - } -} - -impl> FromXmlText for Cow<'_, B> { - /// Return a [`Cow::Owned`] containing the parsed value. - fn from_xml_text(data: String) -> Result { - Ok(Cow::Owned(T::from_xml_text(data)?)) - } -} - -impl FromXmlText for Option { - /// Return a [`Some`] containing the parsed value. - fn from_xml_text(data: String) -> Result { - Ok(Some(T::from_xml_text(data)?)) - } -} - -impl FromXmlText for Box { - /// Return a [`Box`] containing the parsed value. - fn from_xml_text(data: String) -> Result { - Ok(Box::new(T::from_xml_text(data)?)) - } -} - /// Trait to convert a value to an XML text string. /// /// Implementing this trait for a type allows it to be used both for XML @@ -341,48 +275,6 @@ pub trait AsXmlText { } } -impl AsXmlText for String { - /// Return the borrowed string contents. - fn as_xml_text(&self) -> Result, self::error::Error> { - Ok(Cow::Borrowed(self)) - } -} - -impl AsXmlText for str { - /// Return the borrowed string contents. - fn as_xml_text(&self) -> Result, self::error::Error> { - Ok(Cow::Borrowed(self)) - } -} - -impl AsXmlText for &str { - /// Return the borrowed string contents. - fn as_xml_text(&self) -> Result, self::error::Error> { - Ok(Cow::Borrowed(self)) - } -} - -impl AsXmlText for Box { - /// Return the borrowed [`Box`] contents. - fn as_xml_text(&self) -> Result, self::error::Error> { - T::as_xml_text(self) - } -} - -impl AsXmlText for Cow<'_, B> { - /// Return the borrowed [`Cow`] contents. - fn as_xml_text(&self) -> Result, self::error::Error> { - B::as_xml_text(self) - } -} - -impl AsXmlText for &T { - /// Delegate to the `AsXmlText` implementation on `T`. - fn as_xml_text(&self) -> Result, self::error::Error> { - T::as_xml_text(*self) - } -} - /// Specialized variant of [`AsXmlText`]. /// /// Normally, it should not be necessary to implement this trait as it is @@ -407,21 +299,6 @@ pub trait AsOptionalXmlText { fn as_optional_xml_text(&self) -> Result>, self::error::Error>; } -impl AsOptionalXmlText for T { - fn as_optional_xml_text(&self) -> Result>, self::error::Error> { - ::as_optional_xml_text(self) - } -} - -impl AsOptionalXmlText for Option { - fn as_optional_xml_text(&self) -> Result>, self::error::Error> { - self.as_ref() - .map(T::as_optional_xml_text) - .transpose() - .map(Option::flatten) - } -} - /// # Control how unknown attributes are handled /// /// The variants of this enum are referenced in the diff --git a/xso/src/text.rs b/xso/src/text.rs index 3f586d60cec5b374c6b2fdeda909e674a9a35db9..a7469579842d1452cc6939c67d868f48fba670d6 100644 --- a/xso/src/text.rs +++ b/xso/src/text.rs @@ -86,13 +86,14 @@ use core::marker::PhantomData; use alloc::{ - borrow::Cow, + borrow::{Cow, ToOwned}, + boxed::Box, format, string::{String, ToString}, vec::Vec, }; -use crate::{error::Error, AsXmlText, FromXmlText}; +use crate::{error::Error, AsOptionalXmlText, AsXmlText, FromXmlText}; #[cfg(feature = "base64")] use base64::engine::general_purpose::STANDARD as StandardBase64Engine; @@ -251,6 +252,91 @@ convert_via_fromstr_and_display! { serde_json::Value, } +impl FromXmlText for String { + /// Return the string unchanged. + fn from_xml_text(data: String) -> Result { + Ok(data) + } +} + +impl> FromXmlText for Cow<'_, B> { + /// Return a [`Cow::Owned`] containing the parsed value. + fn from_xml_text(data: String) -> Result { + Ok(Cow::Owned(T::from_xml_text(data)?)) + } +} + +impl FromXmlText for Option { + /// Return a [`Some`] containing the parsed value. + fn from_xml_text(data: String) -> Result { + Ok(Some(T::from_xml_text(data)?)) + } +} + +impl FromXmlText for Box { + /// Return a [`Box`] containing the parsed value. + fn from_xml_text(data: String) -> Result { + Ok(Box::new(T::from_xml_text(data)?)) + } +} + +impl AsXmlText for String { + /// Return the borrowed string contents. + fn as_xml_text(&self) -> Result, Error> { + Ok(Cow::Borrowed(self)) + } +} + +impl AsXmlText for str { + /// Return the borrowed string contents. + fn as_xml_text(&self) -> Result, Error> { + Ok(Cow::Borrowed(self)) + } +} + +impl AsXmlText for &str { + /// Return the borrowed string contents. + fn as_xml_text(&self) -> Result, Error> { + Ok(Cow::Borrowed(self)) + } +} + +impl AsXmlText for Box { + /// Return the borrowed [`Box`] contents. + fn as_xml_text(&self) -> Result, Error> { + T::as_xml_text(self) + } +} + +impl AsXmlText for Cow<'_, B> { + /// Return the borrowed [`Cow`] contents. + fn as_xml_text(&self) -> Result, Error> { + B::as_xml_text(self) + } +} + +impl AsXmlText for &T { + /// Delegate to the `AsXmlText` implementation on `T`. + fn as_xml_text(&self) -> Result, Error> { + T::as_xml_text(*self) + } +} + +impl AsOptionalXmlText for T { + fn as_optional_xml_text(&self) -> Result>, Error> { + ::as_optional_xml_text(self) + } +} + +impl AsOptionalXmlText for Option { + fn as_optional_xml_text(&self) -> Result>, Error> { + self.as_ref() + .map(T::as_optional_xml_text) + .transpose() + .map(Option::flatten) + } +} + /// Represent a way to encode/decode text data into a Rust type. /// /// This trait can be used in scenarios where implementing [`FromXmlText`]