Skip to content

Commit

Permalink
feat: return bytes written from write_event
Browse files Browse the repository at this point in the history
  • Loading branch information
phdavis1027 committed Feb 28, 2024
1 parent adf873e commit b7f8d00
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 7 deletions.
17 changes: 10 additions & 7 deletions src/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,12 @@ impl<W: Write> Writer<W> {
/// # }
/// ```
/// [Byte-Order-Mark]: https://unicode.org/faq/utf_bom.html#BOM
pub fn write_bom(&mut self) -> Result<()> {
pub fn write_bom(&mut self) -> Result<usize> {
self.write(UTF8_BOM)
}

/// Writes the given event to the underlying writer.
pub fn write_event<'a, E: AsRef<Event<'a>>>(&mut self, event: E) -> Result<()> {
pub fn write_event<'a, E: AsRef<Event<'a>>>(&mut self, event: E) -> Result<usize> {
let mut next_should_line_break = true;
let result = match *event.as_ref() {
Event::Start(ref e) => {
Expand Down Expand Up @@ -221,7 +221,7 @@ impl<W: Write> Writer<W> {
Event::Decl(ref e) => self.write_wrapped(b"<?", e, b"?>"),
Event::PI(ref e) => self.write_wrapped(b"<?", e, b"?>"),
Event::DocType(ref e) => self.write_wrapped(b"<!DOCTYPE ", e, b">"),
Event::Eof => Ok(()),
Event::Eof => Ok(0),
};
if let Some(i) = self.indent.as_mut() {
i.should_line_break = next_should_line_break;
Expand All @@ -231,22 +231,25 @@ impl<W: Write> Writer<W> {

/// Writes bytes
#[inline]
pub(crate) fn write(&mut self, value: &[u8]) -> Result<()> {
self.writer.write_all(value).map_err(Into::into)
pub(crate) fn write(&mut self, value: &[u8]) -> Result<usize> {
self.writer.write_all(value)?;
Ok(value.len())
}

#[inline]
fn write_wrapped(&mut self, before: &[u8], value: &[u8], after: &[u8]) -> Result<()> {
fn write_wrapped(&mut self, before: &[u8], value: &[u8], after: &[u8]) -> Result<usize> {
let mut n = 0;
if let Some(ref i) = self.indent {
if i.should_line_break {
self.writer.write_all(b"\n")?;
self.writer.write_all(i.current())?;
n += i.current().len();
}
}
self.write(before)?;
self.write(value)?;
self.write(after)?;
Ok(())
Ok(before.len() + value.len() + after.len() + n)
}

/// Manually write a newline and indentation at the proper level.
Expand Down
52 changes: 52 additions & 0 deletions tests/unit_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -588,3 +588,55 @@ fn test_closing_bracket_in_single_quote_mixed() {
}
next_eq!(r, End, b"a");
}

#[test]
fn write_event_reports_bytes_written() {
// Example from docs: https://docs.rs/quick-xml/latest/quick_xml/writer/struct.Writer.html
let xml = r#"<this_tag k1="v1" k2="v2"><child>text</child></this_tag>"#;
let mut reader = Reader::from_str(xml);
reader.config_mut().trim_text(true);
let mut writer = Writer::new(Cursor::new(Vec::new()));
let mut n = 0;
loop {
match reader.read_event() {
Ok(Start(e)) if e.name().as_ref() == b"this_tag" => {

// crates a new element ... alternatively we could reuse `e` by calling
// `e.into_owned()`
let mut elem = BytesStart::new("my_elem");

// collect existing attributes
elem.extend_attributes(e.attributes().map(|attr| attr.unwrap()));

// copy existing attributes, adds a new my-key="some value" attribute
elem.push_attribute(("my-key", "some value"));

// writes the event to the writer
n += match writer.write_event(Start(elem)) {
Ok(b) => b,
Err(_) => panic!("Unexpected error in sample code")
}
},
Ok(End(e)) if e.name().as_ref() == b"this_tag" => {
n += match writer.write_event(End(BytesEnd::new("my_elem"))) {
Ok(b) => b,
Err(_) => panic!("Unexpected error in sample code")
}
},
Ok(Eof) => break,
// we can either move or borrow the event to write, depending on your use-case
Ok(e) => {
n += match writer.write_event(e) {
Ok(b) => b,
Err(_) => panic!("Unexpected error in sample code")
}
},
Err(e) => panic!("Error at position {}: {:?}", reader.buffer_position(), e),
}
}

let result = writer.into_inner().into_inner();
let expected = r#"<my_elem k1="v1" k2="v2" my-key="some value"><child>text</child></my_elem>"#;
assert_eq!(result, expected.as_bytes());
assert_eq!(n, expected.len());
}

0 comments on commit b7f8d00

Please sign in to comment.