msg_tool\scripts\qlie\archive\pack/
delphi.rs

1use crate::ext::io::*;
2use crate::types::*;
3use crate::utils::encoding::*;
4use crate::utils::struct_pack::*;
5use anyhow::Result;
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use std::io::{Read, Seek};
9
10#[derive(Serialize, Deserialize, Debug, Clone)]
11#[serde(tag = "type", content = "value")]
12pub enum DelphiValue {
13    Uint8(u8),
14    Uint16(u16),
15    LongDouble([u8; 10]),
16    Unk6,
17    String(String),
18    Unk8,
19    Bool(bool),
20    ByteString(Vec<u8>),
21    StringArray(Vec<String>),
22    UnicodeString(String),
23}
24
25impl DelphiValue {
26    pub fn as_bytes<'a>(&'a self) -> Option<&'a [u8]> {
27        match self {
28            DelphiValue::ByteString(b) => Some(b),
29            _ => None,
30        }
31    }
32}
33
34impl StructUnpack for DelphiValue {
35    fn unpack<R: Read + Seek>(
36        reader: &mut R,
37        big: bool,
38        encoding: Encoding,
39        info: &Option<Box<dyn std::any::Any>>,
40    ) -> Result<Self> {
41        let type_id = u8::unpack(reader, big, encoding, info)?;
42        match type_id {
43            2 => Ok(DelphiValue::Uint8(u8::unpack(reader, big, encoding, info)?)),
44            3 => Ok(DelphiValue::Uint16(u16::unpack(
45                reader, big, encoding, info,
46            )?)),
47            5 => Ok(DelphiValue::LongDouble({
48                let mut buf = [0u8; 10];
49                reader.read_exact(&mut buf)?;
50                buf
51            })),
52            6 | 7 => Ok(DelphiValue::String({
53                let slen = u8::unpack(reader, big, encoding, info)? as usize;
54                let buf = reader.read_exact_vec(slen)?;
55                decode_to_string(encoding, &buf, true)?
56            })),
57            8 => Ok(DelphiValue::Bool(false)),
58            9 => Ok(DelphiValue::Bool(true)),
59            10 => Ok(DelphiValue::ByteString({
60                let slen = u32::unpack(reader, big, encoding, info)? as usize;
61                reader.read_exact_vec(slen)?
62            })),
63            11 => Ok(DelphiValue::StringArray({
64                let mut arr = Vec::new();
65                let mut len;
66                while {
67                    len = u8::unpack(reader, big, encoding, info)?;
68                    len > 0
69                } {
70                    let buf = reader.read_exact_vec(len as usize)?;
71                    arr.push(decode_to_string(encoding, &buf, true)?);
72                }
73                arr
74            })),
75            18 => Ok(DelphiValue::UnicodeString({
76                let slen = u32::unpack(reader, big, encoding, info)? as usize;
77                let buf = reader.read_exact_vec(slen * 2)?;
78                decode_to_string(
79                    if big {
80                        Encoding::Utf16BE
81                    } else {
82                        Encoding::Utf16LE
83                    },
84                    &buf,
85                    true,
86                )?
87            })),
88            _ => Err(anyhow::anyhow!("Unknown Delphi value type: {}", type_id)),
89        }
90    }
91}
92
93#[derive(Serialize, Deserialize, Debug, Clone)]
94
95pub struct DelphiObject {
96    pub type_name: String,
97    pub name: String,
98    pub properties: HashMap<String, DelphiValue>,
99    pub contents: Vec<DelphiObject>,
100}
101
102impl StructUnpack for DelphiObject {
103    fn unpack<R: Read + Seek>(
104        reader: &mut R,
105        big: bool,
106        encoding: Encoding,
107        info: &Option<Box<dyn std::any::Any>>,
108    ) -> Result<Self> {
109        let type_len = u8::unpack(reader, big, encoding, info)? as usize;
110        let type_name = {
111            let buf = reader.read_exact_vec(type_len)?;
112            decode_to_string(encoding, &buf, true)?
113        };
114        let name_len = u8::unpack(reader, big, encoding, info)? as usize;
115        let name = {
116            let buf = reader.read_exact_vec(name_len)?;
117            decode_to_string(encoding, &buf, true)?
118        };
119        let mut properties = HashMap::new();
120        let mut keylen;
121        while {
122            keylen = u8::unpack(reader, big, encoding, info)?;
123            keylen > 0
124        } {
125            let key_buf = reader.read_exact_vec(keylen as usize)?;
126            let key = decode_to_string(encoding, &key_buf, true)?;
127            let value = DelphiValue::unpack(reader, big, encoding, info)?;
128            properties.insert(key, value);
129        }
130        let mut contents = Vec::new();
131        while reader.peek_u8()? != 0 {
132            contents.push(DelphiObject::unpack(reader, big, encoding, info)?);
133        }
134        reader.read_u8()?; // consume the terminating 0
135        return Ok(Self {
136            type_name,
137            name,
138            properties,
139            contents,
140        });
141    }
142}
143
144pub fn deser_delphi<R: Read + Seek>(reader: &mut R) -> Result<DelphiObject> {
145    let sig = reader.read_u32()?;
146    if sig != 0x30465054 {
147        return Err(anyhow::anyhow!(
148            "Invalid Delphi object signature: {:08X}",
149            sig
150        ));
151    }
152    Ok(DelphiObject::unpack(reader, false, Encoding::Cp932, &None)?)
153}