use std::iter::FusedIterator;
use std::io::{Read, Seek, SeekFrom};
use byteorder::{LE, ReadBytesExt};
use encoding::{EncodingRef, DecoderTrap};
use encoding::all::UTF_8;
use crate::{Label, SubString, ResRef, StrRef};
use crate::error::{Error, Result};
use crate::header::Header;
use crate::index::{Index, LabelIndex, U64Index, I64Index, F64Index, StringIndex, ResRefIndex, LocStringIndex, BinaryIndex};
use crate::string::{LocString, StringKey};
use crate::value::{SimpleValue, SimpleValueRef};
mod token;
mod states;
use self::states::State;
pub use self::token::Token;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Tag(u32);
pub struct Parser<R: Read + Seek> {
reader: R,
header: Header,
encoding: EncodingRef,
trap: DecoderTrap,
state: State,
}
impl<R: Read + Seek> Parser<R> {
pub fn new(reader: R) -> Result<Self> {
Self::with_encoding(reader, UTF_8, DecoderTrap::Strict)
}
pub fn with_encoding(mut reader: R, encoding: EncodingRef, trap: DecoderTrap) -> Result<Self> {
let header = Header::read(&mut reader)?;
Ok(Parser { header, reader, encoding, trap, state: State::default() })
}
pub fn next_token(&mut self) -> Result<Token> {
let (token, next) = self.state.clone().next(self)?;
self.state = next;
Ok(token)
}
#[inline]
pub fn skip_next(&mut self, token: Token) {
self.state = self.state.clone().skip(token);
}
pub fn read_label(&mut self, index: LabelIndex) -> Result<Label> {
let old = self.offset()?;
self.seek(index)?;
let mut label = [0u8; 16];
self.reader.read_exact(&mut label)?;
self.reader.seek(old)?;
Ok(label.into())
}
pub fn read_u64(&mut self, index: U64Index) -> Result<u64> {
self.seek(index)?;
self.reader.read_u64::<LE>().map_err(Into::into)
}
pub fn read_i64(&mut self, index: I64Index) -> Result<i64> {
self.seek(index)?;
self.reader.read_i64::<LE>().map_err(Into::into)
}
pub fn read_f64(&mut self, index: F64Index) -> Result<f64> {
self.seek(index)?;
self.reader.read_f64::<LE>().map_err(Into::into)
}
pub fn read_string(&mut self, index: StringIndex) -> Result<String> {
self.seek(index)?;
self.read_string_impl()
}
pub fn read_resref(&mut self, index: ResRefIndex) -> Result<ResRef> {
self.seek(index)?;
let size = self.reader.read_u8()? as usize;
let mut bytes = Vec::with_capacity(size);
unsafe { bytes.set_len(size); }
self.reader.read_exact(&mut bytes)?;
Ok(ResRef(bytes))
}
pub fn read_loc_string(&mut self, index: LocStringIndex) -> Result<LocString> {
self.seek(index)?;
let _total_size = self.read_u32()?;
let str_ref = StrRef(self.read_u32()?);
let count = self.read_u32()?;
let mut strings = Vec::with_capacity(count as usize);
for _i in 0..count {
strings.push(self.read_substring()?);
}
Ok(LocString { str_ref, strings })
}
pub fn read_byte_buf(&mut self, index: BinaryIndex) -> Result<Vec<u8>> {
self.seek(index)?;
self.read_bytes()
}
pub fn read_value(&mut self, value: SimpleValueRef) -> Result<SimpleValue> {
use self::SimpleValueRef::*;
Ok(match value {
Byte(val) => SimpleValue::Byte(val),
Char(val) => SimpleValue::Char(val),
Word(val) => SimpleValue::Word(val),
Short(val) => SimpleValue::Short(val),
Dword(val) => SimpleValue::Dword(val),
Int(val) => SimpleValue::Int(val),
Dword64(val) => SimpleValue::Dword64(self.read_u64(val)?),
Int64(val) => SimpleValue::Int64(self.read_i64(val)?),
Float(val) => SimpleValue::Float(val),
Double(val) => SimpleValue::Double(self.read_f64(val)?),
String(val) => SimpleValue::String(self.read_string(val)?),
ResRef(val) => SimpleValue::ResRef(self.read_resref(val)?),
LocString(val)=> SimpleValue::LocString(self.read_loc_string(val)?),
Void(val) => SimpleValue::Void(self.read_byte_buf(val)?),
})
}
#[inline]
fn seek<I: Index>(&mut self, index: I) -> Result<()> {
let offset = index.offset(&self.header);
self.reader.seek(SeekFrom::Start(offset))?;
Ok(())
}
#[inline]
fn offset(&mut self) -> Result<SeekFrom> {
Ok(SeekFrom::Start(self.reader.seek(SeekFrom::Current(0))?))
}
#[inline]
fn read_u32(&mut self) -> Result<u32> {
Ok(self.reader.read_u32::<LE>()?)
}
#[inline]
fn read_bytes(&mut self) -> Result<Vec<u8>> {
let size = self.read_u32()? as usize;
let mut bytes = Vec::with_capacity(size);
unsafe { bytes.set_len(size); }
self.reader.read_exact(&mut bytes)?;
Ok(bytes)
}
#[inline]
fn read_string_impl(&mut self) -> Result<String> {
let bytes = self.read_bytes()?;
Ok(self.encoding.decode(&bytes, self.trap)?)
}
#[inline]
fn read_substring(&mut self) -> Result<SubString> {
Ok(SubString {
key : StringKey(self.read_u32()?),
string: self.read_string_impl()?,
})
}
fn read_value_ref(&mut self, tag: u32) -> Result<SimpleValueRef> {
use self::SimpleValueRef::*;
let value = match tag {
0 => Byte (self.reader.read_u8()?),
1 => Char (self.reader.read_i8()?),
2 => Word (self.reader.read_u16::<LE>()?),
3 => Short(self.reader.read_i16::<LE>()?),
4 => Dword(self.reader.read_u32::<LE>()?),
5 => Int (self.reader.read_i32::<LE>()?),
8 => Float(self.reader.read_f32::<LE>()?),
6 => Dword64 (U64Index(self.read_u32()?)),
7 => Int64 (I64Index(self.read_u32()?)),
9 => Double (F64Index(self.read_u32()?)),
10 => String (StringIndex(self.read_u32()?)),
11 => ResRef (ResRefIndex(self.read_u32()?)),
12 => LocString(LocStringIndex(self.read_u32()?)),
13 => Void (BinaryIndex(self.read_u32()?)),
tag => return Err(Error::UnknownValue { tag, value: self.read_u32()? }),
};
Ok(value)
}
}
impl<R: Read + Seek> Iterator for Parser<R> {
type Item = Token;
fn next(&mut self) -> Option<Token> {
if let State::Finish = self.state {
return None;
}
let res = self.next_token();
if let Err(Error::ParsingFinished) = res {
return None;
}
Some(res.expect("Can't read token"))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.header.token_count(), None)
}
}
impl<R: Read + Seek> FusedIterator for Parser<R> {}