1mod encode;
2mod integer;
3mod list;
4
5#[cfg(test)]
6mod tests;
7
8use crate::{
9 DecodeAccumulator, DecodeError, DecodeLimits, checked_len_add, require_exact_consumption,
10 require_range_in_bounds,
11};
12
13pub use encode::{
14 encode_decoded_integer, encode_decoded_item, encode_decoded_list, encode_decoded_scalar,
15 encode_rlp_integer, encode_rlp_list_payload, encode_rlp_scalar, encoded_rlp_integer_len,
16 encoded_rlp_list_len, encoded_rlp_scalar_len,
17};
18pub use integer::{
19 MAX_RLP_U256_BYTES, RlpInteger, decode_rlp_integer, decode_rlp_integer_partial, decode_rlp_u64,
20 decode_rlp_u128, decode_rlp_u256_bytes, rlp_integer_payload_to_u64,
21 rlp_integer_payload_to_u128, rlp_integer_payload_to_u256_bytes, validate_rlp_integer_payload,
22};
23pub use list::{
24 MAX_RLP_LIST_TRAVERSAL_DEPTH, RlpItem, RlpList, RlpListForm, RlpListItems, decode_rlp_list,
25 decode_rlp_list_partial,
26};
27
28pub(super) const SHORT_STRING_OFFSET: u8 = 0x80;
29pub(super) const LONG_STRING_OFFSET: u8 = 0xb7;
33pub(super) const SHORT_LIST_OFFSET: u8 = 0xc0;
34pub(super) const LONG_LIST_OFFSET: u8 = 0xf7;
38pub(super) const SHORT_STRING_LIMIT: usize = 55;
39pub(super) const LENGTH_RADIX: usize = 256;
40
41#[derive(Clone, Copy, Debug, Eq, PartialEq)]
43pub enum RlpScalarForm {
44 SingleByte,
46 ShortString,
48 LongString,
50}
51
52#[derive(Clone, Copy, Debug, Eq, PartialEq)]
57pub struct RlpScalar<'a> {
58 payload: &'a [u8],
59 encoded_len: usize,
60 header_len: usize,
61 form: RlpScalarForm,
62}
63
64impl<'a> RlpScalar<'a> {
65 #[must_use]
67 pub const fn payload(self) -> &'a [u8] {
68 self.payload
69 }
70
71 #[must_use]
73 pub const fn encoded_len(self) -> usize {
74 self.encoded_len
75 }
76
77 #[must_use]
79 pub const fn header_len(self) -> usize {
80 self.header_len
81 }
82
83 #[must_use]
85 pub const fn form(self) -> RlpScalarForm {
86 self.form
87 }
88
89 #[must_use]
91 pub const fn is_empty(self) -> bool {
92 self.payload.is_empty()
93 }
94}
95
96pub fn decode_rlp_scalar<'a>(
98 input: &'a [u8],
99 limits: DecodeLimits,
100) -> Result<RlpScalar<'a>, DecodeError> {
101 let mut accumulator = limits.accumulator();
102 let scalar = decode_rlp_scalar_partial(input, &mut accumulator)?;
103 require_exact_consumption(scalar.encoded_len, input.len())?;
104 Ok(scalar)
105}
106
107pub fn decode_rlp_scalar_partial<'a>(
119 input: &'a [u8],
120 accumulator: &mut DecodeAccumulator,
121) -> Result<RlpScalar<'a>, DecodeError> {
122 accumulator.check_input_len(input.len())?;
123 accumulator.account_items(1)?;
124
125 let prefix = *input.first().ok_or(DecodeError::Malformed)?;
126 match prefix {
127 0x00..=0x7f => decode_single_byte(input),
128 SHORT_STRING_OFFSET..=LONG_STRING_OFFSET => decode_short_string(input, prefix),
129 0xb8..=0xbf => decode_long_string(input, prefix),
130 SHORT_LIST_OFFSET..=0xff => Err(DecodeError::UnexpectedList),
131 }
132}
133
134fn decode_single_byte(input: &[u8]) -> Result<RlpScalar<'_>, DecodeError> {
135 let payload = input.get(..1).ok_or(DecodeError::OffsetOutOfBounds)?;
136 Ok(RlpScalar {
137 payload,
138 encoded_len: 1,
139 header_len: 0,
140 form: RlpScalarForm::SingleByte,
141 })
142}
143
144pub(super) fn decode_short_string(input: &[u8], prefix: u8) -> Result<RlpScalar<'_>, DecodeError> {
145 let payload_len = usize::from(prefix.saturating_sub(SHORT_STRING_OFFSET));
146 let payload = payload(input, 1, payload_len)?;
147 if payload_len == 1 && payload.first().is_some_and(|byte| *byte <= 0x7f) {
148 return Err(DecodeError::Malformed);
149 }
150 Ok(RlpScalar {
151 payload,
152 encoded_len: checked_len_add(1, payload_len)?,
153 header_len: 1,
154 form: RlpScalarForm::ShortString,
155 })
156}
157
158pub(super) fn decode_long_string(input: &[u8], prefix: u8) -> Result<RlpScalar<'_>, DecodeError> {
159 let len_of_len = usize::from(prefix.saturating_sub(LONG_STRING_OFFSET));
160 let payload_len = parse_payload_len(input, 1, len_of_len)?;
161 if payload_len <= SHORT_STRING_LIMIT {
162 return Err(DecodeError::Malformed);
163 }
164 let header_len = checked_len_add(1, len_of_len)?;
165 let payload = payload(input, header_len, payload_len)?;
166 Ok(RlpScalar {
167 payload,
168 encoded_len: checked_len_add(header_len, payload_len)?,
169 header_len,
170 form: RlpScalarForm::LongString,
171 })
172}
173
174pub(super) fn parse_payload_len(
175 input: &[u8],
176 offset: usize,
177 len: usize,
178) -> Result<usize, DecodeError> {
179 let end = require_range_in_bounds(offset, len, input.len())?;
180 let bytes = input
181 .get(offset..end)
182 .ok_or(DecodeError::OffsetOutOfBounds)?;
183 if bytes.first().is_some_and(|byte| *byte == 0) {
184 return Err(DecodeError::Malformed);
185 }
186
187 let mut value = 0usize;
188 for byte in bytes {
189 value = value
190 .checked_mul(LENGTH_RADIX)
191 .ok_or(DecodeError::LengthOverflow)?;
192 value = value
193 .checked_add(usize::from(*byte))
194 .ok_or(DecodeError::LengthOverflow)?;
195 }
196 Ok(value)
197}
198
199pub(super) fn payload(input: &[u8], offset: usize, len: usize) -> Result<&[u8], DecodeError> {
200 let end = require_range_in_bounds(offset, len, input.len())?;
201 input.get(offset..end).ok_or(DecodeError::OffsetOutOfBounds)
202}