1use core::fmt::Debug;
2use serde::{de::DeserializeOwned, Serialize};
3
4pub use super::{
5 block::{serde_bincode_compat as block, serde_bincode_compat::*},
6 header::{serde_bincode_compat as header, serde_bincode_compat::*},
7};
8pub use block_bincode::{Block, BlockBody};
9
10pub trait SerdeBincodeCompat: Sized + 'static {
15 type BincodeRepr<'a>: Debug + Serialize + DeserializeOwned;
19
20 fn as_repr(&self) -> Self::BincodeRepr<'_>;
22
23 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self;
25}
26
27impl SerdeBincodeCompat for alloy_consensus::Header {
28 type BincodeRepr<'a> = alloy_consensus::serde_bincode_compat::Header<'a>;
29
30 fn as_repr(&self) -> Self::BincodeRepr<'_> {
31 self.into()
32 }
33
34 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
35 repr.into()
36 }
37}
38
39pub type BincodeReprFor<'a, T> = <T as SerdeBincodeCompat>::BincodeRepr<'a>;
41
42mod block_bincode {
43 use crate::serde_bincode_compat::SerdeBincodeCompat;
44 use alloc::{borrow::Cow, vec::Vec};
45 use alloy_consensus::TxEip4844;
46 use alloy_eips::eip4895::Withdrawals;
47 use serde::{Deserialize, Deserializer, Serialize, Serializer};
48 use serde_with::{DeserializeAs, SerializeAs};
49
50 #[derive(derive_more::Debug, Serialize, Deserialize)]
67 #[debug(bound())]
68 pub struct Block<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat> {
69 header: H::BincodeRepr<'a>,
70 #[serde(bound = "BlockBody<'a, T, H>: Serialize + serde::de::DeserializeOwned")]
71 body: BlockBody<'a, T, H>,
72 }
73
74 impl<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat> From<&'a alloy_consensus::Block<T, H>>
75 for Block<'a, T, H>
76 {
77 fn from(value: &'a alloy_consensus::Block<T, H>) -> Self {
78 Self { header: value.header.as_repr(), body: (&value.body).into() }
79 }
80 }
81
82 impl<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat> From<Block<'a, T, H>>
83 for alloy_consensus::Block<T, H>
84 {
85 fn from(value: Block<'a, T, H>) -> Self {
86 Self { header: SerdeBincodeCompat::from_repr(value.header), body: value.body.into() }
87 }
88 }
89
90 impl<T: SerdeBincodeCompat, H: SerdeBincodeCompat> SerializeAs<alloy_consensus::Block<T, H>>
91 for Block<'_, T, H>
92 {
93 fn serialize_as<S>(
94 source: &alloy_consensus::Block<T, H>,
95 serializer: S,
96 ) -> Result<S::Ok, S::Error>
97 where
98 S: Serializer,
99 {
100 Block::from(source).serialize(serializer)
101 }
102 }
103
104 impl<'de, T: SerdeBincodeCompat, H: SerdeBincodeCompat>
105 DeserializeAs<'de, alloy_consensus::Block<T, H>> for Block<'de, T, H>
106 {
107 fn deserialize_as<D>(deserializer: D) -> Result<alloy_consensus::Block<T, H>, D::Error>
108 where
109 D: Deserializer<'de>,
110 {
111 Block::deserialize(deserializer).map(Into::into)
112 }
113 }
114
115 impl<T: SerdeBincodeCompat, H: SerdeBincodeCompat> SerdeBincodeCompat
116 for alloy_consensus::Block<T, H>
117 {
118 type BincodeRepr<'a> = Block<'a, T, H>;
119
120 fn as_repr(&self) -> Self::BincodeRepr<'_> {
121 self.into()
122 }
123
124 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
125 repr.into()
126 }
127 }
128
129 #[derive(derive_more::Debug, Serialize, Deserialize)]
145 #[debug(bound())]
146 pub struct BlockBody<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat> {
147 transactions: Vec<T::BincodeRepr<'a>>,
148 ommers: Vec<H::BincodeRepr<'a>>,
149 withdrawals: Cow<'a, Option<Withdrawals>>,
150 }
151
152 impl<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat>
153 From<&'a alloy_consensus::BlockBody<T, H>> for BlockBody<'a, T, H>
154 {
155 fn from(value: &'a alloy_consensus::BlockBody<T, H>) -> Self {
156 Self {
157 transactions: value.transactions.iter().map(|tx| tx.as_repr()).collect(),
158 ommers: value.ommers.iter().map(|h| h.as_repr()).collect(),
159 withdrawals: Cow::Borrowed(&value.withdrawals),
160 }
161 }
162 }
163
164 impl<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat> From<BlockBody<'a, T, H>>
165 for alloy_consensus::BlockBody<T, H>
166 {
167 fn from(value: BlockBody<'a, T, H>) -> Self {
168 Self {
169 transactions: value
170 .transactions
171 .into_iter()
172 .map(SerdeBincodeCompat::from_repr)
173 .collect(),
174 ommers: value.ommers.into_iter().map(SerdeBincodeCompat::from_repr).collect(),
175 withdrawals: value.withdrawals.into_owned(),
176 }
177 }
178 }
179
180 impl<T: SerdeBincodeCompat, H: SerdeBincodeCompat> SerializeAs<alloy_consensus::BlockBody<T, H>>
181 for BlockBody<'_, T, H>
182 {
183 fn serialize_as<S>(
184 source: &alloy_consensus::BlockBody<T, H>,
185 serializer: S,
186 ) -> Result<S::Ok, S::Error>
187 where
188 S: Serializer,
189 {
190 BlockBody::from(source).serialize(serializer)
191 }
192 }
193
194 impl<'de, T: SerdeBincodeCompat, H: SerdeBincodeCompat>
195 DeserializeAs<'de, alloy_consensus::BlockBody<T, H>> for BlockBody<'de, T, H>
196 {
197 fn deserialize_as<D>(deserializer: D) -> Result<alloy_consensus::BlockBody<T, H>, D::Error>
198 where
199 D: Deserializer<'de>,
200 {
201 BlockBody::deserialize(deserializer).map(Into::into)
202 }
203 }
204
205 impl<T: SerdeBincodeCompat, H: SerdeBincodeCompat> SerdeBincodeCompat
206 for alloy_consensus::BlockBody<T, H>
207 {
208 type BincodeRepr<'a> = BlockBody<'a, T, H>;
209
210 fn as_repr(&self) -> Self::BincodeRepr<'_> {
211 self.into()
212 }
213
214 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
215 repr.into()
216 }
217 }
218
219 impl super::SerdeBincodeCompat for alloy_consensus::EthereumTxEnvelope<TxEip4844> {
220 type BincodeRepr<'a> =
221 alloy_consensus::serde_bincode_compat::transaction::EthereumTxEnvelope<'a>;
222
223 fn as_repr(&self) -> Self::BincodeRepr<'_> {
224 self.into()
225 }
226
227 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
228 repr.into()
229 }
230 }
231
232 #[cfg(feature = "op")]
233 impl super::SerdeBincodeCompat for op_alloy_consensus::OpTxEnvelope {
234 type BincodeRepr<'a> =
235 op_alloy_consensus::serde_bincode_compat::transaction::OpTxEnvelope<'a>;
236
237 fn as_repr(&self) -> Self::BincodeRepr<'_> {
238 self.into()
239 }
240
241 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
242 repr.into()
243 }
244 }
245}