Skip to content

Commit

Permalink
Merge pull request #652 from Mingun/custom-errors-in-writing
Browse files Browse the repository at this point in the history
Allow to raise application errors in `ElementWriter::write_inner_content`
  • Loading branch information
Mingun authored Sep 25, 2023
2 parents ad7553b + d4f0621 commit e1b2c46
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 16 deletions.
5 changes: 5 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ MSRV bumped to 1.56! Crate now uses Rust 2021 edition.

- [#545]: Resolve well-known namespaces (`xml` and `xmlns`) to their appropriate URIs.
Also, enforce namespace constraints related to these well-known namespaces.
- [#635]: Add support for async `ElementWriter` operations.

### Bug Fixes

Expand All @@ -27,8 +28,12 @@ MSRV bumped to 1.56! Crate now uses Rust 2021 edition.
- [#651]: Relax requirement for version of `arbitrary` dependency -- we're actually
compatible with version 1.0.0 and up.
- [#649]: Make features linkable and reference them in the docs.
- [#619]: Allow to raise application errors in `ElementWriter::write_inner_content`
(and newly added `ElementWriter::write_inner_content_async` of course).

[#545]: https://github.com/tafia/quick-xml/pull/545
[#619]: https://github.com/tafia/quick-xml/issues/619
[#635]: https://github.com/tafia/quick-xml/pull/635
[#643]: https://github.com/tafia/quick-xml/pull/643
[#649]: https://github.com/tafia/quick-xml/pull/646
[#651]: https://github.com/tafia/quick-xml/pull/651
Expand Down
18 changes: 10 additions & 8 deletions src/writer.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
//! Contains high-level interface for an events-based XML emitter.

use std::io::Write;
use std::result::Result as StdResult;

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

#[cfg(feature = "async-tokio")]
Expand Down Expand Up @@ -105,7 +106,7 @@ impl<W> Writer<W> {
///
/// # Example
///
/// ```rust
/// ```
/// # use quick_xml::Result;
/// # fn main() -> Result<()> {
/// use quick_xml::events::{BytesStart, BytesText, Event};
Expand All @@ -127,7 +128,8 @@ impl<W> Writer<W> {
///
/// // writes <tag><fruit quantity="0">apple</fruit><fruit quantity="1">orange</fruit></tag>
/// writer.create_element("tag")
/// .write_inner_content(|writer| {
/// // We need to provide error type, because it is not named somewhere explicitly
/// .write_inner_content::<_, Error>(|writer| {
/// let fruits = ["apple", "orange"];
/// for (quant, item) in fruits.iter().enumerate() {
/// writer
Expand Down Expand Up @@ -401,9 +403,10 @@ impl<'a, W: Write> ElementWriter<'a, W> {
}

/// Create a new scope for writing XML inside the current element.
pub fn write_inner_content<F>(self, closure: F) -> Result<&'a mut Writer<W>>
pub fn write_inner_content<F, E>(self, closure: F) -> StdResult<&'a mut Writer<W>, E>
where
F: FnOnce(&mut Writer<W>) -> Result<()>,
F: FnOnce(&mut Writer<W>) -> StdResult<(), E>,
E: From<Error>,
{
self.writer
.write_event(Event::Start(self.start_tag.borrow()))?;
Expand Down Expand Up @@ -748,7 +751,7 @@ mod indentation {
.create_element("outer")
.with_attribute(("attr1", "value1"))
.with_attribute(("attr2", "value2"))
.write_inner_content(|writer| {
.write_inner_content::<_, Error>(|writer| {
let fruits = ["apple", "orange", "banana"];
for (quant, item) in fruits.iter().enumerate() {
writer
Expand All @@ -759,8 +762,7 @@ mod indentation {
writer
.create_element("inner")
.write_inner_content(|writer| {
writer.create_element("empty").write_empty()?;
Ok(())
writer.create_element("empty").write_empty().map(|_| ())
})?;

Ok(())
Expand Down
20 changes: 12 additions & 8 deletions src/writer/async_tokio.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use std::future::Future;
use std::result::Result as StdResult;

use tokio::io::{AsyncWrite, AsyncWriteExt};

use crate::errors::Result;
use crate::errors::{Error, Result};
use crate::events::{BytesCData, BytesText, Event};
use crate::{ElementWriter, Writer};

Expand Down Expand Up @@ -252,6 +253,8 @@ impl<'a, W: AsyncWrite + Unpin> ElementWriter<'a, W> {
/// # use quick_xml::writer::Writer;
/// # use quick_xml::events::BytesText;
/// # use tokio::io::AsyncWriteExt;
/// use quick_xml::Error;
///
/// # #[tokio::main(flavor = "current_thread")] async fn main() {
/// let mut buffer = Vec::new();
/// let mut tokio_buffer = tokio::io::BufWriter::new(&mut buffer);
Expand All @@ -260,7 +263,8 @@ impl<'a, W: AsyncWrite + Unpin> ElementWriter<'a, W> {
/// writer
/// .create_element("outer")
/// .with_attributes([("attr1", "value1"), ("attr2", "value2")])
/// .write_inner_content_async(|writer| async move {
/// // We need to provide error type, because it is not named somewhere explicitly
/// .write_inner_content_async::<_, _, Error>(|writer| async move {
/// let fruits = ["apple", "orange", "banana"];
/// for (quant, item) in fruits.iter().enumerate() {
/// writer
Expand All @@ -272,12 +276,11 @@ impl<'a, W: AsyncWrite + Unpin> ElementWriter<'a, W> {
/// writer
/// .create_element("inner")
/// .write_inner_content_async(|writer| async move {
/// writer.create_element("empty").write_empty_async().await?;
/// Ok(writer)
/// writer.create_element("empty").write_empty_async().await
/// })
/// .await?;
///
/// Ok(writer)
/// Ok(writer)
/// })
/// .await
/// .expect("cannot write content");
Expand All @@ -295,13 +298,14 @@ impl<'a, W: AsyncWrite + Unpin> ElementWriter<'a, W> {
/// </outer>"#
/// );
/// # }
pub async fn write_inner_content_async<F, Fut>(
pub async fn write_inner_content_async<F, Fut, E>(
mut self,
closure: F,
) -> Result<&'a mut Writer<W>>
) -> StdResult<&'a mut Writer<W>, E>
where
F: FnOnce(&'a mut Writer<W>) -> Fut,
Fut: Future<Output = Result<&'a mut Writer<W>>>,
Fut: Future<Output = StdResult<&'a mut Writer<W>, E>>,
E: From<Error>,
{
self.writer
.write_event_async(Event::Start(self.start_tag.borrow()))
Expand Down

0 comments on commit e1b2c46

Please sign in to comment.