Skip to content

Commit f8f0e4d

Browse files
authored
Merge pull request #583 from pigeonhands/feature/entity-resolver
Add EntityResolver to deserializer
2 parents 9c60819 + 9b5e0e9 commit f8f0e4d

File tree

9 files changed

+315
-50
lines changed

9 files changed

+315
-50
lines changed

Changelog.md

+8
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,20 @@
1212

1313
### New Features
1414

15+
- [#581]: Allow `Deserializer` to set `quick_xml::de::EntityResolver` for
16+
resolving unknown entities that would otherwise cause the parser to return
17+
an [`EscapeError::UnrecognizedSymbol`] error.
18+
1519
### Bug Fixes
1620

1721
### Misc Changes
1822

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

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

2331

src/de/map.rs

+30-17
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use crate::{
44
de::key::QNameDeserializer,
5+
de::resolver::EntityResolver,
56
de::simple_type::SimpleTypeDeserializer,
67
de::{str2bool, DeEvent, Deserializer, XmlRead, TEXT_KEY, VALUE_KEY},
78
encoding::Decoder,
@@ -165,13 +166,14 @@ enum ValueSource {
165166
///
166167
/// - `'a` lifetime represents a parent deserializer, which could own the data
167168
/// buffer.
168-
pub(crate) struct MapAccess<'de, 'a, R>
169+
pub(crate) struct MapAccess<'de, 'a, R, E>
169170
where
170171
R: XmlRead<'de>,
172+
E: EntityResolver,
171173
{
172174
/// Tag -- owner of attributes
173175
start: BytesStart<'de>,
174-
de: &'a mut Deserializer<'de, R>,
176+
de: &'a mut Deserializer<'de, R, E>,
175177
/// State of the iterator over attributes. Contains the next position in the
176178
/// inner `start` slice, from which next attribute should be parsed.
177179
iter: IterState,
@@ -190,13 +192,14 @@ where
190192
has_value_field: bool,
191193
}
192194

193-
impl<'de, 'a, R> MapAccess<'de, 'a, R>
195+
impl<'de, 'a, R, E> MapAccess<'de, 'a, R, E>
194196
where
195197
R: XmlRead<'de>,
198+
E: EntityResolver,
196199
{
197200
/// Create a new MapAccess
198201
pub fn new(
199-
de: &'a mut Deserializer<'de, R>,
202+
de: &'a mut Deserializer<'de, R, E>,
200203
start: BytesStart<'de>,
201204
fields: &'static [&'static str],
202205
) -> Result<Self, DeError> {
@@ -211,9 +214,10 @@ where
211214
}
212215
}
213216

214-
impl<'de, 'a, R> de::MapAccess<'de> for MapAccess<'de, 'a, R>
217+
impl<'de, 'a, R, E> de::MapAccess<'de> for MapAccess<'de, 'a, R, E>
215218
where
216219
R: XmlRead<'de>,
220+
E: EntityResolver,
217221
{
218222
type Error = DeError;
219223

@@ -369,13 +373,14 @@ macro_rules! forward {
369373
/// A deserializer for a value of map or struct. That deserializer slightly
370374
/// differently processes events for a primitive types and sequences than
371375
/// a [`Deserializer`].
372-
struct MapValueDeserializer<'de, 'a, 'm, R>
376+
struct MapValueDeserializer<'de, 'a, 'm, R, E>
373377
where
374378
R: XmlRead<'de>,
379+
E: EntityResolver,
375380
{
376381
/// Access to the map that created this deserializer. Gives access to the
377382
/// context, such as list of fields, that current map known about.
378-
map: &'m mut MapAccess<'de, 'a, R>,
383+
map: &'m mut MapAccess<'de, 'a, R, E>,
379384
/// Determines, should [`Deserializer::read_string_impl()`] expand the second
380385
/// level of tags or not.
381386
///
@@ -453,9 +458,10 @@ where
453458
allow_start: bool,
454459
}
455460

456-
impl<'de, 'a, 'm, R> MapValueDeserializer<'de, 'a, 'm, R>
461+
impl<'de, 'a, 'm, R, E> MapValueDeserializer<'de, 'a, 'm, R, E>
457462
where
458463
R: XmlRead<'de>,
464+
E: EntityResolver,
459465
{
460466
/// Returns a next string as concatenated content of consequent [`Text`] and
461467
/// [`CData`] events, used inside [`deserialize_primitives!()`].
@@ -468,9 +474,10 @@ where
468474
}
469475
}
470476

471-
impl<'de, 'a, 'm, R> de::Deserializer<'de> for MapValueDeserializer<'de, 'a, 'm, R>
477+
impl<'de, 'a, 'm, R, E> de::Deserializer<'de> for MapValueDeserializer<'de, 'a, 'm, R, E>
472478
where
473479
R: XmlRead<'de>,
480+
E: EntityResolver,
474481
{
475482
type Error = DeError;
476483

@@ -629,13 +636,14 @@ impl<'de> TagFilter<'de> {
629636
///
630637
/// [`Text`]: crate::events::Event::Text
631638
/// [`CData`]: crate::events::Event::CData
632-
struct MapValueSeqAccess<'de, 'a, 'm, R>
639+
struct MapValueSeqAccess<'de, 'a, 'm, R, E>
633640
where
634641
R: XmlRead<'de>,
642+
E: EntityResolver,
635643
{
636644
/// Accessor to a map that creates this accessor and to a deserializer for
637645
/// a sequence items.
638-
map: &'m mut MapAccess<'de, 'a, R>,
646+
map: &'m mut MapAccess<'de, 'a, R, E>,
639647
/// Filter that determines whether a tag is a part of this sequence.
640648
///
641649
/// When feature `overlapped-lists` is not activated, iteration will stop
@@ -653,18 +661,20 @@ where
653661
}
654662

655663
#[cfg(feature = "overlapped-lists")]
656-
impl<'de, 'a, 'm, R> Drop for MapValueSeqAccess<'de, 'a, 'm, R>
664+
impl<'de, 'a, 'm, R, E> Drop for MapValueSeqAccess<'de, 'a, 'm, R, E>
657665
where
658666
R: XmlRead<'de>,
667+
E: EntityResolver,
659668
{
660669
fn drop(&mut self) {
661670
self.map.de.start_replay(self.checkpoint);
662671
}
663672
}
664673

665-
impl<'de, 'a, 'm, R> SeqAccess<'de> for MapValueSeqAccess<'de, 'a, 'm, R>
674+
impl<'de, 'a, 'm, R, E> SeqAccess<'de> for MapValueSeqAccess<'de, 'a, 'm, R, E>
666675
where
667676
R: XmlRead<'de>,
677+
E: EntityResolver,
668678
{
669679
type Error = DeError;
670680

@@ -705,18 +715,20 @@ where
705715
////////////////////////////////////////////////////////////////////////////////////////////////////
706716

707717
/// A deserializer for a single item of a sequence.
708-
struct SeqItemDeserializer<'de, 'a, 'm, R>
718+
struct SeqItemDeserializer<'de, 'a, 'm, R, E>
709719
where
710720
R: XmlRead<'de>,
721+
E: EntityResolver,
711722
{
712723
/// Access to the map that created this deserializer. Gives access to the
713724
/// context, such as list of fields, that current map known about.
714-
map: &'m mut MapAccess<'de, 'a, R>,
725+
map: &'m mut MapAccess<'de, 'a, R, E>,
715726
}
716727

717-
impl<'de, 'a, 'm, R> SeqItemDeserializer<'de, 'a, 'm, R>
728+
impl<'de, 'a, 'm, R, E> SeqItemDeserializer<'de, 'a, 'm, R, E>
718729
where
719730
R: XmlRead<'de>,
731+
E: EntityResolver,
720732
{
721733
/// Returns a next string as concatenated content of consequent [`Text`] and
722734
/// [`CData`] events, used inside [`deserialize_primitives!()`].
@@ -729,9 +741,10 @@ where
729741
}
730742
}
731743

732-
impl<'de, 'a, 'm, R> de::Deserializer<'de> for SeqItemDeserializer<'de, 'a, 'm, R>
744+
impl<'de, 'a, 'm, R, E> de::Deserializer<'de> for SeqItemDeserializer<'de, 'a, 'm, R, E>
733745
where
734746
R: XmlRead<'de>,
747+
E: EntityResolver,
735748
{
736749
type Error = DeError;
737750

0 commit comments

Comments
 (0)