1use crate::{
4 transaction::TxEip4844Sidecar, EthereumTxEnvelope, Header, Receipt, TxEip1559, TxEip2930,
5 TxEip4844, TxEip4844Variant, TxEip4844WithSidecar, TxEip7702, TxLegacy, TxType,
6};
7use alloc::vec::Vec;
8use alloy_eips::eip4895::Withdrawals;
9use alloy_primitives::{LogData, Signature, TxHash, B256};
10
11#[auto_impl::auto_impl(&, Arc, Box)]
13pub trait InMemorySize {
14 fn size(&self) -> usize;
16}
17
18impl<T: InMemorySize> InMemorySize for crate::Signed<T> {
19 fn size(&self) -> usize {
20 T::size(self.tx()) + self.signature().size() + core::mem::size_of::<B256>()
21 }
22}
23
24macro_rules! impl_in_mem_size_size_of {
26 ($($ty:ty),*) => {
27 $(
28 impl InMemorySize for $ty {
29 #[inline]
30 fn size(&self) -> usize {
31 core::mem::size_of::<Self>()
32 }
33 }
34 )*
35 };
36}
37
38impl_in_mem_size_size_of!(Signature, TxHash, TxType);
39
40macro_rules! impl_in_mem_size {
42 ($($ty:ty),*) => {
43 $(
44 impl InMemorySize for $ty {
45 #[inline]
46 fn size(&self) -> usize {
47 Self::size(self)
48 }
49 }
50 )*
51 };
52}
53
54impl_in_mem_size!(Header, TxLegacy, TxEip2930, TxEip1559, TxEip7702, TxEip4844);
55
56impl<T: TxEip4844Sidecar> InMemorySize for TxEip4844Variant<T> {
57 #[inline]
58 fn size(&self) -> usize {
59 Self::size(self)
60 }
61}
62
63impl<T: TxEip4844Sidecar> InMemorySize for TxEip4844WithSidecar<T> {
64 #[inline]
65 fn size(&self) -> usize {
66 Self::size(self)
67 }
68}
69
70impl InMemorySize for Receipt {
71 fn size(&self) -> usize {
72 let Self { status, cumulative_gas_used, logs } = self;
73 core::mem::size_of_val(status)
74 + core::mem::size_of_val(cumulative_gas_used)
75 + logs.iter().map(|log| log.size()).sum::<usize>()
76 }
77}
78
79impl InMemorySize for LogData {
80 fn size(&self) -> usize {
81 self.data.len() + core::mem::size_of_val(self.topics())
82 }
83}
84
85impl<T: InMemorySize> InMemorySize for alloy_primitives::Log<T> {
86 fn size(&self) -> usize {
87 core::mem::size_of_val(&self.address) + self.data.size()
88 }
89}
90
91impl<T: InMemorySize> InMemorySize for EthereumTxEnvelope<T> {
92 fn size(&self) -> usize {
93 match self {
94 Self::Legacy(tx) => tx.size(),
95 Self::Eip2930(tx) => tx.size(),
96 Self::Eip1559(tx) => tx.size(),
97 Self::Eip4844(tx) => tx.size(),
98 Self::Eip7702(tx) => tx.size(),
99 }
100 }
101}
102
103impl<T: InMemorySize, H: InMemorySize> InMemorySize for crate::BlockBody<T, H> {
104 #[inline]
106 fn size(&self) -> usize {
107 self.transactions.iter().map(T::size).sum::<usize>()
108 + self.ommers.iter().map(H::size).sum::<usize>()
109 + self
110 .withdrawals
111 .as_ref()
112 .map_or(core::mem::size_of::<Option<Withdrawals>>(), Withdrawals::total_size)
113 }
114}
115
116impl<T: InMemorySize, H: InMemorySize> InMemorySize for crate::Block<T, H> {
117 #[inline]
118 fn size(&self) -> usize {
119 self.header.size() + self.body.size()
120 }
121}
122
123impl<T: InMemorySize> InMemorySize for Vec<T> {
124 fn size(&self) -> usize {
125 self.iter().map(T::size).sum::<usize>()
126 }
127}
128
129impl InMemorySize for u64 {
130 fn size(&self) -> usize {
131 core::mem::size_of::<Self>()
132 }
133}
134
135#[cfg(test)]
136mod tests {
137 use super::*;
138
139 #[test]
141 fn no_in_memory_no_recursion() {
142 fn assert_no_recursion<T: InMemorySize + Default>() {
143 let _ = T::default().size();
144 }
145 assert_no_recursion::<Header>();
146 assert_no_recursion::<TxLegacy>();
147 assert_no_recursion::<TxEip2930>();
148 assert_no_recursion::<TxEip1559>();
149 assert_no_recursion::<TxEip7702>();
150 assert_no_recursion::<TxEip4844>();
151 }
152}