1use nom::bytes::complete::{take, take_while};
2use nom::IResult;
3use nom::multi::count;
4use nom::number::complete::{f32, i32, u32, u64};
5use nom::number::Endianness;
6use nom::sequence::tuple;
7use crate::parser::Pointer;
8use crate::sector::Sector;
9
10#[derive(Debug, PartialEq)]
11pub struct Element {
12 pub name: String,
13 pub element: ElementType
14}
15
16#[derive(Debug, Copy, Clone, PartialEq)]
17pub struct Transform {
18 pub flags: u32,
19 pub translation: [f32; 3],
20 pub rotation: [f32; 4],
21 pub scale_shear: [[f32; 3]; 3]
22}
23
24#[derive(Debug, PartialEq)]
25pub enum ElementType {
26 Reference(Vec<Element>),
28 ArrayOfReferences(Vec<Vec<Element>>),
29 VariantReference,
32 String(String),
34 F32(f32),
36 I32(i32),
38 Transform(Transform),
40
41 Array(Vec<ElementType>)
43}
44
45#[derive(Debug, PartialEq)]
46pub struct TypeInfo {
47 type_id: u32,
48 name_offset: Option<Pointer>,
49 children_offset: Option<Pointer>,
50 array_size: i32,
51}
52
53fn unsigned(is_64bits: bool, endianness: Endianness) -> impl FnMut(&[u8]) -> IResult<&[u8], u64> {
54 move |input| {
55 return if is_64bits {
56 u64(endianness)(input)
57 } else {
58 let (input, val) = u32(endianness)(input)?;
59 Ok((input, val as u64))
60 }
61 }
62}
63
64pub fn parse_type_info(endianness: Endianness, ptr_table: &Vec<Pointer>, is_64bits: bool, offset: u32) -> impl FnMut(&[u8]) -> IResult<&[u8], TypeInfo> + '_ {
65 move |input| {
66 let type_id = u32(endianness); let name_offset = unsigned(is_64bits, endianness); let children_offset = unsigned(is_64bits, endianness); let array_size = i32(endianness);
70
71 let (input, (type_id, _, _, array_size)) = tuple((type_id, name_offset, children_offset, array_size))(input)?;
72
73 let (input, _) = take(if is_64bits { 20usize } else { 16usize })(input)?;
74
75 let name_offset = ptr_table.iter().find(|ptr| ptr.src_offset == offset + 4).map(|ptr| ptr.clone());
76 let children_offset = ptr_table.iter().find(|ptr| ptr.src_offset == offset + if is_64bits { 12 } else { 8 }).map(|ptr| ptr.clone());
77
78 Ok((input, TypeInfo {
79 type_id,
80 name_offset,
81 children_offset,
82 array_size
83 }))
84 }
85}
86
87fn parse_string(input: &[u8]) -> IResult<&[u8], String> {
88 let (input, bytes) = take_while(|n| { n != 0x0 })(input)?;
89
90 Ok((input, std::str::from_utf8(bytes).expect("invalid string").to_string()))
91}
92
93pub fn parse_element(endianness: Endianness, is_64bits: bool, sectors: &Vec<Sector>, data_sector_id: u32, type_sector_id: u32, data_offset: u32, type_offset: u32) -> IResult<&[u8], Vec<Element>> {
94 let data_sector = §ors[data_sector_id as usize];
95 let type_sector = §ors[type_sector_id as usize];
96
97 let all_type_data = &*type_sector.data;
98 let all_data = &*data_sector.data;
99
100 let mut type_data = &all_type_data[type_offset as usize..];
101 let mut data = &all_data[data_offset as usize..];
102
103 let mut elements = Vec::new();
104
105 loop {
106 let (next, type_info) = parse_type_info(endianness, &type_sector.pointer_table, is_64bits, (all_type_data.len() - type_data.len()) as u32)(type_data)?;
107 if type_info.type_id == 0 || type_info.type_id > 22 {
108 break
109 }
110
111 let name = if let Some(name_offset) = type_info.name_offset {
112 let (_, name) = parse_string(§ors[name_offset.dst_sector as usize].data[name_offset.dst_offset as usize..])?;
113 name
114 } else {
115 "".to_string()
116 };
117
118 let element = if type_info.array_size > 0 {
119 let mut inners = Vec::new();
120 for _ in 0..(if type_info.array_size == 0 { 1 } else { type_info.array_size }) {
121 let (next, element_inner) = parse_element_data(endianness, is_64bits, §ors, data_sector_id, data_sector, all_data, data, &type_info)?;
122 data = next;
123
124 inners.push(element_inner);
125 }
126
127 Element {
128 name,
129 element: ElementType::Array(inners)
130 }
131 } else {
132 let (next, element_inner) = parse_element_data(endianness, is_64bits, §ors, data_sector_id, data_sector, all_data, data, &type_info)?;
133 data = next;
134
135 Element {
136 name,
137 element: element_inner
138 }
139 };
140
141 elements.push(element);
142 type_data = next;
143 }
144
145 Ok((data, elements))
146}
147
148fn parse_element_data<'a>(endianness: Endianness, is_64bits: bool, sectors: &'a Vec<Sector>, data_sector_id: u32, data_sector: &Sector, all_data: &[u8], mut data: &'a [u8], type_info: &TypeInfo) -> IResult<&'a [u8], ElementType> {
149 match type_info.type_id {
150 1 => {
151 Ok((data, ElementType::VariantReference))
152 }
153 2 => {
154 let pos = all_data.len() - data.len();
155 let (next, _) = unsigned(is_64bits, endianness)(data)?;
156
157 data = next;
158
159 let ptr = data_sector.resolve_pointer(pos);
160 let elements = if let Some(ptr) = ptr {
161 assert_eq!(ptr.dst_sector, data_sector_id);
162
163 let children_offset = type_info.children_offset.unwrap();
164
165 let (_, elements) = parse_element(
166 endianness,
167 is_64bits,
168 sectors,
169 ptr.dst_sector,
170 children_offset.dst_sector,
171 ptr.dst_offset,
172 children_offset.dst_offset
173 )?;
174
175 elements
176 } else {
177 Vec::new()
178 };
179
180 Ok((data, ElementType::Reference(elements)))
181 }
182 3 => {
183 let pos = all_data.len() - data.len() + 4;
184 let size = u32(endianness);
185 let offset = unsigned(is_64bits, endianness);
186
187 let (next, (size, _)) = tuple((size, offset))(data)?;
188 data = next;
189
190 let mut elements = Vec::new();
191
192 let data_ptr = data_sector.resolve_pointer(pos);
193 if size > 0 {
194 let data_ptr = data_ptr.unwrap();
195 let type_ptr = type_info.children_offset.unwrap();
196
197 let data_sector = §ors[data_ptr.dst_sector as usize];
198
199 let mut data_offset = data_ptr.dst_offset;
200 for _ in 0..size {
201 let (left_data, mut e) = parse_element(endianness, is_64bits, sectors, data_ptr.dst_sector, type_ptr.dst_sector, data_offset, type_ptr.dst_offset)?;
202 elements.append(&mut e);
203
204 data_offset = (data_sector.data.len() - left_data.len()) as u32;
205 }
206 }
207
208 Ok((data, ElementType::Reference(elements)))
209 }
210 4 => {
211 let pos = all_data.len() - data.len() + 4;
212 let size = u32(endianness);
213 let offset = unsigned(is_64bits, endianness);
214
215 let (next, (size, _)) = tuple((size, offset))(data)?;
216 data = next;
217
218 let ptr = data_sector.resolve_pointer(pos);
219
220 let mut references = Vec::new();
221
222 if let Some(ptr) = ptr {
223 let type_ptr = type_info.children_offset.unwrap();
224
225 let element_data_sector = §ors[ptr.dst_sector as usize];
226
227 for i in 0..size {
228 let element_ptr = element_data_sector.resolve_pointer((ptr.dst_offset + if is_64bits { 8 * i } else { 4 * i }) as usize).unwrap();
229
230 let (_, e) = parse_element(endianness, is_64bits, sectors, element_ptr.dst_sector, type_ptr.dst_sector, element_ptr.dst_offset, type_ptr.dst_offset)?;
231
232 references.push(e);
233 }
234 }
235
236 Ok((data, ElementType::ArrayOfReferences(references)))
237 }
238 5 => {
239 let offset = unsigned(is_64bits, endianness);
240 let data_ptr = unsigned(is_64bits, endianness);
241
242 let (next, (_, _)) = tuple((offset, data_ptr))(data)?;
243 data = next;
244
245 Ok((data, ElementType::VariantReference))
246 }
247 7 => {
248 let pos = all_data.len() - data.len();
249
250 let type_ptr = unsigned(is_64bits, endianness);
251 let size = u32(endianness);
252 let data_ptr = unsigned(is_64bits, endianness);
253
254 let (next, (_, size, _)) = tuple((type_ptr, size, data_ptr))(data)?;
255 data = next;
256
257 let type_ptr = data_sector.resolve_pointer(pos).unwrap();
258 let data_ptr = data_sector.resolve_pointer(pos + if is_64bits { 8 + 4 } else { 4 + 4 }).unwrap();
259
260 let mut data_offset = data_ptr.dst_offset;
261
262 let mut elements = Vec::new();
263
264 for _ in 0..size {
265 let (left_data, e) = parse_element(endianness, is_64bits, sectors, data_ptr.dst_sector, type_ptr.dst_sector, data_offset, type_ptr.dst_offset)?;
266
267 data_offset = (sectors[data_ptr.dst_sector as usize].data.len() - left_data.len()) as _;
268
269 elements.push(e);
270 }
271
272 Ok((data, ElementType::ArrayOfReferences(elements)))
273 }
274 8 => {
275 let pos = all_data.len() - data.len();
276 let (next, _) = unsigned(is_64bits, endianness)(data)?;
277
278 data = next;
279
280 let ptr = data_sector.resolve_pointer(pos).unwrap();
281 let (_, value) = parse_string(§ors[ptr.dst_sector as usize].data[ptr.dst_offset as usize..])?;
282
283 Ok((data, ElementType::String(value)))
284 }
285 9 => {
286 let flags = u32(endianness);
287 let translation = count(f32(endianness), 3);
288 let rotation = count(f32(endianness), 4);
289 let scale_shear = count(f32(endianness), 3 * 3);
290
291 let (next, (flags, translation, rotation, scale_shear)) = tuple((flags, translation, rotation, scale_shear))(data)?;
292 data = next;
293
294 Ok((data, ElementType::Transform(Transform {
295 flags,
296 translation: [translation[0], translation[1], translation[2]],
297 rotation: [rotation[0], rotation[1], rotation[2], rotation[3]],
298 scale_shear: [
299 [scale_shear[0], scale_shear[1], scale_shear[2]],
300 [scale_shear[3], scale_shear[4], scale_shear[5]],
301 [scale_shear[6], scale_shear[7], scale_shear[8]],
302 ]
303 })))
304 }
305 10 => {
306 let (next, val) = f32(endianness)(data)?;
307 data = next;
308
309 Ok((data, ElementType::F32(val)))
310 },
311 19 => {
312 let (next, val) = i32(endianness)(data)?;
313 data = next;
314
315 Ok((data, ElementType::I32(val)))
316 }
317 _ => {
318 panic!("Unknown element type id {}", type_info.type_id);
319 }
320 }
321}