|
1 | 1 | use crate::types::Header;
|
2 | 2 | use arrayvec::ArrayVec;
|
3 | 3 | use bytes::{Buf, Bytes, BytesMut};
|
| 4 | +use core::any::Any; |
4 | 5 |
|
5 | 6 | pub trait Decodable: Sized {
|
6 | 7 | fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError>;
|
@@ -41,6 +42,38 @@ mod alloc_impl {
|
41 | 42 | Self::from_utf8(to).map_err(|_| DecodeError::Custom("invalid string"))
|
42 | 43 | }
|
43 | 44 | }
|
| 45 | + |
| 46 | + impl<T> Decodable for ::alloc::vec::Vec<T> |
| 47 | + where |
| 48 | + T: Decodable + 'static, |
| 49 | + { |
| 50 | + fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> { |
| 51 | + let h = Header::decode(buf)?; |
| 52 | + |
| 53 | + let mut to = ::alloc::vec::Vec::new(); |
| 54 | + if let Some(to) = <dyn Any>::downcast_mut::<::alloc::vec::Vec<u8>>(&mut to) { |
| 55 | + if h.list { |
| 56 | + return Err(DecodeError::UnexpectedList); |
| 57 | + } |
| 58 | + to.extend_from_slice(&buf[..h.payload_length]); |
| 59 | + buf.advance(h.payload_length); |
| 60 | + } else { |
| 61 | + if !h.list { |
| 62 | + return Err(DecodeError::UnexpectedString); |
| 63 | + } |
| 64 | + |
| 65 | + let payload_view = &mut &buf[..h.payload_length]; |
| 66 | + |
| 67 | + while !payload_view.is_empty() { |
| 68 | + to.push(T::decode(payload_view)?); |
| 69 | + } |
| 70 | + |
| 71 | + buf.advance(h.payload_length); |
| 72 | + } |
| 73 | + |
| 74 | + Ok(to) |
| 75 | + } |
| 76 | + } |
44 | 77 | }
|
45 | 78 |
|
46 | 79 | #[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
@@ -283,21 +316,17 @@ mod ethereum_types_support {
|
283 | 316 | fixed_uint_impl!(U512, 64);
|
284 | 317 | }
|
285 | 318 |
|
286 |
| -impl<const N: usize> Decodable for [u8; N] { |
287 |
| - fn decode(from: &mut &[u8]) -> Result<Self, DecodeError> { |
288 |
| - let h = Header::decode(from)?; |
289 |
| - if h.list { |
290 |
| - return Err(DecodeError::UnexpectedList); |
291 |
| - } |
292 |
| - if h.payload_length != N { |
293 |
| - return Err(DecodeError::UnexpectedLength); |
294 |
| - } |
295 |
| - |
296 |
| - let mut to = [0_u8; N]; |
297 |
| - to.copy_from_slice(&from[..N]); |
298 |
| - from.advance(N); |
299 |
| - |
300 |
| - Ok(to) |
| 319 | +impl<T, const LEN: usize> Decodable for [T; LEN] |
| 320 | +where |
| 321 | + T: Decodable + 'static, |
| 322 | +{ |
| 323 | + fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> { |
| 324 | + ArrayVec::<T, LEN>::decode(buf)? |
| 325 | + .into_inner() |
| 326 | + .map_err(|arr| DecodeError::ListLengthMismatch { |
| 327 | + expected: LEN, |
| 328 | + got: arr.len(), |
| 329 | + }) |
301 | 330 | }
|
302 | 331 | }
|
303 | 332 |
|
@@ -345,51 +374,44 @@ impl<'a> Rlp<'a> {
|
345 | 374 | }
|
346 | 375 | }
|
347 | 376 |
|
348 |
| -#[cfg(feature = "alloc")] |
349 |
| -impl<E> Decodable for alloc::vec::Vec<E> |
| 377 | +impl<T, const LEN: usize> Decodable for ArrayVec<T, LEN> |
350 | 378 | where
|
351 |
| - E: Decodable, |
| 379 | + T: Decodable + 'static, |
352 | 380 | {
|
353 | 381 | fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> {
|
354 |
| - let h = Header::decode(buf)?; |
355 |
| - if !h.list { |
356 |
| - return Err(DecodeError::UnexpectedString); |
357 |
| - } |
358 |
| - |
359 |
| - let payload_view = &mut &buf[..h.payload_length]; |
360 |
| - |
361 |
| - let mut to = alloc::vec::Vec::new(); |
362 |
| - while !payload_view.is_empty() { |
363 |
| - to.push(E::decode(payload_view)?); |
364 |
| - } |
| 382 | + let mut arr: ArrayVec<T, LEN> = ArrayVec::new(); |
| 383 | + if let Some(s) = <dyn Any>::downcast_mut::<ArrayVec<u8, LEN>>(&mut arr) { |
| 384 | + let h = Header::decode(buf)?; |
| 385 | + if h.list { |
| 386 | + return Err(DecodeError::UnexpectedList); |
| 387 | + } |
| 388 | + if h.payload_length != LEN { |
| 389 | + return Err(DecodeError::UnexpectedLength); |
| 390 | + } |
365 | 391 |
|
366 |
| - buf.advance(h.payload_length); |
| 392 | + s.try_extend_from_slice(&buf[..LEN]).unwrap(); |
| 393 | + buf.advance(LEN); |
| 394 | + } else { |
| 395 | + let h = Header::decode(buf)?; |
| 396 | + if !h.list { |
| 397 | + return Err(DecodeError::UnexpectedString); |
| 398 | + } |
367 | 399 |
|
368 |
| - Ok(to) |
369 |
| - } |
370 |
| -} |
| 400 | + let payload_view = &mut &buf[..h.payload_length]; |
371 | 401 |
|
372 |
| -impl<E, const LEN: usize> Decodable for ArrayVec<E, LEN> |
373 |
| -where |
374 |
| - E: Decodable, |
375 |
| -{ |
376 |
| - fn decode(buf: &mut &[u8]) -> Result<Self, DecodeError> { |
377 |
| - let h = Header::decode(buf)?; |
378 |
| - if !h.list { |
379 |
| - return Err(DecodeError::UnexpectedString); |
380 |
| - } |
381 |
| - |
382 |
| - let payload_view = &mut &buf[..h.payload_length]; |
| 402 | + while !payload_view.is_empty() { |
| 403 | + if arr.try_push(T::decode(payload_view)?).is_err() { |
| 404 | + return Err(DecodeError::ListLengthMismatch { |
| 405 | + expected: LEN, |
| 406 | + got: LEN + 1, |
| 407 | + }); |
| 408 | + } |
| 409 | + } |
383 | 410 |
|
384 |
| - let mut to = ArrayVec::new(); |
385 |
| - while !payload_view.is_empty() { |
386 |
| - to.try_push(E::decode(payload_view)?) |
387 |
| - .map_err(|_| DecodeError::Custom("arrayvec full"))?; |
| 411 | + buf.advance(h.payload_length); |
388 | 412 | }
|
389 | 413 |
|
390 |
| - buf.advance(h.payload_length); |
391 |
| - |
392 |
| - Ok(to) |
| 414 | + Ok(arr) |
393 | 415 | }
|
394 | 416 | }
|
395 | 417 |
|
@@ -419,7 +441,7 @@ mod tests {
|
419 | 441 |
|
420 | 442 | fn check_decode_list<T, IT>(fixtures: IT)
|
421 | 443 | where
|
422 |
| - T: Decodable + PartialEq + Debug, |
| 444 | + T: Decodable + PartialEq + Debug + 'static, |
423 | 445 | IT: IntoIterator<Item = (Result<alloc::vec::Vec<T>, DecodeError>, &'static [u8])>,
|
424 | 446 | {
|
425 | 447 | for (expected, mut input) in fixtures {
|
@@ -640,4 +662,25 @@ mod tests {
|
640 | 662 | ),
|
641 | 663 | ])
|
642 | 664 | }
|
| 665 | + |
| 666 | + #[test] |
| 667 | + fn vec_specialization() { |
| 668 | + const SPECIALIZED: [u8; 2] = [0x42_u8, 0x43_u8]; |
| 669 | + const GENERAL: [u64; 2] = [0xFFCCB5_u64, 0xFFC0B5_u64]; |
| 670 | + |
| 671 | + const SPECIALIZED_EXP: &[u8] = &hex!("824243"); |
| 672 | + const GENERAL_EXP: &[u8] = &hex!("C883FFCCB583FFC0B5"); |
| 673 | + |
| 674 | + check_decode([(Ok(SPECIALIZED), SPECIALIZED_EXP)]); |
| 675 | + check_decode([(Ok(GENERAL), GENERAL_EXP)]); |
| 676 | + |
| 677 | + check_decode([(Ok(ArrayVec::from(SPECIALIZED)), SPECIALIZED_EXP)]); |
| 678 | + check_decode([(Ok(ArrayVec::from(GENERAL)), GENERAL_EXP)]); |
| 679 | + |
| 680 | + #[cfg(feature = "alloc")] |
| 681 | + { |
| 682 | + check_decode([(Ok(SPECIALIZED.to_vec()), SPECIALIZED_EXP)]); |
| 683 | + check_decode([(Ok(GENERAL.to_vec()), GENERAL_EXP)]); |
| 684 | + } |
| 685 | + } |
643 | 686 | }
|
0 commit comments