reth_era/
e2s_types.rs
1use ssz_derive::{Decode, Encode};
12use std::io::{self, Read, Write};
13use thiserror::Error;
14
15pub const VERSION: [u8; 2] = [0x65, 0x32];
17
18pub const EMPTY: [u8; 2] = [0x00, 0x00];
20
21pub const SLOT_INDEX: [u8; 2] = [0x69, 0x32];
23
24#[derive(Error, Debug)]
26pub enum E2sError {
27 #[error("IO error: {0}")]
29 Io(#[from] io::Error),
30
31 #[error("SSZ error: {0}")]
33 Ssz(String),
34
35 #[error("Reserved field in header not zero")]
37 ReservedNotZero,
38
39 #[error("Snappy compression error: {0}")]
41 SnappyCompression(String),
42
43 #[error("Snappy decompression error: {0}")]
45 SnappyDecompression(String),
46
47 #[error("RLP error: {0}")]
49 Rlp(String),
50}
51
52#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)]
54pub struct Header {
55 pub header_type: [u8; 2],
57
58 pub length: u32,
60
61 pub reserved: u16,
63}
64
65impl Header {
66 pub fn new(header_type: [u8; 2], length: u32) -> Self {
68 Self { header_type, length, reserved: 0 }
69 }
70
71 pub fn read<R: Read>(reader: &mut R) -> Result<Option<Self>, E2sError> {
73 let mut header_bytes = [0u8; 8];
74 match reader.read_exact(&mut header_bytes) {
75 Ok(_) => {}
76 Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => return Ok(None),
77 Err(e) => return Err(e.into()),
78 }
79
80 let header: Self = match ssz::Decode::from_ssz_bytes(&header_bytes) {
81 Ok(h) => h,
82 Err(_) => return Err(E2sError::Ssz(String::from("Failed to decode SSZ header"))),
83 };
84
85 if header.reserved != 0 {
86 return Err(E2sError::ReservedNotZero);
87 }
88
89 Ok(Some(header))
90 }
91
92 pub fn write<W: Write>(&self, writer: &mut W) -> io::Result<()> {
94 let encoded = ssz::Encode::as_ssz_bytes(self);
95 writer.write_all(&encoded)
96 }
97}
98
99#[derive(Debug, Clone, PartialEq, Eq, Default)]
101pub struct Version;
102
103impl Version {
104 pub fn encode<W: Write>(&self, writer: &mut W) -> io::Result<()> {
106 let header = Header::new(VERSION, 0);
107 header.write(writer)
108 }
109}
110
111#[derive(Debug, Clone)]
113pub struct Entry {
114 pub entry_type: [u8; 2],
116
117 pub data: Vec<u8>,
119}
120
121impl Entry {
122 pub fn new(entry_type: [u8; 2], data: Vec<u8>) -> Self {
124 Self { entry_type, data }
125 }
126
127 pub fn read<R: Read>(reader: &mut R) -> Result<Option<Self>, E2sError> {
129 let header = match Header::read(reader)? {
131 Some(h) => h,
132 None => return Ok(None),
133 };
134
135 let mut data = vec![0u8; header.length as usize];
137 match reader.read_exact(&mut data) {
138 Ok(_) => {}
139 Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => {
140 return Err(E2sError::Io(io::Error::new(
141 io::ErrorKind::UnexpectedEof,
142 "Unexpected EOF while reading entry data",
143 )));
144 }
145 Err(e) => return Err(e.into()),
146 }
147
148 Ok(Some(Self { entry_type: header.header_type, data }))
149 }
150
151 pub fn write<W: Write>(&self, writer: &mut W) -> io::Result<()> {
153 let header = Header::new(self.entry_type, self.data.len() as u32);
154 header.write(writer)?;
155 writer.write_all(&self.data)
156 }
157
158 pub fn is_version(&self) -> bool {
160 self.entry_type == VERSION
161 }
162
163 pub fn is_slot_index(&self) -> bool {
165 self.entry_type == SLOT_INDEX
166 }
167}