open_fastrlp/
decode.rs

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}