Skip to content

Commit 7f55cd8

Browse files
committed
Add functions for attribute value normalization
closes tafia#371
1 parent add7406 commit 7f55cd8

File tree

8 files changed

+503
-9
lines changed

8 files changed

+503
-9
lines changed

Changelog.md

+9
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414

1515
- [#541]: Deserialize specially named `$text` enum variant in [externally tagged]
1616
enums from textual content
17+
- [#379]: Improved compliance with the XML attribute value normalization process by
18+
adding `Attribute::normalized_value()` and `Attribute::normalized_value_with()`,
19+
which ought to be used in place of `Attribute::unescape_value()` and
20+
`Attribute::unescape_value_with()`
1721

1822
### Bug Fixes
1923

@@ -22,10 +26,15 @@
2226

2327
### Misc Changes
2428

29+
### New Tests
30+
31+
- [#379]: Added tests for attribute value normalization
32+
2533
[externally tagged]: https://serde.rs/enum-representations.html#externally-tagged
2634
[#490]: https://github.com/tafia/quick-xml/pull/490
2735
[#537]: https://github.com/tafia/quick-xml/issues/537
2836
[#541]: https://github.com/tafia/quick-xml/pull/541
37+
[#379]: https://github.com/tafia/quick-xml/pull/379
2938

3039
## 0.27.1 -- 2022-12-28
3140

benches/macrobenches.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,13 @@ static INPUTS: &[(&str, &str)] = &[
4343
("players.xml", PLAYERS),
4444
];
4545

46-
// TODO: use fully normalized attribute values
4746
fn parse_document_from_str(doc: &str) -> XmlResult<()> {
4847
let mut r = Reader::from_str(doc);
4948
loop {
5049
match criterion::black_box(r.read_event()?) {
5150
Event::Start(e) | Event::Empty(e) => {
5251
for attr in e.attributes() {
53-
criterion::black_box(attr?.decode_and_unescape_value(&r)?);
52+
criterion::black_box(attr?.decode_and_normalize_value(&r)?);
5453
}
5554
}
5655
Event::Text(e) => {

benches/microbenches.rs

+45
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,50 @@ fn attributes(c: &mut Criterion) {
242242
assert_eq!(count, 150);
243243
})
244244
});
245+
246+
group.finish();
247+
}
248+
249+
/// Benchmarks normalizing attribute values
250+
fn attribute_value_normalization(c: &mut Criterion) {
251+
let mut group = c.benchmark_group("attribute_value_normalization");
252+
253+
group.bench_function("noop_short", |b| {
254+
b.iter(|| {
255+
criterion::black_box(unescape("foobar")).unwrap();
256+
})
257+
});
258+
259+
group.bench_function("noop_long", |b| {
260+
b.iter(|| {
261+
criterion::black_box(unescape("just a bit of text without any entities")).unwrap();
262+
})
263+
});
264+
265+
group.bench_function("replacement_chars", |b| {
266+
b.iter(|| {
267+
criterion::black_box(unescape("just a bit\n of text without\tany entities")).unwrap();
268+
})
269+
});
270+
271+
group.bench_function("char_reference", |b| {
272+
b.iter(|| {
273+
let text = "prefix &#34;some stuff&#34;,&#x22;more stuff&#x22;";
274+
criterion::black_box(unescape(text)).unwrap();
275+
let text = "&#38;&#60;";
276+
criterion::black_box(unescape(text)).unwrap();
277+
})
278+
});
279+
280+
group.bench_function("entity_reference", |b| {
281+
b.iter(|| {
282+
let text = "age &gt; 72 &amp;&amp; age &lt; 21";
283+
criterion::black_box(unescape(text)).unwrap();
284+
let text = "&quot;what&apos;s that?&quot;";
285+
criterion::black_box(unescape(text)).unwrap();
286+
})
287+
});
288+
245289
group.finish();
246290
}
247291

@@ -354,6 +398,7 @@ criterion_group!(
354398
read_resolved_event_into,
355399
one_event,
356400
attributes,
401+
attribute_value_normalization,
357402
escaping,
358403
unescaping,
359404
);

src/errors.rs

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ impl From<EscapeError> for Error {
7777
}
7878

7979
impl From<AttrError> for Error {
80+
/// Creates a new `Error::InvalidAttr` from the given error
8081
#[inline]
8182
fn from(error: AttrError) -> Self {
8283
Error::InvalidAttr(error)

0 commit comments

Comments
 (0)