reth_codecs/alloy/
log.rs

1//! Native Compact codec impl for primitive alloy log types.
2
3use crate::Compact;
4use alloc::vec::Vec;
5use alloy_primitives::{Address, Bytes, Log, LogData};
6use bytes::BufMut;
7
8/// Implement `Compact` for `LogData` and `Log`.
9impl Compact for LogData {
10    fn to_compact<B>(&self, buf: &mut B) -> usize
11    where
12        B: BufMut + AsMut<[u8]>,
13    {
14        let mut buffer = Vec::new();
15
16        self.topics().specialized_to_compact(&mut buffer);
17        self.data.to_compact(&mut buffer);
18        buf.put(&buffer[..]);
19        buffer.len()
20    }
21
22    fn from_compact(mut buf: &[u8], _: usize) -> (Self, &[u8]) {
23        let (topics, new_buf) = Vec::specialized_from_compact(buf, buf.len());
24        buf = new_buf;
25        let (data, buf) = Bytes::from_compact(buf, buf.len());
26        let log_data = Self::new_unchecked(topics, data);
27        (log_data, buf)
28    }
29}
30
31impl Compact for Log {
32    fn to_compact<B>(&self, buf: &mut B) -> usize
33    where
34        B: BufMut + AsMut<[u8]>,
35    {
36        let mut buffer = Vec::new();
37        self.address.to_compact(&mut buffer);
38        self.data.to_compact(&mut buffer);
39        buf.put(&buffer[..]);
40        buffer.len()
41    }
42
43    fn from_compact(mut buf: &[u8], _: usize) -> (Self, &[u8]) {
44        let (address, new_buf) = Address::from_compact(buf, buf.len());
45        buf = new_buf;
46        let (log_data, new_buf) = LogData::from_compact(buf, buf.len());
47        buf = new_buf;
48        let log = Self { address, data: log_data };
49        (log, buf)
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::{Compact, Log};
56    use alloy_primitives::{Address, Bytes, LogData, B256};
57    use proptest::proptest;
58    use serde::Deserialize;
59
60    proptest! {
61        #[test]
62        fn roundtrip(log: Log) {
63            let mut buf = Vec::<u8>::new();
64            let len = log.to_compact(&mut buf);
65            let (decoded, _) = Log::from_compact(&buf, len);
66            assert_eq!(log, decoded);
67        }
68    }
69
70    #[derive(Deserialize)]
71    struct CompactLogTestVector {
72        topics: Vec<B256>,
73        address: Address,
74        data: Bytes,
75        encoded_bytes: Bytes,
76    }
77
78    #[test]
79    fn test_compact_log_codec() {
80        let test_vectors: Vec<CompactLogTestVector> =
81            serde_json::from_str(include_str!("../../testdata/log_compact.json"))
82                .expect("Failed to parse test vectors");
83
84        for test_vector in test_vectors {
85            let log_data = LogData::new_unchecked(test_vector.topics, test_vector.data);
86            let log = Log { address: test_vector.address, data: log_data };
87
88            let mut buf = Vec::<u8>::new();
89            let len = log.clone().to_compact(&mut buf);
90            assert_eq!(test_vector.encoded_bytes, buf);
91
92            let (decoded, _) = Log::from_compact(&test_vector.encoded_bytes, len);
93            assert_eq!(log, decoded);
94        }
95    }
96}