FString proper encoding

This commit is contained in:
mykola2312 2023-08-29 07:51:49 +03:00
parent 650cbcaaca
commit 0cd80927be
2 changed files with 11 additions and 10 deletions

View file

@ -6,7 +6,7 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use encoding_rs::WINDOWS_1251; use encoding_rs::WINDOWS_1251;
use std::str; use std::str;
// FString - Fallout String // FString - Fallout
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum FStringEncoding { pub enum FStringEncoding {
@ -17,6 +17,7 @@ pub enum FStringEncoding {
#[derive(Debug)] #[derive(Debug)]
pub struct FString { pub struct FString {
encoding: FStringEncoding, encoding: FStringEncoding,
enc_len: usize,
str: String str: String
} }
@ -28,24 +29,24 @@ impl Decoder for FString {
let start = offset + 4; let start = offset + 4;
if flen & (1<<31) == 0 { // ANSI if flen & (1<<31) == 0 { // ANSI
let str = str::from_utf8(&raw.mem[start..start+len])?; let str = str::from_utf8(&raw.mem[start..start+len])?;
Ok(FString { encoding: FStringEncoding::ANSI, str: str.to_string() }) Ok(FString { encoding: FStringEncoding::ANSI, enc_len: len, str: str.to_string() })
} else { // WCS2 } else { // WCS2
let chars: Vec<u8> = raw.mem[start..start+len*2] let chars: Vec<u8> = raw.mem[start..start+len*2]
.iter().step_by(2).copied().collect(); .iter().step_by(2).copied().collect();
let (str, _, _) = WINDOWS_1251.decode(&chars); let (str, _, _) = WINDOWS_1251.decode(&chars);
Ok(FString { encoding: FStringEncoding::WCS2, str: str.to_string() }) Ok(FString { encoding: FStringEncoding::WCS2, enc_len: len, str: str.to_string() })
} }
} }
fn encode(&self) -> Raw { fn encode(&self) -> Raw {
let mut buf = vec![0u8, 4]; let mut buf = vec![0u8; 4];
let mut wdr = Cursor::new(&mut buf[..]); let mut wdr = Cursor::new(&mut buf[..]);
if self.encoding == FStringEncoding::ANSI { if self.encoding == FStringEncoding::ANSI {
let _ = wdr.write_u32::<LittleEndian>(self.str.len() as u32 ^ (1<<31)); let _ = wdr.write_u32::<LittleEndian>(self.str.len() as u32 ^ (1<<31));
buf.append(&mut self.str.clone().into_bytes()); buf.append(&mut self.str.clone().into_bytes());
} else { // WCS2 } else { // WCS2
let _ = wdr.write_u32::<LittleEndian>(self.str.len() as u32 | (1<<31));
let (chars, _, _) = WINDOWS_1251.encode(self.str.as_str()); let (chars, _, _) = WINDOWS_1251.encode(self.str.as_str());
let _ = wdr.write_u32::<LittleEndian>(chars.len() as u32 | (1<<31));
for &c in chars.iter() { for &c in chars.iter() {
buf.push(c); buf.push(c);
buf.push(0); buf.push(0);
@ -55,9 +56,6 @@ impl Decoder for FString {
} }
fn get_enc_size(&self) -> usize { fn get_enc_size(&self) -> usize {
match self.encoding { 4 + self.enc_len
FStringEncoding::ANSI => 4 + self.str.len(),
FStringEncoding::WCS2 => 4 + self.str.len() * 2
}
} }
} }

View file

@ -22,9 +22,12 @@ impl World {
const WORLD_HDR_LEN: usize = 0x13; const WORLD_HDR_LEN: usize = 0x13;
pub fn test(&self) -> Result<()> { pub fn test(&self) -> Result<()> {
let a = FString::decode(&self.data, 0xF6, 0)?; let a = FString::decode(&self.data, 0xA2, 0)?;
dbg!(&a); dbg!(&a);
let b = a.encode();
dbg!(&b);
Ok(()) Ok(())
} }
} }