Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix double escape #96

Merged
merged 4 commits into from
Nov 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions src/events/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,22 +303,31 @@ pub struct BytesText<'a> {
}

impl<'a> BytesText<'a> {
/// Creates a new `BytesEnd` borrowing a slice
/// Creates a new `BytesText` borrowing a slice
#[inline]
pub fn borrowed(content: &'a [u8]) -> BytesText<'a> {
BytesText {
content: Cow::Borrowed(content),
}
}

/// Creates a new `BytesEnd` owning its name
/// Creates a new `BytesText` owning its name
#[inline]
pub fn owned(content: Vec<u8>) -> BytesText<'static> {
BytesText {
content: Cow::Owned(content),
}
}

/// Creates a new `BytesText` from text
#[inline]
pub fn from_str<S: AsRef<str>>(text: S) -> BytesText<'static> {
let bytes = escape(text.as_ref().as_bytes()).into_owned();
BytesText {
content: Cow::Owned(bytes),
}
}

/// gets escaped content
///
/// Searches for '&' into content and try to escape the coded character if possible
Expand All @@ -340,8 +349,8 @@ impl<'a> BytesText<'a> {
/// Gets escaped content
///
/// Searches for any of `<, >, &, ', "` and xml escapes them.
pub fn escaped(&self) -> Cow<[u8]> {
escape(self)
pub fn escaped(&self) -> &[u8] {
self.content.as_ref()
}
}

Expand Down
66 changes: 64 additions & 2 deletions tests/unit_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,33 @@ fn test_read_write_roundtrip_results_in_identity() {
assert_eq!(result, input.as_bytes());
}

#[test]
fn test_read_write_roundtrip() {
let input = r#"
<?xml version="1.0" encoding="UTF-8"?>
<section ns:label="header">
<section ns:label="empty element section" />
<section ns:label="start/end section"></section>
<section ns:label="with text">data &lt;escaped&gt;</section>
</section>
"#;

let mut reader = Reader::from_str(input);
reader.trim_text(false).expand_empty_elements(false);
let mut writer = Writer::new(Cursor::new(Vec::new()));
let mut buf = Vec::new();
loop {
match reader.read_event(&mut buf) {
Ok(Eof) => break,
Ok(e) => assert!(writer.write_event(e).is_ok()),
Err(e) => panic!(e),
}
}

let result = writer.into_inner().into_inner();
assert_eq!(String::from_utf8(result).unwrap(), input.to_string());
}

#[test]
fn test_read_write_roundtrip_escape() {
let input = r#"
Expand All @@ -615,10 +642,45 @@ fn test_read_write_roundtrip_escape() {
match reader.read_event(&mut buf) {
Ok(Eof) => break,
Ok(Text(e)) => {
let t = e.unescaped().unwrap();
let t = e.escaped();
assert!(
writer
.write_event(Event::Text(BytesText::owned(t.to_vec())))
.is_ok()
);
}
Ok(e) => assert!(writer.write_event(e).is_ok()),
Err(e) => panic!(e),
}
}

let result = writer.into_inner().into_inner();
assert_eq!(String::from_utf8(result).unwrap(), input.to_string());
}

#[test]
fn test_read_write_roundtrip_escape_text() {
let input = r#"
<?xml version="1.0" encoding="UTF-8"?>
<section ns:label="header">
<section ns:label="empty element section" />
<section ns:label="start/end section"></section>
<section ns:label="with text">data &lt;escaped&gt;</section>
</section>
"#;

let mut reader = Reader::from_str(input);
reader.trim_text(false).expand_empty_elements(false);
let mut writer = Writer::new(Cursor::new(Vec::new()));
let mut buf = Vec::new();
loop {
match reader.read_event(&mut buf) {
Ok(Eof) => break,
Ok(Text(e)) => {
let t = e.unescape_and_decode(&reader).unwrap();
assert!(
writer
.write_event(Event::Text(BytesText::borrowed(&t)))
.write_event(Event::Text(BytesText::from_str(t)))
.is_ok()
);
}
Expand Down