Skip to content

Commit

Permalink
ns: Change BytesStart::name() and BytesEnd::name() to return QName
Browse files Browse the repository at this point in the history
and `BytesStart::local_name()` and `BytesEnd::local_name()` to return `LocalName`
  • Loading branch information
Mingun committed Jun 13, 2022
1 parent 2a83743 commit ae2219f
Show file tree
Hide file tree
Showing 17 changed files with 105 additions and 98 deletions.
2 changes: 2 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
and returns `ResolveResult` and `LocalName`, `read_event_namespaced` now
returns `ResolveResult` instead of `Option<[u8]>`
- [#393]: Types of `Attribute::key` and `Attr::key()` changed to `QName`
- [#393]: Now `BytesStart::name()` and `BytesEnd::name()` returns `QName`, and
`BytesStart::local_name()` and `BytesEnd::local_name()` returns `LocalName`

### New Tests

Expand Down
2 changes: 1 addition & 1 deletion examples/custom_entities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
custom_entities.insert(cap[1].to_vec(), cap[2].to_vec());
}
}
Ok(Event::Start(ref e)) => match e.name() {
Ok(Event::Start(ref e)) => match e.name().as_ref() {
b"test" => println!(
"attributes values: {:?}",
e.attributes()
Expand Down
13 changes: 6 additions & 7 deletions examples/issue68.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,11 @@ fn parse_report(xml_data: &str) -> Vec<Resource> {

loop {
match reader.read_namespaced_event(&mut buf, &mut ns_buffer) {
Ok((namespace_value, Event::Start(e))) => {
let namespace_value = Option::<Namespace>::try_from(namespace_value)
Ok((ns, Event::Start(e))) => {
let ns = Option::<Namespace>::try_from(ns)
.unwrap_or_default() // Treat unknown prefixes as not bound to any namespace
.unwrap_or(Namespace(b""));
match (depth, state, namespace_value.as_ref(), e.local_name()) {
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;
Expand All @@ -100,12 +100,11 @@ fn parse_report(xml_data: &str) -> Vec<Resource> {
}
depth += 1;
}
Ok((namespace_value, Event::End(e))) => {
let namespace_value = Option::<Namespace>::try_from(namespace_value)
Ok((ns, Event::End(e))) => {
let ns = Option::<Namespace>::try_from(ns)
.unwrap_or_default() // Treat unknown prefixes as not bound to any namespace
.unwrap_or(Namespace(b""));
let local_name = e.local_name();
match (depth, state, namespace_value.as_ref(), local_name) {
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,
_ => {}
Expand Down
12 changes: 7 additions & 5 deletions examples/nested_readers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fn main() -> Result<(), quick_xml::Error> {
let mut found_tables = Vec::new();
loop {
match reader.read_event(&mut buf)? {
Event::Start(element) => match element.name() {
Event::Start(element) => match element.name().as_ref() {
b"w:tbl" => {
count += 1;
let mut stats = TableStat {
Expand All @@ -34,19 +34,21 @@ fn main() -> Result<(), quick_xml::Error> {
loop {
skip_buf.clear();
match reader.read_event(&mut skip_buf)? {
Event::Start(element) => match element.name() {
Event::Start(element) => match element.name().as_ref() {
b"w:tr" => {
stats.rows.push(vec![]);
row_index = stats.rows.len() - 1;
}
b"w:tc" => {
stats.rows[row_index]
.push(String::from_utf8(element.name().to_vec()).unwrap());
stats.rows[row_index].push(
String::from_utf8(element.name().as_ref().to_vec())
.unwrap(),
);
}
_ => {}
},
Event::End(element) => {
if element.name() == b"w:tbl" {
if element.name().as_ref() == b"w:tbl" {
found_tables.push(stats);
break;
}
Expand Down
2 changes: 1 addition & 1 deletion examples/read_texts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fn main() {

loop {
match reader.read_event(&mut buf) {
Ok(Event::Start(ref e)) if e.name() == b"tag2" => {
Ok(Event::Start(ref e)) if e.name().as_ref() == b"tag2" => {
txt.push(
reader
.read_text(b"tag2", &mut Vec::new())
Expand Down
6 changes: 3 additions & 3 deletions src/de/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ where
let key = if let Some(p) = self
.unflatten_fields
.iter()
.position(|f| e.name() == &f[UNFLATTEN_PREFIX.len()..])
.position(|f| e.name().as_ref() == &f[UNFLATTEN_PREFIX.len()..])
{
// Used to deserialize elements, like:
// <root>
Expand All @@ -290,7 +290,7 @@ where
// }
seed.deserialize(self.unflatten_fields.remove(p).into_deserializer())
} else {
let name = Cow::Borrowed(e.local_name());
let name = Cow::Borrowed(e.local_name().into_inner());
seed.deserialize(EscapedDeserializer::new(name, decoder, false))
};
key.map(Some)
Expand Down Expand Up @@ -606,7 +606,7 @@ where
// Stop iteration after reaching a closing tag
DeEvent::End(e) if e.name() == self.map.start.name() => Ok(None),
// This is a unmatched closing tag, so the XML is invalid
DeEvent::End(e) => Err(DeError::UnexpectedEnd(e.name().to_owned())),
DeEvent::End(e) => Err(DeError::UnexpectedEnd(e.name().as_ref().to_owned())),
// We cannot get `Eof` legally, because we always inside of the
// opened tag `self.map.start`
DeEvent::Eof => Err(DeError::UnexpectedEof),
Expand Down
42 changes: 24 additions & 18 deletions src/de/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -514,16 +514,16 @@ where
match self.write.back() {
// Skip all subtree, if we skip a start event
Some(DeEvent::Start(e)) => {
let end = e.name().to_owned();
let end = e.name().as_ref().to_owned();
let mut depth = 0;
loop {
let event = self.next()?;
match event {
DeEvent::Start(ref e) if e.name() == end => {
DeEvent::Start(ref e) if e.name().as_ref() == end => {
self.skip_event(event)?;
depth += 1;
}
DeEvent::End(ref e) if e.name() == end => {
DeEvent::End(ref e) if e.name().as_ref() == end => {
self.skip_event(event)?;
if depth == 0 {
return Ok(());
Expand Down Expand Up @@ -571,7 +571,9 @@ where
let e = self.next()?;
match e {
DeEvent::Start(e) => return Ok(Some(e)),
DeEvent::End(e) => return Err(DeError::UnexpectedEnd(e.name().to_owned())),
DeEvent::End(e) => {
return Err(DeError::UnexpectedEnd(e.name().as_ref().to_owned()))
}
DeEvent::Eof => return Ok(None),
_ => (), // ignore texts
}
Expand Down Expand Up @@ -631,20 +633,24 @@ where
DeEvent::Text(t) if unescape => t.unescape()?,
DeEvent::Text(t) => BytesCData::new(t.into_inner()),
DeEvent::CData(t) => t,
DeEvent::Start(s) => return Err(DeError::UnexpectedStart(s.name().to_owned())),
DeEvent::Start(s) => {
return Err(DeError::UnexpectedStart(s.name().as_ref().to_owned()))
}
// We can get End event in case of `<tag></tag>` or `<tag/>` input
// Return empty text in that case
DeEvent::End(end) if end.name() == e.name() => {
return Ok(BytesCData::new(&[] as &[u8]));
}
DeEvent::End(end) => return Err(DeError::UnexpectedEnd(end.name().to_owned())),
DeEvent::End(end) => {
return Err(DeError::UnexpectedEnd(end.name().as_ref().to_owned()))
}
DeEvent::Eof => return Err(DeError::UnexpectedEof),
};
self.read_to_end(e.name())?;
self.read_to_end(e.name().as_ref())?;
Ok(t)
}
DeEvent::Start(e) => Err(DeError::UnexpectedStart(e.name().to_owned())),
DeEvent::End(e) => Err(DeError::UnexpectedEnd(e.name().to_owned())),
DeEvent::Start(e) => Err(DeError::UnexpectedStart(e.name().as_ref().to_owned())),
DeEvent::End(e) => Err(DeError::UnexpectedEnd(e.name().as_ref().to_owned())),
DeEvent::Eof => Err(DeError::UnexpectedEof),
}
}
Expand All @@ -662,10 +668,10 @@ where
let mut depth = 0;
loop {
match self.read.pop_front() {
Some(DeEvent::Start(e)) if e.name() == name => {
Some(DeEvent::Start(e)) if e.name().as_ref() == name => {
depth += 1;
}
Some(DeEvent::End(e)) if e.name() == name => {
Some(DeEvent::End(e)) if e.name().as_ref() == name => {
if depth == 0 {
return Ok(());
}
Expand All @@ -685,8 +691,8 @@ where
fn read_to_end(&mut self, name: &[u8]) -> Result<(), DeError> {
// First one might be in self.peek
match self.next()? {
DeEvent::Start(e) => self.reader.read_to_end(e.name())?,
DeEvent::End(e) if e.name() == name => return Ok(()),
DeEvent::Start(e) => self.reader.read_to_end(e.name().as_ref())?,
DeEvent::End(e) if e.name().as_ref() == name => return Ok(()),
_ => (),
}
self.reader.read_to_end(name)
Expand Down Expand Up @@ -751,7 +757,7 @@ where
{
// Try to go to the next `<tag ...>...</tag>` or `<tag .../>`
if let Some(e) = self.next_start()? {
let name = e.name().to_vec();
let name = e.name().as_ref().to_vec();
let map = map::MapAccess::new(self, e, fields)?;
let value = visitor.visit_map(map)?;
self.read_to_end(&name)?;
Expand Down Expand Up @@ -785,11 +791,11 @@ where
{
match self.next()? {
DeEvent::Start(s) => {
self.read_to_end(s.name())?;
self.read_to_end(s.name().as_ref())?;
visitor.visit_unit()
}
DeEvent::Text(_) | DeEvent::CData(_) => visitor.visit_unit(),
DeEvent::End(e) => Err(DeError::UnexpectedEnd(e.name().to_owned())),
DeEvent::End(e) => Err(DeError::UnexpectedEnd(e.name().as_ref().to_owned())),
DeEvent::Eof => Err(DeError::UnexpectedEof),
}
}
Expand Down Expand Up @@ -892,8 +898,8 @@ where
V: Visitor<'de>,
{
match self.next()? {
DeEvent::Start(e) => self.read_to_end(e.name())?,
DeEvent::End(e) => return Err(DeError::UnexpectedEnd(e.name().to_owned())),
DeEvent::Start(e) => self.read_to_end(e.name().as_ref())?,
DeEvent::End(e) => return Err(DeError::UnexpectedEnd(e.name().as_ref().to_owned())),
DeEvent::Eof => return Err(DeError::UnexpectedEof),
_ => (),
}
Expand Down
4 changes: 2 additions & 2 deletions src/de/seq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ pub fn not_in(
decoder: Decoder,
) -> Result<bool, DeError> {
#[cfg(not(feature = "encoding"))]
let tag = Cow::Borrowed(decoder.decode(start.name())?);
let tag = Cow::Borrowed(decoder.decode(start.name().into_inner())?);

#[cfg(feature = "encoding")]
let tag = decoder.decode(start.name());
let tag = decoder.decode(start.name().into_inner());

Ok(fields.iter().all(|&field| field != tag.as_ref()))
}
Expand Down
6 changes: 4 additions & 2 deletions src/de/var.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ where
DeEvent::Text(t) => EscapedDeserializer::new(Cow::Borrowed(t), decoder, true),
// Escape sequences does not processed inside CDATA section
DeEvent::CData(t) => EscapedDeserializer::new(Cow::Borrowed(t), decoder, false),
DeEvent::Start(e) => EscapedDeserializer::new(Cow::Borrowed(e.name()), decoder, false),
DeEvent::Start(e) => {
EscapedDeserializer::new(Cow::Borrowed(e.name().into_inner()), decoder, false)
}
_ => {
return Err(DeError::Unsupported(
"Invalid event for Enum, expecting `Text` or `Start`",
Expand All @@ -65,7 +67,7 @@ where

fn unit_variant(self) -> Result<(), DeError> {
match self.de.next()? {
DeEvent::Start(e) => self.de.read_to_end(e.name()),
DeEvent::Start(e) => self.de.read_to_end(e.name().as_ref()),
DeEvent::Text(_) | DeEvent::CData(_) => Ok(()),
_ => unreachable!(),
}
Expand Down
52 changes: 24 additions & 28 deletions src/events/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,14 @@ use encoding_rs::Encoding;
use std::{borrow::Cow, collections::HashMap, io::BufRead, ops::Deref, str::from_utf8};

use crate::escape::{do_unescape, escape, partial_escape};
use crate::name::{LocalName, QName};
use crate::utils::write_cow_string;
use crate::{errors::Error, errors::Result, reader::Reader};
use attributes::{Attribute, Attributes};

#[cfg(feature = "serialize")]
use crate::escape::EscapeError;

use memchr;

/// Opening tag data (`Event::Start`), with optional attributes.
///
/// `<name attr="value">`.
Expand Down Expand Up @@ -156,22 +155,22 @@ impl<'a> BytesStart<'a> {

/// Creates new paired close tag
pub fn to_end(&self) -> BytesEnd {
BytesEnd::borrowed(self.name())
BytesEnd::borrowed(self.name().into_inner())
}

/// Gets the undecoded raw tag name as a `&[u8]`.
/// Gets the undecoded raw tag name, as present in the input stream.
#[inline]
pub fn name(&self) -> &[u8] {
&self.buf[..self.name_len]
pub fn name(&self) -> QName {
QName(&self.buf[..self.name_len])
}

/// Gets the undecoded raw local tag name (excluding namespace) as a `&[u8]`.
/// Gets the undecoded raw local tag name (excluding namespace) as present
/// in the input stream.
///
/// All content up to and including the first `:` character is removed from the tag name.
#[inline]
pub fn local_name(&self) -> &[u8] {
let name = self.name();
memchr::memchr(b':', name).map_or(name, |i| &name[i + 1..])
pub fn local_name(&self) -> LocalName {
self.name().into()
}

/// Gets the unescaped tag name.
Expand Down Expand Up @@ -641,22 +640,19 @@ impl<'a> BytesEnd<'a> {
}
}

/// Gets `BytesEnd` event name
/// Gets the undecoded raw tag name, as present in the input stream.
#[inline]
pub fn name(&self) -> &[u8] {
&*self.name
pub fn name(&self) -> QName {
QName(&*self.name)
}

/// local name (excluding namespace) as &[u8] (without eventual attributes)
/// returns the name() with any leading namespace removed (all content up to
/// and including the first ':' character)
/// Gets the undecoded raw local tag name (excluding namespace) as present
/// in the input stream.
///
/// All content up to and including the first `:` character is removed from the tag name.
#[inline]
pub fn local_name(&self) -> &[u8] {
if let Some(i) = self.name().iter().position(|b| *b == b':') {
&self.name()[i + 1..]
} else {
self.name()
}
pub fn local_name(&self) -> LocalName {
self.name().into()
}
}

Expand Down Expand Up @@ -1179,12 +1175,12 @@ mod test {
loop {
match rdr.read_event(&mut buf).expect("unable to read xml event") {
Event::Start(ref e) => parsed_local_names.push(
from_utf8(e.local_name())
from_utf8(e.local_name().as_ref())
.expect("unable to build str from local_name")
.to_string(),
),
Event::End(ref e) => parsed_local_names.push(
from_utf8(e.local_name())
from_utf8(e.local_name().as_ref())
.expect("unable to build str from local_name")
.to_string(),
),
Expand All @@ -1206,21 +1202,21 @@ mod test {
fn bytestart_create() {
let b = BytesStart::owned_name("test");
assert_eq!(b.len(), 4);
assert_eq!(b.name(), b"test");
assert_eq!(b.name(), QName(b"test"));
}

#[test]
fn bytestart_set_name() {
let mut b = BytesStart::owned_name("test");
assert_eq!(b.len(), 4);
assert_eq!(b.name(), b"test");
assert_eq!(b.name(), QName(b"test"));
assert_eq!(b.attributes_raw(), b"");
b.push_attribute(("x", "a"));
assert_eq!(b.len(), 10);
assert_eq!(b.attributes_raw(), b" x=\"a\"");
b.set_name(b"g");
assert_eq!(b.len(), 7);
assert_eq!(b.name(), b"g");
assert_eq!(b.name(), QName(b"g"));
}

#[test]
Expand All @@ -1231,6 +1227,6 @@ mod test {
b.clear_attributes();
assert!(b.attributes().next().is_none());
assert_eq!(b.len(), 4);
assert_eq!(b.name(), b"test");
assert_eq!(b.name(), QName(b"test"));
}
}
Loading

0 comments on commit ae2219f

Please sign in to comment.