revm_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::{b256, bytes, Bytes, B256};
11use core::cmp::min;
12use std::{fmt, vec, vec::Vec};
13
14pub const EOF_MAGIC_HASH: B256 =
16 b256!("9dbf3648db8210552e9c4f75c6a1c3057c0ca432043bd648be15fe7be05646f5");
17
18pub const EOF_MAGIC: u16 = 0xEF00;
20
21pub static EOF_MAGIC_BYTES: Bytes = bytes!("ef00");
23
24#[derive(Clone, Debug, PartialEq, Eq, Hash)]
28#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
29pub struct Eof {
30 pub header: EofHeader,
31 pub body: EofBody,
32 pub raw: Bytes,
33}
34
35impl Default for Eof {
36 fn default() -> Self {
37 let body = EofBody {
38 types_section: vec![TypesSection::default()],
40 code_section: vec![Bytes::from_static(&[0x00])],
42 container_section: vec![],
43 data_section: Bytes::new(),
44 is_data_filled: true,
45 };
46 body.into_eof()
47 }
48}
49
50impl Eof {
51 pub fn new(body: EofBody) -> Self {
53 body.into_eof()
54 }
55
56 pub fn size(&self) -> usize {
58 self.header.size() + self.header.body_size()
59 }
60
61 pub fn raw(&self) -> &Bytes {
63 &self.raw
64 }
65
66 pub fn data_slice(&self, offset: usize, len: usize) -> &[u8] {
70 self.body
71 .data_section
72 .get(offset..)
73 .and_then(|bytes| bytes.get(..min(len, bytes.len())))
74 .unwrap_or(&[])
75 }
76
77 pub fn data(&self) -> &[u8] {
79 &self.body.data_section
80 }
81
82 pub fn encode_slow(&self) -> Bytes {
84 let mut buffer: Vec<u8> = Vec::with_capacity(self.size());
85 self.header.encode(&mut buffer);
86 self.body.encode(&mut buffer);
87 buffer.into()
88 }
89
90 pub fn decode_dangling(mut raw: Bytes) -> Result<(Self, Bytes), EofDecodeError> {
93 let (header, _) = EofHeader::decode(&raw)?;
94 let eof_size = header.body_size() + header.size();
95 if eof_size > raw.len() {
96 return Err(EofDecodeError::MissingInput);
97 }
98 let dangling_data = raw.split_off(eof_size);
99 let body = EofBody::decode(&raw, &header)?;
100 Ok((Self { header, body, raw }, dangling_data))
101 }
102
103 pub fn decode(raw: Bytes) -> Result<Self, EofDecodeError> {
105 let (header, _) = EofHeader::decode(&raw)?;
106 let body = EofBody::decode(&raw, &header)?;
107 Ok(Self { header, body, raw })
108 }
109}
110
111#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
113#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
114pub enum EofDecodeError {
115 MissingInput,
117 MissingBodyWithoutData,
119 DanglingData,
121 InvalidTypesSection,
123 InvalidTypesSectionSize,
125 InvalidEOFMagicNumber,
127 InvalidEOFVersion,
129 InvalidTypesKind,
131 InvalidCodeKind,
133 InvalidTerminalByte,
135 InvalidDataKind,
137 InvalidKindAfterCode,
139 MismatchCodeAndTypesSize,
141 NonSizes,
143 ShortInputForSizes,
145 ZeroSize,
147 TooManyCodeSections,
149 ZeroCodeSections,
151 TooManyContainerSections,
153 InvalidEOFSize,
155}
156
157impl fmt::Display for EofDecodeError {
158 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159 let s = match self {
160 Self::MissingInput => "Short input while processing EOF",
161 Self::MissingBodyWithoutData => "Short body while processing EOF",
162 Self::DanglingData => "Body size is more than specified in the header",
163 Self::InvalidTypesSection => "Invalid types section data",
164 Self::InvalidTypesSectionSize => "Invalid types section size",
165 Self::InvalidEOFMagicNumber => "Invalid EOF magic number",
166 Self::InvalidEOFVersion => "Invalid EOF version",
167 Self::InvalidTypesKind => "Invalid number for types kind",
168 Self::InvalidCodeKind => "Invalid number for code kind",
169 Self::InvalidTerminalByte => "Invalid terminal code",
170 Self::InvalidDataKind => "Invalid data kind",
171 Self::InvalidKindAfterCode => "Invalid kind after code",
172 Self::MismatchCodeAndTypesSize => "Mismatch of code and types sizes",
173 Self::NonSizes => "There should be at least one size",
174 Self::ShortInputForSizes => "Missing size",
175 Self::ZeroSize => "Size cant be zero",
176 Self::TooManyCodeSections => "Invalid code number",
177 Self::ZeroCodeSections => "Invalid number of code sections",
178 Self::TooManyContainerSections => "Invalid container number",
179 Self::InvalidEOFSize => "Invalid initcode size",
180 };
181 f.write_str(s)
182 }
183}
184
185#[cfg(feature = "std")]
186impl std::error::Error for EofDecodeError {}
187
188#[cfg(test)]
189mod test {
190
191 use super::*;
192 use crate::bytes;
193
194 #[test]
195 fn decode_eof() {
196 let bytes = bytes!("ef000101000402000100010400000000800000fe");
197 let eof = Eof::decode(bytes.clone()).unwrap();
198 assert_eq!(bytes, eof.encode_slow());
199 }
200
201 #[test]
202 fn decode_eof_dangling() {
203 let test_cases = [
204 (
205 bytes!("ef000101000402000100010400000000800000fe"),
206 bytes!("010203"),
207 false,
208 ),
209 (
210 bytes!("ef000101000402000100010400000000800000fe"),
211 bytes!(""),
212 false,
213 ),
214 (
215 bytes!("ef000101000402000100010400000000800000"),
216 bytes!(""),
217 true,
218 ),
219 ];
220
221 for (eof_bytes, dangling_data, is_err) in test_cases {
222 let mut raw = eof_bytes.to_vec();
223 raw.extend(&dangling_data);
224 let raw = Bytes::from(raw);
225
226 let result = Eof::decode_dangling(raw.clone());
227 assert_eq!(result.is_err(), is_err);
228 if is_err {
229 continue;
230 }
231 let (decoded_eof, decoded_dangling) = result.unwrap();
232 assert_eq!(eof_bytes, decoded_eof.encode_slow());
233 assert_eq!(decoded_dangling, dangling_data);
234 }
235 }
236
237 #[test]
238 fn data_slice() {
239 let bytes = bytes!("ef000101000402000100010400000000800000fe");
240 let mut eof = Eof::decode(bytes.clone()).unwrap();
241 eof.body.data_section = bytes!("01020304");
242 assert_eq!(eof.data_slice(0, 1), &[0x01]);
243 assert_eq!(eof.data_slice(0, 4), &[0x01, 0x02, 0x03, 0x04]);
244 assert_eq!(eof.data_slice(0, 5), &[0x01, 0x02, 0x03, 0x04]);
245 assert_eq!(eof.data_slice(1, 2), &[0x02, 0x03]);
246
247 const EMPTY: &[u8] = &[];
248 assert_eq!(eof.data_slice(10, 2), EMPTY);
249 assert_eq!(eof.data_slice(1, 0), EMPTY);
250 assert_eq!(eof.data_slice(10, 0), EMPTY);
251 }
252}