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,
21};
22pub use list::{
23 MAX_RLP_LIST_TRAVERSAL_DEPTH, RlpItem, RlpList, RlpListForm, RlpListItems, decode_rlp_list,
24 decode_rlp_list_partial,
25};
26
27pub(super) const SHORT_STRING_OFFSET: u8 = 0x80;
28pub(super) const LONG_STRING_OFFSET: u8 = 0xb7;
32pub(super) const SHORT_LIST_OFFSET: u8 = 0xc0;
33pub(super) const LONG_LIST_OFFSET: u8 = 0xf7;
37pub(super) const SHORT_STRING_LIMIT: usize = 55;
38pub(super) const LENGTH_RADIX: usize = 256;
39
40#[derive(Clone, Copy, Debug, Eq, PartialEq)]
42pub enum RlpScalarForm {
43 SingleByte,
45 ShortString,
47 LongString,
49}
50
51#[derive(Clone, Copy, Debug, Eq, PartialEq)]
56pub struct RlpScalar<'a> {
57 payload: &'a [u8],
58 encoded_len: usize,
59 header_len: usize,
60 form: RlpScalarForm,
61}
62
63impl<'a> RlpScalar<'a> {
64 #[must_use]
66 pub const fn payload(self) -> &'a [u8] {
67 self.payload
68 }
69
70 #[must_use]
72 pub const fn encoded_len(self) -> usize {
73 self.encoded_len
74 }
75
76 #[must_use]
78 pub const fn header_len(self) -> usize {
79 self.header_len
80 }
81
82 #[must_use]
84 pub const fn form(self) -> RlpScalarForm {
85 self.form
86 }
87
88 #[must_use]
90 pub const fn is_empty(self) -> bool {
91 self.payload.is_empty()
92 }
93}
94
95pub fn decode_rlp_scalar<'a>(
97 input: &'a [u8],
98 limits: DecodeLimits,
99) -> Result<RlpScalar<'a>, DecodeError> {
100 let mut accumulator = limits.accumulator();
101 let scalar = decode_rlp_scalar_partial(input, &mut accumulator)?;
102 require_exact_consumption(scalar.encoded_len, input.len())?;
103 Ok(scalar)
104}
105
106pub fn decode_rlp_scalar_partial<'a>(
118 input: &'a [u8],
119 accumulator: &mut DecodeAccumulator,
120) -> Result<RlpScalar<'a>, DecodeError> {
121 accumulator.check_input_len(input.len())?;
122 accumulator.account_items(1)?;
123
124 let prefix = *input.first().ok_or(DecodeError::Malformed)?;
125 match prefix {
126 0x00..=0x7f => decode_single_byte(input),
127 SHORT_STRING_OFFSET..=LONG_STRING_OFFSET => decode_short_string(input, prefix),
128 0xb8..=0xbf => decode_long_string(input, prefix),
129 SHORT_LIST_OFFSET..=0xff => Err(DecodeError::UnexpectedList),
130 }
131}
132
133fn decode_single_byte(input: &[u8]) -> Result<RlpScalar<'_>, DecodeError> {
134 let payload = input.get(..1).ok_or(DecodeError::OffsetOutOfBounds)?;
135 Ok(RlpScalar {
136 payload,
137 encoded_len: 1,
138 header_len: 0,
139 form: RlpScalarForm::SingleByte,
140 })
141}
142
143pub(super) fn decode_short_string(input: &[u8], prefix: u8) -> Result<RlpScalar<'_>, DecodeError> {
144 let payload_len = usize::from(prefix.saturating_sub(SHORT_STRING_OFFSET));
145 let payload = payload(input, 1, payload_len)?;
146 if payload_len == 1 && payload.first().is_some_and(|byte| *byte <= 0x7f) {
147 return Err(DecodeError::Malformed);
148 }
149 Ok(RlpScalar {
150 payload,
151 encoded_len: checked_len_add(1, payload_len)?,
152 header_len: 1,
153 form: RlpScalarForm::ShortString,
154 })
155}
156
157pub(super) fn decode_long_string(input: &[u8], prefix: u8) -> Result<RlpScalar<'_>, DecodeError> {
158 let len_of_len = usize::from(prefix.saturating_sub(LONG_STRING_OFFSET));
159 let payload_len = parse_payload_len(input, 1, len_of_len)?;
160 if payload_len <= SHORT_STRING_LIMIT {
161 return Err(DecodeError::Malformed);
162 }
163 let header_len = checked_len_add(1, len_of_len)?;
164 let payload = payload(input, header_len, payload_len)?;
165 Ok(RlpScalar {
166 payload,
167 encoded_len: checked_len_add(header_len, payload_len)?,
168 header_len,
169 form: RlpScalarForm::LongString,
170 })
171}
172
173pub(super) fn parse_payload_len(
174 input: &[u8],
175 offset: usize,
176 len: usize,
177) -> Result<usize, DecodeError> {
178 let end = require_range_in_bounds(offset, len, input.len())?;
179 let bytes = input
180 .get(offset..end)
181 .ok_or(DecodeError::OffsetOutOfBounds)?;
182 if bytes.first().is_some_and(|byte| *byte == 0) {
183 return Err(DecodeError::Malformed);
184 }
185
186 let mut value = 0usize;
187 for byte in bytes {
188 value = value
189 .checked_mul(LENGTH_RADIX)
190 .ok_or(DecodeError::LengthOverflow)?;
191 value = value
192 .checked_add(usize::from(*byte))
193 .ok_or(DecodeError::LengthOverflow)?;
194 }
195 Ok(value)
196}
197
198pub(super) fn payload(input: &[u8], offset: usize, len: usize) -> Result<&[u8], DecodeError> {
199 let end = require_range_in_bounds(offset, len, input.len())?;
200 input.get(offset..end).ok_or(DecodeError::OffsetOutOfBounds)
201}