xso: Add std feature ; default-features compiles in no-std

xmppftw created

Change summary

xso/Cargo.toml            |  2 +
xso/src/asxml.rs          |  6 +++-
xso/src/error.rs          | 23 +++++++++++++--------
xso/src/fromxml.rs        |  3 ++
xso/src/lib.rs            | 42 +++++++++++++++++++++++++++-------------
xso/src/minidom_compat.rs |  8 +++++-
xso/src/rxml_util.rs      |  9 +++++++
xso/src/text.rs           |  7 +++++
8 files changed, 71 insertions(+), 29 deletions(-)

Detailed changes

xso/Cargo.toml 🔗

@@ -25,9 +25,11 @@ uuid = { version = "1", optional = true }
 base64 = { version = "0.22", optional = true }
 
 [features]
+default = [ "std" ]
 macros = [ "dep:xso_proc", "rxml/macros" ]
 minidom = [ "xso_proc/minidom"]
 panicking-into-impl = ["xso_proc/panicking-into-impl"]
+std = []
 
 [package.metadata.docs.rs]
 all-features = true

xso/src/asxml.rs 🔗

@@ -12,6 +12,8 @@
 // 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 alloc::boxed::Box;
+
 use crate::error::Error;
 use crate::rxml_util::Item;
 use crate::AsXml;
@@ -99,11 +101,11 @@ where
 mod tests {
     use super::*;
 
-    use std::borrow::Cow;
+    use alloc::{borrow::Cow, vec};
 
     #[test]
     fn option_as_xml_terminates_immediately_for_none() {
-        let mut iter = OptionAsXml::<std::iter::Empty<_>>(None);
+        let mut iter = OptionAsXml::<core::iter::Empty<_>>(None);
         match iter.next() {
             None => (),
             other => panic!("unexpected item: {:?}", other),

xso/src/error.rs 🔗

@@ -9,6 +9,11 @@ This module contains the error types used throughout the `xso` crate.
 // 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 alloc::{
+    boxed::Box,
+    string::{String, ToString},
+};
 use core::fmt;
 
 use rxml::Error as XmlError;
@@ -31,7 +36,7 @@ impl fmt::Display for OpaqueError {
     }
 }
 
-impl std::error::Error for OpaqueError {}
+impl core::error::Error for OpaqueError {}
 
 /// Error variants generated while parsing or serialising XML data.
 #[derive(Debug)]
@@ -40,7 +45,7 @@ pub enum Error {
     XmlError(XmlError),
 
     /// Attempt to parse text data failed with the provided nested error.
-    TextParseError(Box<dyn std::error::Error + Send + Sync + 'static>),
+    TextParseError(Box<dyn core::error::Error + Send + Sync + 'static>),
 
     /// Generic, unspecified other error.
     Other(&'static str),
@@ -58,7 +63,7 @@ impl Error {
     ///
     /// This includes the `Box::new(.)` call, making it directly usable as
     /// argument to [`Result::map_err`].
-    pub fn text_parse_error<T: std::error::Error + Send + Sync + 'static>(e: T) -> Self {
+    pub fn text_parse_error<T: core::error::Error + Send + Sync + 'static>(e: T) -> Self {
         Self::TextParseError(Box::new(e))
     }
 }
@@ -90,8 +95,8 @@ impl fmt::Display for Error {
     }
 }
 
-impl std::error::Error for Error {
-    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+impl core::error::Error for Error {
+    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
         match self {
             Self::XmlError(ref e) => Some(e),
             Self::TextParseError(ref e) => Some(&**e),
@@ -159,8 +164,8 @@ impl fmt::Display for FromEventsError {
     }
 }
 
-impl std::error::Error for FromEventsError {
-    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+impl core::error::Error for FromEventsError {
+    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
         match self {
             Self::Mismatch { .. } => None,
             Self::Invalid(ref e) => Some(e),
@@ -201,8 +206,8 @@ impl fmt::Display for FromElementError {
     }
 }
 
-impl std::error::Error for FromElementError {
-    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+impl core::error::Error for FromElementError {
+    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
         match self {
             Self::Mismatch(_) => None,
             Self::Invalid(ref e) => Some(e),

xso/src/fromxml.rs 🔗

@@ -12,6 +12,8 @@
 // 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 alloc::boxed::Box;
+
 use crate::error::{Error, FromEventsError};
 use crate::{FromEventsBuilder, FromXml};
 
@@ -271,6 +273,7 @@ impl FromEventsBuilder for Discard {
 mod tests {
     use super::*;
 
+    use alloc::borrow::ToOwned;
     use rxml::{parser::EventMetrics, Event, Namespace, NcName};
 
     macro_rules! null_builder {

xso/src/lib.rs 🔗

@@ -22,7 +22,11 @@ use of this library in parsing XML streams like specified in RFC 6120.
 // 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 std::io;
+#![no_std]
+
+extern crate alloc;
+#[cfg(feature = "std")]
+extern crate std;
 
 pub mod asxml;
 pub mod error;
@@ -39,7 +43,12 @@ pub mod exports {
     pub use rxml;
 }
 
-use std::borrow::Cow;
+use alloc::{
+    borrow::{Cow, ToOwned},
+    boxed::Box,
+    string::String,
+    vec::Vec,
+};
 
 #[doc(inline)]
 pub use text::TextCodec;
@@ -444,7 +453,8 @@ pub fn try_from_element<T: FromXml>(
     unreachable!("minidom::Element did not produce enough events to complete element")
 }
 
-fn map_nonio_error<T>(r: Result<T, io::Error>) -> Result<T, self::error::Error> {
+#[cfg(feature = "std")]
+fn map_nonio_error<T>(r: Result<T, std::io::Error>) -> Result<T, self::error::Error> {
     match r {
         Ok(v) => Ok(v),
         Err(e) => match e.downcast::<rxml::Error>() {
@@ -454,6 +464,7 @@ fn map_nonio_error<T>(r: Result<T, io::Error>) -> Result<T, self::error::Error>
     }
 }
 
+#[cfg(feature = "std")]
 fn read_start_event<I: std::io::BufRead>(
     r: &mut rxml::Reader<I>,
 ) -> Result<(rxml::QName, rxml::AttrMap), self::error::Error> {
@@ -475,6 +486,7 @@ fn read_start_event<I: std::io::BufRead>(
 
 /// Attempt to parse a type implementing [`FromXml`] from a byte buffer
 /// containing XML data.
+#[cfg(feature = "std")]
 pub fn from_bytes<T: FromXml>(mut buf: &[u8]) -> Result<T, self::error::Error> {
     let mut reader = rxml::Reader::new(&mut buf);
     let (name, attrs) = read_start_event(&mut reader)?;
@@ -493,23 +505,24 @@ pub fn from_bytes<T: FromXml>(mut buf: &[u8]) -> Result<T, self::error::Error> {
     Err(self::error::Error::XmlError(rxml::Error::InvalidEof(None)))
 }
 
+#[cfg(feature = "std")]
 fn read_start_event_io<I: std::io::BufRead>(
     r: &mut rxml::Reader<I>,
-) -> io::Result<(rxml::QName, rxml::AttrMap)> {
+) -> std::io::Result<(rxml::QName, rxml::AttrMap)> {
     for ev in r {
         match ev? {
             rxml::Event::XmlDeclaration(_, rxml::XmlVersion::V1_0) => (),
             rxml::Event::StartElement(_, name, attrs) => return Ok((name, attrs)),
             _ => {
-                return Err(io::Error::new(
-                    io::ErrorKind::InvalidData,
+                return Err(std::io::Error::new(
+                    std::io::ErrorKind::InvalidData,
                     self::error::Error::Other("Unexpected event at start of document"),
                 ))
             }
         }
     }
-    Err(io::Error::new(
-        io::ErrorKind::InvalidData,
+    Err(std::io::Error::new(
+        std::io::ErrorKind::InvalidData,
         self::error::Error::XmlError(rxml::Error::InvalidEof(Some(
             rxml::error::ErrorContext::DocumentBegin,
         ))),
@@ -517,29 +530,30 @@ fn read_start_event_io<I: std::io::BufRead>(
 }
 
 /// Attempt to parse a type implementing [`FromXml`] from a reader.
-pub fn from_reader<T: FromXml, R: io::BufRead>(r: R) -> io::Result<T> {
+#[cfg(feature = "std")]
+pub fn from_reader<T: FromXml, R: std::io::BufRead>(r: R) -> std::io::Result<T> {
     let mut reader = rxml::Reader::new(r);
     let (name, attrs) = read_start_event_io(&mut reader)?;
     let mut builder = match T::from_events(name, attrs) {
         Ok(v) => v,
         Err(self::error::FromEventsError::Mismatch { .. }) => {
             return Err(self::error::Error::TypeMismatch)
-                .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
+                .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
         }
         Err(self::error::FromEventsError::Invalid(e)) => {
-            return Err(e).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
+            return Err(e).map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
         }
     };
     for ev in reader {
         if let Some(v) = builder
             .feed(ev?)
-            .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?
+            .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?
         {
             return Ok(v);
         }
     }
-    Err(io::Error::new(
-        io::ErrorKind::UnexpectedEof,
+    Err(std::io::Error::new(
+        std::io::ErrorKind::UnexpectedEof,
         self::error::Error::XmlError(rxml::Error::InvalidEof(None)),
     ))
 }

xso/src/minidom_compat.rs 🔗

@@ -5,9 +5,13 @@
 // 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 alloc::{
+    borrow::{Cow, ToOwned},
+    boxed::Box,
+    vec::IntoIter,
+};
 use core::marker::PhantomData;
-use std::borrow::Cow;
-use std::vec::IntoIter;
 
 use minidom::{Element, Node};
 

xso/src/rxml_util.rs 🔗

@@ -6,7 +6,10 @@
 
 //! Utilities which may eventually move upstream to the `rxml` crate.
 
-use std::borrow::Cow;
+use alloc::{
+    borrow::{Cow, ToOwned},
+    string::String,
+};
 
 use rxml::{parser::EventMetrics, AttrMap, Event, Namespace, NcName, NcNameStr, XmlVersion};
 
@@ -283,6 +286,8 @@ impl<'x, I: Iterator<Item = Result<Item<'x>, crate::error::Error>>> Iterator for
 mod tests_minidom {
     use super::*;
 
+    use alloc::{string::ToString, vec, vec::Vec};
+
     fn events_to_items<I: Iterator<Item = Event>>(events: I) -> Vec<Item<'static>> {
         let iter = EventToItem {
             inner: events.map(|ev| Ok(ev)),
@@ -423,6 +428,8 @@ mod tests_minidom {
 mod tests {
     use super::*;
 
+    use alloc::{vec, vec::Vec};
+
     fn items_to_events<'x, I: IntoIterator<Item = Item<'x>>>(
         items: I,
     ) -> Result<Vec<Event>, crate::error::Error> {

xso/src/text.rs 🔗

@@ -8,7 +8,12 @@
 
 use core::marker::PhantomData;
 
-use std::borrow::Cow;
+use alloc::{
+    borrow::Cow,
+    format,
+    string::{String, ToString},
+    vec::Vec,
+};
 
 use crate::{error::Error, AsXmlText, FromXmlText};