Skip to main content

eth_valkyoth_primitives/
rlp_traits.rs

1use 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}