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_eips::eip4895::Withdrawals;
46 use serde::{Deserialize, Deserializer, Serialize, Serializer};
47 use serde_with::{DeserializeAs, SerializeAs};
48
49 #[derive(derive_more::Debug, Serialize, Deserialize)]
66 #[debug(bound())]
67 pub struct Block<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat> {
68 header: H::BincodeRepr<'a>,
69 #[serde(bound = "BlockBody<'a, T, H>: Serialize + serde::de::DeserializeOwned")]
70 body: BlockBody<'a, T, H>,
71 }
72
73 impl<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat> From<&'a alloy_consensus::Block<T, H>>
74 for Block<'a, T, H>
75 {
76 fn from(value: &'a alloy_consensus::Block<T, H>) -> Self {
77 Self { header: value.header.as_repr(), body: (&value.body).into() }
78 }
79 }
80
81 impl<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat> From<Block<'a, T, H>>
82 for alloy_consensus::Block<T, H>
83 {
84 fn from(value: Block<'a, T, H>) -> Self {
85 Self { header: SerdeBincodeCompat::from_repr(value.header), body: value.body.into() }
86 }
87 }
88
89 impl<T: SerdeBincodeCompat, H: SerdeBincodeCompat> SerializeAs<alloy_consensus::Block<T, H>>
90 for Block<'_, T, H>
91 {
92 fn serialize_as<S>(
93 source: &alloy_consensus::Block<T, H>,
94 serializer: S,
95 ) -> Result<S::Ok, S::Error>
96 where
97 S: Serializer,
98 {
99 Block::from(source).serialize(serializer)
100 }
101 }
102
103 impl<'de, T: SerdeBincodeCompat, H: SerdeBincodeCompat>
104 DeserializeAs<'de, alloy_consensus::Block<T, H>> for Block<'de, T, H>
105 {
106 fn deserialize_as<D>(deserializer: D) -> Result<alloy_consensus::Block<T, H>, D::Error>
107 where
108 D: Deserializer<'de>,
109 {
110 Block::deserialize(deserializer).map(Into::into)
111 }
112 }
113
114 impl<T: SerdeBincodeCompat, H: SerdeBincodeCompat> SerdeBincodeCompat
115 for alloy_consensus::Block<T, H>
116 {
117 type BincodeRepr<'a> = Block<'a, T, H>;
118
119 fn as_repr(&self) -> Self::BincodeRepr<'_> {
120 self.into()
121 }
122
123 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
124 repr.into()
125 }
126 }
127
128 #[derive(derive_more::Debug, Serialize, Deserialize)]
144 #[debug(bound())]
145 pub struct BlockBody<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat> {
146 transactions: Vec<T::BincodeRepr<'a>>,
147 ommers: Vec<H::BincodeRepr<'a>>,
148 withdrawals: Cow<'a, Option<Withdrawals>>,
149 }
150
151 impl<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat>
152 From<&'a alloy_consensus::BlockBody<T, H>> for BlockBody<'a, T, H>
153 {
154 fn from(value: &'a alloy_consensus::BlockBody<T, H>) -> Self {
155 Self {
156 transactions: value.transactions.iter().map(|tx| tx.as_repr()).collect(),
157 ommers: value.ommers.iter().map(|h| h.as_repr()).collect(),
158 withdrawals: Cow::Borrowed(&value.withdrawals),
159 }
160 }
161 }
162
163 impl<'a, T: SerdeBincodeCompat, H: SerdeBincodeCompat> From<BlockBody<'a, T, H>>
164 for alloy_consensus::BlockBody<T, H>
165 {
166 fn from(value: BlockBody<'a, T, H>) -> Self {
167 Self {
168 transactions: value
169 .transactions
170 .into_iter()
171 .map(SerdeBincodeCompat::from_repr)
172 .collect(),
173 ommers: value.ommers.into_iter().map(SerdeBincodeCompat::from_repr).collect(),
174 withdrawals: value.withdrawals.into_owned(),
175 }
176 }
177 }
178
179 impl<T: SerdeBincodeCompat, H: SerdeBincodeCompat> SerializeAs<alloy_consensus::BlockBody<T, H>>
180 for BlockBody<'_, T, H>
181 {
182 fn serialize_as<S>(
183 source: &alloy_consensus::BlockBody<T, H>,
184 serializer: S,
185 ) -> Result<S::Ok, S::Error>
186 where
187 S: Serializer,
188 {
189 BlockBody::from(source).serialize(serializer)
190 }
191 }
192
193 impl<'de, T: SerdeBincodeCompat, H: SerdeBincodeCompat>
194 DeserializeAs<'de, alloy_consensus::BlockBody<T, H>> for BlockBody<'de, T, H>
195 {
196 fn deserialize_as<D>(deserializer: D) -> Result<alloy_consensus::BlockBody<T, H>, D::Error>
197 where
198 D: Deserializer<'de>,
199 {
200 BlockBody::deserialize(deserializer).map(Into::into)
201 }
202 }
203
204 impl<T: SerdeBincodeCompat, H: SerdeBincodeCompat> SerdeBincodeCompat
205 for alloy_consensus::BlockBody<T, H>
206 {
207 type BincodeRepr<'a> = BlockBody<'a, T, H>;
208
209 fn as_repr(&self) -> Self::BincodeRepr<'_> {
210 self.into()
211 }
212
213 fn from_repr(repr: Self::BincodeRepr<'_>) -> Self {
214 repr.into()
215 }
216 }
217}