Skip to content
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
1 change: 0 additions & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ jobs:
- name: Build
run: cargo build
- name: Run tests (no features)
run: cargo test
run: cargo test --no-default-features
- name: Run tests (serialize)
run: cargo test --features serialize
Expand Down
18 changes: 16 additions & 2 deletions src/de/map.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
//! Serde `Deserializer` module

use crate::{
de::{escape::EscapedDeserializer, BorrowingReader, Deserializer, INNER_VALUE},
de::{
escape::EscapedDeserializer, BorrowingReader, Deserializer, INNER_VALUE, UNFLATTEN_PREFIX,
},
errors::serialize::DeError,
events::{BytesStart, Event},
};
use serde::de::{self, DeserializeSeed, IntoDeserializer};

enum MapValue {
Empty,
Attribute { value: Vec<u8> },
/// Value should be deserialized from the attribute value
Attribute {
value: Vec<u8>,
},
Nested,
/// Value should be deserialized from the text content of the XML node:
///
/// ```xml
/// <...>text content for field value<...>
/// ```
InnerValue,
}

Expand Down Expand Up @@ -58,6 +68,7 @@ impl<'de, 'a, R: BorrowingReader<'de> + 'a> de::MapAccess<'de> for MapAccess<'de
) -> Result<Option<K::Value>, Self::Error> {
let decoder = self.de.reader.decoder();
let has_value_field = self.de.has_value_field;
let has_unflatten_field = self.de.has_unflatten_field;
if let Some((key, value)) = self.next_attr()? {
// try getting map from attributes (key= "value")
self.value = MapValue::Attribute { value };
Expand All @@ -68,6 +79,9 @@ impl<'de, 'a, R: BorrowingReader<'de> + 'a> de::MapAccess<'de> for MapAccess<'de
match self.de.peek()? {
Some(Event::Text(_)) => {
self.value = MapValue::InnerValue;
// Deserialize `key` from special attribute name which means
// that value should be taken from the text content of the
// XML node
seed.deserialize(INNER_VALUE.into_deserializer()).map(Some)
}
// Used to deserialize collections of enums, like:
Expand Down
9 changes: 8 additions & 1 deletion src/de/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,13 @@ pub(crate) const UNFLATTEN_PREFIX: &str = "$unflatten=";
pub struct Deserializer<'de, R: BorrowingReader<'de>> {
reader: R,
peek: Option<Event<'de>>,
/// Special sing that deserialized struct have a field with the special
/// name (see constant `INNER_VALUE`). That field should be deserialized
/// from the text content of the XML node:
///
/// ```xml
/// <tag>value for INNER_VALUE field<tag>
/// ```
has_value_field: bool,
has_unflatten_field: bool,
}
Expand Down Expand Up @@ -282,6 +289,7 @@ impl<'de, 'a, R: BorrowingReader<'de>> de::Deserializer<'de> for &'a mut Deseria
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, DeError> {
// Try to go to the next `<tag ...>...</tag>` or `<tag .../>`
if let Some(e) = self.next_start()? {
let name = e.name().to_vec();
self.has_value_field = fields.contains(&INNER_VALUE);
Expand Down Expand Up @@ -318,7 +326,6 @@ impl<'de, 'a, R: BorrowingReader<'de>> de::Deserializer<'de> for &'a mut Deseria

#[cfg(feature = "encoding")]
{
#[cfg(feature = "encoding")]
let value = self.reader.decoder().decode(&*txt);

match value.as_ref() {
Expand Down
22 changes: 11 additions & 11 deletions src/events/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,14 +349,14 @@ impl<'a> Iterator for Attributes<'a> {
if self.html {
attr!($key, 0..0)
} else {
return None;
};
None
}
}};
($key:expr, $val:expr) => {
return Some(Ok(Attribute {
Some(Ok(Attribute {
key: &self.bytes[$key],
value: Cow::Borrowed(&self.bytes[$val]),
}));
}))
};
}

Expand All @@ -373,7 +373,7 @@ impl<'a> Iterator for Attributes<'a> {
.find(|&(_, &b)| !is_whitespace(b))
{
Some((i, _)) => i,
None => attr!(self.position..len),
None => return attr!(self.position..len),
};

// key ends with either whitespace or =
Expand All @@ -391,17 +391,17 @@ impl<'a> Iterator for Attributes<'a> {
Some((_, &b'=')) => i,
Some((j, _)) if self.html => {
self.position = j - 1;
attr!(start_key..i, 0..0);
return attr!(start_key..i, 0..0);
}
Some((j, _)) => err!(Error::NoEqAfterName(j)),
None if self.html => {
self.position = len;
attr!(start_key..len, 0..0);
return attr!(start_key..len, 0..0);
}
None => err!(Error::NoEqAfterName(len)),
}
}
None => attr!(start_key..len),
None => return attr!(start_key..len),
};

if self.with_checks {
Expand All @@ -423,7 +423,7 @@ impl<'a> Iterator for Attributes<'a> {
match bytes.by_ref().find(|&(_, &b)| b == *quote) {
Some((j, _)) => {
self.position = j + 1;
attr!(start_key..end_key, i + 1..j)
return attr!(start_key..end_key, i + 1..j);
}
None => err!(Error::UnquotedValue(i)),
}
Expand All @@ -434,10 +434,10 @@ impl<'a> Iterator for Attributes<'a> {
.find(|&(_, &b)| is_whitespace(b))
.map_or(len, |(j, _)| j);
self.position = j;
attr!(start_key..end_key, i..j)
return attr!(start_key..end_key, i..j);
}
Some((i, _)) => err!(Error::UnquotedValue(i)),
None => attr!(start_key..end_key),
None => return attr!(start_key..end_key),
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/se/var.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::{
de::{INNER_VALUE, UNFLATTEN_PREFIX},
errors::{serialize::DeError, Error},
events::{BytesEnd, BytesStart, Event},
se::Serializer,
writer::Writer,
};
use de::{INNER_VALUE, UNFLATTEN_PREFIX};
use serde::ser::{self, Serialize, SerializeMap};
use serde::ser::{self, Serialize};
use serde::Serializer as _;
use std::io::Write;

Expand Down Expand Up @@ -127,7 +127,7 @@ where
if key.starts_with(UNFLATTEN_PREFIX) {
let key = key.split_at(UNFLATTEN_PREFIX.len()).1;
let mut serializer = Serializer::with_root(writer, Some(key));
serializer.serialize_newtype_struct(key, value);
serializer.serialize_newtype_struct(key, value)?;
self.children.append(&mut self.buffer);
} else {
let mut serializer = Serializer::with_root(writer, Some(key));
Expand Down
8 changes: 4 additions & 4 deletions tests/xmlrs_reader_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ fn sample_2_full() {
#[ignore]
fn html5() {
test(
include_bytes!("documents/html5.html"),
include_bytes!("documents/html5.txt"),
include_str!("documents/html5.html"),
include_str!("documents/html5.txt"),
false,
);
}
Expand All @@ -65,8 +65,8 @@ fn html5() {
#[ignore]
fn html5() {
test(
include_bytes!("documents/html5.html"),
include_bytes!("documents/html5-windows.txt"),
include_str!("documents/html5.html"),
include_str!("documents/html5-windows.txt"),
false,
);
}
Expand Down