1mod body;
2mod decode_helpers;
3mod header;
4pub mod printer;
5mod types_section;
6pub mod verification;
7
8pub use body::EofBody;
9pub use header::EofHeader;
10pub use types_section::TypesSection;
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!("9dbf3648db8210552e9c4f75c6a1c3057c0ca432043bd648be15fe7be05646f5");
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 types_section: vec![TypesSection::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 validate(&self) -> Result<(), EofError> {
57 validate_eof(self)
58 }
59
60 pub fn valitate_raw(bytes: Bytes) -> Result<Eof, EofError> {
61 validate_raw_eof(bytes)
62 }
63
64 pub fn validate_mode(&self, mode: CodeType) -> Result<(), EofError> {
65 validate_eof_inner(self, Some(mode))
66 }
67
68 pub fn new(body: EofBody) -> Self {
70 body.into_eof()
71 }
72
73 pub fn size(&self) -> usize {
75 self.header.size() + self.header.body_size()
76 }
77
78 pub fn raw(&self) -> &Bytes {
80 &self.raw
81 }
82
83 pub fn data_slice(&self, offset: usize, len: usize) -> &[u8] {
87 self.body
88 .data_section
89 .get(offset..)
90 .and_then(|bytes| bytes.get(..min(len, bytes.len())))
91 .unwrap_or(&[])
92 }
93
94 pub fn data(&self) -> &[u8] {
96 &self.body.data_section
97 }
98
99 pub fn encode_slow(&self) -> Bytes {
101 let mut buffer: Vec<u8> = Vec::with_capacity(self.size());
102 self.header.encode(&mut buffer);
103 self.body.encode(&mut buffer);
104 buffer.into()
105 }
106
107 pub fn decode_dangling(mut raw: Bytes) -> Result<(Self, Bytes), EofDecodeError> {
111 let (header, _) = EofHeader::decode(&raw)?;
112 let eof_size = header.body_size() + header.size();
113 if eof_size > raw.len() {
114 return Err(EofDecodeError::MissingInput);
115 }
116 let dangling_data = raw.split_off(eof_size);
117 let body = EofBody::decode(&raw, &header)?;
118 Ok((Self { header, body, raw }, dangling_data))
119 }
120
121 pub fn decode(raw: Bytes) -> Result<Self, EofDecodeError> {
123 let (header, _) = EofHeader::decode(&raw)?;
124 let body = EofBody::decode(&raw, &header)?;
125 Ok(Self { header, body, raw })
126 }
127}
128
129#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
131#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
132pub enum EofDecodeError {
133 MissingInput,
135 MissingBodyWithoutData,
137 DanglingData,
139 InvalidTypesSection,
141 InvalidTypesSectionSize,
143 InvalidEOFMagicNumber,
145 InvalidEOFVersion,
147 InvalidTypesKind,
149 InvalidCodeKind,
151 InvalidTerminalByte,
153 InvalidDataKind,
155 InvalidKindAfterCode,
157 MismatchCodeAndTypesSize,
159 NonSizes,
161 ShortInputForSizes,
163 ZeroSize,
165 TooManyCodeSections,
167 ZeroCodeSections,
169 TooManyContainerSections,
171 InvalidEOFSize,
173}
174
175impl fmt::Display for EofDecodeError {
176 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177 let s = match self {
178 Self::MissingInput => "Short input while processing EOF",
179 Self::MissingBodyWithoutData => "Short body while processing EOF",
180 Self::DanglingData => "Body size is more than specified in the header",
181 Self::InvalidTypesSection => "Invalid types section data",
182 Self::InvalidTypesSectionSize => "Invalid types section size",
183 Self::InvalidEOFMagicNumber => "Invalid EOF magic number",
184 Self::InvalidEOFVersion => "Invalid EOF version",
185 Self::InvalidTypesKind => "Invalid number for types kind",
186 Self::InvalidCodeKind => "Invalid number for code kind",
187 Self::InvalidTerminalByte => "Invalid terminal code",
188 Self::InvalidDataKind => "Invalid data kind",
189 Self::InvalidKindAfterCode => "Invalid kind after code",
190 Self::MismatchCodeAndTypesSize => "Mismatch of code and types sizes",
191 Self::NonSizes => "There should be at least one size",
192 Self::ShortInputForSizes => "Missing size",
193 Self::ZeroSize => "Size cant be zero",
194 Self::TooManyCodeSections => "Invalid code number",
195 Self::ZeroCodeSections => "Invalid number of code sections",
196 Self::TooManyContainerSections => "Invalid container number",
197 Self::InvalidEOFSize => "Invalid initcode size",
198 };
199 f.write_str(s)
200 }
201}
202
203impl core::error::Error for EofDecodeError {}
204
205#[cfg(test)]
206mod test {
207
208 use super::*;
209 use primitives::bytes;
210
211 #[test]
212 fn decode_eof() {
213 let bytes = bytes!("ef000101000402000100010400000000800000fe");
214 let eof = Eof::decode(bytes.clone()).unwrap();
215 assert_eq!(bytes, eof.encode_slow());
216 }
217
218 #[test]
219 fn decode_eof_dangling() {
220 let test_cases = [
221 (
222 bytes!("ef000101000402000100010400000000800000fe"),
223 bytes!("010203"),
224 false,
225 ),
226 (
227 bytes!("ef000101000402000100010400000000800000fe"),
228 bytes!(""),
229 false,
230 ),
231 (
232 bytes!("ef000101000402000100010400000000800000"),
233 bytes!(""),
234 true,
235 ),
236 ];
237
238 for (eof_bytes, dangling_data, is_err) in test_cases {
239 let mut raw = eof_bytes.to_vec();
240 raw.extend(&dangling_data);
241 let raw = Bytes::from(raw);
242
243 let result = Eof::decode_dangling(raw.clone());
244 assert_eq!(result.is_err(), is_err);
245 if is_err {
246 continue;
247 }
248 let (decoded_eof, decoded_dangling) = result.unwrap();
249 assert_eq!(eof_bytes, decoded_eof.encode_slow());
250 assert_eq!(decoded_dangling, dangling_data);
251 }
252 }
253
254 #[test]
255 fn data_slice() {
256 let bytes = bytes!("ef000101000402000100010400000000800000fe");
257 let mut eof = Eof::decode(bytes.clone()).unwrap();
258 eof.body.data_section = bytes!("01020304");
259 assert_eq!(eof.data_slice(0, 1), &[0x01]);
260 assert_eq!(eof.data_slice(0, 4), &[0x01, 0x02, 0x03, 0x04]);
261 assert_eq!(eof.data_slice(0, 5), &[0x01, 0x02, 0x03, 0x04]);
262 assert_eq!(eof.data_slice(1, 2), &[0x02, 0x03]);
263
264 const EMPTY: &[u8] = &[];
265 assert_eq!(eof.data_slice(10, 2), EMPTY);
266 assert_eq!(eof.data_slice(1, 0), EMPTY);
267 assert_eq!(eof.data_slice(10, 0), EMPTY);
268 }
269}