Skip to main content

oxixml_xml/de/
xml_read.rs

1//! The [`XmlRead`] abstraction over borrowing and copying XML input sources.
2
3use std::io::BufRead;
4
5use crate::XmlVersion;
6use crate::de::event::PayloadEvent;
7use crate::encoding::Decoder;
8use crate::errors::serialize::DeError;
9use crate::events::{BytesStart, Event};
10use crate::name::QName;
11use crate::reader::NsReader;
12
13////////////////////////////////////////////////////////////////////////////////////////////////////
14
15/// Converts raw reader's event into a payload event.
16/// Returns `None`, if event should be skipped.
17#[inline(always)]
18fn skip_uninterested<'a>(event: Event<'a>) -> Option<PayloadEvent<'a>> {
19    let event = match event {
20        Event::DocType(e) => PayloadEvent::DocType(e),
21        Event::Start(e) => PayloadEvent::Start(e),
22        Event::End(e) => PayloadEvent::End(e),
23        Event::Eof => PayloadEvent::Eof,
24
25        // Do not trim next text event after Text, CDATA or reference event
26        Event::CData(e) => PayloadEvent::CData(e),
27        Event::Text(e) => PayloadEvent::Text(e),
28        Event::GeneralRef(e) => PayloadEvent::GeneralRef(e),
29
30        _ => return None,
31    };
32    Some(event)
33}
34
35////////////////////////////////////////////////////////////////////////////////////////////////////
36
37/// Trait used by the deserializer for iterating over input. This is manually
38/// "specialized" for iterating over `&[u8]`.
39///
40/// You do not need to implement this trait, it is needed to abstract from
41/// [borrowing](SliceReader) and [copying](IoReader) data sources and reuse code in
42/// deserializer
43pub trait XmlRead<'i> {
44    /// Return an input-borrowing event.
45    fn next(&mut self) -> Result<PayloadEvent<'i>, DeError>;
46
47    /// Skips until end element is found. Unlike `next()` it will not allocate
48    /// when it cannot satisfy the lifetime.
49    fn read_to_end(&mut self, name: QName) -> Result<(), DeError>;
50
51    /// Return an XML version of the source.
52    fn xml_version(&self) -> XmlVersion;
53
54    /// A copy of the reader's decoder used to decode strings.
55    fn decoder(&self) -> Decoder;
56
57    /// Checks if the `start` tag has a [`xsi:nil`] attribute. This method ignores
58    /// any errors in attributes.
59    ///
60    /// [`xsi:nil`]: https://www.w3.org/TR/xmlschema-1/#xsi_nil
61    fn has_nil_attr(&self, start: &BytesStart) -> bool;
62}
63
64/// XML input source that reads from a std::io input stream.
65///
66/// You cannot create it, it is created automatically when you call
67/// [`Deserializer::from_reader`](crate::de::Deserializer::from_reader)
68pub struct IoReader<R: BufRead> {
69    pub(crate) reader: NsReader<R>,
70    pub(crate) buf: Vec<u8>,
71    pub(crate) version: XmlVersion,
72}
73
74impl<R: BufRead> IoReader<R> {
75    /// Returns the underlying XML reader.
76    ///
77    /// ```
78    /// use serde::Deserialize;
79    /// use std::io::Cursor;
80    /// use oxixml_xml::de::Deserializer;
81    /// use oxixml_xml::NsReader;
82    ///
83    /// #[derive(Deserialize)]
84    /// struct SomeStruct {
85    ///     field1: String,
86    ///     field2: String,
87    /// }
88    ///
89    /// // Try to deserialize from broken XML
90    /// let mut de = Deserializer::from_reader(Cursor::new(
91    ///     "<SomeStruct><field1><field2></SomeStruct>"
92    /// //   0                           ^= 28        ^= 41
93    /// ));
94    ///
95    /// let err = SomeStruct::deserialize(&mut de);
96    /// assert!(err.is_err());
97    ///
98    /// let reader: &NsReader<Cursor<&str>> = de.get_ref().get_ref();
99    ///
100    /// assert_eq!(reader.error_position(), 28);
101    /// assert_eq!(reader.buffer_position(), 41);
102    /// ```
103    pub const fn get_ref(&self) -> &NsReader<R> {
104        &self.reader
105    }
106}
107
108impl<'i, R: BufRead> XmlRead<'i> for IoReader<R> {
109    fn next(&mut self) -> Result<PayloadEvent<'static>, DeError> {
110        loop {
111            self.buf.clear();
112
113            let event = self.reader.read_event_into(&mut self.buf)?;
114            if let Event::Decl(e) = &event {
115                self.version = e.xml_version()?;
116            }
117            if let Some(event) = skip_uninterested(event) {
118                return Ok(event.into_owned());
119            }
120        }
121    }
122
123    fn read_to_end(&mut self, name: QName) -> Result<(), DeError> {
124        match self.reader.read_to_end_into(name, &mut self.buf) {
125            Err(e) => Err(e.into()),
126            Ok(_) => Ok(()),
127        }
128    }
129
130    #[inline]
131    fn xml_version(&self) -> XmlVersion {
132        self.version
133    }
134
135    #[inline]
136    fn decoder(&self) -> Decoder {
137        self.reader.decoder()
138    }
139
140    fn has_nil_attr(&self, start: &BytesStart) -> bool {
141        start.attributes().has_nil(self.reader.resolver())
142    }
143}
144
145/// XML input source that reads from a slice of bytes and can borrow from it.
146///
147/// You cannot create it, it is created automatically when you call
148/// [`Deserializer::from_str`](crate::de::Deserializer::from_str).
149pub struct SliceReader<'de> {
150    pub(crate) reader: NsReader<&'de [u8]>,
151    pub(crate) version: XmlVersion,
152}
153
154impl<'de> SliceReader<'de> {
155    /// Returns the underlying XML reader.
156    ///
157    /// ```
158    /// use serde::Deserialize;
159    /// use oxixml_xml::de::Deserializer;
160    /// use oxixml_xml::NsReader;
161    ///
162    /// #[derive(Deserialize)]
163    /// struct SomeStruct {
164    ///     field1: String,
165    ///     field2: String,
166    /// }
167    ///
168    /// // Try to deserialize from broken XML
169    /// let mut de = Deserializer::from_str(
170    ///     "<SomeStruct><field1><field2></SomeStruct>"
171    /// //   0                           ^= 28        ^= 41
172    /// );
173    ///
174    /// let err = SomeStruct::deserialize(&mut de);
175    /// assert!(err.is_err());
176    ///
177    /// let reader: &NsReader<&[u8]> = de.get_ref().get_ref();
178    ///
179    /// assert_eq!(reader.error_position(), 28);
180    /// assert_eq!(reader.buffer_position(), 41);
181    /// ```
182    pub const fn get_ref(&self) -> &NsReader<&'de [u8]> {
183        &self.reader
184    }
185}
186
187impl<'de> XmlRead<'de> for SliceReader<'de> {
188    fn next(&mut self) -> Result<PayloadEvent<'de>, DeError> {
189        loop {
190            let event = self.reader.read_event()?;
191            if let Event::Decl(e) = &event {
192                self.version = e.xml_version()?;
193            }
194            if let Some(event) = skip_uninterested(event) {
195                return Ok(event);
196            }
197        }
198    }
199
200    fn read_to_end(&mut self, name: QName) -> Result<(), DeError> {
201        match self.reader.read_to_end(name) {
202            Err(e) => Err(e.into()),
203            Ok(_) => Ok(()),
204        }
205    }
206
207    #[inline]
208    fn xml_version(&self) -> XmlVersion {
209        self.version
210    }
211
212    #[inline]
213    fn decoder(&self) -> Decoder {
214        self.reader.decoder()
215    }
216
217    fn has_nil_attr(&self, start: &BytesStart) -> bool {
218        start.attributes().has_nil(self.reader.resolver())
219    }
220}