Skip to main content

eth_valkyoth_codec/rlp/
traits.rs

1use core::fmt;
2
3use crate::{DecodeError, DecodeLimits, checked_len_add};
4
5use super::{
6    RlpInteger, RlpItem, decode_rlp_u64, decode_rlp_u128, encode_rlp_integer, encode_rlp_scalar,
7    encoded_rlp_integer_len, encoded_rlp_scalar_len,
8};
9
10/// RLP encoding contract for derive-generated and hand-written domains.
11///
12/// Implementations must return the exact encoded length and must not modify the
13/// output buffer when they reject before writing.
14///
15/// Aggregate encoders, including derive-generated struct encoders, may already
16/// have written a valid prefix when a later field encoder returns an error or
17/// reports an inconsistent byte count. Callers must treat the returned length as
18/// authoritative and must discard the output buffer on any error.
19pub trait RlpEncode {
20    /// Error returned by this encoder.
21    type Error;
22
23    /// Returns the exact canonical RLP encoded length.
24    fn encoded_rlp_len(&self) -> Result<usize, Self::Error>;
25
26    /// Canonically encodes `self` into `output`.
27    ///
28    /// Returns the number of bytes written.
29    fn encode_rlp(&self, output: &mut [u8]) -> Result<usize, Self::Error>;
30}
31
32/// RLP decoding contract for derive-generated and hand-written domains.
33pub trait RlpDecode: Sized {
34    /// Error returned by this decoder.
35    type Error;
36
37    /// Decodes exactly one canonical RLP item from `input`.
38    fn decode_rlp(input: &[u8], limits: DecodeLimits) -> Result<Self, Self::Error>;
39
40    /// Decodes one already-bounded child item from an outer RLP list.
41    fn decode_rlp_item(item: RlpItem<'_>) -> Result<Self, Self::Error>;
42}
43
44/// Error used by derive-generated RLP struct encoders and decoders.
45#[non_exhaustive]
46#[derive(Clone, Copy, Debug, Eq, PartialEq)]
47pub enum RlpDeriveError {
48    /// The bounded codec rejected the input or output buffer.
49    Decode(DecodeError),
50    /// A field-specific codec rejected one generated field operation.
51    Field,
52    /// The decoded list field count did not match the generated struct shape.
53    WrongFieldCount {
54        /// Expected encoded field count.
55        expected: usize,
56        /// Decoded encoded field count.
57        found: usize,
58    },
59}
60
61impl From<DecodeError> for RlpDeriveError {
62    fn from(error: DecodeError) -> Self {
63        Self::Decode(error)
64    }
65}
66
67impl fmt::Display for RlpDeriveError {
68    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
69        match self {
70            Self::Decode(error) => write!(formatter, "RLP codec error: {error}"),
71            Self::Field => formatter.write_str("RLP field codec error"),
72            Self::WrongFieldCount { expected, found } => write!(
73                formatter,
74                "RLP list field count mismatch: expected {expected}, found {found}"
75            ),
76        }
77    }
78}
79
80#[cfg(feature = "std")]
81impl std::error::Error for RlpDeriveError {
82    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
83        match self {
84            Self::Decode(error) => Some(error),
85            Self::Field | Self::WrongFieldCount { .. } => None,
86        }
87    }
88}
89
90impl From<core::convert::Infallible> for RlpDeriveError {
91    fn from(error: core::convert::Infallible) -> Self {
92        match error {}
93    }
94}
95
96impl RlpEncode for u64 {
97    type Error = DecodeError;
98
99    fn encoded_rlp_len(&self) -> Result<usize, Self::Error> {
100        let bytes = self.to_be_bytes();
101        encoded_rlp_integer_len(trim_payload(&bytes))
102    }
103
104    fn encode_rlp(&self, output: &mut [u8]) -> Result<usize, Self::Error> {
105        let bytes = self.to_be_bytes();
106        encode_rlp_integer(trim_payload(&bytes), output)
107    }
108}
109
110impl RlpDecode for u64 {
111    type Error = DecodeError;
112
113    fn decode_rlp(input: &[u8], limits: DecodeLimits) -> Result<Self, Self::Error> {
114        decode_rlp_u64(input, limits)
115    }
116
117    fn decode_rlp_item(item: RlpItem<'_>) -> Result<Self, Self::Error> {
118        let scalar = item.as_scalar().ok_or(DecodeError::UnexpectedList)?;
119        RlpInteger::try_from_scalar(scalar)?.to_u64()
120    }
121}
122
123impl RlpEncode for u128 {
124    type Error = DecodeError;
125
126    fn encoded_rlp_len(&self) -> Result<usize, Self::Error> {
127        let bytes = self.to_be_bytes();
128        encoded_rlp_integer_len(trim_payload(&bytes))
129    }
130
131    fn encode_rlp(&self, output: &mut [u8]) -> Result<usize, Self::Error> {
132        let bytes = self.to_be_bytes();
133        encode_rlp_integer(trim_payload(&bytes), output)
134    }
135}
136
137impl RlpDecode for u128 {
138    type Error = DecodeError;
139
140    fn decode_rlp(input: &[u8], limits: DecodeLimits) -> Result<Self, Self::Error> {
141        decode_rlp_u128(input, limits)
142    }
143
144    fn decode_rlp_item(item: RlpItem<'_>) -> Result<Self, Self::Error> {
145        let scalar = item.as_scalar().ok_or(DecodeError::UnexpectedList)?;
146        RlpInteger::try_from_scalar(scalar)?.to_u128()
147    }
148}
149
150impl<const N: usize> RlpEncode for [u8; N] {
151    type Error = DecodeError;
152
153    fn encoded_rlp_len(&self) -> Result<usize, Self::Error> {
154        encoded_rlp_scalar_len(self)
155    }
156
157    fn encode_rlp(&self, output: &mut [u8]) -> Result<usize, Self::Error> {
158        encode_rlp_scalar(self, output)
159    }
160}
161
162impl<const N: usize> RlpDecode for [u8; N] {
163    type Error = DecodeError;
164
165    fn decode_rlp(input: &[u8], limits: DecodeLimits) -> Result<Self, Self::Error> {
166        let scalar = super::decode_rlp_scalar(input, limits)?;
167        scalar
168            .payload()
169            .try_into()
170            .map_err(|_| DecodeError::Malformed)
171    }
172
173    fn decode_rlp_item(item: RlpItem<'_>) -> Result<Self, Self::Error> {
174        let scalar = item.as_scalar().ok_or(DecodeError::UnexpectedList)?;
175        scalar
176            .payload()
177            .try_into()
178            .map_err(|_| DecodeError::Malformed)
179    }
180}
181
182fn trim_payload<const N: usize>(bytes: &[u8; N]) -> &[u8] {
183    let start = bytes.iter().position(|byte| *byte != 0).unwrap_or(N);
184    bytes.get(start..).unwrap_or(&[])
185}
186
187/// Adds two encoded lengths with overflow checking.
188pub fn checked_encoded_len_add(left: usize, right: usize) -> Result<usize, RlpDeriveError> {
189    checked_len_add(left, right).map_err(Into::into)
190}