assembly_data/fdb/
parser.rs

1//! # Parse structures from a byte buffer
2
3use super::file::*;
4use assembly_core::nom::{
5    combinator::map, number::complete::le_u32, sequence::tuple, take, IResult,
6};
7use std::convert::TryInto;
8
9fn u8_4(i: &[u8]) -> IResult<&[u8], [u8; 4]> {
10    let (i, slice) = take!(i, 4)?;
11    Ok((i, slice.try_into().unwrap()))
12}
13
14/// Marker trait that implies that `Self` can be parsed in little-endian mode
15#[allow(clippy::upper_case_acronyms)]
16pub trait ParseLE: Sized + Copy {
17    /// Same as `std::mem::size_of::<Self>()`
18    const BYTE_COUNT: usize;
19    /// A byte array of the same length that can be parsed as `Self`
20    type Buf: AsMut<[u8]> + Default;
21    /// Function to parse the buffer into self
22    fn parse(i: &[u8]) -> IResult<&[u8], Self>;
23}
24
25impl ParseLE for u32 {
26    const BYTE_COUNT: usize = 4;
27    type Buf = [u8; 4];
28    fn parse(input: &[u8]) -> IResult<&[u8], u32> {
29        le_u32(input)
30    }
31}
32
33impl ParseLE for (u32, u32) {
34    const BYTE_COUNT: usize = 8;
35    type Buf = [u8; 8];
36    fn parse(input: &[u8]) -> IResult<&[u8], (u32, u32)> {
37        tuple((le_u32, le_u32))(input)
38    }
39}
40
41impl ParseLE for (u32, [u8; 4]) {
42    const BYTE_COUNT: usize = 8;
43    type Buf = [u8; 8];
44    fn parse(input: &[u8]) -> IResult<&[u8], (u32, [u8; 4])> {
45        tuple((le_u32, u8_4))(input)
46    }
47}
48
49impl ParseLE for (u32, u32, u32) {
50    const BYTE_COUNT: usize = 12;
51    type Buf = [u8; 12];
52    fn parse(input: &[u8]) -> IResult<&[u8], (u32, u32, u32)> {
53        tuple((le_u32, le_u32, le_u32))(input)
54    }
55}
56
57/// Trait that implements parsing from a FDB file
58#[allow(clippy::upper_case_acronyms)]
59pub trait ParseFDB: Sized + Copy {
60    /// The [`ParseLE`] compatible type that is equivalent to `Self`
61    type IO: ParseLE;
62    /// Create `Self` from an instance of IO
63    fn new(i: Self::IO) -> Self;
64
65    /// Parse an FDB structure from a input slice
66    ///
67    /// This function chains [`ParseLE::parse`] with [`ParseFDB::new`]
68    fn parse(input: &[u8]) -> IResult<&[u8], Self> {
69        map(Self::IO::parse, Self::new)(input)
70    }
71}
72
73impl ParseFDB for ArrayHeader {
74    type IO = (u32, u32);
75
76    fn new((a, b): Self::IO) -> Self {
77        ArrayHeader {
78            count: a,
79            base_offset: b,
80        }
81    }
82}
83
84impl ParseFDB for FDBTableDefHeader {
85    type IO = (u32, u32, u32);
86
87    fn new((a, b, c): Self::IO) -> Self {
88        FDBTableDefHeader {
89            column_count: a,
90            table_name_addr: b,
91            column_header_list_addr: c,
92        }
93    }
94}
95
96impl ParseFDB for FDBTableDataHeader {
97    type IO = (u32, u32);
98
99    fn new((a, b): Self::IO) -> Self {
100        FDBTableDataHeader {
101            buckets: ArrayHeader::new((a, b)),
102        }
103    }
104}
105
106impl ParseFDB for FDBColumnHeader {
107    type IO = (u32, u32);
108
109    fn new((a, b): Self::IO) -> Self {
110        FDBColumnHeader {
111            column_data_type: a,
112            column_name_addr: b,
113        }
114    }
115}
116
117impl ParseFDB for FDBRowHeaderListEntry {
118    type IO = (u32, u32);
119
120    fn new((a, b): Self::IO) -> Self {
121        FDBRowHeaderListEntry {
122            row_header_addr: a,
123            row_header_list_next_addr: b,
124        }
125    }
126}
127
128impl ParseFDB for FDBRowHeader {
129    type IO = (u32, u32);
130
131    fn new(io: Self::IO) -> Self {
132        FDBRowHeader {
133            fields: ArrayHeader::from(io),
134        }
135    }
136}
137
138impl ParseFDB for FDBTableHeader {
139    type IO = (u32, u32);
140
141    fn new((a, b): Self::IO) -> Self {
142        FDBTableHeader {
143            table_def_header_addr: a,
144            table_data_header_addr: b,
145        }
146    }
147}
148
149impl ParseFDB for FDBHeader {
150    type IO = (u32, u32);
151
152    fn new((a, b): Self::IO) -> Self {
153        FDBHeader {
154            tables: ArrayHeader::from((a, b)),
155        }
156    }
157}
158
159impl ParseFDB for FDBBucketHeader {
160    type IO = u32;
161
162    fn new(a: Self::IO) -> Self {
163        FDBBucketHeader {
164            row_header_list_head_addr: a,
165        }
166    }
167}
168
169impl ParseFDB for FDBFieldData {
170    type IO = (u32, [u8; 4]);
171
172    fn new((data_type, value): Self::IO) -> Self {
173        FDBFieldData { data_type, value }
174    }
175}