rtvm_primitives/bytecode/eof/
header.rs1use super::{
2 decode_helpers::{consume_u16, consume_u8},
3 EofDecodeError,
4};
5use std::vec::Vec;
6
7#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct EofHeader {
11 pub types_size: u16,
14 pub code_sizes: Vec<u16>,
17 pub container_sizes: Vec<u16>,
20 pub data_size: u16,
22 pub sum_code_sizes: usize,
24 pub sum_container_sizes: usize,
26}
27
28const KIND_TERMINAL: u8 = 0;
29const KIND_TYPES: u8 = 1;
30const KIND_CODE: u8 = 2;
31const KIND_CONTAINER: u8 = 3;
32const KIND_DATA: u8 = 4;
33
34#[inline]
35fn consume_header_section_size(input: &[u8]) -> Result<(&[u8], Vec<u16>, usize), EofDecodeError> {
36 let (input, num_sections) = consume_u16(input)?;
39 if num_sections == 0 {
40 return Err(EofDecodeError::NonSizes);
41 }
42 let byte_size = (num_sections * 2) as usize;
43 if input.len() < byte_size {
44 return Err(EofDecodeError::ShortInputForSizes);
45 }
46 let mut sizes = Vec::with_capacity(num_sections as usize);
47 let mut sum = 0;
48 for i in 0..num_sections as usize {
49 let code_size = u16::from_be_bytes([input[i * 2], input[i * 2 + 1]]);
52 if code_size == 0 {
53 return Err(EofDecodeError::ZeroSize);
54 }
55 sum += code_size as usize;
56 sizes.push(code_size);
57 }
58
59 Ok((&input[byte_size..], sizes, sum))
60}
61
62impl EofHeader {
63 pub fn size(&self) -> usize {
78 let optional_container_sizes = if self.container_sizes.is_empty() {
79 0
80 } else {
81 3 + self.container_sizes.len() * 2
82 };
83 13 + self.code_sizes.len() * 2 + optional_container_sizes
84 }
85
86 pub fn types_count(&self) -> usize {
88 self.types_size as usize / 4
89 }
90
91 pub fn body_size(&self) -> usize {
93 self.sum_code_sizes + self.sum_container_sizes + self.data_size as usize
94 }
95
96 pub fn eof_size(&self) -> usize {
98 self.size() + self.body_size()
99 }
100
101 pub fn encode(&self, buffer: &mut Vec<u8>) {
103 buffer.extend_from_slice(&0xEF00u16.to_be_bytes());
105 buffer.push(0x01);
107 buffer.push(KIND_TYPES);
109 buffer.extend_from_slice(&self.types_size.to_be_bytes());
111 buffer.push(KIND_CODE);
113 buffer.extend_from_slice(&(self.code_sizes.len() as u16).to_be_bytes());
115 for size in &self.code_sizes {
116 buffer.extend_from_slice(&size.to_be_bytes());
117 }
118 if self.container_sizes.is_empty() {
120 buffer.push(KIND_DATA);
121 } else {
122 buffer.push(KIND_CONTAINER);
123 buffer.extend_from_slice(&(self.container_sizes.len() as u16).to_be_bytes());
125 for size in &self.container_sizes {
126 buffer.extend_from_slice(&size.to_be_bytes());
127 }
128 buffer.push(KIND_DATA);
130 }
131 buffer.extend_from_slice(&self.data_size.to_be_bytes());
133 buffer.push(KIND_TERMINAL);
135 }
136
137 pub fn decode(input: &[u8]) -> Result<(Self, &[u8]), EofDecodeError> {
139 let mut header = EofHeader::default();
140
141 let (input, kind) = consume_u16(input)?;
143 if kind != 0xEF00 {
144 return Err(EofDecodeError::InvalidEOFMagicNumber);
145 }
146
147 let (input, version) = consume_u8(input)?;
149 if version != 0x01 {
150 return Err(EofDecodeError::InvalidEOFVersion);
151 }
152
153 let (input, kind_types) = consume_u8(input)?;
155 if kind_types != KIND_TYPES {
156 return Err(EofDecodeError::InvalidTypesKind);
157 }
158
159 let (input, types_size) = consume_u16(input)?;
162 header.types_size = types_size;
163
164 if header.types_size % 4 != 0 {
165 return Err(EofDecodeError::InvalidTypesSection);
166 }
167
168 let (input, kind_types) = consume_u8(input)?;
170 if kind_types != KIND_CODE {
171 return Err(EofDecodeError::InvalidCodeKind);
172 }
173
174 let (input, sizes, sum) = consume_header_section_size(input)?;
176
177 if sizes.len() > 1024 {
178 return Err(EofDecodeError::TooManyCodeSections);
179 }
180
181 if sizes.is_empty() {
182 return Err(EofDecodeError::ZeroCodeSections);
183 }
184
185 if sizes.len() != (types_size / 4) as usize {
186 return Err(EofDecodeError::MismatchCodeAndTypesSize);
187 }
188
189 header.code_sizes = sizes;
190 header.sum_code_sizes = sum;
191
192 let (input, kind_container_or_data) = consume_u8(input)?;
193
194 let input = match kind_container_or_data {
195 KIND_CONTAINER => {
196 let (input, sizes, sum) = consume_header_section_size(input)?;
198 if sizes.len() > 256 {
200 return Err(EofDecodeError::TooManyContainerSections);
201 }
202 header.container_sizes = sizes;
203 header.sum_container_sizes = sum;
204 let (input, kind_data) = consume_u8(input)?;
205 if kind_data != KIND_DATA {
206 return Err(EofDecodeError::InvalidDataKind);
207 }
208 input
209 }
210 KIND_DATA => input,
211 _ => return Err(EofDecodeError::InvalidKindAfterCode),
212 };
213
214 let (input, data_size) = consume_u16(input)?;
219 header.data_size = data_size;
220
221 let (input, terminator) = consume_u8(input)?;
223 if terminator != KIND_TERMINAL {
224 return Err(EofDecodeError::InvalidTerminalByte);
225 }
226
227 Ok((header, input))
228 }
229}
230
231#[cfg(test)]
232mod tests {
233 use super::*;
234 use crate::hex;
235
236 #[test]
237 fn sanity_header_decode() {
238 let input = hex!("ef000101000402000100010400000000800000fe");
239 let (header, _) = EofHeader::decode(&input).unwrap();
240 assert_eq!(header.types_size, 4);
241 assert_eq!(header.code_sizes, vec![1]);
242 assert_eq!(header.container_sizes, vec![]);
243 assert_eq!(header.data_size, 0);
244 }
245
246 #[test]
247 fn decode_header_not_terminated() {
248 let input = hex!("ef0001010004");
249 assert_eq!(EofHeader::decode(&input), Err(EofDecodeError::MissingInput));
250 }
251
252 #[test]
253 fn failing_test() {
254 let input = hex!("ef00010100040200010006030001001404000200008000016000e0000000ef000101000402000100010400000000800000fe");
255 let _ = EofHeader::decode(&input).unwrap();
256 }
257}