1mod body;
2mod code_info;
3mod decode_helpers;
4mod header;
5pub mod printer;
6pub mod verification;
7
8pub use body::EofBody;
9pub use code_info::CodeInfo;
10pub use header::EofHeader;
11pub use verification::*;
12
13use core::cmp::min;
14use primitives::{b256, bytes, Bytes, B256};
15use std::{fmt, vec, vec::Vec};
16
17pub const EOF_MAGIC_HASH: B256 =
19 b256!("0x9dbf3648db8210552e9c4f75c6a1c3057c0ca432043bd648be15fe7be05646f5");
20
21pub const EOF_MAGIC: u16 = 0xEF00;
23
24pub static EOF_MAGIC_BYTES: Bytes = bytes!("ef00");
26
27#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
31#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
32pub struct Eof {
33 pub header: EofHeader,
34 pub body: EofBody,
35 pub raw: Bytes,
36}
37
38impl Default for Eof {
39 fn default() -> Self {
40 let body = EofBody {
41 code_info: vec![CodeInfo::default()],
43 code_section: vec![1],
44 code: Bytes::from_static(&[0x00]),
46 code_offset: 0,
47 container_section: vec![],
48 data_section: Bytes::new(),
49 is_data_filled: true,
50 };
51 body.into_eof()
52 }
53}
54
55impl Eof {
56 pub fn new(body: EofBody) -> Self {
58 body.into_eof()
59 }
60
61 pub fn validate(&self) -> Result<(), EofError> {
63 validate_eof(self)
64 }
65
66 pub fn validate_raw(bytes: Bytes) -> Result<Eof, EofError> {
68 validate_raw_eof(bytes)
69 }
70
71 pub fn validate_mode(&self, mode: CodeType) -> Result<(), EofError> {
73 validate_eof_inner(self, Some(mode))
74 }
75
76 pub fn size(&self) -> usize {
78 self.header.size() + self.header.body_size()
79 }
80
81 pub fn raw(&self) -> &Bytes {
83 &self.raw
84 }
85
86 pub fn data_slice(&self, offset: usize, len: usize) -> &[u8] {
90 self.body
91 .data_section
92 .get(offset..)
93 .and_then(|bytes| bytes.get(..min(len, bytes.len())))
94 .unwrap_or(&[])
95 }
96
97 pub fn data(&self) -> &[u8] {
99 &self.body.data_section
100 }
101
102 pub fn encode_slow(&self) -> Bytes {
104 let mut buffer: Vec<u8> = Vec::with_capacity(self.size());
105 self.header.encode(&mut buffer);
106 self.body.encode(&mut buffer);
107 buffer.into()
108 }
109
110 pub fn decode_dangling(mut raw: Bytes) -> Result<(Self, Bytes), EofDecodeError> {
114 let (header, _) = EofHeader::decode(&raw)?;
115 let eof_size = header.body_size() + header.size();
116 if eof_size > raw.len() {
117 return Err(EofDecodeError::MissingInput);
118 }
119 let dangling_data = raw.split_off(eof_size);
120 let body = EofBody::decode(&raw, &header)?;
121 Ok((Self { header, body, raw }, dangling_data))
122 }
123
124 pub fn decode(raw: Bytes) -> Result<Self, EofDecodeError> {
126 let (header, _) = EofHeader::decode(&raw)?;
127 let body = EofBody::decode(&raw, &header)?;
128 Ok(Self { header, body, raw })
129 }
130}
131
132#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
134#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
135pub enum EofDecodeError {
136 MissingInput,
138 MissingBodyWithoutData,
140 DanglingData,
142 InvalidCodeInfo,
144 InvalidCodeInfoSize,
146 InvalidEOFMagicNumber,
148 InvalidEOFVersion,
150 InvalidTypesKind,
152 InvalidCodeKind,
154 InvalidTerminalByte,
156 InvalidDataKind,
158 InvalidKindAfterCode,
160 MismatchCodeAndInfoSize,
162 NonSizes,
164 ShortInputForSizes,
166 ZeroSize,
168 TooManyCodeSections,
170 ZeroCodeSections,
172 TooManyContainerSections,
174 InvalidEOFSize,
176}
177
178impl fmt::Display for EofDecodeError {
179 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180 let s = match self {
181 Self::MissingInput => "Short input while processing EOF",
182 Self::MissingBodyWithoutData => "Short body while processing EOF",
183 Self::DanglingData => "Body size is more than specified in the header",
184 Self::InvalidCodeInfo => "Invalid types section data",
185 Self::InvalidCodeInfoSize => "Invalid types section size",
186 Self::InvalidEOFMagicNumber => "Invalid EOF magic number",
187 Self::InvalidEOFVersion => "Invalid EOF version",
188 Self::InvalidTypesKind => "Invalid number for types kind",
189 Self::InvalidCodeKind => "Invalid number for code kind",
190 Self::InvalidTerminalByte => "Invalid terminal code",
191 Self::InvalidDataKind => "Invalid data kind",
192 Self::InvalidKindAfterCode => "Invalid kind after code",
193 Self::MismatchCodeAndInfoSize => "Mismatch of code and types sizes",
194 Self::NonSizes => "There should be at least one size",
195 Self::ShortInputForSizes => "Missing size",
196 Self::ZeroSize => "Size cant be zero",
197 Self::TooManyCodeSections => "Invalid code number",
198 Self::ZeroCodeSections => "Invalid number of code sections",
199 Self::TooManyContainerSections => "Invalid container number",
200 Self::InvalidEOFSize => "Invalid initcode size",
201 };
202 f.write_str(s)
203 }
204}
205
206impl core::error::Error for EofDecodeError {}
207
208#[cfg(test)]
209mod test {
210
211 use super::*;
212 use primitives::bytes;
213
214 #[test]
215 fn decode_eof() {
216 let bytes = bytes!("ef000101000402000100010400000000800000fe");
217 let eof = Eof::decode(bytes.clone()).unwrap();
218 assert_eq!(bytes, eof.encode_slow());
219 }
220
221 #[test]
222 fn decode_eof_dangling() {
223 let test_cases = [
224 (
225 bytes!("ef000101000402000100010400000000800000fe"),
226 bytes!("010203"),
227 false,
228 ),
229 (
230 bytes!("ef000101000402000100010400000000800000fe"),
231 bytes!(""),
232 false,
233 ),
234 (
235 bytes!("ef000101000402000100010400000000800000"),
236 bytes!(""),
237 true,
238 ),
239 ];
240
241 for (eof_bytes, dangling_data, is_err) in test_cases {
242 let mut raw = eof_bytes.to_vec();
243 raw.extend(&dangling_data);
244 let raw = Bytes::from(raw);
245
246 let result = Eof::decode_dangling(raw.clone());
247 assert_eq!(result.is_err(), is_err);
248 if is_err {
249 continue;
250 }
251 let (decoded_eof, decoded_dangling) = result.unwrap();
252 assert_eq!(eof_bytes, decoded_eof.encode_slow());
253 assert_eq!(decoded_dangling, dangling_data);
254 }
255 }
256
257 #[test]
258 fn data_slice() {
259 let bytes = bytes!("ef000101000402000100010400000000800000fe");
260 let mut eof = Eof::decode(bytes.clone()).unwrap();
261 eof.body.data_section = bytes!("01020304");
262 assert_eq!(eof.data_slice(0, 1), &[0x01]);
263 assert_eq!(eof.data_slice(0, 4), &[0x01, 0x02, 0x03, 0x04]);
264 assert_eq!(eof.data_slice(0, 5), &[0x01, 0x02, 0x03, 0x04]);
265 assert_eq!(eof.data_slice(1, 2), &[0x02, 0x03]);
266
267 const EMPTY: &[u8] = &[];
268 assert_eq!(eof.data_slice(10, 2), EMPTY);
269 assert_eq!(eof.data_slice(1, 0), EMPTY);
270 assert_eq!(eof.data_slice(10, 0), EMPTY);
271 }
272}