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

This commit is contained in:
xmppftw xmppftw 2024-12-18 22:21:56 +01:00 committed by Emmanuel Gil Peyrot
commit 1c1b960265
8 changed files with 71 additions and 29 deletions

View file

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

View file

@ -12,6 +12,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this // 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/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
use alloc::boxed::Box;
use crate::error::Error; use crate::error::Error;
use crate::rxml_util::Item; use crate::rxml_util::Item;
use crate::AsXml; use crate::AsXml;
@ -99,11 +101,11 @@ where
mod tests { mod tests {
use super::*; use super::*;
use std::borrow::Cow; use alloc::{borrow::Cow, vec};
#[test] #[test]
fn option_as_xml_terminates_immediately_for_none() { 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() { match iter.next() {
None => (), None => (),
other => panic!("unexpected item: {:?}", other), other => panic!("unexpected item: {:?}", other),

View file

@ -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 // 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 // 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/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
use alloc::{
boxed::Box,
string::{String, ToString},
};
use core::fmt; use core::fmt;
use rxml::Error as XmlError; 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. /// Error variants generated while parsing or serialising XML data.
#[derive(Debug)] #[derive(Debug)]
@ -40,7 +45,7 @@ pub enum Error {
XmlError(XmlError), XmlError(XmlError),
/// Attempt to parse text data failed with the provided nested error. /// 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. /// Generic, unspecified other error.
Other(&'static str), Other(&'static str),
@ -58,7 +63,7 @@ impl Error {
/// ///
/// This includes the `Box::new(.)` call, making it directly usable as /// This includes the `Box::new(.)` call, making it directly usable as
/// argument to [`Result::map_err`]. /// 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)) Self::TextParseError(Box::new(e))
} }
} }
@ -90,8 +95,8 @@ impl fmt::Display for Error {
} }
} }
impl std::error::Error for Error { impl core::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
match self { match self {
Self::XmlError(ref e) => Some(e), Self::XmlError(ref e) => Some(e),
Self::TextParseError(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 { impl core::error::Error for FromEventsError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
match self { match self {
Self::Mismatch { .. } => None, Self::Mismatch { .. } => None,
Self::Invalid(ref e) => Some(e), Self::Invalid(ref e) => Some(e),
@ -201,8 +206,8 @@ impl fmt::Display for FromElementError {
} }
} }
impl std::error::Error for FromElementError { impl core::error::Error for FromElementError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
match self { match self {
Self::Mismatch(_) => None, Self::Mismatch(_) => None,
Self::Invalid(ref e) => Some(e), Self::Invalid(ref e) => Some(e),

View file

@ -12,6 +12,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this // 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/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
use alloc::boxed::Box;
use crate::error::{Error, FromEventsError}; use crate::error::{Error, FromEventsError};
use crate::{FromEventsBuilder, FromXml}; use crate::{FromEventsBuilder, FromXml};
@ -271,6 +273,7 @@ impl FromEventsBuilder for Discard {
mod tests { mod tests {
use super::*; use super::*;
use alloc::borrow::ToOwned;
use rxml::{parser::EventMetrics, Event, Namespace, NcName}; use rxml::{parser::EventMetrics, Event, Namespace, NcName};
macro_rules! null_builder { macro_rules! null_builder {

View file

@ -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 // 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/. // 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 asxml;
pub mod error; pub mod error;
@ -39,7 +43,12 @@ pub mod exports {
pub use rxml; pub use rxml;
} }
use std::borrow::Cow; use alloc::{
borrow::{Cow, ToOwned},
boxed::Box,
string::String,
vec::Vec,
};
#[doc(inline)] #[doc(inline)]
pub use text::TextCodec; 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") 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 { match r {
Ok(v) => Ok(v), Ok(v) => Ok(v),
Err(e) => match e.downcast::<rxml::Error>() { 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>( fn read_start_event<I: std::io::BufRead>(
r: &mut rxml::Reader<I>, r: &mut rxml::Reader<I>,
) -> Result<(rxml::QName, rxml::AttrMap), self::error::Error> { ) -> 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 /// Attempt to parse a type implementing [`FromXml`] from a byte buffer
/// containing XML data. /// containing XML data.
#[cfg(feature = "std")]
pub fn from_bytes<T: FromXml>(mut buf: &[u8]) -> Result<T, self::error::Error> { pub fn from_bytes<T: FromXml>(mut buf: &[u8]) -> Result<T, self::error::Error> {
let mut reader = rxml::Reader::new(&mut buf); let mut reader = rxml::Reader::new(&mut buf);
let (name, attrs) = read_start_event(&mut reader)?; 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))) Err(self::error::Error::XmlError(rxml::Error::InvalidEof(None)))
} }
#[cfg(feature = "std")]
fn read_start_event_io<I: std::io::BufRead>( fn read_start_event_io<I: std::io::BufRead>(
r: &mut rxml::Reader<I>, r: &mut rxml::Reader<I>,
) -> io::Result<(rxml::QName, rxml::AttrMap)> { ) -> std::io::Result<(rxml::QName, rxml::AttrMap)> {
for ev in r { for ev in r {
match ev? { match ev? {
rxml::Event::XmlDeclaration(_, rxml::XmlVersion::V1_0) => (), rxml::Event::XmlDeclaration(_, rxml::XmlVersion::V1_0) => (),
rxml::Event::StartElement(_, name, attrs) => return Ok((name, attrs)), rxml::Event::StartElement(_, name, attrs) => return Ok((name, attrs)),
_ => { _ => {
return Err(io::Error::new( return Err(std::io::Error::new(
io::ErrorKind::InvalidData, std::io::ErrorKind::InvalidData,
self::error::Error::Other("Unexpected event at start of document"), self::error::Error::Other("Unexpected event at start of document"),
)) ))
} }
} }
} }
Err(io::Error::new( Err(std::io::Error::new(
io::ErrorKind::InvalidData, std::io::ErrorKind::InvalidData,
self::error::Error::XmlError(rxml::Error::InvalidEof(Some( self::error::Error::XmlError(rxml::Error::InvalidEof(Some(
rxml::error::ErrorContext::DocumentBegin, 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. /// 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 mut reader = rxml::Reader::new(r);
let (name, attrs) = read_start_event_io(&mut reader)?; let (name, attrs) = read_start_event_io(&mut reader)?;
let mut builder = match T::from_events(name, attrs) { let mut builder = match T::from_events(name, attrs) {
Ok(v) => v, Ok(v) => v,
Err(self::error::FromEventsError::Mismatch { .. }) => { Err(self::error::FromEventsError::Mismatch { .. }) => {
return Err(self::error::Error::TypeMismatch) 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)) => { 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 { for ev in reader {
if let Some(v) = builder if let Some(v) = builder
.feed(ev?) .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); return Ok(v);
} }
} }
Err(io::Error::new( Err(std::io::Error::new(
io::ErrorKind::UnexpectedEof, std::io::ErrorKind::UnexpectedEof,
self::error::Error::XmlError(rxml::Error::InvalidEof(None)), self::error::Error::XmlError(rxml::Error::InvalidEof(None)),
)) ))
} }

View file

@ -5,9 +5,13 @@
// This Source Code Form is subject to the terms of the Mozilla Public // 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 // 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/. // 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 core::marker::PhantomData;
use std::borrow::Cow;
use std::vec::IntoIter;
use minidom::{Element, Node}; use minidom::{Element, Node};

View file

@ -6,7 +6,10 @@
//! Utilities which may eventually move upstream to the `rxml` crate. //! 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}; 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 { mod tests_minidom {
use super::*; use super::*;
use alloc::{string::ToString, vec, vec::Vec};
fn events_to_items<I: Iterator<Item = Event>>(events: I) -> Vec<Item<'static>> { fn events_to_items<I: Iterator<Item = Event>>(events: I) -> Vec<Item<'static>> {
let iter = EventToItem { let iter = EventToItem {
inner: events.map(|ev| Ok(ev)), inner: events.map(|ev| Ok(ev)),
@ -423,6 +428,8 @@ mod tests_minidom {
mod tests { mod tests {
use super::*; use super::*;
use alloc::{vec, vec::Vec};
fn items_to_events<'x, I: IntoIterator<Item = Item<'x>>>( fn items_to_events<'x, I: IntoIterator<Item = Item<'x>>>(
items: I, items: I,
) -> Result<Vec<Event>, crate::error::Error> { ) -> Result<Vec<Event>, crate::error::Error> {

View file

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