eth_valkyoth_primitives/
rlp_traits.rs1use eth_valkyoth_codec::{DecodeError, RlpDecode, RlpDeriveError, RlpEncode, RlpInteger, RlpItem};
2
3use crate::{
4 Address, B256, BlockNumber, ChainId, Gas, Nonce, PrimitiveError, PrimitiveRlpError,
5 UnixTimestamp, Wei,
6};
7
8impl From<PrimitiveRlpError> for RlpDeriveError {
9 fn from(_error: PrimitiveRlpError) -> Self {
10 Self::Field
11 }
12}
13
14macro_rules! rlp_u64_traits {
15 ($name:ident) => {
16 impl RlpEncode for $name {
17 type Error = PrimitiveRlpError;
18
19 fn encoded_rlp_len(&self) -> Result<usize, Self::Error> {
20 $name::encoded_rlp_len(*self)
21 }
22
23 fn encode_rlp(&self, output: &mut [u8]) -> Result<usize, Self::Error> {
24 $name::encode_rlp(*self, output)
25 }
26 }
27
28 impl RlpDecode for $name {
29 type Error = PrimitiveRlpError;
30
31 fn decode_rlp(
32 input: &[u8],
33 limits: eth_valkyoth_codec::DecodeLimits,
34 ) -> Result<Self, Self::Error> {
35 $name::try_from_rlp(input, limits)
36 }
37
38 fn decode_rlp_item(item: RlpItem<'_>) -> Result<Self, Self::Error> {
39 decode_u64_item(item).map($name::new)
40 }
41 }
42 };
43}
44
45rlp_u64_traits!(ChainId);
46rlp_u64_traits!(BlockNumber);
47rlp_u64_traits!(Gas);
48rlp_u64_traits!(Nonce);
49rlp_u64_traits!(UnixTimestamp);
50
51impl RlpEncode for Wei {
52 type Error = PrimitiveRlpError;
53
54 fn encoded_rlp_len(&self) -> Result<usize, Self::Error> {
55 Self::encoded_rlp_len(*self)
56 }
57
58 fn encode_rlp(&self, output: &mut [u8]) -> Result<usize, Self::Error> {
59 Self::encode_rlp(*self, output)
60 }
61}
62
63impl RlpDecode for Wei {
64 type Error = PrimitiveRlpError;
65
66 fn decode_rlp(
67 input: &[u8],
68 limits: eth_valkyoth_codec::DecodeLimits,
69 ) -> Result<Self, Self::Error> {
70 Self::try_from_rlp(input, limits)
71 }
72
73 fn decode_rlp_item(item: RlpItem<'_>) -> Result<Self, Self::Error> {
74 let scalar = item.as_scalar().ok_or(DecodeError::UnexpectedList)?;
75 RlpInteger::try_from_scalar(scalar)?
76 .to_be_bytes32()
77 .map(Self::from_be_bytes)
78 .map_err(Into::into)
79 }
80}
81
82macro_rules! rlp_fixed_scalar_traits {
83 ($name:ident, $len:expr) => {
84 impl RlpEncode for $name {
85 type Error = PrimitiveRlpError;
86
87 fn encoded_rlp_len(&self) -> Result<usize, Self::Error> {
88 $name::encoded_rlp_len(*self)
89 }
90
91 fn encode_rlp(&self, output: &mut [u8]) -> Result<usize, Self::Error> {
92 $name::encode_rlp(*self, output)
93 }
94 }
95
96 impl RlpDecode for $name {
97 type Error = PrimitiveRlpError;
98
99 fn decode_rlp(
100 input: &[u8],
101 limits: eth_valkyoth_codec::DecodeLimits,
102 ) -> Result<Self, Self::Error> {
103 $name::try_from_rlp(input, limits)
104 }
105
106 fn decode_rlp_item(item: RlpItem<'_>) -> Result<Self, Self::Error> {
107 let scalar = item.as_scalar().ok_or(DecodeError::UnexpectedList)?;
108 let found = scalar.payload().len();
109 let bytes = scalar.payload().try_into().map_err(|_| {
110 PrimitiveRlpError::FixedWidthScalar {
111 expected: $len,
112 found,
113 }
114 })?;
115 Ok($name::from_bytes(bytes))
116 }
117 }
118 };
119}
120
121rlp_fixed_scalar_traits!(Address, 20);
122rlp_fixed_scalar_traits!(B256, 32);
123
124fn decode_u64_item(item: RlpItem<'_>) -> Result<u64, PrimitiveRlpError> {
125 let scalar = item.as_scalar().ok_or(DecodeError::UnexpectedList)?;
126 RlpInteger::try_from_scalar(scalar)?
127 .to_u64()
128 .map_err(map_decode_u64_error)
129}
130
131fn map_decode_u64_error(error: DecodeError) -> PrimitiveRlpError {
132 match error {
133 DecodeError::Malformed => PrimitiveRlpError::Primitive(PrimitiveError::NonCanonicalInteger),
134 DecodeError::LengthOverflow | DecodeError::OffsetOutOfBounds => {
135 PrimitiveRlpError::Primitive(PrimitiveError::IntegerTooLarge)
136 }
137 _ => PrimitiveRlpError::Decode(error),
138 }
139}