use std::io::{Read, Seek};
use crate::index::{FieldIndex, FieldIndicesIndex, LabelIndex, ListIndicesIndex, StructIndex};
use crate::error::{Error, Result};
use crate::parser::{Parser, Token, Tag};
use self::State::*;
#[derive(Debug, Clone)]
pub enum State {
Start(ReadStruct<Root>),
ReadLabel(ReadLabel),
ReadField(ReadField),
ReadFields(ReadFields),
ReadItems(ReadItems),
EndRoot(EndStruct<Root>),
EndItem(EndStruct<Item>),
EndStruct(EndStruct<Struct>),
Finish,
}
impl State {
pub fn next<R: Read + Seek>(self, parser: &mut Parser<R>) -> Result<(Token, State)> {
match self {
Start(state) => state.next(parser),
ReadLabel(state) => state.next(parser),
ReadField(state) => state.next(parser),
ReadFields(state) => state.next(parser),
ReadItems(state) => state.next(parser),
EndRoot(state) => state.next(),
EndStruct(state) => state.next(),
EndItem(state) => state.next(),
Finish => Err(Error::ParsingFinished),
}
}
pub fn skip(self, token: Token) -> State {
match self {
Start(state) => state.skip(),
ReadLabel(state) => state.skip(),
ReadField(state) => state.skip(),
ReadFields(state) => state.skip(token),
ReadItems(state) => state.skip(),
EndRoot(state) => state.skip(),
EndStruct(state) => state.skip(),
EndItem(state) => state.skip(),
Finish => unreachable!(),
}
}
}
impl Default for State {
fn default() -> Self {
State::Start(ReadStruct::<Root>::default())
}
}
pub trait TokenEmitter {
fn begin(&self, tag: Tag, count: u32) -> Token;
fn end(&self) -> Token;
fn next(self, state: Box<State>) -> State;
}
#[derive(Debug, Clone, Copy)]
pub struct Root;
impl TokenEmitter for Root {
fn begin(&self, tag: Tag, count: u32) -> Token {
Token::RootBegin { tag, count }
}
fn end(&self) -> Token { Token::RootEnd }
fn next(self, state: Box<State>) -> State {
State::EndRoot(EndStruct::<Self> {
state: state,
data: self,
})
}
}
#[derive(Debug, Clone, Copy)]
pub struct Struct;
impl TokenEmitter for Struct {
fn begin(&self, tag: Tag, count: u32) -> Token {
Token::StructBegin { tag, count }
}
fn end(&self) -> Token { Token::StructEnd }
fn next(self, state: Box<State>) -> State {
State::EndStruct(EndStruct::<Self> {
state: state,
data: self,
})
}
}
#[derive(Debug, Clone, Copy)]
pub struct Item {
index: u32,
}
impl TokenEmitter for Item {
fn begin(&self, tag: Tag, count: u32) -> Token {
Token::ItemBegin { tag, count, index: self.index }
}
fn end(&self) -> Token { Token::ItemEnd }
fn next(self, state: Box<State>) -> State {
State::EndItem(EndStruct::<Self> {
state: state,
data: self,
})
}
}
#[derive(Debug, Clone)]
pub struct ReadStruct<Data: TokenEmitter> {
index: StructIndex,
state: Box<State>,
data: Data,
}
impl<Data: TokenEmitter> ReadStruct<Data> {
fn next<R: Read + Seek>(self, parser: &mut Parser<R>) -> Result<(Token, State)> {
parser.seek(self.index)?;
let tag = parser.read_u32()?;
let index = parser.read_u32()?;
let count = parser.read_u32()?;
let token = self.data.begin(Tag(tag), count);
let next = self.data.next(self.state);
let state = match count {
0 => next,
1 => State::ReadLabel(ReadLabel { index: FieldIndex(index), state: next.into() }),
_ => State::ReadFields(ReadFields { index: FieldIndicesIndex(index, 0), count, state: next.into() }),
};
Ok((token, state))
}
#[inline]
fn skip(self) -> State { *self.state }
}
impl Default for ReadStruct<Root> {
fn default() -> Self {
ReadStruct::<Root> {
index: StructIndex(0),
state: Finish.into(),
data: Root,
}
}
}
#[derive(Debug, Clone)]
pub struct EndStruct<Data: TokenEmitter> {
state: Box<State>,
data: Data,
}
impl<Data: TokenEmitter> EndStruct<Data> {
fn next(self) -> Result<(Token, State)> {
Ok((self.data.end(), *self.state))
}
#[inline]
fn skip(self) -> State { *self.state }
}
#[derive(Debug, Clone)]
pub struct ReadLabel {
index: FieldIndex,
state: Box<State>,
}
impl ReadLabel {
fn next<R: Read + Seek>(self, parser: &mut Parser<R>) -> Result<(Token, State)> {
parser.seek(self.index)?;
let tag = parser.read_u32()?;
let label = LabelIndex(parser.read_u32()?);
let token = Token::Label(label);
let state = ReadField { tag, state: self.state };
Ok((token, State::ReadField(state)))
}
#[inline]
fn skip(self) -> State { *self.state }
}
#[derive(Debug, Clone)]
pub struct ReadField {
tag: u32,
state: Box<State>,
}
impl ReadField {
fn next<R: Read + Seek>(self, parser: &mut Parser<R>) -> Result<(Token, State)> {
match self.tag {
14 => { let next = ReadStruct::<Struct> {
index: StructIndex(parser.read_u32()?),
state: self.state,
data: Struct,
};
next.next(parser)
},
15 => { let next = ReadList {
index: ListIndicesIndex(parser.read_u32()?, 0),
state: self.state,
};
next.next(parser)
},
_ => {
let value = parser.read_value_ref(self.tag)?;
let token = Token::Value(value);
Ok((token, *self.state))
},
}
}
#[inline]
fn skip(self) -> State { *self.state }
}
#[derive(Debug, Clone)]
pub struct ReadFields {
index: FieldIndicesIndex,
count: u32,
state: Box<State>,
}
impl ReadFields {
fn next<R: Read + Seek>(self, parser: &mut Parser<R>) -> Result<(Token, State)> {
if self.count == 0 {
return self.state.next(parser);
}
parser.seek(self.index)?;
let field = parser.read_u32()?;
let state = ReadLabel {
index: FieldIndex(field),
state: State::ReadFields(ReadFields {
index: self.index + 1,
count: self.count - 1,
state: self.state,
}).into(),
};
state.next(parser)
}
fn skip(self, token: Token) -> State {
match token {
Token::Value(..) => State::ReadFields(self),
_ => self.state.skip(token),
}
}
}
#[derive(Debug, Clone)]
struct ReadList {
index: ListIndicesIndex,
state: Box<State>,
}
impl ReadList {
fn next<R: Read + Seek>(self, parser: &mut Parser<R>) -> Result<(Token, State)> {
parser.seek(self.index)?;
let count = parser.read_u32()?;
let token = Token::ListBegin(count);
let state = ReadItems {
index: self.index + 1,
count: count,
state: self.state,
};
Ok((token, State::ReadItems(state)))
}
}
#[derive(Debug, Clone)]
pub struct ReadItems {
index: ListIndicesIndex,
count: u32,
state: Box<State>,
}
impl ReadItems {
fn next<R: Read + Seek>(self, parser: &mut Parser<R>) -> Result<(Token, State)> {
if self.count == 0 {
return Ok((Token::ListEnd, *self.state));
}
parser.seek(self.index)?;
let struc = parser.read_u32()?;
let state = ReadStruct::<Item> {
index: StructIndex(struc),
state: State::ReadItems(ReadItems {
index: self.index + 1,
count: self.count - 1,
state: self.state,
}).into(),
data: Item { index: self.index.1 },
};
state.next(parser)
}
#[inline]
fn skip(self) -> State { *self.state }
}