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}