Skip to content

Commit

Permalink
Merge pull request #583 from pigeonhands/feature/entity-resolver
Browse files Browse the repository at this point in the history
Add EntityResolver to deserializer
  • Loading branch information
Mingun authored Apr 12, 2023
2 parents 9c60819 + 9b5e0e9 commit f8f0e4d
Show file tree
Hide file tree
Showing 9 changed files with 315 additions and 50 deletions.
8 changes: 8 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,20 @@

### New Features

- [#581]: Allow `Deserializer` to set `quick_xml::de::EntityResolver` for
resolving unknown entities that would otherwise cause the parser to return
an [`EscapeError::UnrecognizedSymbol`] error.

### Bug Fixes

### Misc Changes

- [#584]: Export `EscapeError` from the crate
- [#581]: Relax requirements for `unsescape_*` set of functions -- their now use
`FnMut` instead of `Fn` for `resolve_entity` parameters, like `Iterator::map`
from `std`.

[#581]: https://github.com/tafia/quick-xml/pull/581
[#584]: https://github.com/tafia/quick-xml/pull/584


Expand Down
47 changes: 30 additions & 17 deletions src/de/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use crate::{
de::key::QNameDeserializer,
de::resolver::EntityResolver,
de::simple_type::SimpleTypeDeserializer,
de::{str2bool, DeEvent, Deserializer, XmlRead, TEXT_KEY, VALUE_KEY},
encoding::Decoder,
Expand Down Expand Up @@ -165,13 +166,14 @@ enum ValueSource {
///
/// - `'a` lifetime represents a parent deserializer, which could own the data
/// buffer.
pub(crate) struct MapAccess<'de, 'a, R>
pub(crate) struct MapAccess<'de, 'a, R, E>
where
R: XmlRead<'de>,
E: EntityResolver,
{
/// Tag -- owner of attributes
start: BytesStart<'de>,
de: &'a mut Deserializer<'de, R>,
de: &'a mut Deserializer<'de, R, E>,
/// State of the iterator over attributes. Contains the next position in the
/// inner `start` slice, from which next attribute should be parsed.
iter: IterState,
Expand All @@ -190,13 +192,14 @@ where
has_value_field: bool,
}

impl<'de, 'a, R> MapAccess<'de, 'a, R>
impl<'de, 'a, R, E> MapAccess<'de, 'a, R, E>
where
R: XmlRead<'de>,
E: EntityResolver,
{
/// Create a new MapAccess
pub fn new(
de: &'a mut Deserializer<'de, R>,
de: &'a mut Deserializer<'de, R, E>,
start: BytesStart<'de>,
fields: &'static [&'static str],
) -> Result<Self, DeError> {
Expand All @@ -211,9 +214,10 @@ where
}
}

impl<'de, 'a, R> de::MapAccess<'de> for MapAccess<'de, 'a, R>
impl<'de, 'a, R, E> de::MapAccess<'de> for MapAccess<'de, 'a, R, E>
where
R: XmlRead<'de>,
E: EntityResolver,
{
type Error = DeError;

Expand Down Expand Up @@ -369,13 +373,14 @@ macro_rules! forward {
/// A deserializer for a value of map or struct. That deserializer slightly
/// differently processes events for a primitive types and sequences than
/// a [`Deserializer`].
struct MapValueDeserializer<'de, 'a, 'm, R>
struct MapValueDeserializer<'de, 'a, 'm, R, E>
where
R: XmlRead<'de>,
E: EntityResolver,
{
/// Access to the map that created this deserializer. Gives access to the
/// context, such as list of fields, that current map known about.
map: &'m mut MapAccess<'de, 'a, R>,
map: &'m mut MapAccess<'de, 'a, R, E>,
/// Determines, should [`Deserializer::read_string_impl()`] expand the second
/// level of tags or not.
///
Expand Down Expand Up @@ -453,9 +458,10 @@ where
allow_start: bool,
}

impl<'de, 'a, 'm, R> MapValueDeserializer<'de, 'a, 'm, R>
impl<'de, 'a, 'm, R, E> MapValueDeserializer<'de, 'a, 'm, R, E>
where
R: XmlRead<'de>,
E: EntityResolver,
{
/// Returns a next string as concatenated content of consequent [`Text`] and
/// [`CData`] events, used inside [`deserialize_primitives!()`].
Expand All @@ -468,9 +474,10 @@ where
}
}

impl<'de, 'a, 'm, R> de::Deserializer<'de> for MapValueDeserializer<'de, 'a, 'm, R>
impl<'de, 'a, 'm, R, E> de::Deserializer<'de> for MapValueDeserializer<'de, 'a, 'm, R, E>
where
R: XmlRead<'de>,
E: EntityResolver,
{
type Error = DeError;

Expand Down Expand Up @@ -629,13 +636,14 @@ impl<'de> TagFilter<'de> {
///
/// [`Text`]: crate::events::Event::Text
/// [`CData`]: crate::events::Event::CData
struct MapValueSeqAccess<'de, 'a, 'm, R>
struct MapValueSeqAccess<'de, 'a, 'm, R, E>
where
R: XmlRead<'de>,
E: EntityResolver,
{
/// Accessor to a map that creates this accessor and to a deserializer for
/// a sequence items.
map: &'m mut MapAccess<'de, 'a, R>,
map: &'m mut MapAccess<'de, 'a, R, E>,
/// Filter that determines whether a tag is a part of this sequence.
///
/// When feature `overlapped-lists` is not activated, iteration will stop
Expand All @@ -653,18 +661,20 @@ where
}

#[cfg(feature = "overlapped-lists")]
impl<'de, 'a, 'm, R> Drop for MapValueSeqAccess<'de, 'a, 'm, R>
impl<'de, 'a, 'm, R, E> Drop for MapValueSeqAccess<'de, 'a, 'm, R, E>
where
R: XmlRead<'de>,
E: EntityResolver,
{
fn drop(&mut self) {
self.map.de.start_replay(self.checkpoint);
}
}

impl<'de, 'a, 'm, R> SeqAccess<'de> for MapValueSeqAccess<'de, 'a, 'm, R>
impl<'de, 'a, 'm, R, E> SeqAccess<'de> for MapValueSeqAccess<'de, 'a, 'm, R, E>
where
R: XmlRead<'de>,
E: EntityResolver,
{
type Error = DeError;

Expand Down Expand Up @@ -705,18 +715,20 @@ where
////////////////////////////////////////////////////////////////////////////////////////////////////

/// A deserializer for a single item of a sequence.
struct SeqItemDeserializer<'de, 'a, 'm, R>
struct SeqItemDeserializer<'de, 'a, 'm, R, E>
where
R: XmlRead<'de>,
E: EntityResolver,
{
/// Access to the map that created this deserializer. Gives access to the
/// context, such as list of fields, that current map known about.
map: &'m mut MapAccess<'de, 'a, R>,
map: &'m mut MapAccess<'de, 'a, R, E>,
}

impl<'de, 'a, 'm, R> SeqItemDeserializer<'de, 'a, 'm, R>
impl<'de, 'a, 'm, R, E> SeqItemDeserializer<'de, 'a, 'm, R, E>
where
R: XmlRead<'de>,
E: EntityResolver,
{
/// Returns a next string as concatenated content of consequent [`Text`] and
/// [`CData`] events, used inside [`deserialize_primitives!()`].
Expand All @@ -729,9 +741,10 @@ where
}
}

impl<'de, 'a, 'm, R> de::Deserializer<'de> for SeqItemDeserializer<'de, 'a, 'm, R>
impl<'de, 'a, 'm, R, E> de::Deserializer<'de> for SeqItemDeserializer<'de, 'a, 'm, R, E>
where
R: XmlRead<'de>,
E: EntityResolver,
{
type Error = DeError;

Expand Down
Loading

0 comments on commit f8f0e4d

Please sign in to comment.