1 use crate::debug_expect;
2 use crate::error::Result;
3 use std::{collections::VecDeque, io::Read};
4 use xml::reader::{EventReader, XmlEvent};
5
6 /// Retrieve XML events from an underlying reader.
7 pub trait BufferedXmlReader<R: Read> {
8 /// Get and "consume" the next event.
next(&mut self) -> Result<XmlEvent>9 fn next(&mut self) -> Result<XmlEvent>;
10
11 /// Get the next event without consuming.
peek(&mut self) -> Result<&XmlEvent>12 fn peek(&mut self) -> Result<&XmlEvent>;
13
14 /// Spawn a child buffer whose cursor starts at the same position as this buffer.
child_buffer<'a>(&'a mut self) -> ChildXmlBuffer<'a, R>15 fn child_buffer<'a>(&'a mut self) -> ChildXmlBuffer<'a, R>;
16 }
17
18 pub struct RootXmlBuffer<R: Read> {
19 reader: EventReader<R>,
20 buffer: VecDeque<CachedXmlEvent>,
21 }
22
23 impl<R: Read> RootXmlBuffer<R> {
new(reader: EventReader<R>) -> Self24 pub fn new(reader: EventReader<R>) -> Self {
25 RootXmlBuffer {
26 reader,
27 buffer: VecDeque::new(),
28 }
29 }
30 }
31
32 impl<R: Read> BufferedXmlReader<R> for RootXmlBuffer<R> {
33 /// Consumed XML events in the root buffer are moved to the caller
next(&mut self) -> Result<XmlEvent>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
peek(&mut self) -> Result<&XmlEvent>44 fn peek(&mut self) -> Result<&XmlEvent> {
45 get_from_buffer_or_reader(&mut self.buffer, &mut self.reader, &mut 0)
46 }
47
child_buffer<'root>(&'root mut self) -> ChildXmlBuffer<'root, R>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
58 pub struct ChildXmlBuffer<'parent, R: Read> {
59 reader: &'parent mut EventReader<R>,
60 buffer: &'parent mut VecDeque<CachedXmlEvent>,
61 cursor: usize,
62 }
63
64 impl<'parent, R: Read> ChildXmlBuffer<'parent, R> {
65 /// Advance the child buffer without marking an event as "used"
skip(&mut self)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
76 impl<'parent, R: Read> BufferedXmlReader<R> for ChildXmlBuffer<'parent, R> {
77 /// Consumed XML events in a child buffer are marked as "used"
next(&mut self) -> Result<XmlEvent>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
peek(&mut self) -> Result<&XmlEvent>108 fn peek(&mut self) -> Result<&XmlEvent> {
109 get_from_buffer_or_reader(self.buffer, self.reader, &mut self.cursor)
110 }
111
child_buffer<'a>(&'a mut self) -> ChildXmlBuffer<'a, R>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)]
128 enum CachedXmlEvent {
129 Unused(XmlEvent),
130 Used,
131 }
132
get_from_buffer_or_reader<'buf>( buffer: &'buf mut VecDeque<CachedXmlEvent>, reader: &mut EventReader<impl Read>, index: &mut usize, ) -> Result<&'buf XmlEvent>133 fn 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.
next_significant_event(reader: &mut EventReader<impl Read>) -> Result<XmlEvent>159 fn 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 }
170