xml_stinks/deserializer/
buffered.rs1use std::convert::Infallible;
3use std::io::BufRead;
4
5use quick_xml::events::Event;
6use quick_xml::Reader;
7
8use crate::deserializer::{Deserializer, Error, IgnoreEnd, MaybeStatic};
9use crate::event::EventExt;
10use crate::tagged::TagStart;
11use crate::util::trait_alias;
12use crate::DeserializeTagged;
13
14trait_alias! {
15 pub Source: BufRead + MaybeStatic;
17}
18
19pub struct Buffered<TSource: Source>
21{
22 reader: Reader<TSource>,
23 leftover_event: Option<Event<'static>>,
24 buf: Vec<u8>,
25}
26
27impl<TSource: Source> Buffered<TSource>
28{
29 pub fn new(source: TSource) -> Self
31 {
32 let mut reader = Reader::from_reader(source);
33
34 reader.trim_text(true);
35 reader.expand_empty_elements(true);
36
37 Self {
38 reader,
39 leftover_event: None,
40 buf: Vec::new(),
41 }
42 }
43}
44
45impl<TSource: Source> Deserializer for Buffered<TSource>
46{
47 fn de_tag<De: DeserializeTagged>(
48 &mut self,
49 tag_name: &str,
50 ignore_end: IgnoreEnd,
51 ) -> Result<De, Error<De::Error>>
52 {
53 self.de_tag_with(tag_name, ignore_end, De::deserialize)
54 }
55
56 fn de_tag_with<Output, Err, DeserializeFn>(
57 &mut self,
58 tag_name: &str,
59 ignore_end: IgnoreEnd,
60 deserialize: DeserializeFn,
61 ) -> Result<Output, Error<Err>>
62 where
63 Err: std::error::Error + Send + Sync + 'static,
64 DeserializeFn: FnOnce(&TagStart, &mut Self) -> Result<Output, Err>,
65 {
66 let deserialized = match self.read_event()? {
67 Event::Start(start) if start.name().as_ref() == tag_name.as_bytes() => {
68 deserialize(&TagStart::from_inner(start), self)
69 .map_err(Error::DeserializeFailed)?
70 }
71 event => {
72 self.leftover_event = Some(event.clone().into_owned());
73
74 return Err(Error::UnexpectedEvent {
75 expected_event_name: format!("start({tag_name})"),
76 found_event: event.describe().unwrap(),
77 });
78 }
79 };
80
81 if let IgnoreEnd::No = ignore_end {
82 self.read_end_event(tag_name.as_bytes())
83 .map_err(Error::into_with_de_error)?;
84 }
85
86 Ok(deserialized)
87 }
88
89 fn de_tag_list<De: DeserializeTagged, Name: AsRef<str>>(
90 &mut self,
91 tag_name: Option<Name>,
92 ) -> Result<Vec<De>, Error<De::Error>>
93 {
94 let mut deserialized_items = Vec::new();
95
96 loop {
97 let start = match self.read_event()? {
98 Event::Start(start)
99 if tag_name.as_ref().map_or_else(
100 || true,
101 |expected_tag_name| {
102 start.name().as_ref() == expected_tag_name.as_ref().as_bytes()
103 },
104 ) =>
105 {
106 TagStart::from_inner(start)
107 }
108 Event::Comment(_) => {
109 continue;
110 }
111 event => {
112 self.leftover_event = Some(event.into_owned());
113 break;
114 }
115 };
116
117 let deserialized =
118 De::deserialize(&start, self).map_err(Error::DeserializeFailed)?;
119
120 self.read_end_event(start.name_bytes())
121 .map_err(Error::into_with_de_error)?;
122
123 deserialized_items.push(deserialized);
124 }
125
126 Ok(deserialized_items)
127 }
128
129 fn de_text(&mut self) -> Result<String, Error<Infallible>>
130 {
131 let text = match self.read_event::<Infallible>()? {
132 Event::Text(text) => Ok(text),
133 event => {
134 self.leftover_event = Some(event.clone().into_owned());
135
136 Err(Error::<Infallible>::UnexpectedEvent {
137 expected_event_name: "text".to_string(),
138 found_event: event.describe().unwrap(),
139 })
140 }
141 }?
142 .unescape()
143 .map_err(|err| Error::<Infallible>::XMLError(err.into()))?;
144
145 Ok(text.to_string())
146 }
147
148 fn skip_to_tag_start(&mut self, tag_name: &str) -> Result<(), Error<Infallible>>
149 {
150 loop {
151 match self.read_event::<Infallible>()? {
152 Event::Start(start) if start.name().as_ref() == tag_name.as_bytes() => {
153 self.leftover_event = Some(Event::Start(start).into_owned());
154
155 break;
156 }
157 _ => {}
158 }
159 }
160
161 Ok(())
162 }
163
164 fn skip_to_tag_end(&mut self, tag_name: &str) -> Result<(), Error<Infallible>>
165 {
166 loop {
167 match self.read_event::<Infallible>()? {
168 Event::End(end) if end.name().as_ref() == tag_name.as_bytes() => {
169 self.leftover_event = Some(Event::End(end).into_owned());
170
171 return Ok(());
172 }
173 _ => {}
174 }
175 }
176 }
177}
178
179impl<TSource: Source> Buffered<TSource>
180{
181 fn read_end_event(&mut self, tag_name: &[u8]) -> Result<(), Error<Infallible>>
182 {
183 let event = self.read_event::<Infallible>()?;
184
185 if matches!(&event, Event::End(end) if end.name().as_ref() == tag_name) {
186 return Ok(());
187 }
188
189 Err(Error::UnexpectedEvent {
190 expected_event_name: "end".to_string(),
191 found_event: event.describe().unwrap(),
192 })
193 }
194
195 fn read_event<DeError>(&mut self) -> Result<Event<'static>, Error<DeError>>
196 {
197 let event = if let Some(leftover_event) = self.leftover_event.take() {
198 leftover_event
199 } else {
200 self.reader
201 .read_event_into(&mut self.buf)
202 .map_err(|err| Error::<DeError>::XMLError(err.into()))?
203 .into_owned()
204 };
205
206 if let Event::Eof = &event {
207 return Err(Error::UnexpectedEndOfFile);
208 }
209
210 Ok(event)
211 }
212}