1use crate::{error::Result, format::Parser, reader::ReadSeek};
2use std::io::{Read, Seek};
3
4pub type Reader<R> = crate::reader::Reader<Lsf, R>;
6
7pub struct LsfData {
9 names: Vec<Vec<String>>,
10 nodes: Vec<NodeInfo>,
11 attribute_entries: Vec<AttributeEntry>,
12 value_bytes: Vec<u8>,
13 #[allow(dead_code)]
14 key_entries: Option<Vec<KeyEntry>>,
15}
16
17#[derive(Debug, Clone, Copy)]
18enum ValueType {
19 String,
20 Int64,
21 Bool,
22}
23
24impl ValueType {
25 const fn from_u32(value: u32) -> Option<Self> {
26 match value & 0b111_111 {
27 19 => Some(Self::Bool),
28 22 | 23 => Some(Self::String),
29 32 => Some(Self::Int64),
30 _anything_else => None,
31 }
32 }
33}
34
35impl LsfData {
36 pub fn print_summary(&self) {
38 let Some(mut current_node) = self.get_first() else {
39 return;
40 };
41
42 loop {
43 let NodeInfo {
44 name_index_outer,
45 name_index_inner,
46 next_sibling_index,
47 first_attribute_index,
48 ..
49 } = current_node;
50
51 let name = &self.names[*name_index_outer][*name_index_inner];
52
53 println!("{name}:");
54
55 self.print_attribute_summary(*first_attribute_index);
56
57 match u32::try_from(*next_sibling_index) {
58 Ok(value) => {
59 current_node = &self.nodes[usize_from_u32!(value)];
60 }
61 Err(_) => {
62 return;
63 }
64 }
65 }
66 }
67
68 fn get_first(&self) -> Option<&NodeInfo> {
69 self.nodes.iter().find(|node| node.parent_index == -1)
70 }
71
72 fn print_attribute_summary(&self, first_attribute_index: usize) {
73 let mut current_attribute = &self.attribute_entries[first_attribute_index];
74
75 loop {
76 let AttributeEntry {
77 name_index_outer,
78 name_index_inner,
79 next_index,
80 type_info,
81 offset,
82 } = current_attribute;
83
84 let name = &self.names[*name_index_outer][*name_index_inner];
85
86 print!("\t{name}: ");
87
88 if let Some(value_type) = ValueType::from_u32(*type_info) {
89 self.print_value(value_type, *offset, usize_from_u32!(type_info >> 6));
90 }
91
92 println!();
93
94 match u32::try_from(*next_index) {
95 Ok(value) => {
96 current_attribute = &self.attribute_entries[usize_from_u32!(value)];
97 }
98 Err(_) => {
99 return;
100 }
101 }
102 }
103 }
104
105 fn print_value(&self, value_type: ValueType, offset: usize, length: usize) {
106 let value_bytes = &self.value_bytes[offset..offset + length];
107
108 match value_type {
109 ValueType::String => {
110 let end = value_bytes
111 .iter()
112 .copied()
113 .enumerate()
114 .find_map(|(i, byte)| (byte == 0).then_some(i))
115 .unwrap_or(value_bytes.len());
116
117 print!("\"{}\"", String::from_utf8_lossy(&value_bytes[..end]));
118 }
119 ValueType::Int64 => match value_bytes.try_into().map(i64::from_le_bytes) {
120 Ok(i) => print!("{i}"),
121 Err(_) => print!("(i64 bytes) {value_bytes:?}"),
122 },
123 ValueType::Bool => match value_bytes {
124 [0] => print!("false"),
125 [1] => print!("true"),
126 other => print!("(bool bytes) {other:?}"),
127 },
128 }
129 }
130}
131
132#[derive(Debug, Default, Clone)]
134pub struct CompressionMetadata<T> {
135 pub num_bytes_compressed: T,
136 pub num_bytes_decompressed: T,
137}
138
139#[derive(Debug, Clone)]
141pub struct NodeInfo {
142 pub name_index_outer: usize,
144
145 pub name_index_inner: usize,
147
148 pub parent_index: i32,
150
151 pub next_sibling_index: i32,
153
154 pub first_attribute_index: usize,
156}
157
158#[derive(Debug, Clone)]
160pub struct AttributeEntry {
161 pub name_index_outer: usize,
163
164 pub name_index_inner: usize,
166
167 pub type_info: u32,
169
170 pub next_index: i32,
173
174 pub offset: usize,
176}
177
178#[derive(Debug, Clone)]
180pub struct KeyEntry {
181 pub node_index: usize,
183
184 pub name_index_outer: usize,
186
187 pub name_index_inner: usize,
189}
190
191#[derive(Default)]
193pub struct Lsf {
194 engine_version: u64,
195 names_metadata: CompressionMetadata<u64>,
196 keys_metadata: CompressionMetadata<u64>,
197 nodes_metadata: CompressionMetadata<u64>,
198 attributes_metadata: CompressionMetadata<u64>,
199 values_metadata: CompressionMetadata<usize>,
200 compression_flag_bytes: u32,
201 extended_format: u32,
202}
203
204impl Parser for Lsf {
205 const ID_BYTES: [u8; 4] = [b'L', b'S', b'O', b'F'];
206
207 const MIN_SUPPORTED_VERSION: u32 = 7;
208
209 type Output = LsfData;
210
211 fn read(&mut self, reader: &mut ReadSeek<impl Read + Seek>) -> Result<Self::Output> {
212 self.engine_version = reader.read_u64_from_le_bytes()?;
213 self.names_metadata.num_bytes_decompressed = reader.read_u32_from_le_bytes()?.into();
214 self.names_metadata.num_bytes_compressed = reader.read_u32_from_le_bytes()?.into();
215 self.keys_metadata.num_bytes_decompressed = reader.read_u32_from_le_bytes()?.into();
216 self.keys_metadata.num_bytes_compressed = reader.read_u32_from_le_bytes()?.into();
217 self.nodes_metadata.num_bytes_decompressed = reader.read_u32_from_le_bytes()?.into();
218 self.nodes_metadata.num_bytes_compressed = reader.read_u32_from_le_bytes()?.into();
219 self.attributes_metadata.num_bytes_decompressed = reader.read_u32_from_le_bytes()?.into();
220 self.attributes_metadata.num_bytes_compressed = reader.read_u32_from_le_bytes()?.into();
221 self.values_metadata.num_bytes_decompressed = reader.read_usize_from_u32_le_bytes()?;
222 self.values_metadata.num_bytes_compressed = reader.read_usize_from_u32_le_bytes()?;
223
224 self.compression_flag_bytes = reader.read_u32_from_le_bytes()?;
225 self.extended_format = reader.read_u32_from_le_bytes()?;
226
227 let names = parse_names(reader)?;
228 let nodes = self.parse_nodes(reader)?;
229 let attribute_entries = self.parse_attribute_entries(reader)?;
230 let value_bytes = self.parse_value_bytes(reader)?;
231 let key_entries = self.parse_key_entries(reader)?;
232
233 Ok(LsfData {
234 names,
235 nodes,
236 attribute_entries,
237 value_bytes,
238 key_entries,
239 })
240 }
241}
242
243impl Lsf {
244 fn parse_nodes(&self, reader: &mut ReadSeek<impl Read + Seek>) -> Result<Vec<NodeInfo>> {
245 let starting_position = reader.stream_position()?;
246 let mut nodes = Vec::new();
247
248 while reader.stream_position()? <
249 starting_position + self.nodes_metadata.num_bytes_decompressed
250 {
251 let name_index_inner = reader.read_u16_from_le_bytes()?.into();
252 let name_index_outer = reader.read_u16_from_le_bytes()?.into();
253 let parent_index = reader.read_i32_from_le_bytes()?;
254 let next_sibling_index = reader.read_i32_from_le_bytes()?;
255 let first_attribute_index = reader.read_usize_from_u32_le_bytes()?;
256
257 nodes.push(NodeInfo {
258 name_index_outer,
259 name_index_inner,
260 parent_index,
261 next_sibling_index,
262 first_attribute_index,
263 });
264 }
265
266 Ok(nodes)
267 }
268
269 fn parse_attribute_entries(
270 &self,
271 reader: &mut ReadSeek<impl Read + Seek>,
272 ) -> Result<Vec<AttributeEntry>> {
273 let starting_position = reader.stream_position()?;
274 let mut attributes = Vec::new();
275
276 while reader.stream_position()? <
277 starting_position + self.attributes_metadata.num_bytes_decompressed
278 {
279 let name_index_inner = reader.read_u16_from_le_bytes()?.into();
280 let name_index_outer = reader.read_u16_from_le_bytes()?.into();
281 let type_info = reader.read_u32_from_le_bytes()?;
282 let next_index = reader.read_i32_from_le_bytes()?;
283 let offset = reader.read_usize_from_u32_le_bytes()?;
284
285 attributes.push(AttributeEntry {
286 name_index_outer,
287 name_index_inner,
288 type_info,
289 next_index,
290 offset,
291 });
292 }
293
294 Ok(attributes)
295 }
296
297 fn parse_value_bytes(&self, reader: &mut ReadSeek<impl Read + Seek>) -> Result<Vec<u8>> {
298 let mut bytes = vec![0_u8; self.values_metadata.num_bytes_decompressed];
299 reader.read_exact(&mut bytes)?;
300
301 Ok(bytes)
302 }
303
304 fn parse_key_entries(
305 &self,
306 reader: &mut ReadSeek<impl Read + Seek>,
307 ) -> Result<Option<Vec<KeyEntry>>> {
308 let starting_position = reader.stream_position()?;
309 let mut key_entries = None;
310
311 while reader.stream_position()? <
312 starting_position + self.keys_metadata.num_bytes_decompressed
313 {
314 let node_index = reader.read_usize_from_u32_le_bytes()?;
315 let name_index_inner = reader.read_u16_from_le_bytes()?.into();
316 let name_index_outer = reader.read_u16_from_le_bytes()?.into();
317
318 key_entries.get_or_insert_with(Vec::new).push(KeyEntry {
319 node_index,
320 name_index_outer,
321 name_index_inner,
322 });
323 }
324
325 Ok(key_entries)
326 }
327}
328
329fn parse_names(reader: &mut ReadSeek<impl Read + Seek>) -> Result<Vec<Vec<String>>> {
330 let num_entries = reader.read_usize_from_u32_le_bytes()?;
331
332 (0..num_entries)
333 .map(|_| {
334 let num_names = reader.read_u16_from_le_bytes()?;
335 (0..num_names)
336 .map(|_| {
337 let num_bytes_in_name = usize::from(reader.read_u16_from_le_bytes()?);
338 let mut bytes = vec![0_u8; num_bytes_in_name];
339 reader.read_exact(&mut bytes)?;
340
341 Ok(String::from_utf8_lossy(&bytes).into_owned())
342 })
343 .collect()
344 })
345 .collect()
346}