Skip to content

Commit a19d4a1

Browse files
authored
Merge pull request #882 from xdm67x/master
feat: Create a `Deserializer` from a custom `NsReader`
2 parents 1fdcadc + c98671c commit a19d4a1

File tree

2 files changed

+121
-7
lines changed

2 files changed

+121
-7
lines changed

Changelog.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,18 @@
1515

1616
### New Features
1717

18+
- [#882]: Add new methods to create `Deserializer` from existing `NsReader`:
19+
- `Deserializer::borrowing`
20+
- `Deserializer::borrowing_with_resolver`
21+
- `Deserializer::buffering`
22+
- `Deserializer::buffering_with_resolver`
23+
1824
### Bug Fixes
1925

2026
### Misc Changes
2127

28+
[#882]: https://github.com/tafia/quick-xml/pull/882
29+
2230

2331
## 0.38.0 -- 2025-06-28
2432

src/de/mod.rs

Lines changed: 113 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2987,23 +2987,71 @@ where
29872987
}
29882988

29892989
impl<'de> Deserializer<'de, SliceReader<'de>> {
2990-
/// Create new deserializer that will borrow data from the specified string.
2990+
/// Create a new deserializer that will borrow data from the specified string.
29912991
///
29922992
/// Deserializer created with this method will not resolve custom entities.
29932993
#[allow(clippy::should_implement_trait)]
29942994
pub fn from_str(source: &'de str) -> Self {
29952995
Self::from_str_with_resolver(source, PredefinedEntityResolver)
29962996
}
2997+
2998+
/// Create a new deserializer that will borrow data from the specified preconfigured
2999+
/// reader.
3000+
///
3001+
/// Deserializer created with this method will not resolve custom entities.
3002+
///
3003+
/// Note, that config option [`Config::expand_empty_elements`] will be set to `true`.
3004+
///
3005+
/// # Example
3006+
///
3007+
/// ```
3008+
/// # use pretty_assertions::assert_eq;
3009+
/// # use quick_xml::de::Deserializer;
3010+
/// # use quick_xml::NsReader;
3011+
/// # use serde::Deserialize;
3012+
/// #
3013+
/// #[derive(Deserialize, PartialEq, Debug)]
3014+
/// struct Object<'a> {
3015+
/// tag: &'a str,
3016+
/// }
3017+
///
3018+
/// let mut reader = NsReader::from_str("<xml><tag> test </tag></xml>");
3019+
///
3020+
/// let mut de = Deserializer::borrowing(reader.clone());
3021+
/// let obj = Object::deserialize(&mut de).unwrap();
3022+
/// assert_eq!(obj, Object { tag: " test " });
3023+
///
3024+
/// reader.config_mut().trim_text(true);
3025+
///
3026+
/// let mut de = Deserializer::borrowing(reader);
3027+
/// let obj = Object::deserialize(&mut de).unwrap();
3028+
/// assert_eq!(obj, Object { tag: "test" });
3029+
/// ```
3030+
///
3031+
/// [`Config::expand_empty_elements`]: crate::reader::Config::expand_empty_elements
3032+
#[inline]
3033+
pub fn borrowing(reader: NsReader<&'de [u8]>) -> Self {
3034+
Self::borrowing_with_resolver(reader, PredefinedEntityResolver)
3035+
}
29973036
}
29983037

29993038
impl<'de, E> Deserializer<'de, SliceReader<'de>, E>
30003039
where
30013040
E: EntityResolver,
30023041
{
3003-
/// Create new deserializer that will borrow data from the specified string
3004-
/// and use specified entity resolver.
3042+
/// Create a new deserializer that will borrow data from the specified string
3043+
/// and use the specified entity resolver.
30053044
pub fn from_str_with_resolver(source: &'de str, entity_resolver: E) -> Self {
3006-
let mut reader = NsReader::from_str(source);
3045+
Self::borrowing_with_resolver(NsReader::from_str(source), entity_resolver)
3046+
}
3047+
3048+
/// Create a new deserializer that will borrow data from the specified preconfigured
3049+
/// reader and use the specified entity resolver.
3050+
///
3051+
/// Note, that config option [`Config::expand_empty_elements`] will be set to `true`.
3052+
///
3053+
/// [`Config::expand_empty_elements`]: crate::reader::Config::expand_empty_elements
3054+
pub fn borrowing_with_resolver(mut reader: NsReader<&'de [u8]>, entity_resolver: E) -> Self {
30073055
let config = reader.config_mut();
30083056
config.expand_empty_elements = true;
30093057

@@ -3015,7 +3063,7 @@ impl<'de, R> Deserializer<'de, IoReader<R>>
30153063
where
30163064
R: BufRead,
30173065
{
3018-
/// Create new deserializer that will copy data from the specified reader
3066+
/// Create a new deserializer that will copy data from the specified reader
30193067
/// into internal buffer.
30203068
///
30213069
/// If you already have a string use [`Self::from_str`] instead, because it
@@ -3026,15 +3074,54 @@ where
30263074
pub fn from_reader(reader: R) -> Self {
30273075
Self::with_resolver(reader, PredefinedEntityResolver)
30283076
}
3077+
3078+
/// Create a new deserializer that will copy data from the specified preconfigured
3079+
/// reader into internal buffer.
3080+
///
3081+
/// Deserializer created with this method will not resolve custom entities.
3082+
///
3083+
/// Note, that config option [`Config::expand_empty_elements`] will be set to `true`.
3084+
///
3085+
/// # Example
3086+
///
3087+
/// ```
3088+
/// # use pretty_assertions::assert_eq;
3089+
/// # use quick_xml::de::Deserializer;
3090+
/// # use quick_xml::NsReader;
3091+
/// # use serde::Deserialize;
3092+
/// #
3093+
/// #[derive(Deserialize, PartialEq, Debug)]
3094+
/// struct Object {
3095+
/// tag: String,
3096+
/// }
3097+
///
3098+
/// let mut reader = NsReader::from_str("<xml><tag> test </tag></xml>");
3099+
///
3100+
/// let mut de = Deserializer::buffering(reader.clone());
3101+
/// let obj = Object::deserialize(&mut de).unwrap();
3102+
/// assert_eq!(obj, Object { tag: " test ".to_string() });
3103+
///
3104+
/// reader.config_mut().trim_text(true);
3105+
///
3106+
/// let mut de = Deserializer::buffering(reader);
3107+
/// let obj = Object::deserialize(&mut de).unwrap();
3108+
/// assert_eq!(obj, Object { tag: "test".to_string() });
3109+
/// ```
3110+
///
3111+
/// [`Config::expand_empty_elements`]: crate::reader::Config::expand_empty_elements
3112+
#[inline]
3113+
pub fn buffering(reader: NsReader<R>) -> Self {
3114+
Self::buffering_with_resolver(reader, PredefinedEntityResolver)
3115+
}
30293116
}
30303117

30313118
impl<'de, R, E> Deserializer<'de, IoReader<R>, E>
30323119
where
30333120
R: BufRead,
30343121
E: EntityResolver,
30353122
{
3036-
/// Create new deserializer that will copy data from the specified reader
3037-
/// into internal buffer and use specified entity resolver.
3123+
/// Create a new deserializer that will copy data from the specified reader
3124+
/// into internal buffer and use the specified entity resolver.
30383125
///
30393126
/// If you already have a string use [`Self::from_str`] instead, because it
30403127
/// will borrow instead of copy. If you have `&[u8]` which is known to represent
@@ -3052,6 +3139,25 @@ where
30523139
entity_resolver,
30533140
)
30543141
}
3142+
3143+
/// Create new deserializer that will copy data from the specified preconfigured reader
3144+
/// into internal buffer and use the specified entity resolver.
3145+
///
3146+
/// Note, that config option [`Config::expand_empty_elements`] will be set to `true`.
3147+
///
3148+
/// [`Config::expand_empty_elements`]: crate::reader::Config::expand_empty_elements
3149+
pub fn buffering_with_resolver(mut reader: NsReader<R>, entity_resolver: E) -> Self {
3150+
let config = reader.config_mut();
3151+
config.expand_empty_elements = true;
3152+
3153+
Self::new(
3154+
IoReader {
3155+
reader,
3156+
buf: Vec::new(),
3157+
},
3158+
entity_resolver,
3159+
)
3160+
}
30553161
}
30563162

30573163
impl<'de, 'a, R, E> de::Deserializer<'de> for &'a mut Deserializer<'de, R, E>

0 commit comments

Comments
 (0)