Decoder now has Opt type of implementing additional info that required to deal with complex decoding and add more context to result objects
This commit is contained in:
parent
c49622e2ac
commit
10fd8bb7cc
11 changed files with 37 additions and 12 deletions
|
|
@ -1,4 +1,5 @@
|
|||
mod decoder;
|
||||
mod entity;
|
||||
mod esh;
|
||||
mod fstring;
|
||||
mod raw;
|
||||
|
|
|
|||
|
|
@ -3,13 +3,15 @@ use anyhow::Result;
|
|||
use std::str;
|
||||
|
||||
pub trait Decoder: Sized {
|
||||
fn decode(raw: &Raw, offset: usize, size: usize) -> Result<Self>;
|
||||
type Opt;
|
||||
fn decode(raw: &Raw, offset: usize, size: usize, opt: Option<Self::Opt>) -> Result<Self>;
|
||||
fn encode(&self) -> Result<Raw>;
|
||||
fn get_enc_size(&self) -> usize;
|
||||
}
|
||||
|
||||
impl Decoder for String {
|
||||
fn decode(raw: &Raw, offset: usize, size: usize) -> Result<Self> {
|
||||
type Opt = ();
|
||||
fn decode(raw: &Raw, offset: usize, size: usize, _: Option<()>) -> Result<Self> {
|
||||
let str = &raw.mem[offset..];
|
||||
match str.iter().position(|&c| c == 0) {
|
||||
Some(pos) => Ok(str::from_utf8(&str[..pos])?.to_string()),
|
||||
|
|
|
|||
0
src/fot/entity.rs
Normal file
0
src/fot/entity.rs
Normal file
|
|
@ -76,7 +76,8 @@ impl ESHValue {
|
|||
}
|
||||
|
||||
impl Decoder for ESHValue {
|
||||
fn decode(raw: &Raw, offset: usize, _: usize) -> Result<Self> {
|
||||
type Opt = ();
|
||||
fn decode(raw: &Raw, offset: usize, _: usize, _: Option<()>) -> Result<Self> {
|
||||
let mut rd = ReadStream::new(raw, offset);
|
||||
let data_type = rd.read_u32()?;
|
||||
let data_size = rd.read_u32()?;
|
||||
|
|
@ -248,7 +249,8 @@ pub struct ESH {
|
|||
}
|
||||
|
||||
impl Decoder for ESH {
|
||||
fn decode(raw: &Raw, offset: usize, _: usize) -> Result<Self> {
|
||||
type Opt = ();
|
||||
fn decode(raw: &Raw, offset: usize, _: usize, _: Option<()>) -> Result<Self> {
|
||||
let mut rd = ReadStream::new(raw, offset);
|
||||
let tag: Tag = rd.read(0)?;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ pub struct FString {
|
|||
}
|
||||
|
||||
impl Decoder for FString {
|
||||
fn decode(raw: &Raw, offset: usize, _: usize) -> Result<Self> {
|
||||
type Opt = ();
|
||||
fn decode(raw: &Raw, offset: usize, _: usize, _: Option<()>) -> Result<Self> {
|
||||
let mut rdr = Cursor::new(&raw.mem[offset..]);
|
||||
let flen = rdr.read_u32::<LittleEndian>()? as usize;
|
||||
let len = flen & !(1 << 31);
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ impl Save {
|
|||
return Err(anyhow!("Unable to determine world block size"));
|
||||
}
|
||||
|
||||
let world = World::decode(&raw, world_offset, world_size)?;
|
||||
let world = World::decode(&raw, world_offset, world_size, None)?;
|
||||
Ok(Save { raw, world })
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ pub struct SGD {
|
|||
}
|
||||
|
||||
impl Decoder for SGD {
|
||||
fn decode(raw: &Raw, offset: usize, _: usize) -> Result<Self> {
|
||||
type Opt = ();
|
||||
fn decode(raw: &Raw, offset: usize, _: usize, _: Option<()>) -> Result<Self> {
|
||||
let mut rd = ReadStream::new(raw, offset);
|
||||
let tag: Tag = rd.read(0)?;
|
||||
let unk1 = rd.read_bytes(0x48)?;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ pub struct SSG {
|
|||
}
|
||||
|
||||
impl Decoder for SSG {
|
||||
fn decode(raw: &Raw, offset: usize, _: usize) -> Result<Self> {
|
||||
type Opt = ();
|
||||
fn decode(raw: &Raw, offset: usize, _: usize, _: Option<()>) -> Result<Self> {
|
||||
let mut rd = ReadStream::new(raw, offset);
|
||||
let tag: Tag = rd.read(0)?;
|
||||
let unk1 = rd.read_bytes(0x14)?;
|
||||
|
|
|
|||
|
|
@ -43,8 +43,17 @@ impl<'a> ReadStream<'a> {
|
|||
// "size" is not required to be actual size, it's only
|
||||
// a hint for Decoder::decode. Most of the structures are
|
||||
// dynamically determining their decoding and encoding sizes
|
||||
|
||||
// read_opt - decode with optional paramters. required for complex structure
|
||||
// with different origins (save / entfile) like entities
|
||||
pub fn read_opt<T: Decoder>(&mut self, size: usize, opt: T::Opt) -> Result<T> {
|
||||
let val = T::decode(&self.raw, self.offset(), size, Some(opt))?;
|
||||
self.skip(val.get_enc_size());
|
||||
Ok(val)
|
||||
}
|
||||
|
||||
pub fn read<T: Decoder>(&mut self, size: usize) -> Result<T> {
|
||||
let val = T::decode(&self.raw, self.offset(), size)?;
|
||||
let val = T::decode(&self.raw, self.offset(), size, None)?;
|
||||
self.skip(val.get_enc_size());
|
||||
Ok(val)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ pub struct Tag {
|
|||
}
|
||||
|
||||
impl Decoder for Tag {
|
||||
fn decode(raw: &Raw, offset: usize, size: usize) -> Result<Self> {
|
||||
type Opt = ();
|
||||
fn decode(raw: &Raw, offset: usize, size: usize, _: Option<()>) -> Result<Self> {
|
||||
let mut rd = ReadStream::new(raw, offset);
|
||||
let name: String = rd.read(0)?;
|
||||
let version: String = rd.read(0)?;
|
||||
|
|
|
|||
|
|
@ -52,7 +52,13 @@ impl World {
|
|||
}
|
||||
|
||||
let name = &types[type_idx as usize];
|
||||
println!("offset {:x} idx {} unk1 {} name {}", rd.offset(), i, unk2, name);
|
||||
println!(
|
||||
"offset {:x} idx {} unk1 {} name {}",
|
||||
rd.offset(),
|
||||
i,
|
||||
unk2,
|
||||
name
|
||||
);
|
||||
let _: ESH = rd.read(0)?;
|
||||
}
|
||||
|
||||
|
|
@ -61,7 +67,8 @@ impl World {
|
|||
}
|
||||
|
||||
impl Decoder for World {
|
||||
fn decode(raw: &Raw, offset: usize, size: usize) -> Result<Self> {
|
||||
type Opt = ();
|
||||
fn decode(raw: &Raw, offset: usize, size: usize, _: Option<()>) -> Result<Self> {
|
||||
let mut enc = ReadStream::new(raw, offset);
|
||||
|
||||
let tag: Tag = enc.read(Self::WORLD_TAG_LEN)?;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue