From 703f0782e8534a94da16583f522a3ed9c383a9fa Mon Sep 17 00:00:00 2001 From: Mingun Date: Wed, 22 Jun 2022 21:35:10 +0500 Subject: [PATCH] Remove `BytesStart::unescaped*` set of methods because they could return wrong results Removed example actually did not show nothing useful and was wrong after all --- Changelog.md | 3 + examples/issue68.rs | 144 -------------------------------------------- src/events/mod.rs | 88 --------------------------- tests/test.rs | 3 - 4 files changed, 3 insertions(+), 235 deletions(-) delete mode 100644 examples/issue68.rs diff --git a/Changelog.md b/Changelog.md index 6854dfc6..5967c8a4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -89,6 +89,9 @@ is returned regardless of the status of the feature. - [#180]: Error variant `Error::Utf8` replaced by `Error::NonDecodable` +- [#118]: Remove `BytesStart::unescaped*` set of methods because they could return wrong results + Use methods on `Attribute` instead + ### New Tests - [#9]: Added tests for incorrect nested tags in input diff --git a/examples/issue68.rs b/examples/issue68.rs deleted file mode 100644 index ccb0e989..00000000 --- a/examples/issue68.rs +++ /dev/null @@ -1,144 +0,0 @@ -#![allow(unused)] - -use quick_xml::events::Event; -use quick_xml::name::Namespace; -use quick_xml::Reader; -use std::convert::TryFrom; -use std::io::Read; - -struct Resource { - etag: String, - calendar_data: String, -} - -struct Prop { - namespace: String, - local_name: String, - value: String, -} - -impl Prop { - fn new() -> Prop { - Prop { - namespace: String::new(), - local_name: String::new(), - value: String::new(), - } - } -} - -struct PropStat { - status: String, - props: Vec, -} - -impl PropStat { - fn new() -> PropStat { - PropStat { - status: String::new(), - props: Vec::::new(), - } - } -} - -struct Response { - href: String, - propstats: Vec, -} - -impl Response { - fn new() -> Response { - Response { - href: String::new(), - propstats: Vec::::new(), - } - } -} - -fn parse_report(xml_data: &str) -> Vec { - let result = Vec::::new(); - - let mut reader = Reader::from_str(xml_data); - reader.trim_text(true); - - let mut count = 0; - let mut buf = Vec::new(); - let mut ns_buffer = Vec::new(); - - #[derive(Clone, Copy)] - enum State { - Root, - MultiStatus, - Response, - Success, - Error, - }; - - let mut responses = Vec::::new(); - let mut current_response = Response::new(); - let mut current_prop = Prop::new(); - - let mut depth = 0; - let mut state = State::MultiStatus; - - loop { - match reader.read_namespaced_event(&mut buf, &mut ns_buffer) { - Ok((ns, Event::Start(e))) => { - let ns = Option::::try_from(ns) - .unwrap_or_default() // Treat unknown prefixes as not bound to any namespace - .unwrap_or(Namespace(b"")); - match (depth, state, ns.as_ref(), e.local_name().as_ref()) { - (0, State::Root, b"DAV:", b"multistatus") => state = State::MultiStatus, - (1, State::MultiStatus, b"DAV:", b"response") => { - state = State::Response; - current_response = Response::new(); - } - (2, State::Response, b"DAV:", b"href") => { - current_response.href = e.unescape_and_decode(&reader).unwrap(); - } - _ => {} - } - depth += 1; - } - Ok((ns, Event::End(e))) => { - let ns = Option::::try_from(ns) - .unwrap_or_default() // Treat unknown prefixes as not bound to any namespace - .unwrap_or(Namespace(b"")); - match (depth, state, ns.as_ref(), e.local_name().as_ref()) { - (1, State::MultiStatus, b"DAV:", b"multistatus") => state = State::Root, - (2, State::MultiStatus, b"DAV:", b"multistatus") => state = State::MultiStatus, - _ => {} - } - depth -= 1; - } - Ok((_, Event::Eof)) => break, - Err(e) => break, - _ => (), - } - } - result -} - -fn main() { - let test_data = r#" - - - - - /caldav/v2/johndoh%40gmail.com/events/07b7it7uonpnlnvjldr0l1ckg8%40google.com.ics - - - HTTP/1.1 200 OK - - "63576798396" - BEGIN:VCALENDAR - - - - -"#; - - parse_report(test_data); -} diff --git a/src/events/mod.rs b/src/events/mod.rs index ea321017..b04e458e 100644 --- a/src/events/mod.rs +++ b/src/events/mod.rs @@ -231,94 +231,6 @@ impl<'a> BytesStart<'a> { self.name().into() } - /// Gets the unescaped tag name. - /// - /// XML escape sequences like "`<`" will be replaced by their unescaped characters like - /// "`<`". - /// - /// See also [`unescaped_with_custom_entities()`](#method.unescaped_with_custom_entities) - #[inline] - pub fn unescaped(&self) -> Result> { - self.make_unescaped(None) - } - - /// Gets the unescaped tag name, using custom entities. - /// - /// XML escape sequences like "`<`" will be replaced by their unescaped characters like - /// "`<`". - /// Additional entities can be provided in `custom_entities`. - /// - /// # Pre-condition - /// - /// The keys and values of `custom_entities`, if any, must be valid UTF-8. - /// - /// See also [`unescaped()`](#method.unescaped) - #[inline] - pub fn unescaped_with_custom_entities<'s>( - &'s self, - custom_entities: &HashMap, Vec>, - ) -> Result> { - self.make_unescaped(Some(custom_entities)) - } - - #[inline] - fn make_unescaped<'s>( - &'s self, - custom_entities: Option<&HashMap, Vec>>, - ) -> Result> { - do_unescape(&*self.buf, custom_entities).map_err(Error::EscapeError) - } - - /// Returns the unescaped and decoded string value. - /// - /// This allocates a `String` in all cases. For performance reasons it might be a better idea to - /// instead use one of: - /// - /// * [`unescaped()`], as it doesn't allocate when no escape sequences are used. - /// * [`Reader::decode()`], as it only allocates when the decoding can't be performed otherwise. - /// - /// [`unescaped()`]: #method.unescaped - /// [`Reader::decode()`]: ../reader/struct.Reader.html#method.decode - #[inline] - pub fn unescape_and_decode(&self, reader: &Reader) -> Result { - self.do_unescape_and_decode_with_custom_entities(reader, None) - } - - /// Returns the unescaped and decoded string value with custom entities. - /// - /// This allocates a `String` in all cases. For performance reasons it might be a better idea to - /// instead use one of: - /// - /// * [`unescaped_with_custom_entities()`], as it doesn't allocate when no escape sequences are used. - /// * [`Reader::decode()`], as it only allocates when the decoding can't be performed otherwise. - /// - /// [`unescaped_with_custom_entities()`]: #method.unescaped_with_custom_entities - /// [`Reader::decode()`]: ../reader/struct.Reader.html#method.decode - /// - /// # Pre-condition - /// - /// The keys and values of `custom_entities`, if any, must be valid UTF-8. - #[inline] - pub fn unescape_and_decode_with_custom_entities( - &self, - reader: &Reader, - custom_entities: &HashMap, Vec>, - ) -> Result { - self.do_unescape_and_decode_with_custom_entities(reader, Some(custom_entities)) - } - - #[inline] - fn do_unescape_and_decode_with_custom_entities( - &self, - reader: &Reader, - custom_entities: Option<&HashMap, Vec>>, - ) -> Result { - let decoded = reader.decoder().decode(&*self)?; - - let unescaped = do_unescape(decoded.as_bytes(), custom_entities)?; - Ok(String::from_utf8(unescaped.into_owned())?) - } - /// Edit the name of the BytesStart in-place /// /// # Warning diff --git a/tests/test.rs b/tests/test.rs index cf547c8e..a47d3015 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -156,9 +156,6 @@ fn fuzz_101() { loop { match reader.read_event(&mut buf) { Ok(Start(ref e)) | Ok(Empty(ref e)) => { - if e.unescaped().is_err() { - break; - } for a in e.attributes() { if a.ok().map_or(true, |a| a.unescaped_value().is_err()) { break;