Skip to content

Commit

Permalink
Split NamespaceError from the Error type
Browse files Browse the repository at this point in the history
  • Loading branch information
RedPhoenixQ authored and Mingun committed Oct 12, 2024
1 parent 13d14ce commit 6dbd39a
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 48 deletions.
2 changes: 2 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@
- [#227]: Split `SeError` from `DeError` in the `serialize` feature.
Serialize functions and methods now return `SeError`.
- [#810]: Return `std::io::Error` from `Writer` methods.
- [#811]: Split `NamespaceError` from `Error`.

[#227]: https://github.com/tafia/quick-xml/issues/227
[#810]: https://github.com/tafia/quick-xml/pull/810
[#811]: https://github.com/tafia/quick-xml/pull/811


## 0.36.2 -- 2024-09-20
Expand Down
45 changes: 13 additions & 32 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
use crate::encoding::Decoder;
use crate::escape::EscapeError;
use crate::events::attributes::AttrError;
use crate::name::QName;
use crate::utils::write_byte_string;
use crate::name::{NamespaceError, QName};
use std::fmt;
use std::io::Error as IoError;
use std::str::Utf8Error;
Expand Down Expand Up @@ -175,24 +174,8 @@ pub enum Error {
InvalidAttr(AttrError),
/// Escape error
EscapeError(EscapeError),
/// Specified namespace prefix is unknown, cannot resolve namespace for it
UnknownPrefix(Vec<u8>),
/// Error for when a reserved namespace is set incorrectly.
///
/// This error returned in following cases:
/// - the XML document attempts to bind `xml` prefix to something other than
/// `http://www.w3.org/XML/1998/namespace`
/// - the XML document attempts to bind `xmlns` prefix
/// - the XML document attempts to bind some prefix (except `xml`) to
/// `http://www.w3.org/XML/1998/namespace`
/// - the XML document attempts to bind some prefix to
/// `http://www.w3.org/2000/xmlns/`
InvalidPrefixBind {
/// The prefix that is tried to be bound
prefix: Vec<u8>,
/// Namespace to which prefix tried to be bound
namespace: Vec<u8>,
},
/// Parsed XML has some namespace-related problems
Namespace(NamespaceError),
}

impl Error {
Expand Down Expand Up @@ -259,6 +242,13 @@ impl From<AttrError> for Error {
}
}

impl From<NamespaceError> for Error {
#[inline]
fn from(error: NamespaceError) -> Self {
Self::Namespace(error)
}
}

/// A specialized `Result` type where the error is hard-wired to [`Error`].
pub type Result<T> = std::result::Result<T, Error>;

Expand All @@ -272,18 +262,7 @@ impl fmt::Display for Error {
Self::NonDecodable(Some(e)) => write!(f, "Malformed UTF-8 input: {}", e),
Self::InvalidAttr(e) => write!(f, "error while parsing attribute: {}", e),
Self::EscapeError(e) => e.fmt(f),
Self::UnknownPrefix(prefix) => {
f.write_str("Unknown namespace prefix '")?;
write_byte_string(f, prefix)?;
f.write_str("'")
}
Self::InvalidPrefixBind { prefix, namespace } => {
f.write_str("The namespace prefix '")?;
write_byte_string(f, prefix)?;
f.write_str("' cannot be bound to '")?;
write_byte_string(f, namespace)?;
f.write_str("'")
}
Self::Namespace(e) => e.fmt(f),
}
}
}
Expand All @@ -297,6 +276,7 @@ impl std::error::Error for Error {
Self::NonDecodable(Some(e)) => Some(e),
Self::InvalidAttr(e) => Some(e),
Self::EscapeError(e) => Some(e),
Self::Namespace(e) => Some(e),
_ => None,
}
}
Expand All @@ -307,6 +287,7 @@ pub mod serialize {
//! A module to handle serde (de)serialization errors
use super::*;
use crate::utils::write_byte_string;
use std::borrow::Cow;
#[cfg(feature = "overlapped-lists")]
use std::num::NonZeroUsize;
Expand Down
77 changes: 61 additions & 16 deletions src/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,58 @@
//!
//! [spec]: https://www.w3.org/TR/xml-names11
use crate::errors::{Error, Result};
use crate::events::attributes::Attribute;
use crate::events::BytesStart;
use crate::utils::write_byte_string;
use memchr::memchr;
use std::fmt::{self, Debug, Formatter};

/// Some namespace was invalid
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum NamespaceError {
/// Specified namespace prefix is unknown, cannot resolve namespace for it
UnknownPrefix(Vec<u8>),
/// Error for when a reserved namespace is set incorrectly.
///
/// This error returned in following cases:
/// - the XML document attempts to bind `xml` prefix to something other than
/// `http://www.w3.org/XML/1998/namespace`
/// - the XML document attempts to bind `xmlns` prefix
/// - the XML document attempts to bind some prefix (except `xml`) to
/// `http://www.w3.org/XML/1998/namespace`
/// - the XML document attempts to bind some prefix to
/// `http://www.w3.org/2000/xmlns/`
InvalidPrefixBind {
/// The prefix that is tried to be bound
prefix: Vec<u8>,
/// Namespace to which prefix tried to be bound
namespace: Vec<u8>,
},
}

impl fmt::Display for NamespaceError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::UnknownPrefix(prefix) => {
f.write_str("unknown namespace prefix '")?;
write_byte_string(f, prefix)?;
f.write_str("'")
}
Self::InvalidPrefixBind { prefix, namespace } => {
f.write_str("the namespace prefix '")?;
write_byte_string(f, prefix)?;
f.write_str("' cannot be bound to '")?;
write_byte_string(f, namespace)?;
f.write_str("'")
}
}
}
}

impl std::error::Error for NamespaceError {}

////////////////////////////////////////////////////////////////////////////////////////////////////

/// A [qualified name] of an element or an attribute, including an optional
/// namespace [prefix](Prefix) and a [local name](LocalName).
///
Expand Down Expand Up @@ -307,17 +352,17 @@ impl<'ns> Debug for ResolveResult<'ns> {
}

impl<'ns> TryFrom<ResolveResult<'ns>> for Option<Namespace<'ns>> {
type Error = Error;
type Error = NamespaceError;

/// Try to convert this result to an optional namespace and returns
/// [`Error::UnknownPrefix`] if this result represents unknown prefix
fn try_from(result: ResolveResult<'ns>) -> Result<Self> {
/// [`NamespaceError::UnknownPrefix`] if this result represents unknown prefix
fn try_from(result: ResolveResult<'ns>) -> Result<Self, NamespaceError> {
use ResolveResult::*;

match result {
Unbound => Ok(None),
Bound(ns) => Ok(Some(ns)),
Unknown(p) => Err(Error::UnknownPrefix(p)),
Unknown(p) => Err(NamespaceError::UnknownPrefix(p)),
}
}
}
Expand Down Expand Up @@ -456,7 +501,7 @@ impl NamespaceResolver {
/// the specified start element.
///
/// [namespace binding]: https://www.w3.org/TR/xml-names11/#dt-NSDecl
pub fn push(&mut self, start: &BytesStart) -> Result<()> {
pub fn push(&mut self, start: &BytesStart) -> Result<(), NamespaceError> {
self.nesting_level += 1;
let level = self.nesting_level;
// adds new namespaces for attributes starting with 'xmlns:' and for the 'xmlns'
Expand All @@ -477,7 +522,7 @@ impl NamespaceResolver {
Some(PrefixDeclaration::Named(b"xml")) => {
if Namespace(&v) != RESERVED_NAMESPACE_XML.1 {
// error, `xml` prefix explicitly set to different value
return Err(Error::InvalidPrefixBind {
return Err(NamespaceError::InvalidPrefixBind {
prefix: b"xml".to_vec(),
namespace: v.to_vec(),
});
Expand All @@ -486,7 +531,7 @@ impl NamespaceResolver {
}
Some(PrefixDeclaration::Named(b"xmlns")) => {
// error, `xmlns` prefix explicitly set
return Err(Error::InvalidPrefixBind {
return Err(NamespaceError::InvalidPrefixBind {
prefix: b"xmlns".to_vec(),
namespace: v.to_vec(),
});
Expand All @@ -497,7 +542,7 @@ impl NamespaceResolver {
if ns == RESERVED_NAMESPACE_XML.1 || ns == RESERVED_NAMESPACE_XMLNS.1 {
// error, non-`xml` prefix set to xml uri
// error, non-`xmlns` prefix set to xmlns uri
return Err(Error::InvalidPrefixBind {
return Err(NamespaceError::InvalidPrefixBind {
prefix: prefix.to_vec(),
namespace: v.to_vec(),
});
Expand Down Expand Up @@ -984,7 +1029,7 @@ mod namespaces {
" xmlns:xml='not_correct_namespace'",
0,
)) {
Err(Error::InvalidPrefixBind { prefix, namespace }) => {
Err(NamespaceError::InvalidPrefixBind { prefix, namespace }) => {
assert_eq!(prefix, b"xml");
assert_eq!(namespace, b"not_correct_namespace");
}
Expand All @@ -1002,7 +1047,7 @@ mod namespaces {
let mut resolver = NamespaceResolver::default();
let s = resolver.buffer.len();
match resolver.push(&BytesStart::from_content(" xmlns:xml=''", 0)) {
Err(Error::InvalidPrefixBind { prefix, namespace }) => {
Err(NamespaceError::InvalidPrefixBind { prefix, namespace }) => {
assert_eq!(prefix, b"xml");
assert_eq!(namespace, b"");
}
Expand All @@ -1023,7 +1068,7 @@ mod namespaces {
" xmlns:not_xml='http://www.w3.org/XML/1998/namespace'",
0,
)) {
Err(Error::InvalidPrefixBind { prefix, namespace }) => {
Err(NamespaceError::InvalidPrefixBind { prefix, namespace }) => {
assert_eq!(prefix, b"not_xml");
assert_eq!(namespace, b"http://www.w3.org/XML/1998/namespace");
}
Expand Down Expand Up @@ -1069,7 +1114,7 @@ mod namespaces {
" xmlns:xmlns='http://www.w3.org/2000/xmlns/'",
0,
)) {
Err(Error::InvalidPrefixBind { prefix, namespace }) => {
Err(NamespaceError::InvalidPrefixBind { prefix, namespace }) => {
assert_eq!(prefix, b"xmlns");
assert_eq!(namespace, b"http://www.w3.org/2000/xmlns/");
}
Expand All @@ -1090,7 +1135,7 @@ mod namespaces {
" xmlns:xmlns='not_correct_namespace'",
0,
)) {
Err(Error::InvalidPrefixBind { prefix, namespace }) => {
Err(NamespaceError::InvalidPrefixBind { prefix, namespace }) => {
assert_eq!(prefix, b"xmlns");
assert_eq!(namespace, b"not_correct_namespace");
}
Expand All @@ -1108,7 +1153,7 @@ mod namespaces {
let mut resolver = NamespaceResolver::default();
let s = resolver.buffer.len();
match resolver.push(&BytesStart::from_content(" xmlns:xmlns=''", 0)) {
Err(Error::InvalidPrefixBind { prefix, namespace }) => {
Err(NamespaceError::InvalidPrefixBind { prefix, namespace }) => {
assert_eq!(prefix, b"xmlns");
assert_eq!(namespace, b"");
}
Expand All @@ -1129,7 +1174,7 @@ mod namespaces {
" xmlns:not_xmlns='http://www.w3.org/2000/xmlns/'",
0,
)) {
Err(Error::InvalidPrefixBind { prefix, namespace }) => {
Err(NamespaceError::InvalidPrefixBind { prefix, namespace }) => {
assert_eq!(prefix, b"not_xmlns");
assert_eq!(namespace, b"http://www.w3.org/2000/xmlns/");
}
Expand Down

0 comments on commit 6dbd39a

Please sign in to comment.