1pub use crate::prelude::*;
2
3#[derive(Debug, PartialEq, Clone)]
4pub struct Parser<R: Read> {
5 reader: R,
6}
7
8impl<R: Read> Parser<R> {
9 pub fn new(reader: R) -> Self {
10 Parser { reader }
11 }
12
13 pub fn parse(&mut self) -> Result<EOFContainer, Error> {
14 let header = self.parse_header()?;
15 let body = self.parse_body(&header)?;
16
17 Ok(EOFContainer { header, body })
18 }
19
20 fn parse_header(&mut self) -> Result<EOFHeader, Error> {
21 let mut magic = [0u8; 2];
22 self.reader.read_exact(&mut magic)?;
23 if magic != EOF_MAGIC {
24 return Err(Error::InvalidMagic);
25 }
26
27 let version = self.reader.read_u8()?;
28 if version != 1 {
29 return Err(Error::InvalidVersion);
30 }
31
32 let kind_type = self.reader.read_u8()?;
33 let type_size = self.reader.read_u16::<LittleEndian>()?;
34 let kind_code = self.reader.read_u8()?;
35 let num_code_sections = self.reader.read_u16::<LittleEndian>()?;
36
37 if num_code_sections == 0 || num_code_sections as usize > MAX_CODE_SECTIONS {
38 return Err(Error::InvalidCodeSectionCount);
39 }
40
41 let code_size = self.reader.read_u16::<LittleEndian>()?;
42 let kind_container = self.reader.read_u8()?;
43 let num_container_sections = self.reader.read_u16::<LittleEndian>()?;
44 let container_size = self.reader.read_u8()?;
45 let kind_data = self.reader.read_u8()?;
46 let data_size = self.reader.read_u16::<LittleEndian>()?;
47 let terminator = self.reader.read_u8()?;
48
49 Ok(EOFHeader {
50 magic,
51 version,
52 kind_type,
53 type_size,
54 kind_code,
55 num_code_sections,
56 code_size,
57 kind_container,
58 num_container_sections,
59 container_size,
60 kind_data,
61 data_size,
62 terminator,
63 })
64 }
65
66 fn parse_body(&mut self, header: &EOFHeader) -> Result<Body, Error> {
67 let types_section = self.parse_types_section(header)?;
68 let code_section = self.read_section(header.code_size as usize)?;
69 let container_section = self.read_section(header.container_size as usize)?;
70 let data_section = self.read_section(header.data_size as usize)?;
71
72 Ok(Body {
73 types_section: types_section.clone().items,
74 inputs: types_section.items[0].inputs,
75 outputs: types_section.items[0].outputs,
76 max_stack_height: types_section.items[0].max_stack_height,
77 code_section,
78 container_section,
79 data_section,
80 })
81 }
82
83 fn parse_types_section(&mut self, header: &EOFHeader) -> Result<TypesSection, Error> {
84 let mut types = Vec::new();
85 let mut remaining_size = header.type_size as usize;
86
87 while remaining_size > 0 {
88 if remaining_size < 4 {
89 return Err(Error::InvalidTypeSectionSize);
90 }
91
92 let inputs = self.reader.read_u8()?;
93 let outputs = self.reader.read_u8()?;
94 let max_stack_height = self.reader.read_u16::<LittleEndian>()?;
95
96 types.push(TypeMetadata {
97 inputs,
98 outputs,
99 max_stack_height,
100 });
101
102 remaining_size -= 4;
103 }
104
105 if types.is_empty() {
106 return Err(Error::InvalidZeroSectionMetadata);
107 }
108
109 Ok(TypesSection { items: types })
110 }
111
112 fn read_section(&mut self, size: usize) -> Result<Vec<u8>, Error> {
113 let mut buffer = vec![0u8; size];
114 self.reader.read_exact(&mut buffer)?;
115 Ok(buffer)
116 }
117}
118
119#[cfg(test)]
120mod tests {
121 use super::*;
122
123 #[test]
124 fn test_parse_valid_eof() {
125 let mock_eof = vec![
127 0xEF, 0x00, 0x01, 0x01, 0x04, 0x00, 0x02, 0x01, 0x00, 0x0A, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00,
143 ];
144
145 let mut parser = Parser::new(Cursor::new(mock_eof));
146 let result = parser.parse();
147 assert!(result.is_ok());
148
149 let container = result.unwrap();
150 assert_eq!(container.header.magic, [0xEF, 0x00]);
151 assert_eq!(container.header.version, 1);
152 assert_eq!(container.body.code_section.len(), 10);
153 }
154
155 #[test]
156 fn test_parse_invalid_magic() {
157 let invalid_eof = vec![0x00, 0x00]; let mut parser = Parser::new(Cursor::new(invalid_eof));
159 let result = parser.parse();
160 assert!(matches!(result, Err(Error::InvalidMagic)));
161 }
162}