xml_stinks/deserializer/
buffered.rs

1//! Buffered XML deserializer.
2use 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    /// A XML deserializer source with an internal buffer.
16    pub Source: BufRead + MaybeStatic;
17}
18
19/// XML deserializer using a source which has an internal buffer.
20pub 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    /// Returns a new [`Buffered`].
30    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}