rtvm_primitives/bytecode/
eof.rs

1mod body;
2mod decode_helpers;
3mod header;
4mod types_section;
5
6pub use body::EofBody;
7pub use header::EofHeader;
8pub use types_section::TypesSection;
9
10use crate::Bytes;
11use core::cmp::min;
12use std::{vec, vec::Vec};
13
14/// EOF - Ethereum Object Format.
15///
16/// It consist of a header, body and raw original bytes Specified in EIP.
17/// Most of body contain Bytes so it references to the raw bytes.
18///
19/// If there is a need to create new EOF from scratch, it is recommended to use `EofBody` and
20/// use `encode` function to create full [`Eof`] object.
21#[derive(Clone, Debug, PartialEq, Eq, Hash)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23pub struct Eof {
24    pub header: EofHeader,
25    pub body: EofBody,
26    pub raw: Bytes,
27}
28
29impl Default for Eof {
30    fn default() -> Self {
31        let body = EofBody {
32            // types section with zero inputs, zero outputs and zero max stack size.
33            types_section: vec![TypesSection::default()],
34            // One code section with a STOP byte.
35            code_section: vec![[0x00].into()],
36            container_section: vec![],
37            data_section: Bytes::new(),
38            is_data_filled: true,
39        };
40        body.into_eof()
41    }
42}
43
44impl Eof {
45    /// Returns len of the header and body in bytes.
46    pub fn size(&self) -> usize {
47        self.header.size() + self.header.body_size()
48    }
49
50    /// Return raw EOF bytes.
51    pub fn raw(&self) -> &Bytes {
52        &self.raw
53    }
54
55    /// Returns a slice of the raw bytes.
56    /// If offset is greater than the length of the raw bytes, an empty slice is returned.
57    /// If len is greater than the length of the raw bytes, the slice is truncated to the length of the raw bytes.
58    pub fn data_slice(&self, offset: usize, len: usize) -> &[u8] {
59        self.body
60            .data_section
61            .get(offset..)
62            .and_then(|bytes| bytes.get(..min(len, bytes.len())))
63            .unwrap_or(&[])
64    }
65
66    /// Returns a slice of the data section.
67    pub fn data(&self) -> &[u8] {
68        &self.body.data_section
69    }
70
71    /// Slow encode EOF bytes.
72    pub fn encode_slow(&self) -> Bytes {
73        let mut buffer: Vec<u8> = Vec::with_capacity(self.size());
74        self.header.encode(&mut buffer);
75        self.body.encode(&mut buffer);
76        buffer.into()
77    }
78
79    /// Decode EOF from raw bytes.
80    pub fn decode(raw: Bytes) -> Result<Self, EofDecodeError> {
81        let (header, _) = EofHeader::decode(&raw)?;
82        let body = EofBody::decode(&raw, &header)?;
83        Ok(Self { header, body, raw })
84    }
85}
86
87/// EOF decode errors.
88#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
89pub enum EofDecodeError {
90    /// Short input while processing EOF.
91    MissingInput,
92    /// Short body while processing EOF.
93    MissingBodyWithoutData,
94    /// Body size is more than specified in the header.
95    DanglingData,
96    /// Invalid types section data.
97    InvalidTypesSection,
98    /// Invalid types section size.
99    InvalidTypesSectionSize,
100    /// Invalid EOF magic number.
101    InvalidEOFMagicNumber,
102    /// Invalid EOF version.
103    InvalidEOFVersion,
104    /// Invalid number for types kind
105    InvalidTypesKind,
106    /// Invalid number for code kind
107    InvalidCodeKind,
108    /// Invalid terminal code
109    InvalidTerminalByte,
110    /// Invalid data kind
111    InvalidDataKind,
112    /// Invalid kind after code
113    InvalidKindAfterCode,
114    /// Mismatch of code and types sizes.
115    MismatchCodeAndTypesSize,
116    /// There should be at least one size.
117    NonSizes,
118    /// Missing size.
119    ShortInputForSizes,
120    /// Size cant be zero
121    ZeroSize,
122    /// Invalid code number.
123    TooManyCodeSections,
124    /// Invalid number of code sections.
125    ZeroCodeSections,
126    /// Invalid container number.
127    TooManyContainerSections,
128}
129
130#[cfg(test)]
131mod test {
132
133    use super::*;
134    use crate::bytes;
135
136    #[test]
137    fn decode_eof() {
138        let bytes = bytes!("ef000101000402000100010400000000800000fe");
139        let eof = Eof::decode(bytes.clone()).unwrap();
140        assert_eq!(bytes, eof.encode_slow());
141    }
142
143    #[test]
144    fn data_slice() {
145        let bytes = bytes!("ef000101000402000100010400000000800000fe");
146        let mut eof = Eof::decode(bytes.clone()).unwrap();
147        eof.body.data_section = bytes!("01020304");
148        assert_eq!(eof.data_slice(0, 1), &[0x01]);
149        assert_eq!(eof.data_slice(0, 4), &[0x01, 0x02, 0x03, 0x04]);
150        assert_eq!(eof.data_slice(0, 5), &[0x01, 0x02, 0x03, 0x04]);
151        assert_eq!(eof.data_slice(1, 2), &[0x02, 0x03]);
152        assert_eq!(eof.data_slice(10, 2), &[]);
153        assert_eq!(eof.data_slice(1, 0), &[]);
154        assert_eq!(eof.data_slice(10, 0), &[]);
155    }
156}