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:
mykola2312 2023-09-01 15:12:05 +03:00
parent c49622e2ac
commit 10fd8bb7cc
11 changed files with 37 additions and 12 deletions

View file

@ -1,4 +1,5 @@
mod decoder; mod decoder;
mod entity;
mod esh; mod esh;
mod fstring; mod fstring;
mod raw; mod raw;

View file

@ -3,13 +3,15 @@ use anyhow::Result;
use std::str; use std::str;
pub trait Decoder: Sized { 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 encode(&self) -> Result<Raw>;
fn get_enc_size(&self) -> usize; fn get_enc_size(&self) -> usize;
} }
impl Decoder for String { 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..]; let str = &raw.mem[offset..];
match str.iter().position(|&c| c == 0) { match str.iter().position(|&c| c == 0) {
Some(pos) => Ok(str::from_utf8(&str[..pos])?.to_string()), Some(pos) => Ok(str::from_utf8(&str[..pos])?.to_string()),

0
src/fot/entity.rs Normal file
View file

View file

@ -76,7 +76,8 @@ impl ESHValue {
} }
impl Decoder for 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 mut rd = ReadStream::new(raw, offset);
let data_type = rd.read_u32()?; let data_type = rd.read_u32()?;
let data_size = rd.read_u32()?; let data_size = rd.read_u32()?;
@ -248,7 +249,8 @@ pub struct ESH {
} }
impl Decoder for 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 mut rd = ReadStream::new(raw, offset);
let tag: Tag = rd.read(0)?; let tag: Tag = rd.read(0)?;

View file

@ -24,7 +24,8 @@ pub struct FString {
} }
impl Decoder for 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 mut rdr = Cursor::new(&raw.mem[offset..]);
let flen = rdr.read_u32::<LittleEndian>()? as usize; let flen = rdr.read_u32::<LittleEndian>()? as usize;
let len = flen & !(1 << 31); let len = flen & !(1 << 31);

View file

@ -46,7 +46,7 @@ impl Save {
return Err(anyhow!("Unable to determine world block size")); 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 }) Ok(Save { raw, world })
} }

View file

@ -15,7 +15,8 @@ pub struct SGD {
} }
impl Decoder for 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 mut rd = ReadStream::new(raw, offset);
let tag: Tag = rd.read(0)?; let tag: Tag = rd.read(0)?;
let unk1 = rd.read_bytes(0x48)?; let unk1 = rd.read_bytes(0x48)?;

View file

@ -11,7 +11,8 @@ pub struct SSG {
} }
impl Decoder for 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 mut rd = ReadStream::new(raw, offset);
let tag: Tag = rd.read(0)?; let tag: Tag = rd.read(0)?;
let unk1 = rd.read_bytes(0x14)?; let unk1 = rd.read_bytes(0x14)?;

View file

@ -43,8 +43,17 @@ impl<'a> ReadStream<'a> {
// "size" is not required to be actual size, it's only // "size" is not required to be actual size, it's only
// a hint for Decoder::decode. Most of the structures are // a hint for Decoder::decode. Most of the structures are
// dynamically determining their decoding and encoding sizes // 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> { 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()); self.skip(val.get_enc_size());
Ok(val) Ok(val)
} }

View file

@ -10,7 +10,8 @@ pub struct Tag {
} }
impl Decoder for 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 mut rd = ReadStream::new(raw, offset);
let name: String = rd.read(0)?; let name: String = rd.read(0)?;
let version: String = rd.read(0)?; let version: String = rd.read(0)?;

View file

@ -52,7 +52,13 @@ impl World {
} }
let name = &types[type_idx as usize]; 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)?; let _: ESH = rd.read(0)?;
} }
@ -61,7 +67,8 @@ impl World {
} }
impl Decoder for 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 mut enc = ReadStream::new(raw, offset);
let tag: Tag = enc.read(Self::WORLD_TAG_LEN)?; let tag: Tag = enc.read(Self::WORLD_TAG_LEN)?;