EOF_Parser/
parser.rs

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        // Create a mock EOF container
126        let mock_eof = vec![
127            0xEF, 0x00, // magic
128            0x01, // version
129            0x01, // kind_type
130            0x04, 0x00, // type_size
131            0x02, // kind_code
132            0x01, 0x00, // num_code_sections
133            0x0A, 0x00, // code_size
134            0x03, // kind_container
135            0x00, 0x00, // num_container_sections
136            0x00, // container_size
137            0x04, // kind_data
138            0x00, 0x00, // data_size
139            0x00, // terminator
140            // Types section
141            0x00, 0x01, 0x02, 0x00, // Code section
142            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]; // Invalid magic number
158        let mut parser = Parser::new(Cursor::new(invalid_eof));
159        let result = parser.parse();
160        assert!(matches!(result, Err(Error::InvalidMagic)));
161    }
162}