reth_era/common/
compression.rs1use crate::e2s::error::E2sError;
6use alloy_rlp::{Decodable, Encodable};
7use snap::{read::FrameDecoder, write::FrameEncoder};
8use std::{
9 io::{Read, Write},
10 marker::PhantomData,
11};
12
13pub fn snappy_compress(data: &[u8]) -> Result<Vec<u8>, E2sError> {
15 let mut compressed = Vec::new();
16 {
17 let mut encoder = FrameEncoder::new(&mut compressed);
18 Write::write_all(&mut encoder, data)
19 .map_err(|e| E2sError::SnappyCompression(format!("Failed to compress: {e}")))?;
20 encoder
21 .flush()
22 .map_err(|e| E2sError::SnappyCompression(format!("Failed to flush encoder: {e}")))?;
23 }
24 Ok(compressed)
25}
26
27pub fn snappy_decompress(data: &[u8]) -> Result<Vec<u8>, E2sError> {
29 let mut decoder = FrameDecoder::new(data);
30 let mut decompressed = Vec::new();
31 Read::read_to_end(&mut decoder, &mut decompressed)
32 .map_err(|e| E2sError::SnappyDecompression(format!("Failed to decompress: {e}")))?;
33 Ok(decompressed)
34}
35
36#[derive(Debug, Clone, Default)]
38pub struct SnappyRlpCodec<T> {
39 _phantom: PhantomData<T>,
40}
41
42impl<T> SnappyRlpCodec<T> {
43 pub const fn new() -> Self {
45 Self { _phantom: PhantomData }
46 }
47}
48
49impl<T: Decodable> SnappyRlpCodec<T> {
50 pub fn decode(&self, compressed_data: &[u8]) -> Result<T, E2sError> {
55 let decompressed = snappy_decompress(compressed_data)?;
56 let mut slice = decompressed.as_slice();
57 let value = T::decode(&mut slice)
58 .map_err(|e| E2sError::Rlp(format!("Failed to decode RLP data: {e}")))?;
59 if !slice.is_empty() {
60 return Err(E2sError::Rlp(format!(
61 "Trailing bytes after RLP value: {} byte(s) remain",
62 slice.len()
63 )));
64 }
65 Ok(value)
66 }
67}
68
69impl<T: Encodable> SnappyRlpCodec<T> {
70 pub fn encode(&self, data: &T) -> Result<Vec<u8>, E2sError> {
72 let mut rlp_data = Vec::new();
73 data.encode(&mut rlp_data);
74 snappy_compress(&rlp_data)
75 }
76}