Skip to content

Commit

Permalink
Merge pull request #440 from dralley/split-readers
Browse files Browse the repository at this point in the history
Remove the ability to use un-buffered functions with Reader<&[u8]>
  • Loading branch information
dralley authored Jul 25, 2022
2 parents 6d883b5 + 682a6bb commit 8ab2dbe
Show file tree
Hide file tree
Showing 10 changed files with 136 additions and 176 deletions.
82 changes: 28 additions & 54 deletions benches/microbenches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use quick_xml::events::Event;
use quick_xml::name::QName;
use quick_xml::{NsReader, Reader};

static SAMPLE: &[u8] = include_bytes!("../tests/documents/sample_rss.xml");
static PLAYERS: &[u8] = include_bytes!("../tests/documents/players.xml");
static SAMPLE: &str = include_str!("../tests/documents/sample_rss.xml");
static PLAYERS: &str = include_str!("../tests/documents/players.xml");

static LOREM_IPSUM_TEXT: &str =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
Expand All @@ -29,17 +29,15 @@ fn read_event(c: &mut Criterion) {
let mut group = c.benchmark_group("read_event");
group.bench_function("trim_text = false", |b| {
b.iter(|| {
let mut r = Reader::from_reader(SAMPLE);
let mut r = Reader::from_str(SAMPLE);
r.check_end_names(false).check_comments(false);
let mut count = criterion::black_box(0);
let mut buf = Vec::new();
loop {
match r.read_event_into(&mut buf) {
match r.read_event() {
Ok(Event::Start(_)) | Ok(Event::Empty(_)) => count += 1,
Ok(Event::Eof) => break,
_ => (),
}
buf.clear();
}
assert_eq!(
count, 1550,
Expand All @@ -50,19 +48,17 @@ fn read_event(c: &mut Criterion) {

group.bench_function("trim_text = true", |b| {
b.iter(|| {
let mut r = Reader::from_reader(SAMPLE);
let mut r = Reader::from_str(SAMPLE);
r.check_end_names(false)
.check_comments(false)
.trim_text(true);
let mut count = criterion::black_box(0);
let mut buf = Vec::new();
loop {
match r.read_event_into(&mut buf) {
match r.read_event() {
Ok(Event::Start(_)) | Ok(Event::Empty(_)) => count += 1,
Ok(Event::Eof) => break,
_ => (),
}
buf.clear();
}
assert_eq!(
count, 1550,
Expand All @@ -79,17 +75,15 @@ fn read_resolved_event_into(c: &mut Criterion) {
let mut group = c.benchmark_group("NsReader::read_resolved_event_into");
group.bench_function("trim_text = false", |b| {
b.iter(|| {
let mut r = NsReader::from_bytes(SAMPLE);
let mut r = NsReader::from_str(SAMPLE);
r.check_end_names(false).check_comments(false);
let mut count = criterion::black_box(0);
let mut buf = Vec::new();
loop {
match r.read_resolved_event_into(&mut buf) {
match r.read_resolved_event() {
Ok((_, Event::Start(_))) | Ok((_, Event::Empty(_))) => count += 1,
Ok((_, Event::Eof)) => break,
_ => (),
}
buf.clear();
}
assert_eq!(
count, 1550,
Expand All @@ -100,19 +94,17 @@ fn read_resolved_event_into(c: &mut Criterion) {

group.bench_function("trim_text = true", |b| {
b.iter(|| {
let mut r = NsReader::from_bytes(SAMPLE);
let mut r = NsReader::from_str(SAMPLE);
r.check_end_names(false)
.check_comments(false)
.trim_text(true);
let mut count = criterion::black_box(0);
let mut buf = Vec::new();
loop {
match r.read_resolved_event_into(&mut buf) {
match r.read_resolved_event() {
Ok((_, Event::Start(_))) | Ok((_, Event::Empty(_))) => count += 1,
Ok((_, Event::Eof)) => break,
_ => (),
}
buf.clear();
}
assert_eq!(
count, 1550,
Expand All @@ -127,79 +119,67 @@ fn read_resolved_event_into(c: &mut Criterion) {
fn one_event(c: &mut Criterion) {
let mut group = c.benchmark_group("One event");
group.bench_function("StartText", |b| {
let src = "Hello world!".repeat(512 / 12).into_bytes();
let mut buf = Vec::with_capacity(1024);
let src = "Hello world!".repeat(512 / 12);
b.iter(|| {
let mut r = Reader::from_reader(src.as_ref());
let mut r = Reader::from_str(&src);
let mut nbtxt = criterion::black_box(0);
r.check_end_names(false).check_comments(false);
match r.read_event_into(&mut buf) {
match r.read_event() {
Ok(Event::StartText(e)) => nbtxt += e.len(),
something_else => panic!("Did not expect {:?}", something_else),
};

buf.clear();

assert_eq!(nbtxt, 504);
})
});

group.bench_function("Start", |b| {
let src = format!(r#"<hello target="{}">"#, "world".repeat(512 / 5)).into_bytes();
let mut buf = Vec::with_capacity(1024);
let src = format!(r#"<hello target="{}">"#, "world".repeat(512 / 5));
b.iter(|| {
let mut r = Reader::from_reader(src.as_ref());
let mut r = Reader::from_str(&src);
let mut nbtxt = criterion::black_box(0);
r.check_end_names(false)
.check_comments(false)
.trim_text(true);
match r.read_event_into(&mut buf) {
match r.read_event() {
Ok(Event::Start(ref e)) => nbtxt += e.len(),
something_else => panic!("Did not expect {:?}", something_else),
};

buf.clear();

assert_eq!(nbtxt, 525);
})
});

group.bench_function("Comment", |b| {
let src = format!(r#"<!-- hello "{}" -->"#, "world".repeat(512 / 5)).into_bytes();
let mut buf = Vec::with_capacity(1024);
let src = format!(r#"<!-- hello "{}" -->"#, "world".repeat(512 / 5));
b.iter(|| {
let mut r = Reader::from_reader(src.as_ref());
let mut r = Reader::from_str(&src);
let mut nbtxt = criterion::black_box(0);
r.check_end_names(false)
.check_comments(false)
.trim_text(true);
match r.read_event_into(&mut buf) {
match r.read_event() {
Ok(Event::Comment(e)) => nbtxt += e.unescape().unwrap().len(),
something_else => panic!("Did not expect {:?}", something_else),
};

buf.clear();

assert_eq!(nbtxt, 520);
})
});

group.bench_function("CData", |b| {
let src = format!(r#"<![CDATA[hello "{}"]]>"#, "world".repeat(512 / 5)).into_bytes();
let mut buf = Vec::with_capacity(1024);
let src = format!(r#"<![CDATA[hello "{}"]]>"#, "world".repeat(512 / 5));
b.iter(|| {
let mut r = Reader::from_reader(src.as_ref());
let mut r = Reader::from_str(&src);
let mut nbtxt = criterion::black_box(0);
r.check_end_names(false)
.check_comments(false)
.trim_text(true);
match r.read_event_into(&mut buf) {
match r.read_event() {
Ok(Event::CData(ref e)) => nbtxt += e.len(),
something_else => panic!("Did not expect {:?}", something_else),
};

buf.clear();

assert_eq!(nbtxt, 518);
})
});
Expand All @@ -211,12 +191,11 @@ fn attributes(c: &mut Criterion) {
let mut group = c.benchmark_group("attributes");
group.bench_function("with_checks = true", |b| {
b.iter(|| {
let mut r = Reader::from_reader(PLAYERS);
let mut r = Reader::from_str(PLAYERS);
r.check_end_names(false).check_comments(false);
let mut count = criterion::black_box(0);
let mut buf = Vec::new();
loop {
match r.read_event_into(&mut buf) {
match r.read_event() {
Ok(Event::Empty(e)) => {
for attr in e.attributes() {
let _attr = attr.unwrap();
Expand All @@ -226,20 +205,18 @@ fn attributes(c: &mut Criterion) {
Ok(Event::Eof) => break,
_ => (),
}
buf.clear();
}
assert_eq!(count, 1041);
})
});

group.bench_function("with_checks = false", |b| {
b.iter(|| {
let mut r = Reader::from_reader(PLAYERS);
let mut r = Reader::from_str(PLAYERS);
r.check_end_names(false).check_comments(false);
let mut count = criterion::black_box(0);
let mut buf = Vec::new();
loop {
match r.read_event_into(&mut buf) {
match r.read_event() {
Ok(Event::Empty(e)) => {
for attr in e.attributes().with_checks(false) {
let _attr = attr.unwrap();
Expand All @@ -249,20 +226,18 @@ fn attributes(c: &mut Criterion) {
Ok(Event::Eof) => break,
_ => (),
}
buf.clear();
}
assert_eq!(count, 1041);
})
});

group.bench_function("try_get_attribute", |b| {
b.iter(|| {
let mut r = Reader::from_reader(PLAYERS);
let mut r = Reader::from_str(PLAYERS);
r.check_end_names(false).check_comments(false);
let mut count = criterion::black_box(0);
let mut buf = Vec::new();
loop {
match r.read_event_into(&mut buf) {
match r.read_event() {
Ok(Event::Empty(e)) if e.name() == QName(b"player") => {
for name in ["num", "status", "avg"] {
if let Some(_attr) = e.try_get_attribute(name).unwrap() {
Expand All @@ -277,7 +252,6 @@ fn attributes(c: &mut Criterion) {
Ok(Event::Eof) => break,
_ => (),
}
buf.clear();
}
assert_eq!(count, 150);
})
Expand Down
49 changes: 14 additions & 35 deletions src/de/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,15 +296,6 @@ where
T::deserialize(&mut de)
}

/// Deserialize an instance of type `T` from bytes of XML text.
pub fn from_slice<'de, T>(s: &'de [u8]) -> Result<T, DeError>
where
T: Deserialize<'de>,
{
let mut de = Deserializer::from_slice(s);
T::deserialize(&mut de)
}

/// Deserialize from a reader. This method will do internal copies of data
/// readed from `reader`. If you want have a `&[u8]` or `&str` input and want
/// to borrow as much as possible, use [`from_slice`] or [`from_str`]
Expand Down Expand Up @@ -684,17 +675,7 @@ where
impl<'de> Deserializer<'de, SliceReader<'de>> {
/// Create new deserializer that will borrow data from the specified string
pub fn from_str(s: &'de str) -> Self {
Self::from_borrowing_reader(Reader::from_str(s))
}

/// Create new deserializer that will borrow data from the specified byte array
pub fn from_slice(bytes: &'de [u8]) -> Self {
Self::from_borrowing_reader(Reader::from_bytes(bytes))
}

/// Create new deserializer that will borrow data from the specified borrowing reader
#[inline]
fn from_borrowing_reader(mut reader: Reader<&'de [u8]>) -> Self {
let mut reader = Reader::from_str(s);
reader
.expand_empty_elements(true)
.check_end_names(true)
Expand Down Expand Up @@ -1024,8 +1005,8 @@ mod tests {
/// Checks that `peek()` and `read()` behaves correctly after `skip()`
#[test]
fn read_and_peek() {
let mut de = Deserializer::from_slice(
br#"
let mut de = Deserializer::from_str(
r#"
<root>
<inner>
text
Expand Down Expand Up @@ -1144,8 +1125,8 @@ mod tests {
/// Checks that `read_to_end()` behaves correctly after `skip()`
#[test]
fn read_to_end() {
let mut de = Deserializer::from_slice(
br#"
let mut de = Deserializer::from_str(
r#"
<root>
<skip>
text
Expand Down Expand Up @@ -1239,8 +1220,8 @@ mod tests {
item: Vec<()>,
}

let mut de = Deserializer::from_slice(
br#"
let mut de = Deserializer::from_str(
r#"
<any-name>
<item/>
<another-item>
Expand All @@ -1265,8 +1246,8 @@ mod tests {
fn read_to_end() {
use crate::de::DeEvent::*;

let mut de = Deserializer::from_slice(
br#"
let mut de = Deserializer::from_str(
r#"
<root>
<tag a="1"><tag>text</tag>content</tag>
<tag a="2"><![CDATA[cdata content]]></tag>
Expand Down Expand Up @@ -1303,15 +1284,14 @@ mod tests {
<item name="hello" source="world.rs">Some text</item>
<item2/>
<item3 value="world" />
"##
.as_bytes();
"##;

let mut reader1 = IoReader {
reader: Reader::from_reader(s),
reader: Reader::from_reader(s.as_bytes()),
buf: Vec::new(),
};
let mut reader2 = SliceReader {
reader: Reader::from_bytes(s),
reader: Reader::from_str(s),
};

loop {
Expand All @@ -1333,11 +1313,10 @@ mod tests {
<item2></item2>
<item3/>
<item4 value="world" />
"##
.as_bytes();
"##;

let mut reader = SliceReader {
reader: Reader::from_bytes(s),
reader: Reader::from_str(s),
};

reader
Expand Down
7 changes: 4 additions & 3 deletions src/events/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -959,11 +959,12 @@ pub enum Event<'a> {
/// use quick_xml::events::Event;
///
/// // XML in UTF-8 with BOM
/// let xml = b"\xEF\xBB\xBF<?xml version='1.0'?>";
/// let mut reader = Reader::from_bytes(xml);
/// let xml = b"\xEF\xBB\xBF<?xml version='1.0'?>".as_ref();
/// let mut reader = Reader::from_reader(xml);
/// let mut buf = Vec::new();
/// let mut events_processed = 0;
/// loop {
/// match reader.read_event() {
/// match reader.read_event_into(&mut buf) {
/// Ok(Event::StartText(e)) => {
/// assert_eq!(events_processed, 0);
/// // Content contains BOM
Expand Down
Loading

0 comments on commit 8ab2dbe

Please sign in to comment.