Skip to content

Commit c0280cd

Browse files
committed
Accept Decoder instead of Reader when decoding attributes.
This will allow decode them even if Reader does not exists, for example, when you only write events.
1 parent 2b6b506 commit c0280cd

File tree

6 files changed

+22
-18
lines changed

6 files changed

+22
-18
lines changed

Changelog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,14 @@
4848
- `SliceReader::get_ref()`
4949
- `Writer::get_ref()`
5050
- `Writer::new()`
51+
- [#760]: `Attribute::decode_and_unescape_value` and `Attribute::decode_and_unescape_value_with` now
52+
accepts `Decoder` instead of `Reader`. Use `Reader::decoder()` to get it.
5153

5254
[#650]: https://github.com/tafia/quick-xml/issues/650
5355
[#755]: https://github.com/tafia/quick-xml/pull/755
5456
[#758]: https://github.com/tafia/quick-xml/pull/758
5557
[#759]: https://github.com/tafia/quick-xml/pull/759
58+
[#760]: https://github.com/tafia/quick-xml/pull/760
5659

5760

5861
## 0.32.0 -- 2024-06-10

benches/macrobenches.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ fn parse_document_from_str(doc: &str) -> XmlResult<()> {
5050
match criterion::black_box(r.read_event()?) {
5151
Event::Start(e) | Event::Empty(e) => {
5252
for attr in e.attributes() {
53-
criterion::black_box(attr?.decode_and_unescape_value(&r)?);
53+
criterion::black_box(attr?.decode_and_unescape_value(r.decoder())?);
5454
}
5555
}
5656
Event::Text(e) => {
@@ -75,7 +75,7 @@ fn parse_document_from_bytes(doc: &[u8]) -> XmlResult<()> {
7575
match criterion::black_box(r.read_event_into(&mut buf)?) {
7676
Event::Start(e) | Event::Empty(e) => {
7777
for attr in e.attributes() {
78-
criterion::black_box(attr?.decode_and_unescape_value(&r)?);
78+
criterion::black_box(attr?.decode_and_unescape_value(r.decoder())?);
7979
}
8080
}
8181
Event::Text(e) => {
@@ -101,7 +101,7 @@ fn parse_document_from_str_with_namespaces(doc: &str) -> XmlResult<()> {
101101
(resolved_ns, Event::Start(e) | Event::Empty(e)) => {
102102
criterion::black_box(resolved_ns);
103103
for attr in e.attributes() {
104-
criterion::black_box(attr?.decode_and_unescape_value(&r)?);
104+
criterion::black_box(attr?.decode_and_unescape_value(r.decoder())?);
105105
}
106106
}
107107
(resolved_ns, Event::Text(e)) => {
@@ -129,7 +129,7 @@ fn parse_document_from_bytes_with_namespaces(doc: &[u8]) -> XmlResult<()> {
129129
(resolved_ns, Event::Start(e) | Event::Empty(e)) => {
130130
criterion::black_box(resolved_ns);
131131
for attr in e.attributes() {
132-
criterion::black_box(attr?.decode_and_unescape_value(&r)?);
132+
criterion::black_box(attr?.decode_and_unescape_value(r.decoder())?);
133133
}
134134
}
135135
(resolved_ns, Event::Text(e)) => {

examples/custom_entities.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
4747
.attributes()
4848
.map(|a| {
4949
a.unwrap()
50-
.decode_and_unescape_value_with(&reader, |ent| {
50+
.decode_and_unescape_value_with(reader.decoder(), |ent| {
5151
custom_entities.get(ent).map(|s| s.as_str())
5252
})
5353
.unwrap()

examples/read_nodes.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ impl Translation {
7070
for attr_result in element.attributes() {
7171
let a = attr_result?;
7272
match a.key.as_ref() {
73-
b"Language" => lang = a.decode_and_unescape_value(reader)?,
74-
b"Tag" => tag = a.decode_and_unescape_value(reader)?,
73+
b"Language" => lang = a.decode_and_unescape_value(reader.decoder())?,
74+
b"Tag" => tag = a.decode_and_unescape_value(reader.decoder())?,
7575
_ => (),
7676
}
7777
}
@@ -138,7 +138,7 @@ fn main() -> Result<(), AppError> {
138138
Ok::<Cow<'_, str>, Infallible>(std::borrow::Cow::from(""))
139139
})
140140
.unwrap().to_string();
141-
let value = a.decode_and_unescape_value(&reader).or_else(|err| {
141+
let value = a.decode_and_unescape_value(reader.decoder()).or_else(|err| {
142142
dbg!("unable to read key in DefaultSettings attribute {:?}, utf8 error {:?}", &a, err);
143143
Ok::<Cow<'_, str>, Infallible>(std::borrow::Cow::from(""))
144144
}).unwrap().to_string();

src/events/attributes.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
//!
33
//! Provides an iterator over attributes key/value pairs
44
5+
use crate::encoding::Decoder;
56
use crate::errors::Result as XmlResult;
67
use crate::escape::{escape, resolve_predefined_entity, unescape_with};
78
use crate::name::QName;
8-
use crate::reader::Reader;
99
use crate::utils::{is_whitespace, write_byte_string, write_cow_string, Bytes};
10+
1011
use std::fmt::{self, Debug, Display, Formatter};
1112
use std::iter::FusedIterator;
1213
use std::{borrow::Cow, ops::Range};
@@ -84,23 +85,23 @@ impl<'a> Attribute<'a> {
8485
///
8586
/// This will allocate if the value contains any escape sequences or in
8687
/// non-UTF-8 encoding.
87-
pub fn decode_and_unescape_value<B>(&self, reader: &Reader<B>) -> XmlResult<Cow<'a, str>> {
88-
self.decode_and_unescape_value_with(reader, resolve_predefined_entity)
88+
pub fn decode_and_unescape_value(&self, decoder: Decoder) -> XmlResult<Cow<'a, str>> {
89+
self.decode_and_unescape_value_with(decoder, resolve_predefined_entity)
8990
}
9091

9192
/// Decodes then unescapes the value with custom entities.
9293
///
9394
/// This will allocate if the value contains any escape sequences or in
9495
/// non-UTF-8 encoding.
95-
pub fn decode_and_unescape_value_with<'entity, B>(
96+
pub fn decode_and_unescape_value_with<'entity>(
9697
&self,
97-
reader: &Reader<B>,
98+
decoder: Decoder,
9899
resolve_entity: impl FnMut(&str) -> Option<&'entity str>,
99100
) -> XmlResult<Cow<'a, str>> {
100101
let decoded = match &self.value {
101-
Cow::Borrowed(bytes) => reader.decoder().decode(bytes)?,
102+
Cow::Borrowed(bytes) => decoder.decode(bytes)?,
102103
// Convert to owned, because otherwise Cow will be bound with wrong lifetime
103-
Cow::Owned(bytes) => reader.decoder().decode(bytes)?.into_owned().into(),
104+
Cow::Owned(bytes) => decoder.decode(bytes)?.into_owned().into(),
104105
};
105106

106107
match unescape_with(&decoded, resolve_entity)? {

tests/fuzzing.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ fn fuzz_101() {
3030
match reader.read_event_into(&mut buf) {
3131
Ok(Event::Start(e)) | Ok(Event::Empty(e)) => {
3232
for a in e.attributes() {
33-
if a.ok()
34-
.map_or(true, |a| a.decode_and_unescape_value(&reader).is_err())
35-
{
33+
if a.ok().map_or(true, |a| {
34+
a.decode_and_unescape_value(reader.decoder()).is_err()
35+
}) {
3636
break;
3737
}
3838
}

0 commit comments

Comments
 (0)