diff --git a/xso-proc/src/field/child.rs b/xso-proc/src/field/child.rs index 9474926c9baa6a9aa43fbceb168cb080168536fc..7da846ed89289a80295d2d61f61956e8c298c6c0 100644 --- a/xso-proc/src/field/child.rs +++ b/xso-proc/src/field/child.rs @@ -389,7 +389,7 @@ impl ExtractDef { // corresponding to this code above, and we will not repeat it // here. quote! { - ::xso::OptionAsXml::new(::core::option::Option::from(#bound_name).map(|#bound_name| { + ::xso::asxml::OptionAsXml::new(::core::option::Option::from(#bound_name).map(|#bound_name| { #item_iter_ty_ident::new((#bound_name,)) }).transpose()?) }, diff --git a/xso-proc/src/types.rs b/xso-proc/src/types.rs index 975afcfdbe5974b09d7373f8cc94c024db5e5595..b3713083e7b16b7f18b00b30e9bac6aab5a173c5 100644 --- a/xso-proc/src/types.rs +++ b/xso-proc/src/types.rs @@ -768,6 +768,10 @@ pub(crate) fn option_as_xml_ty(inner_ty: Type) -> Type { ident: Ident::new("xso", span), arguments: PathArguments::None, }, + PathSegment { + ident: Ident::new("asxml", span), + arguments: PathArguments::None, + }, PathSegment { ident: Ident::new("OptionAsXml", span), arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments { diff --git a/xso/src/asxml.rs b/xso/src/asxml.rs new file mode 100644 index 0000000000000000000000000000000000000000..b7bee08c6694f6b3f94a1415b25de76a98f84764 --- /dev/null +++ b/xso/src/asxml.rs @@ -0,0 +1,69 @@ +//! # Generic iterator type implementations +//! +//! This module contains [`AsXml`] iterator implementations for types from +//! foreign libraries (such as the standard library). +//! +//! In order to not clutter the `xso` crate's main namespace, they are +//! stashed away in a separate module. + +// Copyright (c) 2024 Jonas Schäfer +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +use crate::error::Error; +use crate::rxml_util::Item; +use crate::AsXml; + +/// Helper iterator to convert an `Option` to XML. +pub struct OptionAsXml(Option); + +impl OptionAsXml { + /// Construct a new iterator, wrapping the given iterator. + /// + /// If `inner` is `None`, this iterator terminates immediately. Otherwise, + /// it yields the elements yielded by `inner` until `inner` finishes, + /// after which this iterator completes, too. + pub fn new(inner: Option) -> Self { + Self(inner) + } +} + +impl<'x, T: Iterator, Error>>> Iterator for OptionAsXml { + type Item = Result, Error>; + + fn next(&mut self) -> Option { + self.0.as_mut()?.next() + } +} + +impl AsXml for Option { + type ItemIter<'x> = OptionAsXml> where T: 'x; + + fn as_xml_iter(&self) -> Result, Error> { + match self { + Some(ref value) => Ok(OptionAsXml(Some(T::as_xml_iter(value)?))), + None => Ok(OptionAsXml(None)), + } + } +} + +/// Helper iterator to convert an `Box` to XML. +pub struct BoxAsXml(Box); + +impl<'x, T: Iterator, Error>>> Iterator for BoxAsXml { + type Item = Result, Error>; + + fn next(&mut self) -> Option { + self.0.next() + } +} + +impl AsXml for Box { + type ItemIter<'x> = BoxAsXml> where T: 'x; + + fn as_xml_iter(&self) -> Result, Error> { + Ok(BoxAsXml(Box::new(T::as_xml_iter(&self)?))) + } +} diff --git a/xso/src/fromxml.rs b/xso/src/fromxml.rs new file mode 100644 index 0000000000000000000000000000000000000000..f76604400c775b297cf9b8a1f28bf2add760334d --- /dev/null +++ b/xso/src/fromxml.rs @@ -0,0 +1,60 @@ +//! # Generic builder type implementations +//! +//! This module contains [`FromEventsBuilder`] implementations for types from +//! foreign libraries (such as the standard library). +//! +//! In order to not clutter the `xso` crate's main namespace, they are +//! stashed away in a separate module. + +// Copyright (c) 2024 Jonas Schäfer +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +use crate::error::{Error, FromEventsError}; +use crate::{FromEventsBuilder, FromXml}; + +/// Helper struct to construct an `Option` from XML events. +pub struct OptionBuilder(T); + +impl FromEventsBuilder for OptionBuilder { + type Output = Option; + + fn feed(&mut self, ev: rxml::Event) -> Result, Error> { + self.0.feed(ev).map(|ok| ok.map(|value| Some(value))) + } +} + +impl FromXml for Option { + type Builder = OptionBuilder; + + fn from_events( + name: rxml::QName, + attrs: rxml::AttrMap, + ) -> Result { + Ok(OptionBuilder(T::from_events(name, attrs)?)) + } +} + +/// Helper struct to construct an `Box` from XML events. +pub struct BoxBuilder(Box); + +impl FromEventsBuilder for BoxBuilder { + type Output = Box; + + fn feed(&mut self, ev: rxml::Event) -> Result, Error> { + self.0.feed(ev).map(|ok| ok.map(|value| Box::new(value))) + } +} + +impl FromXml for Box { + type Builder = BoxBuilder; + + fn from_events( + name: rxml::QName, + attrs: rxml::AttrMap, + ) -> Result { + Ok(BoxBuilder(Box::new(T::from_events(name, attrs)?))) + } +} diff --git a/xso/src/lib.rs b/xso/src/lib.rs index a7884ad6dc5fcd043c3df0224df9090441768b94..9741b8d32c62422bfe0d2adbd8c6a51b0d2a47ff 100644 --- a/xso/src/lib.rs +++ b/xso/src/lib.rs @@ -21,7 +21,9 @@ use of this library in parsing XML streams like specified in RFC 6120. // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +pub mod asxml; pub mod error; +pub mod fromxml; #[cfg(feature = "minidom")] pub mod minidom_compat; mod rxml_util; @@ -81,58 +83,6 @@ pub trait AsXml { fn as_xml_iter(&self) -> Result, self::error::Error>; } -/// Helper iterator to convert an `Option` to XML. -pub struct OptionAsXml(Option); - -impl OptionAsXml { - /// Construct a new iterator, wrapping the given iterator. - /// - /// If `inner` is `None`, this iterator terminates immediately. Otherwise, - /// it yields the elements yielded by `inner` until `inner` finishes, - /// after which this iterator completes, too. - pub fn new(inner: Option) -> Self { - Self(inner) - } -} - -impl<'x, T: Iterator, self::error::Error>>> Iterator for OptionAsXml { - type Item = Result, self::error::Error>; - - fn next(&mut self) -> Option { - self.0.as_mut()?.next() - } -} - -/// Helper iterator to convert an `Box` to XML. -pub struct BoxAsXml(Box); - -impl<'x, T: Iterator, self::error::Error>>> Iterator for BoxAsXml { - type Item = Result, self::error::Error>; - - fn next(&mut self) -> Option { - self.0.next() - } -} - -impl AsXml for Option { - type ItemIter<'x> = OptionAsXml> where T: 'x; - - fn as_xml_iter(&self) -> Result, self::error::Error> { - match self { - Some(ref value) => Ok(OptionAsXml(Some(T::as_xml_iter(value)?))), - None => Ok(OptionAsXml(None)), - } - } -} - -impl AsXml for Box { - type ItemIter<'x> = BoxAsXml> where T: 'x; - - fn as_xml_iter(&self) -> Result, self::error::Error> { - Ok(BoxAsXml(Box::new(T::as_xml_iter(&self)?))) - } -} - /// Trait for a temporary object allowing to construct a struct from /// [`rxml::Event`] items. /// @@ -159,28 +109,6 @@ pub trait FromEventsBuilder { fn feed(&mut self, ev: rxml::Event) -> Result, self::error::Error>; } -/// Helper struct to construct an `Option` from XML events. -pub struct OptionBuilder(T); - -/// Helper struct to construct an `Box` from XML events. -pub struct BoxBuilder(Box); - -impl FromEventsBuilder for OptionBuilder { - type Output = Option; - - fn feed(&mut self, ev: rxml::Event) -> Result, self::error::Error> { - self.0.feed(ev).map(|ok| ok.map(|value| Some(value))) - } -} - -impl FromEventsBuilder for BoxBuilder { - type Output = Box; - - fn feed(&mut self, ev: rxml::Event) -> Result, self::error::Error> { - self.0.feed(ev).map(|ok| ok.map(|value| Box::new(value))) - } -} - /// Trait allowing to construct a struct from a stream of /// [`rxml::Event`] items. /// @@ -218,28 +146,6 @@ pub trait FromXml { ) -> Result; } -impl FromXml for Option { - type Builder = OptionBuilder; - - fn from_events( - name: rxml::QName, - attrs: rxml::AttrMap, - ) -> Result { - Ok(OptionBuilder(T::from_events(name, attrs)?)) - } -} - -impl FromXml for Box { - type Builder = BoxBuilder; - - fn from_events( - name: rxml::QName, - attrs: rxml::AttrMap, - ) -> Result { - Ok(BoxBuilder(Box::new(T::from_events(name, attrs)?))) - } -} - /// Trait allowing to convert XML text to a value. /// /// This trait is similar to [`core::str::FromStr`], however, due to