Skip to content

Commit eb417b0

Browse files
committed
Add Decoder::decode_into to enable usage of pre-allocated buffers if available.
1 parent 1f6260a commit eb417b0

File tree

2 files changed

+44
-8
lines changed

2 files changed

+44
-8
lines changed

src/de/key.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,18 +81,18 @@ impl<'i, 'd> QNameDeserializer<'i, 'd> {
8181
decoder: Decoder,
8282
key_buf: &'d mut String,
8383
) -> Result<Self, DeError> {
84+
key_buf.clear();
85+
key_buf.push('@');
86+
8487
// https://github.com/tafia/quick-xml/issues/537
8588
// Namespace bindings (xmlns:xxx) map to `@xmlns:xxx` instead of `@xxx`
86-
let field = if name.as_namespace_binding().is_some() {
87-
decoder.decode(name.into_inner())?
89+
if name.as_namespace_binding().is_some() {
90+
decoder.decode_into(name.into_inner(), key_buf)?;
8891
} else {
89-
decode_name(name, decoder)?
92+
let local = name.local_name();
93+
decoder.decode_into(local.into_inner(), key_buf)?;
9094
};
9195

92-
key_buf.clear();
93-
key_buf.push('@');
94-
key_buf.push_str(&field);
95-
9696
Ok(Self {
9797
name: CowRef::Slice(key_buf),
9898
})

src/encoding.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use std::borrow::Cow;
44

55
#[cfg(feature = "encoding")]
6-
use encoding_rs::{Encoding, UTF_16BE, UTF_16LE, UTF_8};
6+
use encoding_rs::{DecoderResult, Encoding, UTF_16BE, UTF_16LE, UTF_8};
77

88
#[cfg(feature = "encoding")]
99
use crate::Error;
@@ -88,6 +88,17 @@ impl Decoder {
8888

8989
decoded
9090
}
91+
92+
/// Like [`decode`][Self::decode] but using a pre-allocated buffer.
93+
pub fn decode_into(&self, bytes: &[u8], buf: &mut String) -> Result<()> {
94+
#[cfg(not(feature = "encoding"))]
95+
buf.push_str(std::str::from_utf8(bytes)?);
96+
97+
#[cfg(feature = "encoding")]
98+
decode_into(bytes, self.encoding, buf)?;
99+
100+
Ok(())
101+
}
91102
}
92103

93104
/// Decodes the provided bytes using the specified encoding.
@@ -100,6 +111,31 @@ pub fn decode<'b>(bytes: &'b [u8], encoding: &'static Encoding) -> Result<Cow<'b
100111
.ok_or(Error::NonDecodable(None))
101112
}
102113

114+
/// Like [`decode`] but using a pre-allocated buffer.
115+
#[cfg(feature = "encoding")]
116+
pub fn decode_into(bytes: &[u8], encoding: &'static Encoding, buf: &mut String) -> Result<()> {
117+
if encoding == UTF_8 {
118+
buf.push_str(std::str::from_utf8(bytes)?);
119+
return Ok(());
120+
}
121+
122+
let mut decoder = encoding.new_decoder_without_bom_handling();
123+
buf.reserve(
124+
decoder
125+
.max_utf8_buffer_length_without_replacement(bytes.len())
126+
.unwrap(),
127+
);
128+
let (result, read) = decoder.decode_to_string_without_replacement(bytes, buf, true);
129+
match result {
130+
DecoderResult::InputEmpty => {
131+
debug_assert_eq!(read, bytes.len());
132+
Ok(())
133+
}
134+
DecoderResult::Malformed(_, _) => Err(Error::NonDecodable(None)),
135+
DecoderResult::OutputFull => unreachable!(),
136+
}
137+
}
138+
103139
/// Automatic encoding detection of XML files based using the
104140
/// [recommended algorithm](https://www.w3.org/TR/xml11/#sec-guessing).
105141
///

0 commit comments

Comments
 (0)