1use crate::{Identifier, Result};
2use byteorder::{ByteOrder, ReadBytesExt, WriteBytesExt};
3use std::{
4 fmt::Debug,
5 io::{Read, Write},
6};
7
8#[repr(C, align(16))]
11#[derive(Copy, Eq, PartialEq, Clone, Hash)]
12pub struct Table {
13 identifier: Identifier,
15 metadata_length: u64,
17 metadata_offset: u64,
19 child_count: u32,
22 sibling: u32,
24 chunk_index: u32,
26 chunk_count: u32,
28}
29
30impl Debug for Table {
31 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32 write!(
33 f,
34 "({:X}): meta \"{}:{}\", sib: {}, children: {}, chunks(count: {}, index: {})",
35 *self.identifier,
36 self.metadata_length,
37 self.metadata_offset,
38 self.sibling,
39 self.child_count,
40 self.chunk_count,
41 self.chunk_index
42 )
43 }
44}
45
46impl Default for Table {
47 fn default() -> Self {
48 Self {
49 identifier: Identifier::INVALID,
50 metadata_length: 0,
51 metadata_offset: 0,
52 child_count: 0,
53 sibling: 0,
54 chunk_index: 0,
55 chunk_count: 0,
56 }
57 }
58}
59
60impl Table {
61 pub const SIZE: usize = std::mem::size_of::<Self>();
63
64 pub fn create() -> TableBuilder {
66 TableBuilder::new()
67 }
68
69 pub fn identifier(&self) -> Identifier {
71 self.identifier
72 }
73
74 pub fn metadata_length(&self) -> u64 {
76 self.metadata_length
77 }
78
79 pub fn metadata_length_mut(&mut self) -> &mut u64 {
81 &mut self.metadata_length
82 }
83
84 pub fn metadata_offset(&self) -> u64 {
87 self.metadata_offset
88 }
89
90 pub fn metadata_offset_mut(&mut self) -> &mut u64 {
92 &mut self.metadata_offset
93 }
94
95 pub fn offset(&mut self, data_length: u64, chunk_count: u32) {
97 if self.metadata_length > 0 {
98 self.metadata_offset += data_length;
99 }
100 if self.chunk_count > 0 {
101 self.chunk_index += chunk_count;
102 }
103 }
104
105 pub fn child_count(&self) -> u32 {
107 self.child_count
108 }
109
110 pub fn sibling(&self) -> u32 {
113 self.sibling
114 }
115
116 pub fn sibling_mut(&mut self) -> &mut u32 {
118 &mut self.sibling
119 }
120
121 pub fn chunk_index(&self) -> u32 {
123 self.chunk_index
124 }
125
126 pub fn chunk_count(&self) -> u32 {
128 self.chunk_count
129 }
130
131 pub fn read<E: ByteOrder>(reader: &mut dyn Read) -> Result<Self> {
133 Ok(Self {
134 identifier: Identifier::new(reader.read_u128::<E>()?),
135 metadata_length: reader.read_u64::<E>()?,
136 metadata_offset: reader.read_u64::<E>()?,
137 child_count: reader.read_u32::<E>()?,
138 sibling: reader.read_u32::<E>()?,
139 chunk_index: reader.read_u32::<E>()?,
140 chunk_count: reader.read_u32::<E>()?,
141 })
142 }
143
144 pub fn write<E: ByteOrder>(self, writer: &mut dyn Write) -> Result<()> {
146 writer.write_u128::<E>(*self.identifier)?;
147 writer.write_u64::<E>(self.metadata_length)?;
148 writer.write_u64::<E>(self.metadata_offset)?;
149 writer.write_u32::<E>(self.child_count)?;
150 writer.write_u32::<E>(self.sibling)?;
151 writer.write_u32::<E>(self.chunk_index)?;
152 writer.write_u32::<E>(self.chunk_count)?;
153
154 Ok(())
155 }
156}
157
158pub struct TableBuilder {
160 table: Table,
161}
162
163impl TableBuilder {
164 fn new() -> Self {
166 Self {
167 table: Table::default(),
168 }
169 }
170
171 pub fn identifier(mut self, value: Identifier) -> Self {
173 self.table.identifier = value;
174 self
175 }
176
177 pub fn metadata_length(mut self, value: u64) -> Self {
179 self.table.metadata_length = value;
180 self
181 }
182
183 pub fn metadata_offset(mut self, value: u64) -> Self {
185 self.table.metadata_offset = value;
186 self
187 }
188
189 pub fn child_count(mut self, value: u32) -> Self {
191 self.table.child_count = value;
192 self
193 }
194
195 pub fn sibling(mut self, value: u32) -> Self {
197 self.table.sibling = value;
198 self
199 }
200
201 pub fn chunk_index(mut self, value: u32) -> Self {
203 self.table.chunk_index = value;
204 self
205 }
206
207 pub fn chunk_count(mut self, value: u32) -> Self {
209 self.table.chunk_count = value;
210 self
211 }
212
213 pub fn end(self) -> Table {
215 self.table
216 }
217}
218
219#[cfg(test)]
220mod tests {
221 use crate::Ecc;
222
223 use super::*;
224
225 #[test]
226 fn test_layout() {
227 assert_eq!(std::mem::size_of::<Table>(), 48);
228 }
229
230 #[test]
231 fn test_basics() {
232 let table = Table::create()
233 .identifier((Ecc::from("test1"), Ecc::INVALID).into())
234 .metadata_length(1)
235 .metadata_offset(2)
236 .child_count(3)
237 .sibling(4)
238 .chunk_count(5)
239 .chunk_index(6)
240 .end();
241
242 assert_eq!(
243 table.identifier().as_ecc2(),
244 (Ecc::new("test1"), Ecc::INVALID)
245 );
246 assert_eq!(table.metadata_length(), 1);
247 assert_eq!(table.metadata_offset(), 2);
248 assert_eq!(table.child_count(), 3);
249 assert_eq!(table.sibling(), 4);
250 assert_eq!(table.chunk_count(), 5);
251 assert_eq!(table.chunk_index(), 6);
252 }
253
254 #[test]
255 fn test_serialization() {
256 let mut buffer = vec![];
257 let table = Table::create()
258 .identifier((Ecc::from("test1"), Ecc::INVALID).into())
259 .metadata_length(1)
260 .metadata_offset(2)
261 .child_count(3)
262 .sibling(4)
263 .chunk_count(5)
264 .chunk_index(6)
265 .end();
266 assert!(table.write::<crate::LE>(&mut buffer).is_ok());
267
268 let result = Table::read::<crate::LE>(&mut buffer.as_slice()).unwrap();
269 assert_eq!(table, result);
270 }
271}