1use crate::types::Header;
2use bytes::{Buf, Bytes, BytesMut};
3
4pub trait Decodable: Sized {
5 fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError>;
6}
7
8#[cfg(feature = "alloc")]
9mod alloc_impl {
10 use super::*;
11
12 impl<T> Decodable for ::alloc::boxed::Box<T>
13 where
14 T: Decodable + Sized,
15 {
16 fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
17 T::decode(buf).map(::alloc::boxed::Box::new)
18 }
19 }
20
21 impl<T> Decodable for ::alloc::sync::Arc<T>
22 where
23 T: Decodable + Sized,
24 {
25 fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
26 T::decode(buf).map(::alloc::sync::Arc::new)
27 }
28 }
29
30 impl Decodable for ::alloc::string::String {
31 fn decode(from: &mut &[u8]) -> Result<Self, DecodeError> {
32 let h = Header::decode(from)?;
33 if h.list {
34 return Err(DecodeError::UnexpectedList)
35 }
36 let mut to = ::alloc::vec::Vec::with_capacity(h.payload_length);
37 to.extend_from_slice(&from[..h.payload_length]);
38 from.advance(h.payload_length);
39
40 Self::from_utf8(to).map_err(|_| DecodeError::Custom("invalid string"))
41 }
42 }
43}
44
45#[derive(Clone, Copy, Debug, PartialEq)]
46pub enum DecodeError {
47 Overflow,
48 LeadingZero,
49 InputTooShort,
50 NonCanonicalSingleByte,
51 NonCanonicalSize,
52 UnexpectedLength,
53 UnexpectedString,
54 UnexpectedList,
55 ListLengthMismatch { expected: usize, got: usize },
56 Custom(&'static str),
57}
58
59#[cfg(feature = "std")]
60impl std::error::Error for DecodeError {}
61
62impl core::fmt::Display for DecodeError {
63 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
64 match self {
65 DecodeError::Overflow => write!(f, "overflow"),
66 DecodeError::LeadingZero => write!(f, "leading zero"),
67 DecodeError::InputTooShort => write!(f, "input too short"),
68 DecodeError::NonCanonicalSingleByte => write!(f, "non-canonical single byte"),
69 DecodeError::NonCanonicalSize => write!(f, "non-canonical size"),
70 DecodeError::UnexpectedLength => write!(f, "unexpected length"),
71 DecodeError::UnexpectedString => write!(f, "unexpected string"),
72 DecodeError::UnexpectedList => write!(f, "unexpected list"),
73 DecodeError::ListLengthMismatch { expected, got } => {
74 write!(f, "list length mismatch: expected {expected}, got {got}")
75 }
76 DecodeError::Custom(err) => write!(f, "{err}"),
77 }
78 }
79}
80
81impl Header {
82 pub fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
83 if !buf.has_remaining() {
84 return Err(DecodeError::InputTooShort)
85 }
86
87 let b = buf[0];
88 let h: Self = {
89 if b < 0x80 {
90 Self { list: false, payload_length: 1 }
91 } else if b < 0xB8 {
92 buf.advance(1);
93 let h = Self { list: false, payload_length: b as usize - 0x80 };
94
95 if h.payload_length == 1 {
96 if !buf.has_remaining() {
97 return Err(DecodeError::InputTooShort)
98 }
99 if buf[0] < 0x80 {
100 return Err(DecodeError::NonCanonicalSingleByte)
101 }
102 }
103
104 h
105 } else if b < 0xC0 {
106 buf.advance(1);
107 let len_of_len = b as usize - 0xB7;
108 if buf.len() < len_of_len {
109 return Err(DecodeError::InputTooShort)
110 }
111 let payload_length = usize::try_from(u64::from_be_bytes(
112 static_left_pad(&buf[..len_of_len]).ok_or(DecodeError::LeadingZero)?,
113 ))
114 .map_err(|_| DecodeError::Custom("Input too big"))?;
115 buf.advance(len_of_len);
116 if payload_length < 56 {
117 return Err(DecodeError::NonCanonicalSize)
118 }
119
120 Self { list: false, payload_length }
121 } else if b < 0xF8 {
122 buf.advance(1);
123 Self { list: true, payload_length: b as usize - 0xC0 }
124 } else {
125 buf.advance(1);
126 let list = true;
127 let len_of_len = b as usize - 0xF7;
128 if buf.len() < len_of_len {
129 return Err(DecodeError::InputTooShort)
130 }
131 let payload_length = usize::try_from(u64::from_be_bytes(
132 static_left_pad(&buf[..len_of_len]).ok_or(DecodeError::LeadingZero)?,
133 ))
134 .map_err(|_| DecodeError::Custom("Input too big"))?;
135 buf.advance(len_of_len);
136 if payload_length < 56 {
137 return Err(DecodeError::NonCanonicalSize)
138 }
139
140 Self { list, payload_length }
141 }
142 };
143
144 if buf.remaining() < h.payload_length {
145 return Err(DecodeError::InputTooShort)
146 }
147
148 Ok(h)
149 }
150}
151
152fn static_left_pad<const LEN: usize>(data: &[u8]) -> Option<[u8; LEN]> {
153 if data.len() > LEN {
154 return None
155 }
156
157 let mut v = [0; LEN];
158
159 if data.is_empty() {
160 return Some(v)
161 }
162
163 if data[0] == 0 {
164 return None
165 }
166
167 v[LEN - data.len()..].copy_from_slice(data);
168 Some(v)
169}
170
171macro_rules! decode_integer {
172 ($t:ty) => {
173 impl Decodable for $t {
174 fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
175 let h = Header::decode(buf)?;
176 if h.list {
177 return Err(DecodeError::UnexpectedList)
178 }
179 if h.payload_length > (<$t>::BITS as usize / 8) {
180 return Err(DecodeError::Overflow)
181 }
182 if buf.remaining() < h.payload_length {
183 return Err(DecodeError::InputTooShort)
184 }
185 let v = <$t>::from_be_bytes(
186 static_left_pad(&buf[..h.payload_length]).ok_or(DecodeError::LeadingZero)?,
187 );
188 buf.advance(h.payload_length);
189 Ok(v)
190 }
191 }
192 };
193}
194
195decode_integer!(usize);
196decode_integer!(u8);
197decode_integer!(u16);
198decode_integer!(u32);
199decode_integer!(u64);
200decode_integer!(u128);
201
202impl Decodable for bool {
203 fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
204 Ok(match u8::decode(buf)? {
205 0 => false,
206 1 => true,
207 _ => return Err(DecodeError::Custom("invalid bool value, must be 0 or 1")),
208 })
209 }
210}
211
212#[cfg(feature = "ethnum")]
213decode_integer!(ethnum::U256);
214
215#[cfg(feature = "ethereum-types")]
216mod ethereum_types_support {
217 use super::*;
218 use ethereum_types::*;
219
220 macro_rules! fixed_hash_impl {
221 ($t:ty) => {
222 impl Decodable for $t {
223 fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
224 Decodable::decode(buf).map(Self)
225 }
226 }
227 };
228 }
229
230 fixed_hash_impl!(H64);
231 fixed_hash_impl!(H128);
232 fixed_hash_impl!(H160);
233 fixed_hash_impl!(H256);
234 fixed_hash_impl!(H512);
235 fixed_hash_impl!(H520);
236 fixed_hash_impl!(Bloom);
237
238 macro_rules! fixed_uint_impl {
239 ($t:ty, $n_bytes:tt) => {
240 impl Decodable for $t {
241 fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
242 let h = Header::decode(buf)?;
243 if h.list {
244 return Err(DecodeError::UnexpectedList)
245 }
246 if h.payload_length > $n_bytes {
247 return Err(DecodeError::Overflow)
248 }
249 if buf.remaining() < h.payload_length {
250 return Err(DecodeError::InputTooShort)
251 }
252 let n = <$t>::from_big_endian(
253 &static_left_pad::<$n_bytes>(&buf[..h.payload_length])
254 .ok_or(DecodeError::LeadingZero)?,
255 );
256 buf.advance(h.payload_length);
257 Ok(n)
258 }
259 }
260 };
261 }
262
263 fixed_uint_impl!(U64, 8);
264 fixed_uint_impl!(U128, 16);
265 fixed_uint_impl!(U256, 32);
266 fixed_uint_impl!(U512, 64);
267}
268
269impl<const N: usize> Decodable for [u8; N] {
270 fn decode(from: &mut &[u8]) -> Result<Self, DecodeError> {
271 let h = Header::decode(from)?;
272 if h.list {
273 return Err(DecodeError::UnexpectedList)
274 }
275 if h.payload_length != N {
276 return Err(DecodeError::UnexpectedLength)
277 }
278
279 let mut to = [0_u8; N];
280 to.copy_from_slice(&from[..N]);
281 from.advance(N);
282
283 Ok(to)
284 }
285}
286
287impl Decodable for BytesMut {
288 fn decode(from: &mut &[u8]) -> Result<Self, DecodeError> {
289 let h = Header::decode(from)?;
290 if h.list {
291 return Err(DecodeError::UnexpectedList)
292 }
293 let mut to = BytesMut::with_capacity(h.payload_length);
294 to.extend_from_slice(&from[..h.payload_length]);
295 from.advance(h.payload_length);
296
297 Ok(to)
298 }
299}
300
301impl Decodable for Bytes {
302 fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
303 BytesMut::decode(buf).map(BytesMut::freeze)
304 }
305}
306
307pub struct Rlp<'a> {
308 payload_view: &'a [u8],
309}
310
311impl<'a> Rlp<'a> {
312 pub fn new(mut payload: &'a [u8]) -> Result<Self, DecodeError> {
313 let h = Header::decode(&mut payload)?;
314 if !h.list {
315 return Err(DecodeError::UnexpectedString)
316 }
317
318 let payload_view = &payload[..h.payload_length];
319 Ok(Self { payload_view })
320 }
321
322 pub fn get_next<T: Decodable>(&mut self) -> Result<Option<T>, DecodeError> {
323 if self.payload_view.is_empty() {
324 return Ok(None)
325 }
326
327 Ok(Some(T::decode(&mut self.payload_view)?))
328 }
329}
330
331#[cfg(feature = "alloc")]
332impl<E> Decodable for alloc::vec::Vec<E>
333where
334 E: Decodable,
335{
336 fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
337 let h = Header::decode(buf)?;
338 if !h.list {
339 return Err(DecodeError::UnexpectedString)
340 }
341
342 let payload_view = &mut &buf[..h.payload_length];
343
344 let mut to = alloc::vec::Vec::new();
345 while !payload_view.is_empty() {
346 to.push(E::decode(payload_view)?);
347 }
348
349 buf.advance(h.payload_length);
350
351 Ok(to)
352 }
353}
354
355#[cfg(test)]
356mod tests {
357 extern crate alloc;
358
359 use super::*;
360 use alloc::vec;
361 use core::fmt::Debug;
362 use ethereum_types::{U128, U256, U512, U64};
363 use ethnum::AsU256;
364 use hex_literal::hex;
365
366 fn check_decode<T, IT>(fixtures: IT)
367 where
368 T: Decodable + PartialEq + Debug,
369 IT: IntoIterator<Item = (Result<T, DecodeError>, &'static [u8])>,
370 {
371 for (expected, mut input) in fixtures {
372 assert_eq!(T::decode(&mut input), expected);
373 if expected.is_ok() {
374 assert_eq!(input, &[]);
375 }
376 }
377 }
378
379 fn check_decode_list<T, IT>(fixtures: IT)
380 where
381 T: Decodable + PartialEq + Debug,
382 IT: IntoIterator<Item = (Result<alloc::vec::Vec<T>, DecodeError>, &'static [u8])>,
383 {
384 for (expected, mut input) in fixtures {
385 assert_eq!(vec::Vec::<T>::decode(&mut input), expected);
386 if expected.is_ok() {
387 assert_eq!(input, &[]);
388 }
389 }
390 }
391
392 #[test]
393 fn rlp_strings() {
394 check_decode::<Bytes, _>(vec![
395 (Ok((&hex!("00")[..]).to_vec().into()), &hex!("00")[..]),
396 (
397 Ok((&hex!("6f62636465666768696a6b6c6d")[..]).to_vec().into()),
398 &hex!("8D6F62636465666768696A6B6C6D")[..],
399 ),
400 (Err(DecodeError::UnexpectedList), &hex!("C0")[..]),
401 ])
402 }
403
404 #[test]
405 fn rlp_fixed_length() {
406 check_decode(vec![
407 (Ok(hex!("6f62636465666768696a6b6c6d")), &hex!("8D6F62636465666768696A6B6C6D")[..]),
408 (Err(DecodeError::UnexpectedLength), &hex!("8C6F62636465666768696A6B6C")[..]),
409 (Err(DecodeError::UnexpectedLength), &hex!("8E6F62636465666768696A6B6C6D6E")[..]),
410 ])
411 }
412
413 #[test]
414 fn rlp_u64() {
415 check_decode(vec![
416 (Ok(9_u64), &hex!("09")[..]),
417 (Ok(0_u64), &hex!("80")[..]),
418 (Ok(0x0505_u64), &hex!("820505")[..]),
419 (Ok(0xCE05050505_u64), &hex!("85CE05050505")[..]),
420 (Err(DecodeError::Overflow), &hex!("8AFFFFFFFFFFFFFFFFFF7C")[..]),
421 (Err(DecodeError::InputTooShort), &hex!("8BFFFFFFFFFFFFFFFFFF7C")[..]),
422 (Err(DecodeError::UnexpectedList), &hex!("C0")[..]),
423 (Err(DecodeError::LeadingZero), &hex!("00")[..]),
424 (Err(DecodeError::NonCanonicalSingleByte), &hex!("8105")[..]),
425 (Err(DecodeError::LeadingZero), &hex!("8200F4")[..]),
426 (Err(DecodeError::NonCanonicalSize), &hex!("B8020004")[..]),
427 (
428 Err(DecodeError::Overflow),
429 &hex!("A101000000000000000000000000000000000000008B000000000000000000000000")[..],
430 ),
431 ])
432 }
433
434 #[test]
435 fn rlp_u256() {
436 check_decode(vec![
437 (Ok(9_u8.as_u256()), &hex!("09")[..]),
438 (Ok(0_u8.as_u256()), &hex!("80")[..]),
439 (Ok(0x0505_u16.as_u256()), &hex!("820505")[..]),
440 (Ok(0xCE05050505_u64.as_u256()), &hex!("85CE05050505")[..]),
441 (Ok(0xFFFFFFFFFFFFFFFFFF7C_u128.as_u256()), &hex!("8AFFFFFFFFFFFFFFFFFF7C")[..]),
442 (Err(DecodeError::InputTooShort), &hex!("8BFFFFFFFFFFFFFFFFFF7C")[..]),
443 (Err(DecodeError::UnexpectedList), &hex!("C0")[..]),
444 (Err(DecodeError::LeadingZero), &hex!("00")[..]),
445 (Err(DecodeError::NonCanonicalSingleByte), &hex!("8105")[..]),
446 (Err(DecodeError::LeadingZero), &hex!("8200F4")[..]),
447 (Err(DecodeError::NonCanonicalSize), &hex!("B8020004")[..]),
448 (
449 Err(DecodeError::Overflow),
450 &hex!("A101000000000000000000000000000000000000008B000000000000000000000000")[..],
451 ),
452 ])
453 }
454
455 #[cfg(feature = "ethereum-types")]
456 #[test]
457 fn rlp_ethereum_types_u64() {
458 check_decode(vec![
459 (Ok(U64::from(9_u8)), &hex!("09")[..]),
460 (Ok(U64::from(0_u8)), &hex!("80")[..]),
461 (Ok(U64::from(0x0505_u16)), &hex!("820505")[..]),
462 (Ok(U64::from(0xCE05050505_u64)), &hex!("85CE05050505")[..]),
463 (Err(DecodeError::Overflow), &hex!("8AFFFFFFFFFFFFFFFFFF7C")[..]),
464 (Err(DecodeError::InputTooShort), &hex!("8BFFFFFFFFFFFFFFFFFF7C")[..]),
465 (Err(DecodeError::UnexpectedList), &hex!("C0")[..]),
466 (Err(DecodeError::LeadingZero), &hex!("00")[..]),
467 (Err(DecodeError::NonCanonicalSingleByte), &hex!("8105")[..]),
468 (Err(DecodeError::LeadingZero), &hex!("8200F4")[..]),
469 (Err(DecodeError::NonCanonicalSize), &hex!("B8020004")[..]),
470 (
471 Err(DecodeError::Overflow),
472 &hex!("A101000000000000000000000000000000000000008B000000000000000000000000")[..],
473 ),
474 ])
475 }
476
477 #[cfg(feature = "ethereum-types")]
478 #[test]
479 fn rlp_ethereum_types_u128() {
480 check_decode(vec![
481 (Ok(U128::from(9_u8)), &hex!("09")[..]),
482 (Ok(U128::from(0_u8)), &hex!("80")[..]),
483 (Ok(U128::from(0x0505_u16)), &hex!("820505")[..]),
484 (Ok(U128::from(0xCE05050505_u64)), &hex!("85CE05050505")[..]),
485 (Ok(U128::from(0xFFFFFFFFFFFFFFFFFF7C_u128)), &hex!("8AFFFFFFFFFFFFFFFFFF7C")[..]),
486 (Err(DecodeError::InputTooShort), &hex!("8BFFFFFFFFFFFFFFFFFF7C")[..]),
487 (Err(DecodeError::UnexpectedList), &hex!("C0")[..]),
488 (Err(DecodeError::LeadingZero), &hex!("00")[..]),
489 (Err(DecodeError::NonCanonicalSingleByte), &hex!("8105")[..]),
490 (Err(DecodeError::LeadingZero), &hex!("8200F4")[..]),
491 (Err(DecodeError::NonCanonicalSize), &hex!("B8020004")[..]),
492 (
493 Err(DecodeError::Overflow),
494 &hex!("A101000000000000000000000000000000000000008B000000000000000000000000")[..],
495 ),
496 ])
497 }
498
499 #[cfg(feature = "ethereum-types")]
500 #[test]
501 fn rlp_ethereum_types_u256() {
502 check_decode(vec![
503 (Ok(U256::from(9_u8)), &hex!("09")[..]),
504 (Ok(U256::from(0_u8)), &hex!("80")[..]),
505 (Ok(U256::from(0x0505_u16)), &hex!("820505")[..]),
506 (Ok(U256::from(0xCE05050505_u64)), &hex!("85CE05050505")[..]),
507 (Ok(U256::from(0xFFFFFFFFFFFFFFFFFF7C_u128)), &hex!("8AFFFFFFFFFFFFFFFFFF7C")[..]),
508 (Err(DecodeError::InputTooShort), &hex!("8BFFFFFFFFFFFFFFFFFF7C")[..]),
509 (Err(DecodeError::UnexpectedList), &hex!("C0")[..]),
510 (Err(DecodeError::LeadingZero), &hex!("00")[..]),
511 (Err(DecodeError::NonCanonicalSingleByte), &hex!("8105")[..]),
512 (Err(DecodeError::LeadingZero), &hex!("8200F4")[..]),
513 (Err(DecodeError::NonCanonicalSize), &hex!("B8020004")[..]),
514 (
515 Err(DecodeError::Overflow),
516 &hex!("A101000000000000000000000000000000000000008B000000000000000000000000")[..],
517 ),
518 ])
519 }
520
521 #[cfg(feature = "ethereum-types")]
522 #[test]
523 fn rlp_ethereum_types_u512() {
524 check_decode(vec![
525 (Ok(U512::from(9_u8)), &hex!("09")[..]),
526 (Ok(U512::from(0_u8)), &hex!("80")[..]),
527 (Ok(U512::from(0x0505_u16)), &hex!("820505")[..]),
528 (Ok(U512::from(0xCE05050505_u64)), &hex!("85CE05050505")[..]),
529 (
530 Ok(U512::from(0xFFFFFFFFFFFFFFFFFF7C_u128)),
531 &hex!("8AFFFFFFFFFFFFFFFFFF7C")[..],
532 ),
533 (
534 Err(DecodeError::InputTooShort),
535 &hex!("8BFFFFFFFFFFFFFFFFFF7C")[..],
536 ),
537 (Err(DecodeError::UnexpectedList), &hex!("C0")[..]),
538 (Err(DecodeError::LeadingZero), &hex!("00")[..]),
539 (Err(DecodeError::NonCanonicalSingleByte), &hex!("8105")[..]),
540 (Err(DecodeError::LeadingZero), &hex!("8200F4")[..]),
541 (Err(DecodeError::NonCanonicalSize), &hex!("B8020004")[..]),
542 (
543 Ok(U512::from_dec_str("115792089237316195423570985008687907853269984676653278628940326933415738736640").unwrap()),
544 &hex!("A101000000000000000000000000000000000000008B000000000000000000000000")[..],
545 ),
546 (
547 Err(DecodeError::Overflow),
548 &hex!("B84101000000000000000000000000000000000000008B000000000000000000000000000000000000000000000000000000000000008B000000000000000000000000")[..],
549 ),
550 ])
551 }
552
553 #[test]
554 fn rlp_vectors() {
555 check_decode_list(vec![
556 (Ok(vec![]), &hex!("C0")[..]),
557 (Ok(vec![0xBBCCB5_u64, 0xFFC0B5_u64]), &hex!("C883BBCCB583FFC0B5")[..]),
558 ])
559 }
560}