HUGE PERFOMANCE UPDATE: Now Decoder::encode uses mutable ref to WriteStream to write new data, instead of creating allocation every time something needs to be encoded

This commit is contained in:
mykola2312 2023-09-07 15:20:23 +03:00
parent d060e5ca63
commit a6bfa194b9
9 changed files with 44 additions and 46 deletions

View file

@ -1,10 +1,11 @@
use super::raw::Raw; use super::raw::Raw;
use super::stream::WriteStream;
use anyhow::Result; 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>; fn decode(raw: &Raw, offset: usize, size: usize) -> Result<Self>;
fn encode(&self) -> Result<Raw>; fn encode(&self, wd: &mut WriteStream) -> Result<()>;
fn get_enc_size(&self) -> usize; fn get_enc_size(&self) -> usize;
} }
@ -23,14 +24,10 @@ impl Decoder for String {
} }
} }
fn encode(&self) -> Result<Raw> { fn encode(&self, wd: &mut WriteStream) -> Result<()> {
let mut str = self.as_bytes().to_vec(); wd.write_bytes(self.as_bytes());
str.push(0); wd.write_u8(0)?;
Ok(Raw { Ok(())
offset: 0,
size: str.len(),
mem: str,
})
} }
fn get_enc_size(&self) -> usize { fn get_enc_size(&self) -> usize {

View file

@ -119,8 +119,7 @@ impl Decoder for ESHValue {
}) })
} }
fn encode(&self) -> Result<Raw> { fn encode(&self, wd: &mut WriteStream) -> Result<()> {
let mut wd = WriteStream::new(self.get_enc_size());
match self { match self {
ESHValue::Unknown(unk) => { ESHValue::Unknown(unk) => {
wd.write_u32(unk.data_type)?; wd.write_u32(unk.data_type)?;
@ -191,7 +190,7 @@ impl Decoder for ESHValue {
} }
}; };
Ok(wd.into_raw(0, 0)) Ok(())
} }
fn get_enc_size(&self) -> usize { fn get_enc_size(&self) -> usize {
@ -268,8 +267,7 @@ impl Decoder for ESH {
}) })
} }
fn encode(&self) -> Result<Raw> { fn encode(&self, wd: &mut WriteStream) -> Result<()> {
let mut wd = WriteStream::new(self.get_enc_size());
wd.write(&self.tag)?; wd.write(&self.tag)?;
wd.write_u32(self.props.len() as u32)?; wd.write_u32(self.props.len() as u32)?;
@ -278,7 +276,7 @@ impl Decoder for ESH {
wd.write(value)?; wd.write(value)?;
} }
Ok(wd.into_raw(0, 0)) Ok(())
} }
fn get_enc_size(&self) -> usize { fn get_enc_size(&self) -> usize {

View file

@ -1,7 +1,8 @@
use super::decoder::Decoder; use super::decoder::Decoder;
use super::raw::Raw; use super::raw::Raw;
use super::stream::WriteStream;
use anyhow::Result; use anyhow::Result;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt};
use encoding_rs::WINDOWS_1251; use encoding_rs::WINDOWS_1251;
use std::borrow::Borrow; use std::borrow::Borrow;
use std::fmt; use std::fmt;
@ -53,26 +54,20 @@ impl Decoder for FString {
} }
} }
fn encode(&self) -> Result<Raw> { fn encode(&self, wd: &mut WriteStream) -> Result<()> {
let mut buf = vec![0u8; 4];
let mut wdr = Cursor::new(&mut buf[..]);
let (chars, _, _) = WINDOWS_1251.encode(self.str.as_str()); let (chars, _, _) = WINDOWS_1251.encode(self.str.as_str());
if self.encoding == FStringEncoding::ANSI { if self.encoding == FStringEncoding::ANSI {
wdr.write_u32::<LittleEndian>(chars.len() as u32 & !(1 << 31))?; wd.write_u32(chars.len() as u32 & !(1 << 31))?;
buf.extend(chars.iter()); wd.write_bytes(&chars);
} else { } else {
// WCS2 // WCS2
wdr.write_u32::<LittleEndian>(chars.len() as u32 | (1 << 31))?; wd.write_u32(chars.len() as u32 | (1 << 31))?;
for &c in chars.iter() { for &c in chars.iter() {
buf.push(c); wd.write_u8(c)?;
buf.push(0); wd.write_u8(0)?;
} }
}; };
Ok(Raw { Ok(())
offset: 0,
size: buf.len(),
mem: buf,
})
} }
fn get_enc_size(&self) -> usize { fn get_enc_size(&self) -> usize {

View file

@ -1,5 +1,6 @@
use super::decoder::Decoder; use super::decoder::Decoder;
use super::raw::Raw; use super::raw::Raw;
use super::stream::WriteStream;
use super::world::World; use super::world::World;
use anyhow::anyhow; use anyhow::anyhow;
use anyhow::Result; use anyhow::Result;
@ -50,7 +51,12 @@ impl Save {
} }
pub fn save(&self, path: &Path) -> Result<()> { pub fn save(&self, path: &Path) -> Result<()> {
self.raw.assemble_file(path, vec![self.world.encode()?])?; let raw = {
let mut wd = WriteStream::new(0);
wd.write(&self.world)?;
wd.into_raw(self.world.offset, self.world.size)
};
self.raw.assemble_file(path, vec![raw])?;
Ok(()) Ok(())
} }

View file

@ -48,8 +48,7 @@ impl Decoder for SGD {
}) })
} }
fn encode(&self) -> Result<Raw> { fn encode(&self, wd: &mut WriteStream) -> Result<()> {
let mut wd = WriteStream::new(self.enc_size);
wd.write(&self.tag)?; wd.write(&self.tag)?;
wd.write_bytes(&self.unk1); wd.write_bytes(&self.unk1);
@ -66,7 +65,7 @@ impl Decoder for SGD {
} }
} }
Ok(wd.into_raw(0, 0)) Ok(())
} }
fn get_enc_size(&self) -> usize { fn get_enc_size(&self) -> usize {

View file

@ -18,11 +18,10 @@ impl Decoder for SSG {
Ok(SSG { tag, unk1 }) Ok(SSG { tag, unk1 })
} }
fn encode(&self) -> Result<Raw> { fn encode(&self, wd: &mut WriteStream) -> Result<()> {
let mut wd = WriteStream::new(self.get_enc_size());
wd.write(&self.tag)?; wd.write(&self.tag)?;
wd.write_bytes(&self.unk1); wd.write_bytes(&self.unk1);
Ok(wd.into_raw(0, 0x14)) Ok(())
} }
fn get_enc_size(&self) -> usize { fn get_enc_size(&self) -> usize {

View file

@ -116,6 +116,10 @@ impl WriteStream {
self.buf.get_mut().extend(bytes.iter()); self.buf.get_mut().extend(bytes.iter());
} }
pub fn reserve(&mut self, size: usize) {
self.buf.get_mut().reserve(size);
}
pub fn write_opt<T: DecoderCtx<DCtx, ECtx>, DCtx, ECtx>( pub fn write_opt<T: DecoderCtx<DCtx, ECtx>, DCtx, ECtx>(
&mut self, &mut self,
val: &T, val: &T,
@ -128,9 +132,11 @@ impl WriteStream {
} }
pub fn write<T: Decoder>(&mut self, val: &T) -> Result<()> { pub fn write<T: Decoder>(&mut self, val: &T) -> Result<()> {
let mut raw = val.encode()?; //let mut raw = val.encode()?;
self.skip(raw.mem.len()); //self.skip(raw.mem.len());
self.buf.get_mut().append(&mut raw.mem); //self.buf.get_mut().append(&mut raw.mem);
self.reserve(val.get_enc_size());
val.encode(self)?;
Ok(()) Ok(())
} }

View file

@ -17,11 +17,10 @@ impl Decoder for Tag {
Ok(Tag { name, version }) Ok(Tag { name, version })
} }
fn encode(&self) -> Result<Raw> { fn encode(&self, wd: &mut WriteStream) -> Result<()> {
let mut wd = WriteStream::new(self.get_enc_size());
wd.write(&self.name)?; wd.write(&self.name)?;
wd.write(&self.version)?; wd.write(&self.version)?;
Ok(wd.into_raw(0, self.get_enc_size())) Ok(())
} }
fn get_enc_size(&self) -> usize { fn get_enc_size(&self) -> usize {

View file

@ -88,7 +88,7 @@ impl Decoder for World {
}) })
} }
fn encode(&self) -> Result<Raw> { fn encode(&self, wd: &mut WriteStream) -> Result<()> {
let data = { let data = {
let mut wd = WriteStream::new(self.uncompressed_size as usize); let mut wd = WriteStream::new(self.uncompressed_size as usize);
@ -101,14 +101,13 @@ impl Decoder for World {
let raw = wd.into_raw(0, 0); let raw = wd.into_raw(0, 0);
deflate_bytes_zlib(&raw.mem) deflate_bytes_zlib(&raw.mem)
}; };
let mut wd = WriteStream::new(self.get_enc_size());
wd.write(&self.tag)?; wd.write(&self.tag)?;
wd.write_u32(self.uncompressed_size)?; wd.write_u32(self.uncompressed_size)?;
wd.write_u32(self.uncompressed_size)?; wd.write_u32(self.uncompressed_size)?;
wd.write_bytes(&data); wd.write_bytes(&data);
Ok(wd.into_raw(self.offset, self.size)) Ok(())
} }
fn get_enc_size(&self) -> usize { fn get_enc_size(&self) -> usize {