use quick_xml::errors::IllFormedError;
use quick_xml::events::attributes::{Attribute, Attributes};
use quick_xml::events::{BytesStart, Event};
use quick_xml::{Decoder, Error, Reader, XmlVersion};
use std::borrow::Cow;
use std::cell::RefCell;
use std::io::BufRead;
type BufferHandle = usize;
struct BufferManager {
buffers: Vec<Vec<u8>>,
free_buffers: Vec<BufferHandle>,
}
impl BufferManager {
fn alloc(&mut self) -> (&mut Vec<u8>, BufferHandle) {
if let Some(index) = self.free_buffers.pop() {
let mut_buffer = self.buffers.get_mut(index).unwrap();
mut_buffer.clear();
(mut_buffer, index)
} else {
let index = self.buffers.len();
self.buffers.push(Vec::new());
let mut_buffer = self.buffers.last_mut().unwrap();
(mut_buffer, index)
}
}
fn release(&mut self, index: BufferHandle) {
self.free_buffers.push(index);
}
}
pub struct PullReader<B: BufRead> {
reader: Reader<B>,
buffer_manager: RefCell<BufferManager>,
}
pub struct Element<'a, B: BufRead> {
pending_close: bool,
handle: BufferHandle,
reader: &'a mut Reader<B>,
buffer_manager: &'a RefCell<BufferManager>,
data: BytesStart<'a>,
}
pub struct AttributesView<'a> {
decoder: Decoder,
attributes: Attributes<'a>,
}
pub struct AttributeView<'a> {
decoder: Decoder,
attribute: Attribute<'a>,
}
pub struct Text<'a> {
handle: Option<BufferHandle>,
buffer_manager: Option<&'a RefCell<BufferManager>>,
data: Cow<'a, str>,
}
impl<B: BufRead> PullReader<B> {
pub fn new(input: B) -> Self {
let mut reader = Reader::from_reader(input);
let config = reader.config_mut();
config.trim_text(true);
config.expand_empty_elements = true;
config.check_end_names = true;
PullReader::from_reader(reader)
}
pub fn from_reader(reader: Reader<B>) -> Self {
PullReader {
reader,
buffer_manager: RefCell::new(BufferManager {
buffers: Vec::new(),
free_buffers: Vec::new(),
}),
}
}
pub fn root<'a>(&'a mut self) -> quick_xml::Result<Element<'a, B>> {
let mut buffer_manager = self.buffer_manager.borrow_mut();
let (buffer, handle) = buffer_manager.alloc();
loop {
match self.reader.read_event_into(buffer)? {
Event::Start(data) => {
return Ok(Element {
pending_close: false,
handle,
reader: &mut self.reader,
buffer_manager: &self.buffer_manager,
data: unsafe {
std::mem::transmute::<BytesStart<'_>, BytesStart<'a>>(data)
},
});
}
Event::Eof => {
buffer_manager.release(handle);
return Err(Error::IllFormed(IllFormedError::MissingEndTag(
"root".to_owned(),
)));
}
_ => {}
}
}
}
}
impl<B: BufRead> Element<'_, B> {
pub fn name(&'_ self) -> Cow<'_, str> {
self.reader
.decoder()
.decode(self.data.name().into_inner())
.unwrap_or_default()
}
pub fn attributes(&'_ self) -> AttributesView<'_> {
AttributesView {
decoder: self.reader.decoder(),
attributes: self.data.attributes(),
}
}
pub fn find_attribute(
&'_ self,
name: impl AsRef<str>,
) -> quick_xml::Result<Option<AttributeView<'_>>> {
for attribute in self.attributes() {
match attribute {
Ok(attribute) => {
if attribute.key().as_ref() == name.as_ref() {
return Ok(Some(attribute));
}
}
Err(error) => return Err(error),
}
}
Ok(None)
}
pub fn next_child<'a>(&'a mut self) -> quick_xml::Result<Option<Element<'a, B>>> {
if self.pending_close {
return Ok(None);
}
let mut buffer_manager = self.buffer_manager.borrow_mut();
let (buffer, handle) = buffer_manager.alloc();
loop {
buffer.clear();
match self.reader.read_event_into(buffer)? {
Event::Start(data) => {
return Ok(Some(Element {
pending_close: false,
handle,
buffer_manager: self.buffer_manager,
reader: self.reader,
data: unsafe {
std::mem::transmute::<BytesStart<'_>, BytesStart<'a>>(data)
},
}));
}
Event::End(_) => {
buffer_manager.release(handle);
self.pending_close = true;
return Ok(None);
}
Event::Eof => {
buffer_manager.release(handle);
return Err(Error::IllFormed(IllFormedError::MissingEndTag(
"next_child".to_owned(),
)));
}
_ => {}
}
}
}
pub fn find_next_child<'a>(
&'a mut self,
name: impl AsRef<str>,
) -> quick_xml::Result<Option<Element<'a, B>>> {
let needle = self.reader.decoder().encoding().encode(name.as_ref()).0;
while let Some(element) = self.next_child()? {
if element.data.name().into_inner() == needle.as_ref() {
return Ok(Some(unsafe {
std::mem::transmute::<Element<'_, B>, Element<'a, B>>(element)
}));
}
}
Ok(None)
}
pub fn try_text<'a>(&'a mut self) -> quick_xml::Result<Option<Text<'a>>> {
if self.pending_close {
return Ok(None);
}
let mut buffer_manager = self.buffer_manager.borrow_mut();
let (buffer, handle) = buffer_manager.alloc();
let mut depth = 1;
loop {
match self.reader.read_event_into(buffer)? {
Event::Start(_) => depth += 1,
Event::End(_) => {
depth -= 1;
if depth == 0 {
self.pending_close = true;
return Ok(None);
}
}
Event::Eof => {
return Err(Error::IllFormed(IllFormedError::MissingEndTag(
"try_text".to_owned(),
)))
}
Event::Text(data) => {
return Ok(Some(Text {
handle: Some(handle),
buffer_manager: Some(self.buffer_manager),
data: unsafe {
std::mem::transmute::<Cow<'_, str>, Cow<'a, str>>(data.decode()?)
},
}));
}
Event::CData(data) => {
return Ok(Some(Text {
handle: Some(handle),
buffer_manager: Some(self.buffer_manager),
data: unsafe {
std::mem::transmute::<Cow<'_, str>, Cow<'a, str>>(data.decode()?)
},
}));
}
_ => {}
}
}
}
pub fn text(&'_ mut self) -> quick_xml::Result<Text<'_>> {
match self.try_text() {
Ok(Some(text)) => Ok(text),
Ok(None) => Ok(Text {
handle: None,
buffer_manager: None,
data: Cow::Owned(String::new()),
}),
Err(error) => Err(error),
}
}
}
impl<B: BufRead> Drop for Element<'_, B> {
fn drop(&mut self) {
let mut buffer_manager = self.buffer_manager.borrow_mut();
buffer_manager.release(self.handle);
if !self.pending_close {
let mut depth = 1;
let (tmp_buffer, tmp_handle) = buffer_manager.alloc();
loop {
if let Ok(event) = self.reader.read_event_into(tmp_buffer) {
match event {
Event::Start(_) => depth += 1,
Event::End(_) => {
depth -= 1;
if depth == 0 {
buffer_manager.release(tmp_handle);
return;
}
}
Event::Eof => {
buffer_manager.release(tmp_handle);
return;
}
Event::Text(_) => {}
Event::CData(_) => {}
_ => {}
}
tmp_buffer.clear();
} else {
buffer_manager.release(tmp_handle);
return;
}
}
}
}
}
impl AttributeView<'_> {
pub fn key(&'_ self) -> Cow<'_, str> {
self.decoder
.decode(self.attribute.key.as_ref())
.unwrap_or_default()
}
pub fn value(&'_ self) -> quick_xml::Result<Text<'_>> {
Ok(Text {
handle: None,
buffer_manager: None,
data: self
.attribute
.decoded_and_normalized_value(XmlVersion::Implicit1_0, self.decoder)?,
})
}
}
impl<'a> Iterator for AttributesView<'a> {
type Item = quick_xml::Result<AttributeView<'a>>;
fn next(&mut self) -> Option<Self::Item> {
if let Some(attribute_result) = self.attributes.next() {
match attribute_result {
Ok(attribute) => Some(Ok(AttributeView {
decoder: self.decoder,
attribute,
})),
Err(error) => Some(Err(Error::InvalidAttr(error))),
}
} else {
None
}
}
}
impl Text<'_> {
pub fn contents(&'_ self) -> Cow<'_, str> {
Cow::Borrowed(self.data.as_ref())
}
}
impl Drop for Text<'_> {
fn drop(&mut self) {
if let Some(handle) = self.handle {
self.buffer_manager.unwrap().borrow_mut().release(handle);
}
}
}