diff --git a/Changelog.md b/Changelog.md
index 4b607d0f..c98325ca 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -15,6 +15,8 @@
### New Features
+- [#836]: Add `se::to_utf8_io_writer()` helper compatible with `std::io::Write` and restricted to UTF-8 encoding.
+
### Bug Fixes
### Misc Changes
diff --git a/src/se/mod.rs b/src/se/mod.rs
index c8a71d46..2ec9dab7 100644
--- a/src/se/mod.rs
+++ b/src/se/mod.rs
@@ -82,7 +82,7 @@ mod text;
use self::content::ContentSerializer;
use self::element::{ElementSerializer, Map, Struct, Tuple};
use crate::de::TEXT_KEY;
-use crate::writer::Indentation;
+use crate::writer::{Indentation, ToFmtWrite};
use serde::ser::{self, Serialize};
use serde::serde_if_integer128;
use std::fmt::Write;
@@ -136,6 +136,54 @@ where
value.serialize(Serializer::new(&mut writer))
}
+/// Serialize struct into a `io::Write`r restricted to utf-8 encoding.
+///
+/// Returns the classification of the last written type.
+///
+/// # Examples
+///
+/// ```
+/// # use quick_xml::se::to_utf8_io_writer;
+/// # use serde::Serialize;
+/// # use pretty_assertions::assert_eq;
+/// # use std::io::BufWriter;
+/// # use std::str;
+/// #[derive(Serialize)]
+/// struct Root<'a> {
+/// #[serde(rename = "@attribute")]
+/// attribute: &'a str,
+/// element: &'a str,
+/// #[serde(rename = "$text")]
+/// text: &'a str,
+/// }
+///
+/// let data = Root {
+/// attribute: "attribute content",
+/// element: "element content",
+/// text: "text content",
+/// };
+///
+/// let mut buffer = Vec::new();
+/// to_utf8_io_writer(&mut BufWriter::new(&mut buffer), &data).unwrap();
+///
+/// assert_eq!(
+/// str::from_utf8(&buffer).unwrap(),
+/// // The root tag name is automatically deduced from the struct name
+/// // This will not work for other types or struct with #[serde(flatten)] fields
+/// "\
+/// element content\
+/// text content\
+/// "
+/// );
+/// ```
+pub fn to_utf8_io_writer(writer: W, value: &T) -> Result
+where
+ W: std::io::Write,
+ T: ?Sized + Serialize,
+{
+ value.serialize(Serializer::new(&mut ToFmtWrite(writer)))
+}
+
/// Serialize struct into a `String`.
///
/// # Examples
diff --git a/src/writer.rs b/src/writer.rs
index 19d120bf..af2c7496 100644
--- a/src/writer.rs
+++ b/src/writer.rs
@@ -577,7 +577,7 @@ impl<'a, W: Write> ElementWriter<'a, W> {
}
}
#[cfg(feature = "serialize")]
-struct ToFmtWrite(pub T);
+pub(crate) struct ToFmtWrite(pub T);
#[cfg(feature = "serialize")]
impl std::fmt::Write for ToFmtWrite