serde_xml_rs/de/
buffer.rs

1use crate::debug_expect;
2use crate::error::Result;
3use std::{collections::VecDeque, io::Read};
4use xml::reader::{EventReader, XmlEvent};
5
6/// Retrieve XML events from an underlying reader.
7pub trait BufferedXmlReader<R: Read> {
8    /// Get and "consume" the next event.
9    fn next(&mut self) -> Result<XmlEvent>;
10
11    /// Get the next event without consuming.
12    fn peek(&mut self) -> Result<&XmlEvent>;
13
14    /// Spawn a child buffer whose cursor starts at the same position as this buffer.
15    fn child_buffer<'a>(&'a mut self) -> ChildXmlBuffer<'a, R>;
16}
17
18pub struct RootXmlBuffer<R: Read> {
19    reader: EventReader<R>,
20    buffer: VecDeque<CachedXmlEvent>,
21}
22
23impl<R: Read> RootXmlBuffer<R> {
24    pub fn new(reader: EventReader<R>) -> Self {
25        RootXmlBuffer {
26            reader,
27            buffer: VecDeque::new(),
28        }
29    }
30}
31
32impl<R: Read> BufferedXmlReader<R> for RootXmlBuffer<R> {
33    /// Consumed XML events in the root buffer are moved to the caller
34    fn next(&mut self) -> Result<XmlEvent> {
35        loop {
36            match self.buffer.pop_front() {
37                Some(CachedXmlEvent::Unused(ev)) => break Ok(ev),
38                Some(CachedXmlEvent::Used) => continue,
39                None => break next_significant_event(&mut self.reader),
40            }
41        }
42    }
43
44    fn peek(&mut self) -> Result<&XmlEvent> {
45        get_from_buffer_or_reader(&mut self.buffer, &mut self.reader, &mut 0)
46    }
47
48    fn child_buffer<'root>(&'root mut self) -> ChildXmlBuffer<'root, R> {
49        let RootXmlBuffer { reader, buffer } = self;
50        ChildXmlBuffer {
51            reader,
52            buffer,
53            cursor: 0,
54        }
55    }
56}
57
58pub struct ChildXmlBuffer<'parent, R: Read> {
59    reader: &'parent mut EventReader<R>,
60    buffer: &'parent mut VecDeque<CachedXmlEvent>,
61    cursor: usize,
62}
63
64impl<'parent, R: Read> ChildXmlBuffer<'parent, R> {
65    /// Advance the child buffer without marking an event as "used"
66    pub fn skip(&mut self) {
67        debug_assert!(
68            self.cursor < self.buffer.len(),
69            ".skip() only should be called after .peek()"
70        );
71
72        self.cursor += 1;
73    }
74}
75
76impl<'parent, R: Read> BufferedXmlReader<R> for ChildXmlBuffer<'parent, R> {
77    /// Consumed XML events in a child buffer are marked as "used"
78    fn next(&mut self) -> Result<XmlEvent> {
79        loop {
80            match self.buffer.get_mut(self.cursor) {
81                Some(entry @ CachedXmlEvent::Unused(_)) => {
82                    let taken = if self.cursor == 0 {
83                        self.buffer.pop_front().unwrap()
84                    } else {
85                        std::mem::replace(entry, CachedXmlEvent::Used)
86                    };
87
88                    return debug_expect!(taken, CachedXmlEvent::Unused(ev) => Ok(ev));
89                }
90                Some(CachedXmlEvent::Used) => {
91                    debug_assert!(
92                        self.cursor != 0,
93                        "Event buffer should not start with 'used' slot (should have been popped)"
94                    );
95                    self.cursor += 1;
96                    continue;
97                }
98                None => {
99                    debug_assert_eq!(self.buffer.len(), self.cursor);
100
101                    // Skip creation of buffer entry when consuming event straight away
102                    return next_significant_event(&mut self.reader);
103                }
104            }
105        }
106    }
107
108    fn peek(&mut self) -> Result<&XmlEvent> {
109        get_from_buffer_or_reader(self.buffer, self.reader, &mut self.cursor)
110    }
111
112    fn child_buffer<'a>(&'a mut self) -> ChildXmlBuffer<'a, R> {
113        let ChildXmlBuffer {
114            reader,
115            buffer,
116            cursor,
117        } = self;
118
119        ChildXmlBuffer {
120            reader,
121            buffer,
122            cursor: *cursor,
123        }
124    }
125}
126
127#[derive(Debug)]
128enum CachedXmlEvent {
129    Unused(XmlEvent),
130    Used,
131}
132
133fn get_from_buffer_or_reader<'buf>(
134    buffer: &'buf mut VecDeque<CachedXmlEvent>,
135    reader: &mut EventReader<impl Read>,
136    index: &mut usize,
137) -> Result<&'buf XmlEvent> {
138    // We should only be attempting to get an event already in the buffer, or the next event to place in the buffer
139    debug_assert!(*index <= buffer.len());
140
141    loop {
142        match buffer.get_mut(*index) {
143            Some(CachedXmlEvent::Unused(_)) => break,
144            Some(CachedXmlEvent::Used) => {
145                *index += 1;
146            }
147            None => {
148                let next = next_significant_event(reader)?;
149                buffer.push_back(CachedXmlEvent::Unused(next));
150            }
151        }
152    }
153
154    // Returning of borrowed data must be done after of loop/match due to current limitation of borrow checker
155    debug_expect!(buffer.get_mut(*index), Some(CachedXmlEvent::Unused(event)) => Ok(event))
156}
157
158/// Reads the next XML event from the underlying reader, skipping events we're not interested in.
159fn next_significant_event(reader: &mut EventReader<impl Read>) -> Result<XmlEvent> {
160    loop {
161        match reader.next()? {
162            XmlEvent::StartDocument { .. }
163            | XmlEvent::ProcessingInstruction { .. }
164            | XmlEvent::Whitespace { .. }
165            | XmlEvent::Comment(_) => { /* skip */ }
166            other => return Ok(other),
167        }
168    }
169}