Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split out namespace aware reader to a struct that manage the internal namespaces buffer #437

Merged
merged 11 commits into from Jul 24, 2022
Merged
12 changes: 12 additions & 0 deletions Changelog.md
Expand Up @@ -27,6 +27,17 @@
the XML declared encoding and always use UTF-8
- [#416]: Add `borrow()` methods in all event structs which allows to get
a borrowed version of any event
- [#437]: Split out namespace reading functionality to a dedicated `NsReader`, namely:
|Old function in `Reader`|New function in `NsReader`
|------------------------|--------------------------
| |`read_event` -- borrow from input
| |`read_resolved_event` -- borrow from input
| |`read_event_into`
|`read_namespaced_event` |`read_resolved_event_into`
| |`resolve`
|`event_namespace` |`resolve_element`
|`attribute_namespace` |`resolve_attribute`


### Bug Fixes

Expand Down Expand Up @@ -167,6 +178,7 @@
[#418]: https://github.com/tafia/quick-xml/pull/418
[#421]: https://github.com/tafia/quick-xml/pull/421
[#423]: https://github.com/tafia/quick-xml/pull/423
[#437]: https://github.com/tafia/quick-xml/pull/437

## 0.23.0 -- 2022-05-08

Expand Down
20 changes: 9 additions & 11 deletions benches/microbenches.rs
Expand Up @@ -3,7 +3,7 @@ use pretty_assertions::assert_eq;
use quick_xml::escape::{escape, unescape};
use quick_xml::events::Event;
use quick_xml::name::QName;
use quick_xml::Reader;
use quick_xml::{NsReader, Reader};

static SAMPLE: &[u8] = include_bytes!("../tests/documents/sample_rss.xml");
static PLAYERS: &[u8] = include_bytes!("../tests/documents/players.xml");
Expand Down Expand Up @@ -73,19 +73,18 @@ fn read_event(c: &mut Criterion) {
group.finish();
}

/// Benchmarks the `Reader::read_namespaced_event` function with all XML well-formless
/// Benchmarks the `NsReader::read_resolved_event_into` function with all XML well-formless
/// checks disabled (with and without trimming content of #text nodes)
fn read_namespaced_event(c: &mut Criterion) {
let mut group = c.benchmark_group("read_namespaced_event");
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 = Reader::from_reader(SAMPLE);
let mut r = NsReader::from_bytes(SAMPLE);
r.check_end_names(false).check_comments(false);
let mut count = criterion::black_box(0);
let mut buf = Vec::new();
let mut ns_buf = Vec::new();
loop {
match r.read_namespaced_event(&mut buf, &mut ns_buf) {
match r.read_resolved_event_into(&mut buf) {
Ok((_, Event::Start(_))) | Ok((_, Event::Empty(_))) => count += 1,
Ok((_, Event::Eof)) => break,
_ => (),
Expand All @@ -101,15 +100,14 @@ fn read_namespaced_event(c: &mut Criterion) {

group.bench_function("trim_text = true", |b| {
b.iter(|| {
let mut r = Reader::from_reader(SAMPLE);
let mut r = NsReader::from_bytes(SAMPLE);
r.check_end_names(false)
.check_comments(false)
.trim_text(true);
let mut count = criterion::black_box(0);
let mut buf = Vec::new();
let mut ns_buf = Vec::new();
loop {
match r.read_namespaced_event(&mut buf, &mut ns_buf) {
match r.read_resolved_event_into(&mut buf) {
Ok((_, Event::Start(_))) | Ok((_, Event::Empty(_))) => count += 1,
Ok((_, Event::Eof)) => break,
_ => (),
Expand Down Expand Up @@ -393,7 +391,7 @@ purus. Consequat id porta nibh venenatis cras sed felis.";
criterion_group!(
benches,
read_event,
read_namespaced_event,
read_resolved_event_into,
one_event,
attributes,
escaping,
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Expand Up @@ -65,5 +65,5 @@ mod writer;
#[cfg(feature = "serialize")]
pub use crate::errors::serialize::DeError;
pub use crate::errors::{Error, Result};
pub use crate::reader::{Decoder, Reader};
pub use crate::reader::{Decoder, NsReader, Reader};
pub use crate::writer::{ElementWriter, Writer};
12 changes: 7 additions & 5 deletions src/name.rs
Expand Up @@ -274,13 +274,15 @@ impl<'a> AsRef<[u8]> for Namespace<'a> {

////////////////////////////////////////////////////////////////////////////////////////////////////

/// Result of [prefix] resolution which creates by [`Reader::attribute_namespace`],
/// [`Reader::event_namespace`] and [`Reader::read_namespaced_event`] methods.
/// Result of [prefix] resolution which creates by [`NsReader::resolve_attribute`],
/// [`NsReader::resolve_element`], [`NsReader::read_resolved_event`] and
/// [`NsReader::read_resolved_event_into`] methods.
///
/// [prefix]: Prefix
/// [`Reader::attribute_namespace`]: crate::reader::Reader::attribute_namespace
/// [`Reader::event_namespace`]: crate::reader::Reader::event_namespace
/// [`Reader::read_namespaced_event`]: crate::reader::Reader::read_namespaced_event
/// [`NsReader::resolve_attribute`]: crate::reader::NsReader::resolve_attribute
/// [`NsReader::resolve_element`]: crate::reader::NsReader::resolve_element
/// [`NsReader::read_resolved_event`]: crate::reader::NsReader::read_resolved_event
/// [`NsReader::read_resolved_event_into`]: crate::reader::NsReader::read_resolved_event_into
#[derive(Clone, PartialEq, Eq, Hash)]
pub enum ResolveResult<'ns> {
/// Qualified name does not contain prefix, and resolver does not define
Expand Down