From b8f6a1e8cfae0c0c79c587cb436475b9287300da Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 18 Sep 2023 21:53:36 +0500 Subject: [PATCH 1/2] Restore lost changelog from #635 Sometimes TortoiseGit loses commits during rebase... What a dangerous bug --- Changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changelog.md b/Changelog.md index b5889714..6ff603c1 100644 --- a/Changelog.md +++ b/Changelog.md @@ -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 @@ -29,6 +30,7 @@ MSRV bumped to 1.56! Crate now uses Rust 2021 edition. - [#649]: Make features linkable and reference them in the docs. [#545]: https://github.com/tafia/quick-xml/pull/545 +[#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 From d4f0621cb900034c0f6066bcd6a1969babe69a57 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 18 Sep 2023 22:02:29 +0500 Subject: [PATCH 2/2] Allow to raise application errors in `ElementWriter::write_inner_content` --- Changelog.md | 3 +++ src/writer.rs | 18 ++++++++++-------- src/writer/async_tokio.rs | 20 ++++++++++++-------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/Changelog.md b/Changelog.md index 6ff603c1..4d712574 100644 --- a/Changelog.md +++ b/Changelog.md @@ -28,8 +28,11 @@ 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 diff --git a/src/writer.rs b/src/writer.rs index d874cfe2..9533721d 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -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")] @@ -105,7 +106,7 @@ impl Writer { /// /// # Example /// - /// ```rust + /// ``` /// # use quick_xml::Result; /// # fn main() -> Result<()> { /// use quick_xml::events::{BytesStart, BytesText, Event}; @@ -127,7 +128,8 @@ impl Writer { /// /// // writes appleorange /// 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 @@ -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(self, closure: F) -> Result<&'a mut Writer> + pub fn write_inner_content(self, closure: F) -> StdResult<&'a mut Writer, E> where - F: FnOnce(&mut Writer) -> Result<()>, + F: FnOnce(&mut Writer) -> StdResult<(), E>, + E: From, { self.writer .write_event(Event::Start(self.start_tag.borrow()))?; @@ -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 @@ -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(()) diff --git a/src/writer/async_tokio.rs b/src/writer/async_tokio.rs index b7a8b562..390ad927 100644 --- a/src/writer/async_tokio.rs +++ b/src/writer/async_tokio.rs @@ -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}; @@ -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); @@ -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 @@ -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"); @@ -295,13 +298,14 @@ impl<'a, W: AsyncWrite + Unpin> ElementWriter<'a, W> { /// "# /// ); /// # } - pub async fn write_inner_content_async( + pub async fn write_inner_content_async( mut self, closure: F, - ) -> Result<&'a mut Writer> + ) -> StdResult<&'a mut Writer, E> where F: FnOnce(&'a mut Writer) -> Fut, - Fut: Future>>, + Fut: Future, E>>, + E: From, { self.writer .write_event_async(Event::Start(self.start_tag.borrow()))