Skip to content

Commit

Permalink
in Element, renamed as_bytes to name; added AsStr trait for as_str()
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthieu Wipliez committed Feb 26, 2016
1 parent 1765672 commit 44a245b
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 37 deletions.
8 changes: 3 additions & 5 deletions src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl<'a> Attributes<'a> {
}

impl<'a> Iterator for Attributes<'a> {
type Item = Result<(&'a[u8], &'a str)>;
type Item = Result<(&'a [u8], &'a [u8])>;
fn next(&mut self) -> Option<Self::Item> {

if self.was_error { return None; }
Expand Down Expand Up @@ -101,9 +101,7 @@ impl<'a> Iterator for Attributes<'a> {
}
self.position += end_val.unwrap() + 1;

match ::std::str::from_utf8(&self.bytes[(p + start_val.unwrap())..(p + end_val.unwrap())]) {
Ok(s) => Some(Ok((&self.bytes[(p + start_key)..(p + end_key.unwrap())], s))),
Err(e) => Some(Err(Error::from(e))),
}
Some(Ok((&self.bytes[(p + start_key)..(p + end_key.unwrap())],
&self.bytes[(p + start_val.unwrap())..(p + end_val.unwrap())])))
}
}
57 changes: 32 additions & 25 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
//! for r in reader {
//! match r {
//! Ok(Event::Start(ref e)) => {
//! match e.as_bytes() {
//! match e.name() {
//! b"tag1" => println!("attributes values: {:?}",
//! e.attributes().map(|a| a.unwrap().1).collect::<Vec<_>>()),
//! b"tag2" => count += 1,
Expand All @@ -34,7 +34,7 @@
//! # Example of transforming XML
//!
//! ```
//! use quick_xml::{Element, Event, XmlReader, XmlWriter};
//! use quick_xml::{AsStr, Element, Event, XmlReader, XmlWriter};
//! use quick_xml::Event::*;
//! use std::io::Cursor;
//! use std::iter;
Expand All @@ -44,7 +44,7 @@
//! let mut writer = XmlWriter::new(Cursor::new(Vec::new()));
//! for r in reader {
//! match r {
//! Ok(Event::Start(ref e)) if e.as_bytes() == b"this_tag" => {
//! Ok(Event::Start(ref e)) if e.name().as_str().unwrap() == "this_tag" => {
//! // collect existing attributes
//! let mut attrs = e.attributes().map(|attr| attr.unwrap()).collect::<Vec<_>>();
//!
Expand All @@ -55,7 +55,7 @@
//! // writes the event to the writer
//! assert!(writer.write(Start(elem)).is_ok());
//! },
//! Ok(Event::End(ref e)) if e.as_bytes() == b"this_tag" => {
//! Ok(Event::End(ref e)) if e.name() == b"this_tag" => {
//! assert!(writer.write(End(Element::new("my_elem"))).is_ok());
//! },
//! Ok(e) => assert!(writer.write(e).is_ok()),
Expand Down Expand Up @@ -94,6 +94,19 @@ enum TagState {
Closed,
}

/// A trait to support on-demand conversion from UTF-8
pub trait AsStr {
/// Converts this to an &str
fn as_str(&self) -> Result<&str>;
}

/// Implements AsStr for a byte slice
impl AsStr for [u8] {
fn as_str(&self) -> Result<&str> {
from_utf8(self).map_err(Error::Utf8)
}
}

/// Xml reader
///
/// Consumes a `BufRead` and streams xml Event
Expand Down Expand Up @@ -154,11 +167,11 @@ impl<B: BufRead> XmlReader<B> {
let end = end.as_ref();
loop {
match self.next() {
Some(Ok(Event::End(ref e))) if e.as_bytes() == end => {
Some(Ok(Event::End(ref e))) if e.name() == end => {
if depth == 0 { return Ok(()); }
depth -= 1;
},
Some(Ok(Event::Start(ref e))) if e.as_bytes() == end => depth += 1,
Some(Ok(Event::Start(ref e))) if e.name() == end => depth += 1,
Some(Err(e)) => return Err(e),
None => {
warn!("EOF instead of {:?}", from_utf8(end));
Expand All @@ -177,7 +190,7 @@ impl<B: BufRead> XmlReader<B> {
Some(Ok(Event::Text(e))) => {
self.read_to_end(end).and_then(|_| e.into_string())
},
Some(Ok(Event::End(ref e))) if e.as_bytes() == end.as_ref() => Ok("".to_owned()),
Some(Ok(Event::End(ref e))) if e.name() == end.as_ref() => Ok("".to_owned()),
Some(Err(e)) => Err(e),
None => Err(Error::Unexpected("Reached EOF while reading text".to_owned())),
Some(Ok(_)) => {
Expand All @@ -197,8 +210,8 @@ impl<B: BufRead> XmlReader<B> {
/// let mut r = XmlReader::from_str("<a><b>test</b>\
/// <b>test 2</b><c/><b>test 3</b></a>").trim_text(true);
/// let mut tests = Vec::new();
/// r.map_starts::<_, &str>(None, |r, e| match e.as_bytes() {
/// b"a" => r.map_starts(Some("a"), |r, e| match e.as_bytes() {
/// r.map_starts::<_, &str>(None, |r, e| match e.name() {
/// b"a" => r.map_starts(Some("a"), |r, e| match e.name() {
/// b"b" => r.read_text("b").map(|t| tests.push(t)),
/// name => r.read_to_end(name)
/// }),
Expand All @@ -214,7 +227,7 @@ impl<B: BufRead> XmlReader<B> {
let end = end.as_ref();
loop {
match self.next() {
Some(Ok(Event::End(ref e))) if e.as_bytes() == end => return Ok(()),
Some(Ok(Event::End(ref e))) if e.name() == end => return Ok(()),
Some(Ok(Event::Start(ref e))) => try!(f(self, e)),
Some(Err(e)) => return Err(e),
None => return Err(Error::Unexpected(format!("Unexpected end of {:?}",
Expand Down Expand Up @@ -271,7 +284,7 @@ impl<B: BufRead> XmlReader<B> {
b'/' => {
if self.with_check {
let e = self.opened.pop().unwrap();
if &buf[1..] != e.as_bytes() {
if &buf[1..] != e.name() {
self.exit = true;
return Some(Err(Error::Malformed(format!(
"End event {:?} doesn't match last opened element {:?}, opened: {:?}",
Expand Down Expand Up @@ -431,13 +444,13 @@ impl Element {
}

/// name as &[u8] (without eventual attributes)
pub fn as_bytes(&self) -> &[u8] {
pub fn name(&self) -> &[u8] {
&self.buf[self.start..self.name_end]
}

/// name as str, (without eventual attributes)
pub fn as_str(&self) -> Result<&str> {
from_utf8(self.as_bytes()).map_err(Error::Utf8)
/// whole content as &[u8] (including eventual attributes)
pub fn content(&self) -> &[u8] {
&self.buf[self.start..self.end]
}

/// get attributes iterator
Expand Down Expand Up @@ -486,7 +499,7 @@ impl Element {
impl fmt::Debug for Element {
fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
write!(f, "Element {{ buf: {:?}, name_end: {}, end: {} }}",
self.as_str(), self.name_end, self.end)
self.content().as_str(), self.name_end, self.end)
}
}

Expand Down Expand Up @@ -596,9 +609,9 @@ impl<W: Write> XmlWriter<W> {
/// Writes the given event to the underlying writer.
pub fn write(&mut self, event: Event) -> Result<()> {
match event {
Event::Start(e) => self.write_start_tag(e),
Event::Start(ref e) => self.write_wrapped_str(b"<", e, b">"),
Event::End(ref e) => self.write_wrapped_str(b"</", e, b">"),
Event::Text(ref e) => self.write_bytes(e.as_bytes()),
Event::Text(ref e) => self.write_bytes(e.content()),
Event::Comment(ref e) => self.write_wrapped_str(b"<!--", e, b"-->"),
Event::CData(ref e) => self.write_wrapped_str(b"<![CDATA[", e, b"]]>"),
Event::Header(ref e) => self.write_wrapped_str(b"<?", e, b"?>"),
Expand All @@ -611,15 +624,9 @@ impl<W: Write> XmlWriter<W> {
Ok(())
}

fn write_start_tag(&mut self, element: Element) -> Result<()> {
try!(self.write_bytes(b"<"));
try!(self.write_bytes(&try!(element.into_string()).into_bytes()));
self.write_bytes(b">")
}

fn write_wrapped_str(&mut self, before: &[u8], element: &Element, after: &[u8]) -> Result<()> {
try!(self.write_bytes(before));
try!(self.write_bytes(element.as_bytes()));
try!(self.write_bytes(&element.content()));
self.write_bytes(after)
}

Expand Down
14 changes: 7 additions & 7 deletions src/test.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{Element, XmlReader, XmlWriter};
use super::{AsStr, Element, XmlReader, XmlWriter};
use super::Event::*;
use std::str::from_utf8;
use std::io::Cursor;
Expand All @@ -9,8 +9,8 @@ macro_rules! next_eq {
$(
match $r.next() {
Some(Ok($t(ref e))) => {
assert!(e.as_bytes() == $bytes, "expecting {:?}, found {:?}",
from_utf8($bytes), e.as_str());
assert!(e.name() == $bytes, "expecting {:?}, found {:?}",
from_utf8($bytes), e.content().as_str());
},
Some(Ok(e)) => {
assert!(false, "expecting {:?}, found {:?}",
Expand Down Expand Up @@ -151,8 +151,8 @@ fn test_write_attrs() {
let event = match event {
Start(elem) => {
let mut attrs = elem.attributes().map(|e| {
let (k,v) = e.unwrap();
(from_utf8(k).unwrap(), v)
let (k, v) = e.unwrap();
(k.as_str().unwrap(), v.as_str().unwrap())
}).collect::<Vec<_>>();
attrs.push(("a", "b"));
let mut elem = Element::new("copy");
Expand All @@ -174,8 +174,8 @@ fn test_map_starts() {
let mut r = XmlReader::from_str("<a><b>test</b>\
<b>test 2</b><c/><b>test 3</b></a>").trim_text(true);
let mut tests = Vec::new();
r.map_starts::<_, &str>(None, |r, e| match e.as_bytes() {
b"a" => r.map_starts(Some("a"), |r, e| match e.as_bytes() {
r.map_starts::<_, &str>(None, |r, e| match e.name() {
b"a" => r.map_starts(Some("a"), |r, e| match e.name() {
b"b" => r.read_text("b").map(|t| tests.push(t)),
name => r.read_to_end(name)
}),
Expand Down

0 comments on commit 44a245b

Please sign in to comment.