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:
parent
d060e5ca63
commit
a6bfa194b9
9 changed files with 44 additions and 46 deletions
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue