Overhaul: migrated from anyhow to my own FError so error handling would be much better and precise
This commit is contained in:
parent
bf5810c4d7
commit
eff42b2605
17 changed files with 133 additions and 93 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
|
@ -8,12 +8,6 @@ version = "1.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
|
|
@ -54,7 +48,6 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
|||
name = "fot-save-edit"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"byteorder",
|
||||
"deflate",
|
||||
"encoding_rs",
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.75"
|
||||
byteorder = "1.4.3"
|
||||
deflate = "1.0.0"
|
||||
encoding_rs = "0.8.33"
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ mod decoder;
|
|||
mod entity;
|
||||
mod entitylist;
|
||||
mod esh;
|
||||
mod ferror;
|
||||
mod fstring;
|
||||
mod raw;
|
||||
pub mod save;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
use crate::fot::decoder::Decoder;
|
||||
|
||||
use super::esh::{ESHValue, ESH};
|
||||
use super::ferror::FError as FE;
|
||||
use super::stream::{ReadStream, WriteStream};
|
||||
use super::tag::Tag;
|
||||
use anyhow::{anyhow, Result};
|
||||
use indexmap::IndexMap;
|
||||
|
||||
const MAX_STATS: usize = 7;
|
||||
|
|
@ -273,13 +273,13 @@ pub struct Attributes {
|
|||
}
|
||||
|
||||
impl Attributes {
|
||||
pub fn from_binary(bin: &[u8]) -> Result<Self> {
|
||||
pub fn from_binary(bin: &[u8]) -> Result<Self, FE> {
|
||||
let mut rd = ReadStream::new(bin, 0);
|
||||
|
||||
let size1 = rd.read_u32()?;
|
||||
let esh: ESH = rd.read()?;
|
||||
if esh.props["Binary"] == ESHValue::Bool(false) {
|
||||
return Err(anyhow!("Attributes Binary == false"));
|
||||
return Err(FE::AttributesNonBinary);
|
||||
}
|
||||
|
||||
let mut stats: IndexMap<&'static str, u32> = IndexMap::with_capacity(7);
|
||||
|
|
@ -339,11 +339,11 @@ impl Attributes {
|
|||
addictions,
|
||||
})
|
||||
} else {
|
||||
return Err(anyhow!("Attributes has no esbin"));
|
||||
return Err(FE::AttributesNoESBIN);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_binary(mut self) -> Result<Vec<u8>> {
|
||||
pub fn into_binary(mut self) -> Result<Vec<u8>, FE> {
|
||||
let esbin = {
|
||||
let mut wd = WriteStream::new(self.enc_size);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,32 +1,32 @@
|
|||
use super::ferror::FError as FE;
|
||||
use super::stream::{ReadStream, WriteStream};
|
||||
use anyhow::{anyhow, Result};
|
||||
use std::str;
|
||||
|
||||
pub trait Decoder: Sized {
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>) -> Result<Self>;
|
||||
fn encode(&self, wd: &mut WriteStream) -> Result<()>;
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>) -> Result<Self, FE>;
|
||||
fn encode(&self, wd: &mut WriteStream) -> Result<(), FE>;
|
||||
fn get_enc_size(&self) -> usize;
|
||||
}
|
||||
|
||||
pub trait DecoderCtx<DCtx, ECtx>: Sized {
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>, ctx: DCtx) -> Result<Self>;
|
||||
fn encode(&self, wd: &mut WriteStream, ctx: ECtx) -> Result<()>;
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>, ctx: DCtx) -> Result<Self, FE>;
|
||||
fn encode(&self, wd: &mut WriteStream, ctx: ECtx) -> Result<(), FE>;
|
||||
fn get_enc_size(&self) -> usize;
|
||||
}
|
||||
|
||||
impl Decoder for String {
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>) -> Result<Self> {
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>) -> Result<Self, FE> {
|
||||
let bytes = rd.as_byte_arr();
|
||||
let pos = match bytes.iter().position(|&c| c == 0) {
|
||||
Some(pos) => pos,
|
||||
None => return Err(anyhow!("No zero-terminator found")),
|
||||
None => return Err(FE::NoZeroTerminator),
|
||||
};
|
||||
let str = str::from_utf8(rd.as_bytes(pos)?)?;
|
||||
rd.skip(1);
|
||||
Ok(str.to_string())
|
||||
}
|
||||
|
||||
fn encode(&self, wd: &mut WriteStream) -> Result<()> {
|
||||
fn encode(&self, wd: &mut WriteStream) -> Result<(), FE> {
|
||||
wd.write_bytes(self.as_bytes());
|
||||
wd.write_u8(0)?;
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ use super::attributes::Attributes;
|
|||
use super::decoder::DecoderCtx;
|
||||
use super::entitylist::{EntityEncoding, EntityList};
|
||||
use super::esh::{ESHValue, ESH};
|
||||
use super::ferror::FError as FE;
|
||||
use super::stream::{ReadStream, WriteStream};
|
||||
use anyhow::{anyhow, Result};
|
||||
|
||||
pub const NO_FLAGS: u32 = 0;
|
||||
pub const NO_ESH: usize = 0xFFFF;
|
||||
|
|
@ -16,34 +16,34 @@ pub struct Entity {
|
|||
}
|
||||
|
||||
impl Entity {
|
||||
pub fn get_esh(&self) -> Result<&ESH> {
|
||||
pub fn get_esh(&self) -> Result<&ESH, FE> {
|
||||
match &self.esh {
|
||||
Some(esh) => Ok(esh),
|
||||
None => Err(anyhow!("Entity has no ESH")),
|
||||
None => Err(FE::EntityNoESH),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_esh_mut(&mut self) -> Result<&mut ESH> {
|
||||
pub fn get_esh_mut(&mut self) -> Result<&mut ESH, FE> {
|
||||
match &mut self.esh {
|
||||
Some(esh) => Ok(esh),
|
||||
None => Err(anyhow!("Entity has no ESH")),
|
||||
None => Err(FE::EntityNoESH),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_attributes(&self) -> Result<Attributes> {
|
||||
pub fn get_attributes(&self) -> Result<Attributes, FE> {
|
||||
let value = match self.get_esh()?.get("Attributes") {
|
||||
Some(value) => value,
|
||||
None => return Err(anyhow!("Entity has no Attributes")),
|
||||
None => return Err(FE::EntityNoAttributes),
|
||||
};
|
||||
|
||||
if let ESHValue::Binary(bin) = value {
|
||||
Ok(Attributes::from_binary(&bin)?)
|
||||
} else {
|
||||
Err(anyhow!("Attributes is not binary"))
|
||||
Err(FE::AttributesNonBinary)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_attributes(&mut self, attrs: Attributes) -> Result<()> {
|
||||
pub fn set_attributes(&mut self, attrs: Attributes) -> Result<(), FE> {
|
||||
self.get_esh_mut()?
|
||||
.set("Attributes", ESHValue::Binary(attrs.into_binary()?));
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ impl Entity {
|
|||
}
|
||||
|
||||
impl DecoderCtx<&mut EntityList, &EntityList> for Entity {
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>, ctx: &mut EntityList) -> Result<Self> {
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>, ctx: &mut EntityList) -> Result<Self, FE> {
|
||||
let offset = rd.offset();
|
||||
Ok(match ctx.get_entity_encoding() {
|
||||
EntityEncoding::File => {
|
||||
|
|
@ -87,7 +87,7 @@ impl DecoderCtx<&mut EntityList, &EntityList> for Entity {
|
|||
})
|
||||
}
|
||||
|
||||
fn encode(&self, wd: &mut WriteStream, ctx: &EntityList) -> Result<()> {
|
||||
fn encode(&self, wd: &mut WriteStream, ctx: &EntityList) -> Result<(), FE> {
|
||||
match ctx.get_entity_encoding() {
|
||||
EntityEncoding::File => {
|
||||
wd.write(ctx.get_type_name(self.type_idx))?;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
use super::decoder::{Decoder, DecoderCtx};
|
||||
use super::entity::Entity;
|
||||
use super::ferror::FError as FE;
|
||||
use super::fstring::{FString, FStringEncoding};
|
||||
use super::stream::{ReadStream, WriteStream};
|
||||
use super::tag::{CTag, Tag};
|
||||
use anyhow::anyhow;
|
||||
use anyhow::Result;
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
|
|
@ -66,10 +65,10 @@ impl EntityList {
|
|||
&mut self.ents[id - 1]
|
||||
}
|
||||
|
||||
pub fn dump_to_entfile(&self, ent: &Entity, path: &Path) -> Result<()> {
|
||||
pub fn dump_to_entfile(&self, ent: &Entity, path: &Path) -> Result<(), FE> {
|
||||
let esh = match &ent.esh {
|
||||
Some(esh) => esh,
|
||||
None => return Err(anyhow!("entity has no esh")),
|
||||
None => return Err(FE::EntityNoESH),
|
||||
};
|
||||
|
||||
let tag = DEFAULT_ENTITY_TAG.to_tag();
|
||||
|
|
@ -87,7 +86,7 @@ impl EntityList {
|
|||
}
|
||||
|
||||
impl DecoderCtx<EntityEncoding, EntityEncoding> for EntityList {
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>, ctx: EntityEncoding) -> Result<Self> {
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>, ctx: EntityEncoding) -> Result<Self, FE> {
|
||||
let offset = rd.offset();
|
||||
let mut ent_list = EntityList {
|
||||
encoding: ctx,
|
||||
|
|
@ -137,7 +136,7 @@ impl DecoderCtx<EntityEncoding, EntityEncoding> for EntityList {
|
|||
})
|
||||
}
|
||||
|
||||
fn encode(&self, wd: &mut WriteStream, ctx: EntityEncoding) -> Result<()> {
|
||||
fn encode(&self, wd: &mut WriteStream, ctx: EntityEncoding) -> Result<(), FE> {
|
||||
match ctx {
|
||||
EntityEncoding::File => {
|
||||
for ent in self.ents.iter() {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use super::decoder::Decoder;
|
||||
use super::ferror::FError as FE;
|
||||
use super::fstring::FString;
|
||||
use super::stream::{ReadStream, WriteStream};
|
||||
use super::tag::Tag;
|
||||
use anyhow::Result;
|
||||
use indexmap::IndexMap;
|
||||
use std::fmt;
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ impl ESHValue {
|
|||
}
|
||||
|
||||
impl Decoder for ESHValue {
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>) -> Result<Self> {
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>) -> Result<Self, FE> {
|
||||
let data_type = rd.read_u32()?;
|
||||
let data_size = rd.read_u32()?;
|
||||
|
||||
|
|
@ -120,7 +120,7 @@ impl Decoder for ESHValue {
|
|||
})
|
||||
}
|
||||
|
||||
fn encode(&self, wd: &mut WriteStream) -> Result<()> {
|
||||
fn encode(&self, wd: &mut WriteStream) -> Result<(), FE> {
|
||||
match self {
|
||||
ESHValue::Unknown(unk) => {
|
||||
wd.write_u32(unk.data_type)?;
|
||||
|
|
@ -266,7 +266,7 @@ impl ESH {
|
|||
}
|
||||
|
||||
impl Decoder for ESH {
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>) -> Result<Self> {
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>) -> Result<Self, FE> {
|
||||
let offset = rd.offset();
|
||||
let tag: Tag = rd.read()?;
|
||||
|
||||
|
|
@ -286,7 +286,7 @@ impl Decoder for ESH {
|
|||
})
|
||||
}
|
||||
|
||||
fn encode(&self, wd: &mut WriteStream) -> Result<()> {
|
||||
fn encode(&self, wd: &mut WriteStream) -> Result<(), FE> {
|
||||
wd.write(&self.tag)?;
|
||||
|
||||
wd.write_u32(self.props.len() as u32)?;
|
||||
|
|
|
|||
51
src/fot/ferror.rs
Normal file
51
src/fot/ferror.rs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#[derive(Debug)]
|
||||
pub enum FError {
|
||||
IOError(std::io::Error),
|
||||
Utf8Error(std::str::Utf8Error),
|
||||
DeflateError(String),
|
||||
NoWorld,
|
||||
NoCampaign,
|
||||
UnknownWorldSize,
|
||||
StreamOverflow(usize, usize, usize),
|
||||
NoZeroTerminator,
|
||||
EntityNoESH,
|
||||
EntityNoAttributes,
|
||||
AttributesNonBinary,
|
||||
AttributesNoESBIN,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for FError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
use FError as FE;
|
||||
match self {
|
||||
FE::IOError(e) => write!(f, "IOError {}", e),
|
||||
FE::Utf8Error(e) => write!(f, "Utf8Error {}", e),
|
||||
FE::DeflateError(e) => write!(f, "DeflateError {}", e),
|
||||
FE::NoWorld => write!(f, "No world found in file"),
|
||||
FE::NoCampaign => write!(f, "No campaign found after world"),
|
||||
FE::UnknownWorldSize => write!(f, "Unable to determine world block size"),
|
||||
FE::StreamOverflow(offset, size, read) => write!(
|
||||
f,
|
||||
"stream read {} at offset {} overflow size {}",
|
||||
read, offset, size
|
||||
),
|
||||
FE::NoZeroTerminator => write!(f, "No zero-terminator when String::decode"),
|
||||
FE::EntityNoESH => write!(f, "Entity has no ESH"),
|
||||
FE::EntityNoAttributes => write!(f, "Entity has no Attributes"),
|
||||
FE::AttributesNonBinary => write!(f, "Attributes Binary != true"),
|
||||
FE::AttributesNoESBIN => write!(f, "Attributes has no esbin"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for FError {
|
||||
fn from(value: std::io::Error) -> Self {
|
||||
FError::IOError(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::str::Utf8Error> for FError {
|
||||
fn from(value: std::str::Utf8Error) -> Self {
|
||||
FError::Utf8Error(value)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
use super::decoder::Decoder;
|
||||
use super::ferror::FError as FE;
|
||||
use super::stream::{ReadStream, WriteStream};
|
||||
use anyhow::Result;
|
||||
use encoding_rs::WINDOWS_1251;
|
||||
use std::borrow::Borrow;
|
||||
use std::fmt;
|
||||
|
|
@ -22,7 +22,7 @@ pub struct FString {
|
|||
}
|
||||
|
||||
impl Decoder for FString {
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>) -> Result<Self> {
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>) -> Result<Self, FE> {
|
||||
//let mut rdr = Cursor::new(&raw.mem[offset..]);
|
||||
let flen = rd.read_u32()? as usize;
|
||||
let len = flen & !(1 << 31);
|
||||
|
|
@ -48,7 +48,7 @@ impl Decoder for FString {
|
|||
}
|
||||
}
|
||||
|
||||
fn encode(&self, wd: &mut WriteStream) -> Result<()> {
|
||||
fn encode(&self, wd: &mut WriteStream) -> Result<(), FE> {
|
||||
let (chars, _, _) = WINDOWS_1251.encode(self.str.as_str());
|
||||
if self.encoding == FStringEncoding::ANSI {
|
||||
wd.write_u32(chars.len() as u32 & !(1 << 31))?;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use anyhow::Result;
|
||||
use super::ferror::FError as FE;
|
||||
use memmem::{Searcher, TwoWaySearcher};
|
||||
use std::fs;
|
||||
use std::fs::OpenOptions;
|
||||
|
|
@ -31,7 +31,7 @@ impl Raw {
|
|||
None
|
||||
}
|
||||
|
||||
pub fn load_file(path: &Path) -> Result<Raw> {
|
||||
pub fn load_file(path: &Path) -> Result<Raw, FE> {
|
||||
let mem = fs::read(path)?;
|
||||
|
||||
Ok(Self {
|
||||
|
|
@ -41,7 +41,7 @@ impl Raw {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn assemble_file(&self, path: &Path, blocks: Vec<Raw>) -> Result<()> {
|
||||
pub fn assemble_file(&self, path: &Path, blocks: Vec<Raw>) -> Result<(), FE> {
|
||||
let mut file = BufWriter::new(
|
||||
OpenOptions::new()
|
||||
.create(true)
|
||||
|
|
@ -76,7 +76,7 @@ impl Raw {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn dump(&self, path: &Path) -> Result<()> {
|
||||
pub fn dump(&self, path: &Path) -> Result<(), FE> {
|
||||
let mut file = BufWriter::new(
|
||||
OpenOptions::new()
|
||||
.create(true)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
use super::decoder::DecoderCtx;
|
||||
use super::ferror::FError as FE;
|
||||
use super::raw::Raw;
|
||||
use super::stream::{ReadStream, WriteStream};
|
||||
use super::world::World;
|
||||
use anyhow::anyhow;
|
||||
use anyhow::Result;
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use std::path::Path;
|
||||
use std::str;
|
||||
|
|
@ -17,18 +16,18 @@ impl Save {
|
|||
const WORLD_TAG: &str = "<world>";
|
||||
const CAMPAIGN_TAG: &str = "<campaign>";
|
||||
|
||||
pub fn load(path: &Path) -> Result<Self> {
|
||||
pub fn load(path: &Path) -> Result<Self, FE> {
|
||||
let raw = Raw::load_file(path)?;
|
||||
let world_offset = match raw.find_str_backwards(Self::WORLD_TAG) {
|
||||
Some(offset) => offset,
|
||||
None => return Err(anyhow!("no world found in file")),
|
||||
None => return Err(FE::NoWorld),
|
||||
};
|
||||
|
||||
let mut world_size: usize = 0;
|
||||
{
|
||||
let campaign = match raw.find_str(Self::CAMPAIGN_TAG, world_offset) {
|
||||
Some(campaign) => world_offset + campaign,
|
||||
None => return Err(anyhow!("no campaign found after world")),
|
||||
None => return Err(FE::NoCampaign),
|
||||
};
|
||||
|
||||
for i in (campaign - 256..campaign).rev() {
|
||||
|
|
@ -43,7 +42,7 @@ impl Save {
|
|||
}
|
||||
}
|
||||
if world_size == 0 {
|
||||
return Err(anyhow!("Unable to determine world block size"));
|
||||
return Err(FE::UnknownWorldSize);
|
||||
}
|
||||
|
||||
let mut rd = ReadStream::new(&raw.mem, world_offset);
|
||||
|
|
@ -51,7 +50,7 @@ impl Save {
|
|||
Ok(Save { raw, world })
|
||||
}
|
||||
|
||||
pub fn save(&self, path: &Path) -> Result<()> {
|
||||
pub fn save(&self, path: &Path) -> Result<(), FE> {
|
||||
let raw = {
|
||||
let mut wd = WriteStream::new(0);
|
||||
wd.write_ctx(&self.world, ())?;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use super::decoder::Decoder;
|
||||
use super::ferror::FError as FE;
|
||||
use super::fstring::FString;
|
||||
use super::stream::{ReadStream, WriteStream};
|
||||
use super::tag::Tag;
|
||||
use anyhow::Result;
|
||||
use indexmap::IndexMap;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -14,7 +14,7 @@ pub struct SGD {
|
|||
}
|
||||
|
||||
impl Decoder for SGD {
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>) -> Result<Self> {
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>) -> Result<Self, FE> {
|
||||
let offset = rd.offset();
|
||||
let tag: Tag = rd.read()?;
|
||||
let unk1 = rd.read_bytes(0x48)?;
|
||||
|
|
@ -47,7 +47,7 @@ impl Decoder for SGD {
|
|||
})
|
||||
}
|
||||
|
||||
fn encode(&self, wd: &mut WriteStream) -> Result<()> {
|
||||
fn encode(&self, wd: &mut WriteStream) -> Result<(), FE> {
|
||||
wd.write(&self.tag)?;
|
||||
wd.write_bytes(&self.unk1);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use super::decoder::Decoder;
|
||||
use super::ferror::FError as FE;
|
||||
use super::stream::{ReadStream, WriteStream};
|
||||
use super::tag::Tag;
|
||||
use anyhow::Result;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SSG {
|
||||
|
|
@ -10,13 +10,13 @@ pub struct SSG {
|
|||
}
|
||||
|
||||
impl Decoder for SSG {
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>) -> Result<Self> {
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>) -> Result<Self, FE> {
|
||||
let tag: Tag = rd.read()?;
|
||||
let unk1 = rd.read_bytes(0x14)?;
|
||||
Ok(SSG { tag, unk1 })
|
||||
}
|
||||
|
||||
fn encode(&self, wd: &mut WriteStream) -> Result<()> {
|
||||
fn encode(&self, wd: &mut WriteStream) -> Result<(), FE> {
|
||||
wd.write(&self.tag)?;
|
||||
wd.write_bytes(&self.unk1);
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use super::decoder::{Decoder, DecoderCtx};
|
||||
use super::ferror::FError as FE;
|
||||
use super::raw::Raw;
|
||||
use anyhow::anyhow;
|
||||
use anyhow::Result;
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use std::io::Cursor;
|
||||
|
||||
|
|
@ -37,10 +36,10 @@ impl<'a> ReadStream<'a> {
|
|||
&self.mem[self.offset()..]
|
||||
}
|
||||
|
||||
pub fn as_bytes(&mut self, size: usize) -> Result<&'a [u8]> {
|
||||
pub fn as_bytes(&mut self, size: usize) -> Result<&'a [u8], FE> {
|
||||
if self.offset() + size > self.mem.len() {
|
||||
dbg!(self.offset(), size, self.mem.len());
|
||||
Err(anyhow!("as_bytes/read_bytes size is bigger than buffer"))
|
||||
Err(FE::StreamOverflow(self.offset(), self.size(), size))
|
||||
} else {
|
||||
let buf = &self.mem[self.offset()..self.offset() + size];
|
||||
self.skip(size);
|
||||
|
|
@ -48,7 +47,7 @@ impl<'a> ReadStream<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn read_bytes(&mut self, size: usize) -> Result<Vec<u8>> {
|
||||
pub fn read_bytes(&mut self, size: usize) -> Result<Vec<u8>, FE> {
|
||||
Ok(self.as_bytes(size)?.to_vec())
|
||||
}
|
||||
|
||||
|
|
@ -58,35 +57,35 @@ impl<'a> ReadStream<'a> {
|
|||
|
||||
// read_opt - decode with optional paramters. required for complex structure
|
||||
// with different origins (save / entfile) like entities
|
||||
pub fn read_ctx<T: DecoderCtx<DCtx, ECtx>, DCtx, ECtx>(&mut self, ctx: DCtx) -> Result<T> {
|
||||
pub fn read_ctx<T: DecoderCtx<DCtx, ECtx>, DCtx, ECtx>(&mut self, ctx: DCtx) -> Result<T, FE> {
|
||||
Ok(T::decode(self, ctx)?)
|
||||
}
|
||||
|
||||
pub fn read<T: Decoder>(&mut self) -> Result<T> {
|
||||
pub fn read<T: Decoder>(&mut self) -> Result<T, FE> {
|
||||
Ok(T::decode(self)?)
|
||||
}
|
||||
|
||||
pub fn read_u8(&mut self) -> Result<u8> {
|
||||
pub fn read_u8(&mut self) -> Result<u8, FE> {
|
||||
Ok(self.rdr.read_u8()?)
|
||||
}
|
||||
|
||||
pub fn read_bool(&mut self) -> Result<bool> {
|
||||
pub fn read_bool(&mut self) -> Result<bool, FE> {
|
||||
Ok(self.read_u8()? != 0)
|
||||
}
|
||||
|
||||
pub fn read_u16(&mut self) -> Result<u16> {
|
||||
pub fn read_u16(&mut self) -> Result<u16, FE> {
|
||||
Ok(self.rdr.read_u16::<LittleEndian>()?)
|
||||
}
|
||||
|
||||
pub fn read_i32(&mut self) -> Result<i32> {
|
||||
pub fn read_i32(&mut self) -> Result<i32, FE> {
|
||||
Ok(self.rdr.read_i32::<LittleEndian>()?)
|
||||
}
|
||||
|
||||
pub fn read_u32(&mut self) -> Result<u32> {
|
||||
pub fn read_u32(&mut self) -> Result<u32, FE> {
|
||||
Ok(self.rdr.read_u32::<LittleEndian>()?)
|
||||
}
|
||||
|
||||
pub fn read_f32(&mut self) -> Result<f32> {
|
||||
pub fn read_f32(&mut self) -> Result<f32, FE> {
|
||||
Ok(self.rdr.read_f32::<LittleEndian>()?)
|
||||
}
|
||||
}
|
||||
|
|
@ -132,39 +131,39 @@ impl WriteStream {
|
|||
&mut self,
|
||||
val: &T,
|
||||
ctx: ECtx,
|
||||
) -> Result<()> {
|
||||
) -> Result<(), FE> {
|
||||
self.reserve(val.get_enc_size());
|
||||
val.encode(self, ctx)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn write<T: Decoder>(&mut self, val: &T) -> Result<()> {
|
||||
pub fn write<T: Decoder>(&mut self, val: &T) -> Result<(), FE> {
|
||||
self.reserve(val.get_enc_size());
|
||||
val.encode(self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn write_u8(&mut self, val: u8) -> Result<()> {
|
||||
pub fn write_u8(&mut self, val: u8) -> Result<(), FE> {
|
||||
Ok(self.buf.write_u8(val)?)
|
||||
}
|
||||
|
||||
pub fn write_bool(&mut self, val: bool) -> Result<()> {
|
||||
pub fn write_bool(&mut self, val: bool) -> Result<(), FE> {
|
||||
self.write_u8(val as u8)
|
||||
}
|
||||
|
||||
pub fn write_u16(&mut self, val: u16) -> Result<()> {
|
||||
pub fn write_u16(&mut self, val: u16) -> Result<(), FE> {
|
||||
Ok(self.buf.write_u16::<LittleEndian>(val)?)
|
||||
}
|
||||
|
||||
pub fn write_i32(&mut self, val: i32) -> Result<()> {
|
||||
pub fn write_i32(&mut self, val: i32) -> Result<(), FE> {
|
||||
Ok(self.buf.write_i32::<LittleEndian>(val)?)
|
||||
}
|
||||
|
||||
pub fn write_u32(&mut self, val: u32) -> Result<()> {
|
||||
pub fn write_u32(&mut self, val: u32) -> Result<(), FE> {
|
||||
Ok(self.buf.write_u32::<LittleEndian>(val)?)
|
||||
}
|
||||
|
||||
pub fn write_f32(&mut self, val: f32) -> Result<()> {
|
||||
pub fn write_f32(&mut self, val: f32) -> Result<(), FE> {
|
||||
Ok(self.buf.write_f32::<LittleEndian>(val)?)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use super::decoder::Decoder;
|
||||
use super::ferror::FError as FE;
|
||||
use super::stream::{ReadStream, WriteStream};
|
||||
use anyhow::Result;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Tag {
|
||||
|
|
@ -9,13 +9,13 @@ pub struct Tag {
|
|||
}
|
||||
|
||||
impl Decoder for Tag {
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>) -> Result<Self> {
|
||||
fn decode<'a>(rd: &mut ReadStream<'a>) -> Result<Self, FE> {
|
||||
let name: String = rd.read()?;
|
||||
let version: String = rd.read()?;
|
||||
Ok(Tag { name, version })
|
||||
}
|
||||
|
||||
fn encode(&self, wd: &mut WriteStream) -> Result<()> {
|
||||
fn encode(&self, wd: &mut WriteStream) -> Result<(), FE> {
|
||||
wd.write(&self.name)?;
|
||||
wd.write(&self.version)?;
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
use super::decoder::DecoderCtx;
|
||||
use super::entitylist::{EntityEncoding, EntityList};
|
||||
use super::esh::ESHValue;
|
||||
use super::ferror::FError as FE;
|
||||
use super::fstring::FString;
|
||||
use super::sgd::SGD;
|
||||
use super::ssg::SSG;
|
||||
use super::stream::{ReadStream, WriteStream};
|
||||
use super::tag::Tag;
|
||||
use anyhow::anyhow;
|
||||
use anyhow::Result;
|
||||
use deflate::deflate_bytes_zlib;
|
||||
use inflate::inflate_bytes_zlib;
|
||||
|
||||
|
|
@ -30,7 +29,7 @@ pub struct World {
|
|||
impl World {
|
||||
const WORLD_HDR_LEN: usize = 0x13;
|
||||
|
||||
pub fn test(&mut self) -> Result<()> {
|
||||
pub fn test(&mut self) -> Result<(), FE> {
|
||||
//let actor_type = self.entlist.get_type_idx("Actor").unwrap();
|
||||
//let ent = self.entlist.get_entity_mut(2122);
|
||||
let ent = self.entlist.get_entity_mut(2158);
|
||||
|
|
@ -68,7 +67,7 @@ impl World {
|
|||
|
||||
pub type WorldOffsetSize = (usize, usize);
|
||||
impl DecoderCtx<WorldOffsetSize, ()> for World {
|
||||
fn decode<'a>(enc: &mut ReadStream<'a>, ctx: WorldOffsetSize) -> Result<Self> {
|
||||
fn decode<'a>(enc: &mut ReadStream<'a>, ctx: WorldOffsetSize) -> Result<Self, FE> {
|
||||
let offset = ctx.0;
|
||||
let size = ctx.1;
|
||||
|
||||
|
|
@ -76,7 +75,7 @@ impl DecoderCtx<WorldOffsetSize, ()> for World {
|
|||
let uncompressed_size = enc.read_u32()?;
|
||||
enc.skip(4);
|
||||
|
||||
let data = inflate_bytes_zlib(enc.as_bytes(size)?).map_err(|e| anyhow!(e))?;
|
||||
let data = inflate_bytes_zlib(enc.as_bytes(size)?).map_err(|e| FE::DeflateError(e))?;
|
||||
let mut rd = ReadStream::new(&data, 0);
|
||||
|
||||
let mission: FString = rd.read()?;
|
||||
|
|
@ -101,7 +100,7 @@ impl DecoderCtx<WorldOffsetSize, ()> for World {
|
|||
})
|
||||
}
|
||||
|
||||
fn encode(&self, wd: &mut WriteStream, _: ()) -> Result<()> {
|
||||
fn encode(&self, wd: &mut WriteStream, _: ()) -> Result<(), FE> {
|
||||
let data = {
|
||||
let mut wd = WriteStream::new(self.uncompressed_size as usize);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue