use std::io::Read;
use winnow::{
Partial,
error::{ErrMode, Needed},
stream::{Offset, StreamIsPartial},
};
use super::grammar;
use crate::{Attribute, AttributeValue, Event, Result, render_event};
use std::collections::HashMap;
const INITIAL_BUF: usize = 4096;
const READ_CHUNK: usize = 4096;
#[derive(Debug)]
pub struct AbxStreamParser<R: Read> {
reader: R,
buf: Vec<u8>,
pos: usize,
len: usize,
eof: bool,
pool: Vec<crate::InternedStr>,
}
impl<R: Read> AbxStreamParser<R> {
pub fn new(reader: R) -> Result<Self> {
let mut p = AbxStreamParser {
reader,
buf: vec![0u8; INITIAL_BUF],
pos: 0,
len: 0,
eof: false,
pool: Vec::with_capacity(32),
};
p.ensure(4)?;
crate::decode::check_magic(&p.buf[p.pos..p.len])?;
p.pos += 4;
Ok(p)
}
#[inline]
fn available(&self) -> usize {
self.len - self.pos
}
fn ensure(&mut self, needed: usize) -> Result<()> {
if self.available() >= needed || self.eof {
return Ok(());
}
if self.pos > 0 {
self.buf.copy_within(self.pos..self.len, 0);
self.len -= self.pos;
self.pos = 0;
}
while self.available() < needed && !self.eof {
let spare = self.buf.len() - self.len;
if spare < READ_CHUNK {
self.buf
.resize(self.len + READ_CHUNK.max(needed - self.available()), 0);
}
let n = self.reader.read(&mut self.buf[self.len..])?;
if n == 0 {
self.eof = true;
} else {
self.len += n;
}
}
Ok(())
}
pub fn next_event(&mut self) -> Result<Option<Event>> {
self.ensure(1)?;
if self.available() == 0 {
return Ok(None);
}
let pool_len = self.pool.len();
let result = self.parse_event();
if result.is_err() {
self.pool.truncate(pool_len);
}
result.map(Some)
}
fn parse_event(&mut self) -> Result<Event> {
loop {
let window = &self.buf[self.pos..self.len];
let mut input = Partial::new(window);
if self.eof {
let _ = input.complete();
}
let pool_len = self.pool.len();
match grammar::event(&mut input, &mut self.pool) {
Ok(ev) => {
self.pos += input.offset_from(&Partial::new(window));
return Ok(ev);
}
Err(ErrMode::Incomplete(needed)) => {
self.pool.truncate(pool_len);
let more = match needed {
Needed::Size(n) => n.get(),
Needed::Unknown => 1,
};
self.ensure(self.available() + more)?;
}
Err(e) => return Err(grammar::into_abx_error(e)),
}
}
}
pub fn collect_events(&mut self) -> Result<Vec<Event>> {
let mut out = Vec::new();
while let Some(ev) = self.next_event()? {
out.push(ev);
}
Ok(out)
}
pub fn find_attribute(&mut self, element: &str, attr: &str) -> Result<Option<AttributeValue>> {
loop {
match self.next_event()? {
Some(Event::StartTag { name, attributes }) if name == element => {
if let Some(a) = attributes.into_iter().find(|a| a.name == attr) {
return Ok(Some(a.value));
}
}
Some(Event::EndDocument) | None => return Ok(None),
_ => {}
}
}
}
pub fn find_all_attributes(
&mut self,
element: &str,
attr: &str,
) -> Result<Vec<AttributeValue>> {
let mut out = Vec::new();
while let Some(ev) = self.next_event()? {
if let Event::StartTag { name, attributes } = ev
&& name == element
{
out.extend(
attributes
.into_iter()
.filter(|a| a.name == attr)
.map(|a| a.value),
);
}
}
Ok(out)
}
pub fn attributes_of(&mut self, element: &str) -> Result<Option<Vec<Attribute>>> {
loop {
match self.next_event()? {
Some(Event::StartTag { name, attributes }) if name == element => {
return Ok(Some(attributes));
}
Some(Event::EndDocument) | None => return Ok(None),
_ => {}
}
}
}
pub fn all_attributes_of(&mut self, element: &str) -> Result<Vec<Vec<Attribute>>> {
let mut out = Vec::new();
while let Some(ev) = self.next_event()? {
if let Event::StartTag { name, attributes } = ev
&& name == element
{
out.push(attributes);
}
}
Ok(out)
}
#[cfg(feature = "serde")]
pub fn deserialize_next<T: serde::de::DeserializeOwned>(
&mut self,
element: &str,
) -> Result<Option<T>> {
crate::de::find_and_consume_element(self, element)
}
#[cfg(feature = "serde")]
pub fn deserialize_all<T: serde::de::DeserializeOwned>(
&mut self,
element: &str,
) -> Result<Vec<T>> {
let mut out = Vec::new();
while let Some(item) = self.deserialize_next(element)? {
out.push(item);
}
Ok(out)
}
#[cfg(feature = "serde")]
pub fn deserialize_iter<'p, T: serde::de::DeserializeOwned>(
&'p mut self,
element: &'p str,
) -> DeserializeIter<'p, R, T> {
DeserializeIter {
parser: self,
element,
_marker: std::marker::PhantomData,
}
}
pub fn to_xml(&mut self) -> Result<String> {
let mut buf = String::from(r#"<?xml version="1.0" encoding="UTF-8"?>"#);
while let Some(ev) = self.next_event()? {
if matches!(ev, Event::EndDocument) {
break;
}
render_event(&ev, &mut buf);
}
Ok(buf)
}
pub fn write_xml(&mut self, writer: &mut impl std::io::Write) -> Result<()> {
writer.write_all(b"<?xml version=\"1.0\" encoding=\"UTF-8\"?>")?;
let mut tmp = String::new();
while let Some(ev) = self.next_event()? {
if matches!(ev, Event::EndDocument) {
break;
}
tmp.clear();
render_event(&ev, &mut tmp);
writer.write_all(tmp.as_bytes())?;
}
Ok(())
}
pub fn into_map(mut self) -> Result<HashMap<String, Vec<HashMap<String, String>>>> {
let mut map: HashMap<String, Vec<HashMap<String, String>>> = HashMap::new();
while let Some(ev) = self.next_event()? {
if let Event::StartTag { name, attributes } = ev {
let entry = map.entry(name.into()).or_default();
let mut attrs = HashMap::new();
for attr in attributes {
attrs.insert(attr.name.into(), attr.value.as_str().into_owned());
}
entry.push(attrs);
}
}
Ok(map)
}
pub fn into_inner(self) -> R {
self.reader
}
}
impl<R: Read> Iterator for AbxStreamParser<R> {
type Item = Result<Event>;
fn next(&mut self) -> Option<Self::Item> {
match self.next_event() {
Ok(Some(ev)) => Some(Ok(ev)),
Ok(None) => None,
Err(e) => Some(Err(e)),
}
}
}
#[cfg(feature = "serde")]
pub struct DeserializeIter<'p, R: Read, T> {
parser: &'p mut AbxStreamParser<R>,
element: &'p str,
_marker: std::marker::PhantomData<T>,
}
#[cfg(feature = "serde")]
impl<'p, R: Read, T: serde::de::DeserializeOwned> Iterator for DeserializeIter<'p, R, T> {
type Item = Result<T>;
fn next(&mut self) -> Option<Self::Item> {
self.parser.deserialize_next(self.element).transpose()
}
}