rtvm_primitives/bytecode/eof/
body.rs

1use super::{Eof, EofDecodeError, EofHeader, TypesSection};
2use crate::Bytes;
3use std::vec::Vec;
4
5/// EOF Body, contains types, code, container and data sections.
6///
7/// Can be used to create new EOF object.
8#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct EofBody {
11    pub types_section: Vec<TypesSection>,
12    pub code_section: Vec<Bytes>,
13    pub container_section: Vec<Bytes>,
14    pub data_section: Bytes,
15    pub is_data_filled: bool,
16}
17
18impl EofBody {
19    // Get code section
20    pub fn code(&self, index: usize) -> Option<&Bytes> {
21        self.code_section.get(index)
22    }
23
24    /// Create EOF from body.
25    pub fn into_eof(self) -> Eof {
26        // TODO add bounds checks.
27        let header = EofHeader {
28            types_size: self.types_section.len() as u16 * 4,
29            code_sizes: self.code_section.iter().map(|x| x.len() as u16).collect(),
30            container_sizes: self
31                .container_section
32                .iter()
33                .map(|x| x.len() as u16)
34                .collect(),
35            data_size: self.data_section.len() as u16,
36            sum_code_sizes: self.code_section.iter().map(|x| x.len()).sum(),
37            sum_container_sizes: self.container_section.iter().map(|x| x.len()).sum(),
38        };
39        let mut buffer = Vec::new();
40        header.encode(&mut buffer);
41        self.encode(&mut buffer);
42        Eof {
43            header,
44            body: self,
45            raw: buffer.into(),
46        }
47    }
48
49    /// Encode Body into buffer.
50    pub fn encode(&self, buffer: &mut Vec<u8>) {
51        for types_section in &self.types_section {
52            types_section.encode(buffer);
53        }
54
55        for code_section in &self.code_section {
56            buffer.extend_from_slice(code_section);
57        }
58
59        for container_section in &self.container_section {
60            buffer.extend_from_slice(container_section);
61        }
62
63        buffer.extend_from_slice(&self.data_section);
64    }
65
66    /// Decode EOF body from buffer and Header.
67    pub fn decode(input: &Bytes, header: &EofHeader) -> Result<Self, EofDecodeError> {
68        let header_len = header.size();
69        let partial_body_len =
70            header.sum_code_sizes + header.sum_container_sizes + header.types_size as usize;
71        let full_body_len = partial_body_len + header.data_size as usize;
72
73        if input.len() < header_len + partial_body_len {
74            return Err(EofDecodeError::MissingBodyWithoutData);
75        }
76
77        if input.len() > header_len + full_body_len {
78            return Err(EofDecodeError::DanglingData);
79        }
80
81        let mut body = EofBody::default();
82
83        let mut types_input = &input[header_len..];
84        for _ in 0..header.types_count() {
85            let (types_section, local_input) = TypesSection::decode(types_input)?;
86            types_input = local_input;
87            body.types_section.push(types_section);
88        }
89
90        // extract code section
91        let mut start = header_len + header.types_size as usize;
92        for size in header.code_sizes.iter().map(|x| *x as usize) {
93            body.code_section.push(input.slice(start..start + size));
94            start += size;
95        }
96
97        // extract container section
98        for size in header.container_sizes.iter().map(|x| *x as usize) {
99            body.container_section
100                .push(input.slice(start..start + size));
101            start += size;
102        }
103
104        body.data_section = input.slice(start..);
105        body.is_data_filled = body.data_section.len() == header.data_size as usize;
106
107        Ok(body)
108    }
109}