Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Clone for error enums #521

Merged
merged 3 commits into from Dec 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@1.46.0
- uses: dtolnay/rust-toolchain@1.52.0
- run: cargo check

test:
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Expand Up @@ -10,7 +10,7 @@ repository = "https://github.com/tafia/quick-xml"
keywords = ["xml", "serde", "parser", "writer", "html"]
categories = ["asynchronous", "encoding", "parsing", "parser-implementations"]
license = "MIT"
rust-version = "1.46"
rust-version = "1.52"
include = ["src/*", "LICENSE-MIT.md", "README.md"]

[dependencies]
Expand Down
6 changes: 6 additions & 0 deletions Changelog.md
Expand Up @@ -12,6 +12,10 @@

### New Features

- [#521]: Implement `Clone` for all error types. This required changing `Error::Io` to contain
`Arc<std::io::Error>` instead of `std::io::Error` since `std::io::Error` does not implement
`Clone`.

### Bug Fixes

- [#490]: Ensure that serialization of map keys always produces valid XML names.
Expand Down Expand Up @@ -51,13 +55,15 @@
that should be represented either by an `enum`, or by sequence of `enum`s
(`Vec`, tuple, etc.), or by string. Use it when you want to map field to any
content of the field, text or markup
- [#521]: MSRV bumped to 1.52.

Refer to [documentation] for details.

[#490]: https://github.com/tafia/quick-xml/pull/490
[#500]: https://github.com/tafia/quick-xml/issues/500
[#514]: https://github.com/tafia/quick-xml/issues/514
[#517]: https://github.com/tafia/quick-xml/issues/517
[#521]: https://github.com/tafia/quick-xml/pull/521
[XML name]: https://www.w3.org/TR/xml11/#NT-Name
[documentation]: https://docs.rs/quick-xml/0.27.0/quick_xml/de/index.html#difference-between-text-and-value-special-names

Expand Down
13 changes: 8 additions & 5 deletions src/errors.rs
Expand Up @@ -7,12 +7,15 @@ use std::fmt;
use std::io::Error as IoError;
use std::str::Utf8Error;
use std::string::FromUtf8Error;
use std::sync::Arc;

/// The error type used by this crate.
#[derive(Debug)]
#[derive(Clone, Debug)]
pub enum Error {
/// IO error
Io(IoError),
/// IO error.
///
/// `Arc<IoError>` instead of `IoError` since `IoError` is not `Clone`.
Io(Arc<IoError>),
/// Input decoding error. If `encoding` feature is disabled, contains `None`,
/// otherwise contains the UTF-8 decoding error
NonDecodable(Option<Utf8Error>),
Expand Down Expand Up @@ -45,7 +48,7 @@ impl From<IoError> for Error {
/// Creates a new `Error::Io` from the given error
#[inline]
fn from(error: IoError) -> Error {
Error::Io(error)
Error::Io(Arc::new(error))
}
}

Expand Down Expand Up @@ -140,7 +143,7 @@ pub mod serialize {
use std::num::{ParseFloatError, ParseIntError};

/// (De)serialization error
#[derive(Debug)]
#[derive(Clone, Debug)]
pub enum DeError {
/// Serde custom error
Custom(String),
Expand Down
2 changes: 1 addition & 1 deletion src/escapei.rs
Expand Up @@ -8,7 +8,7 @@ use std::ops::Range;
use pretty_assertions::assert_eq;

/// Error for XML escape / unescape.
#[derive(Debug)]
#[derive(Clone, Debug)]
pub enum EscapeError {
/// Entity with Null character
EntityWithNull(Range<usize>),
Expand Down
2 changes: 1 addition & 1 deletion src/events/attributes.rs
Expand Up @@ -241,7 +241,7 @@ impl<'a> FusedIterator for Attributes<'a> {}
///
/// Recovery position in examples shows the position from which parsing of the
/// next attribute will be attempted.
#[derive(Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum AttrError {
/// Attribute key was not followed by `=`, position relative to the start of
/// the owning tag is provided.
Expand Down
16 changes: 8 additions & 8 deletions src/reader/buffered_reader.rs
Expand Up @@ -27,7 +27,7 @@ macro_rules! impl_buffered_source {
Ok(())
},
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
Err(e) => Err(Error::Io(e)),
Err(e) => Err(Error::Io(e.into())),
};
}
}
Expand All @@ -43,7 +43,7 @@ macro_rules! impl_buffered_source {
Ok(None)
},
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
Err(e) => Err(Error::Io(e)),
Err(e) => Err(Error::Io(e.into())),
};
}
}
Expand All @@ -69,7 +69,7 @@ macro_rules! impl_buffered_source {
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
Err(e) => {
*position += read;
return Err(Error::Io(e));
return Err(Error::Io(e.into()));
}
};

Expand Down Expand Up @@ -136,7 +136,7 @@ macro_rules! impl_buffered_source {
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
Err(e) => {
*position += read;
return Err(Error::Io(e));
return Err(Error::Io(e.into()));
}
}
}
Expand Down Expand Up @@ -181,7 +181,7 @@ macro_rules! impl_buffered_source {
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
Err(e) => {
*position += read;
return Err(Error::Io(e));
return Err(Error::Io(e.into()));
}
};
}
Expand All @@ -207,7 +207,7 @@ macro_rules! impl_buffered_source {
}
}
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
Err(e) => Err(Error::Io(e)),
Err(e) => Err(Error::Io(e.into())),
};
}
}
Expand All @@ -232,7 +232,7 @@ macro_rules! impl_buffered_source {
Ok(n) if n.is_empty() => Ok(None),
Ok(n) => Ok(Some(n[0])),
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
Err(e) => Err(Error::Io(e)),
Err(e) => Err(Error::Io(e.into())),
};
}
}
Expand Down Expand Up @@ -398,7 +398,7 @@ impl<R: BufRead> Reader<R> {
impl Reader<BufReader<File>> {
/// Creates an XML reader from a file path.
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
let file = File::open(path).map_err(Error::Io)?;
let file = File::open(path)?;
let reader = BufReader::new(file);
Ok(Self::from_reader(reader))
}
Expand Down
12 changes: 6 additions & 6 deletions src/writer.rs
Expand Up @@ -3,7 +3,7 @@
use std::io::Write;

use crate::encoding::UTF8_BOM;
use crate::errors::{Error, Result};
use crate::errors::Result;
use crate::events::{attributes::Attribute, BytesCData, BytesStart, BytesText, Event};

/// XML writer. Writes XML [`Event`]s to a [`std::io::Write`] implementor.
Expand Down Expand Up @@ -163,15 +163,15 @@ impl<W: Write> Writer<W> {
/// Writes bytes
#[inline]
pub(crate) fn write(&mut self, value: &[u8]) -> Result<()> {
self.writer.write_all(value).map_err(Error::Io)
self.writer.write_all(value).map_err(Into::into)
}

#[inline]
fn write_wrapped(&mut self, before: &[u8], value: &[u8], after: &[u8]) -> Result<()> {
if let Some(ref i) = self.indent {
if i.should_line_break {
self.writer.write_all(b"\n").map_err(Error::Io)?;
self.writer.write_all(i.current()).map_err(Error::Io)?;
self.writer.write_all(b"\n")?;
self.writer.write_all(i.current())?;
}
}
self.write(before)?;
Expand All @@ -193,8 +193,8 @@ impl<W: Write> Writer<W> {
/// [`new_with_indent`]: Self::new_with_indent
pub fn write_indent(&mut self) -> Result<()> {
if let Some(ref i) = self.indent {
self.writer.write_all(b"\n").map_err(Error::Io)?;
self.writer.write_all(i.current()).map_err(Error::Io)?;
self.writer.write_all(b"\n")?;
self.writer.write_all(i.current())?;
}
Ok(())
}
Expand Down