1use super::{MAGIC, VERSION};
4
5pub mod flags {
7 pub const LINKED: u16 = 0x0001;
10}
11
12#[derive(Clone, Copy, Debug, PartialEq, Eq)]
17#[repr(C, align(64))]
18pub struct Header {
19 pub magic: [u8; 4],
21 pub version: u32,
23 pub checksum: u32,
25 pub total_size: u32,
27
28 pub str_blob_offset: u32,
30 pub str_table_offset: u32,
31 pub node_types_offset: u32,
32 pub node_fields_offset: u32,
33 pub trivia_offset: u32,
34 pub type_meta_offset: u32,
35 pub entrypoints_offset: u32,
36 pub transitions_offset: u32,
37
38 pub str_table_count: u16,
40 pub node_types_count: u16,
41 pub node_fields_count: u16,
42 pub trivia_count: u16,
43 pub entrypoints_count: u16,
44 pub transitions_count: u16,
45 pub flags: u16,
47 pub(crate) _pad: u16,
49}
50
51const _: () = assert!(std::mem::size_of::<Header>() == 64);
52
53impl Default for Header {
54 fn default() -> Self {
55 Self {
56 magic: MAGIC,
57 version: VERSION,
58 checksum: 0,
59 total_size: 0,
60 str_blob_offset: 0,
61 str_table_offset: 0,
62 node_types_offset: 0,
63 node_fields_offset: 0,
64 trivia_offset: 0,
65 type_meta_offset: 0,
66 entrypoints_offset: 0,
67 transitions_offset: 0,
68 str_table_count: 0,
69 node_types_count: 0,
70 node_fields_count: 0,
71 trivia_count: 0,
72 entrypoints_count: 0,
73 transitions_count: 0,
74 flags: 0,
75 _pad: 0,
76 }
77 }
78}
79
80impl Header {
81 pub fn from_bytes(bytes: &[u8]) -> Self {
83 assert!(bytes.len() >= 64, "header too short");
84
85 Self {
86 magic: [bytes[0], bytes[1], bytes[2], bytes[3]],
87 version: u32::from_le_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]),
88 checksum: u32::from_le_bytes([bytes[8], bytes[9], bytes[10], bytes[11]]),
89 total_size: u32::from_le_bytes([bytes[12], bytes[13], bytes[14], bytes[15]]),
90 str_blob_offset: u32::from_le_bytes([bytes[16], bytes[17], bytes[18], bytes[19]]),
91 str_table_offset: u32::from_le_bytes([bytes[20], bytes[21], bytes[22], bytes[23]]),
92 node_types_offset: u32::from_le_bytes([bytes[24], bytes[25], bytes[26], bytes[27]]),
93 node_fields_offset: u32::from_le_bytes([bytes[28], bytes[29], bytes[30], bytes[31]]),
94 trivia_offset: u32::from_le_bytes([bytes[32], bytes[33], bytes[34], bytes[35]]),
95 type_meta_offset: u32::from_le_bytes([bytes[36], bytes[37], bytes[38], bytes[39]]),
96 entrypoints_offset: u32::from_le_bytes([bytes[40], bytes[41], bytes[42], bytes[43]]),
97 transitions_offset: u32::from_le_bytes([bytes[44], bytes[45], bytes[46], bytes[47]]),
98 str_table_count: u16::from_le_bytes([bytes[48], bytes[49]]),
99 node_types_count: u16::from_le_bytes([bytes[50], bytes[51]]),
100 node_fields_count: u16::from_le_bytes([bytes[52], bytes[53]]),
101 trivia_count: u16::from_le_bytes([bytes[54], bytes[55]]),
102 entrypoints_count: u16::from_le_bytes([bytes[56], bytes[57]]),
103 transitions_count: u16::from_le_bytes([bytes[58], bytes[59]]),
104 flags: u16::from_le_bytes([bytes[60], bytes[61]]),
105 _pad: u16::from_le_bytes([bytes[62], bytes[63]]),
106 }
107 }
108
109 pub fn to_bytes(&self) -> [u8; 64] {
111 let mut bytes = [0u8; 64];
112 bytes[0..4].copy_from_slice(&self.magic);
113 bytes[4..8].copy_from_slice(&self.version.to_le_bytes());
114 bytes[8..12].copy_from_slice(&self.checksum.to_le_bytes());
115 bytes[12..16].copy_from_slice(&self.total_size.to_le_bytes());
116 bytes[16..20].copy_from_slice(&self.str_blob_offset.to_le_bytes());
117 bytes[20..24].copy_from_slice(&self.str_table_offset.to_le_bytes());
118 bytes[24..28].copy_from_slice(&self.node_types_offset.to_le_bytes());
119 bytes[28..32].copy_from_slice(&self.node_fields_offset.to_le_bytes());
120 bytes[32..36].copy_from_slice(&self.trivia_offset.to_le_bytes());
121 bytes[36..40].copy_from_slice(&self.type_meta_offset.to_le_bytes());
122 bytes[40..44].copy_from_slice(&self.entrypoints_offset.to_le_bytes());
123 bytes[44..48].copy_from_slice(&self.transitions_offset.to_le_bytes());
124 bytes[48..50].copy_from_slice(&self.str_table_count.to_le_bytes());
125 bytes[50..52].copy_from_slice(&self.node_types_count.to_le_bytes());
126 bytes[52..54].copy_from_slice(&self.node_fields_count.to_le_bytes());
127 bytes[54..56].copy_from_slice(&self.trivia_count.to_le_bytes());
128 bytes[56..58].copy_from_slice(&self.entrypoints_count.to_le_bytes());
129 bytes[58..60].copy_from_slice(&self.transitions_count.to_le_bytes());
130 bytes[60..62].copy_from_slice(&self.flags.to_le_bytes());
131 bytes[62..64].copy_from_slice(&self._pad.to_le_bytes());
132 bytes
133 }
134
135 pub fn validate_magic(&self) -> bool {
136 self.magic == MAGIC
137 }
138
139 pub fn validate_version(&self) -> bool {
140 self.version == VERSION
141 }
142
143 pub fn is_linked(&self) -> bool {
145 self.flags & flags::LINKED != 0
146 }
147
148 pub fn set_linked(&mut self, linked: bool) {
150 if linked {
151 self.flags |= flags::LINKED;
152 } else {
153 self.flags &= !flags::LINKED;
154 }
155 }
156}