Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
20 changes: 13 additions & 7 deletions src/de/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use serde::forward_to_deserialize_any;

use crate::de::key::QNameDeserializer;
use crate::de::SimpleTypeDeserializer;
use crate::de::{EntityResolver, PredefinedEntityResolver};
use crate::errors::serialize::DeError;
use crate::events::attributes::Attributes;
use crate::XmlVersion;
Expand All @@ -25,6 +26,7 @@ impl<'i> Attributes<'i> {
/// ```
/// # use pretty_assertions::assert_eq;
/// use quick_xml::events::BytesStart;
/// use quick_xml::de::PredefinedEntityResolver;
/// use quick_xml::XmlVersion;
/// use serde::Deserialize;
///
Expand All @@ -47,7 +49,7 @@ impl<'i> Attributes<'i> {
/// 3
/// );
/// // Strip nothing from the field names
/// let de = tag.attributes().clone().into_map_access(XmlVersion::V1_0, "");
/// let de = tag.attributes().clone().into_map_access(XmlVersion::V1_0, "", &PredefinedEntityResolver);
/// assert_eq!(
/// MyData::deserialize(de).unwrap(),
/// MyData {
Expand All @@ -57,7 +59,7 @@ impl<'i> Attributes<'i> {
/// );
///
/// // Strip "@" from the field name
/// let de = tag.attributes().into_map_access(XmlVersion::V1_0, "@");
/// let de = tag.attributes().into_map_access(XmlVersion::V1_0, "@", &PredefinedEntityResolver);
/// assert_eq!(
/// MyDataPrefixed::deserialize(de).unwrap(),
/// MyDataPrefixed {
Expand All @@ -67,17 +69,19 @@ impl<'i> Attributes<'i> {
/// );
/// ```
#[inline]
pub const fn into_map_access(
pub const fn into_map_access<E: EntityResolver>(
self,
version: XmlVersion,
prefix: &'static str,
) -> AttributesDeserializer<'i> {
entity_resolver: &'i E,
) -> AttributesDeserializer<'i, E> {
AttributesDeserializer {
iter: self,
value: None,
prefix,
key_buf: String::new(),
version,
entity_resolver,
}
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably

impl AttributesDeserializer {
  fn with_resolver<E: EntityResolver>(self, resolver) -> AttributesDeserializer<E> {
    // replace entity_resolver with new one
  }
}

would be more practical, because I think, in most cases PredefinedEntityResolver will be used. So if you need use specific resolver, you may write a chain:

attributes.into_map_access("@").with_resolver(my_resolver)

}
Expand All @@ -96,7 +100,7 @@ impl<'i> Attributes<'i> {
/// In particular, when reader was created from a string, this is lifetime of the
/// string.
#[derive(Debug, Clone)]
pub struct AttributesDeserializer<'i> {
pub struct AttributesDeserializer<'i, E: EntityResolver = PredefinedEntityResolver> {
iter: Attributes<'i>,
/// The value of the attribute, read in last call to `next_key_seed`.
value: Option<Cow<'i, [u8]>>,
Expand All @@ -106,9 +110,10 @@ pub struct AttributesDeserializer<'i> {
/// Kept in the deserializer to avoid many small allocations
key_buf: String,
version: XmlVersion,
entity_resolver: &'i E,
}

impl<'de> Deserializer<'de> for AttributesDeserializer<'de> {
impl<'de, E: EntityResolver> Deserializer<'de> for AttributesDeserializer<'de, E> {
type Error = DeError;

#[inline]
Expand All @@ -126,7 +131,7 @@ impl<'de> Deserializer<'de> for AttributesDeserializer<'de> {
}
}

impl<'de> MapAccess<'de> for AttributesDeserializer<'de> {
impl<'de, E: EntityResolver> MapAccess<'de> for AttributesDeserializer<'de, E> {
type Error = DeError;

fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
Expand Down Expand Up @@ -160,6 +165,7 @@ impl<'de> MapAccess<'de> for AttributesDeserializer<'de> {
0..value.len(),
self.version,
self.iter.decoder(),
self.entity_resolver,
);
seed.deserialize(de)
}
Expand Down
40 changes: 29 additions & 11 deletions src/de/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ where
value,
self.de.reader.reader.xml_version(),
self.start.decoder(),
&self.de.reader.entity_resolver,
)),
// This arm processes the following XML shape:
// <any-tag>
Expand All @@ -357,7 +358,10 @@ where
// is a `Text` event (the value deserializer will see that event)
// This case are checked by "xml_schema_lists::element" tests in tests/serde-de.rs
ValueSource::Text => match self.de.next()? {
DeEvent::Text(e) => seed.deserialize(SimpleTypeDeserializer::from_text_content(e)),
DeEvent::Text(e) => seed.deserialize(SimpleTypeDeserializer::from_text_content(
e,
&self.de.reader.entity_resolver,
)),
// SAFETY: We set `Text` only when we seen `Text`
_ => unreachable!(),
},
Expand Down Expand Up @@ -555,7 +559,7 @@ where
{
type Error = DeError;

deserialize_primitives!(mut);
deserialize_primitives!(self in &self.map.de.reader.entity_resolver, mut);

#[inline]
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
Expand Down Expand Up @@ -659,9 +663,15 @@ where
let text = self.map.de.read_text(e.name())?;
if text.is_empty() {
// Map empty text (<field/>) to a special `$text` variant
visitor.visit_enum(SimpleTypeDeserializer::from_text(TEXT_KEY.into()))
visitor.visit_enum(SimpleTypeDeserializer::from_text(
TEXT_KEY.into(),
&self.map.de.reader.entity_resolver,
))
} else {
visitor.visit_enum(SimpleTypeDeserializer::from_text(text))
visitor.visit_enum(SimpleTypeDeserializer::from_text(
text,
&self.map.de.reader.entity_resolver,
))
}
}
// SAFETY: we use that deserializer with `fixed_name == true`
Expand Down Expand Up @@ -754,7 +764,10 @@ where
{
if self.is_text {
match self.map.de.next()? {
DeEvent::Text(e) => seed.deserialize(SimpleTypeDeserializer::from_text_content(e)),
DeEvent::Text(e) => seed.deserialize(SimpleTypeDeserializer::from_text_content(
e,
&self.map.de.reader.entity_resolver,
)),
// SAFETY: the other events are filtered in `variant_seed()`
_ => unreachable!("Only `Text` events are possible here"),
}
Expand All @@ -774,9 +787,11 @@ where
{
if self.is_text {
match self.map.de.next()? {
DeEvent::Text(e) => {
SimpleTypeDeserializer::from_text_content(e).deserialize_tuple(len, visitor)
}
DeEvent::Text(e) => SimpleTypeDeserializer::from_text_content(
e,
&self.map.de.reader.entity_resolver,
)
.deserialize_tuple(len, visitor),
// SAFETY: the other events are filtered in `variant_seed()`
_ => unreachable!("Only `Text` events are possible here"),
}
Expand All @@ -802,7 +817,8 @@ where
match self.map.de.next()? {
DeEvent::Start(e) => visitor.visit_map(ElementMapAccess::new(self.map.de, e, fields)),
DeEvent::Text(e) => {
SimpleTypeDeserializer::from_text_content(e).deserialize_struct("", fields, visitor)
SimpleTypeDeserializer::from_text_content(e, &self.map.de.reader.entity_resolver)
.deserialize_struct("", fields, visitor)
}
// SAFETY: the other events are filtered in `variant_seed()`
_ => unreachable!("Only `Start` or `Text` events are possible here"),
Expand Down Expand Up @@ -951,6 +967,7 @@ where
{
type Error = DeError;

#[cfg_attr(not(feature = "overlapped-lists"), allow(clippy::never_loop))]
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, DeError>
where
T: DeserializeSeed<'de>,
Expand Down Expand Up @@ -1083,7 +1100,7 @@ where
{
type Error = DeError;

deserialize_primitives!(mut);
deserialize_primitives!(self in &self.de.reader.entity_resolver, mut);

fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
Expand Down Expand Up @@ -1131,7 +1148,8 @@ where
V: Visitor<'de>,
{
let text = self.read_string()?;
SimpleTypeDeserializer::from_text(text).deserialize_seq(visitor)
SimpleTypeDeserializer::from_text(text, &self.de.reader.entity_resolver)
.deserialize_seq(visitor)
}

fn deserialize_struct<V>(
Expand Down
42 changes: 21 additions & 21 deletions src/de/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1974,42 +1974,42 @@
//! [`impl_deserialize_for_internally_tagged_enum!`]: crate::impl_deserialize_for_internally_tagged_enum

macro_rules! forward_to_simple_type {
($deserialize:ident, $($mut:tt)?) => {
($deserialize:ident, $self:ident in $resolver:expr $(, $mut:tt)?) => {
#[inline]
fn $deserialize<V>($($mut)? self, visitor: V) -> Result<V::Value, DeError>
fn $deserialize<V>($($mut)? $self, visitor: V) -> Result<V::Value, DeError>
where
V: Visitor<'de>,
{
SimpleTypeDeserializer::from_text(self.read_string()?).$deserialize(visitor)
SimpleTypeDeserializer::from_text($self.read_string()?, $resolver).$deserialize(visitor)
}
};
}

/// Implement deserialization methods for scalar types, such as numbers, strings,
/// byte arrays, booleans and identifiers.
macro_rules! deserialize_primitives {
($($mut:tt)?) => {
forward_to_simple_type!(deserialize_i8, $($mut)?);
forward_to_simple_type!(deserialize_i16, $($mut)?);
forward_to_simple_type!(deserialize_i32, $($mut)?);
forward_to_simple_type!(deserialize_i64, $($mut)?);
($self:ident in $resolver:expr $(, $mut:tt)?) => {
forward_to_simple_type!(deserialize_i8, $self in $resolver $(, $mut)?);
forward_to_simple_type!(deserialize_i16, $self in $resolver $(, $mut)?);
forward_to_simple_type!(deserialize_i32, $self in $resolver $(, $mut)?);
forward_to_simple_type!(deserialize_i64, $self in $resolver $(, $mut)?);

forward_to_simple_type!(deserialize_u8, $($mut)?);
forward_to_simple_type!(deserialize_u16, $($mut)?);
forward_to_simple_type!(deserialize_u32, $($mut)?);
forward_to_simple_type!(deserialize_u64, $($mut)?);
forward_to_simple_type!(deserialize_u8, $self in $resolver $(, $mut)?);
forward_to_simple_type!(deserialize_u16, $self in $resolver $(, $mut)?);
forward_to_simple_type!(deserialize_u32, $self in $resolver $(, $mut)?);
forward_to_simple_type!(deserialize_u64, $self in $resolver $(, $mut)?);

forward_to_simple_type!(deserialize_i128, $($mut)?);
forward_to_simple_type!(deserialize_u128, $($mut)?);
forward_to_simple_type!(deserialize_i128, $self in $resolver $(, $mut)?);
forward_to_simple_type!(deserialize_u128, $self in $resolver $(, $mut)?);

forward_to_simple_type!(deserialize_f32, $($mut)?);
forward_to_simple_type!(deserialize_f64, $($mut)?);
forward_to_simple_type!(deserialize_f32, $self in $resolver $(, $mut)?);
forward_to_simple_type!(deserialize_f64, $self in $resolver $(, $mut)?);

forward_to_simple_type!(deserialize_bool, $($mut)?);
forward_to_simple_type!(deserialize_char, $($mut)?);
forward_to_simple_type!(deserialize_bool, $self in $resolver $(, $mut)?);
forward_to_simple_type!(deserialize_char, $self in $resolver $(, $mut)?);

forward_to_simple_type!(deserialize_str, $($mut)?);
forward_to_simple_type!(deserialize_string, $($mut)?);
forward_to_simple_type!(deserialize_str, $self in $resolver $(, $mut)?);
forward_to_simple_type!(deserialize_string, $self in $resolver $(, $mut)?);

/// Forwards deserialization to the [`deserialize_any`](#method.deserialize_any).
#[inline]
Expand Down Expand Up @@ -3195,7 +3195,7 @@ where
{
type Error = DeError;

deserialize_primitives!();
deserialize_primitives!(self in &self.reader.entity_resolver);

fn deserialize_struct<V>(
self,
Expand Down
Loading