wolfrpg_map_parser/db_parser/models/
table.rs

1use crate::byte_utils::{as_u32_le, as_u32_vec, parse_string};
2use crate::common::u32_or_string::U32OrString;
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6/// A database table for storing related data.
7#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8#[derive(PartialEq, Clone)]
9pub struct Table {
10    index: usize,
11    rows: Vec<Vec<U32OrString>>,
12}
13
14impl Table {
15    pub(crate) fn parse(bytes: &[u8], index: usize) -> (usize, Self) {
16        let mut offset: usize = 0;
17
18        let _ = as_u32_le(&bytes[offset..]);
19        offset += 4;
20
21        let _db_type: usize = as_u32_le(&bytes[offset..]) as usize;
22        offset += 4;
23
24        let field_count: usize = as_u32_le(&bytes[offset..]) as usize;
25        offset += 4;
26
27        let fields: Vec<u32> = as_u32_vec(&bytes[offset..][..4 * field_count]);
28        offset += 4 * field_count;
29
30        let fields: Vec<(u32, u32)> = fields.iter().map(|f| {
31            (f / 1000, f % 1000)
32        }).collect();
33
34        let int_count: usize = fields.iter().filter(|(t, _)| *t==1).count();
35        let str_count: usize = fields.iter().filter(|(t, _)| *t==2).count();
36
37        let item_count: usize = as_u32_le(&bytes[offset..]) as usize;
38        offset += 4;
39
40        let mut rows: Vec<Vec<U32OrString>> = Vec::with_capacity(item_count);
41
42        for _ in 0..item_count {
43            let mut row_int: Vec<u32> = vec![];
44            let mut row_str = vec![];
45
46            for _ in 0..int_count {
47                let int: u32 = as_u32_le(&bytes[offset..]);
48                offset += 4;
49
50                row_int.push(int);
51            }
52
53            for _ in 0..str_count {
54                let (bytes_read, str): (usize, String) = parse_string(&bytes[offset..]);
55                offset += bytes_read;
56
57                row_str.push(str);
58            }
59
60            let mut row: Vec<U32OrString> = Vec::with_capacity(field_count);
61
62            for (t, i) in &fields {
63                match t {
64                    1 => row.push(U32OrString::U32(row_int[*i as usize])),
65                    2 => row.push(U32OrString::String(row_str[*i as usize].clone())),
66                    _ => unreachable!(),
67                }
68            }
69
70            rows.push(row);
71        }
72
73        (offset, Table {
74            index,
75            rows
76        })
77    }
78
79    /// The index of this table in the database.
80    pub fn index(&self) -> usize {
81        self.index
82    }
83
84    /// A list of tuples representing the database entries.
85    pub fn rows(&self) -> &Vec<Vec<U32OrString>> {
86        &self.rows
87    }
88
89    /// Mutable reference accessor for [`Table::rows`].
90    pub fn rows_mut(&mut self) -> &mut Vec<Vec<U32OrString>> {
91        &mut self.rows
92    }
93}