diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d13bee..6f43e60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- `decode_exact` function ([#23]) + +### Fixed + - Fix `RlpEncodableWrapper` doc ([#22]) [#22]: https://github.com/alloy-rs/rlp/pull/22 +[#23]: https://github.com/alloy-rs/rlp/pull/23 ## [0.3.7] - 2024-06-29 diff --git a/crates/rlp/src/decode.rs b/crates/rlp/src/decode.rs index 7a34f59..63714a8 100644 --- a/crates/rlp/src/decode.rs +++ b/crates/rlp/src/decode.rs @@ -176,6 +176,25 @@ mod std_impl { } } +/// Decodes the entire input, ensuring no trailing bytes remain. +/// +/// # Errors +/// +/// Returns an error if the encoding is invalid or if data remains after decoding the RLP item. +#[inline] +pub fn decode_exact(bytes: impl AsRef<[u8]>) -> Result { + let mut buf = bytes.as_ref(); + let out = T::decode(&mut buf)?; + + // check if there are any remaining bytes after decoding + if !buf.is_empty() { + // TODO: introduce a new variant TrailingBytes to better distinguish this error + return Err(Error::UnexpectedLength); + } + + Ok(out) +} + /// Left-pads a slice to a statically known size array. /// /// # Errors @@ -212,7 +231,7 @@ fn slice_to_array(slice: &[u8]) -> Result<[u8; N]> { #[cfg(test)] mod tests { use super::*; - use crate::Encodable; + use crate::{encode, Encodable}; use core::fmt::Debug; use hex_literal::hex; @@ -356,4 +375,21 @@ mod tests { check_decode::([(Err(Error::InputTooShort), &hex!("82")[..])]); check_decode::([(Err(Error::InputTooShort), &hex!("82")[..])]); } + + #[test] + fn rlp_full() { + fn check_decode_exact(input: T) { + let encoded = encode(&input); + assert_eq!(decode_exact::(&encoded), Ok(input)); + assert_eq!( + decode_exact::([encoded, vec![0x00]].concat()), + Err(Error::UnexpectedLength) + ); + } + + check_decode_exact::("".into()); + check_decode_exact::("test1234".into()); + check_decode_exact::>(vec![]); + check_decode_exact::>(vec![0; 4]); + } } diff --git a/crates/rlp/src/lib.rs b/crates/rlp/src/lib.rs index fd90349..bcf586c 100644 --- a/crates/rlp/src/lib.rs +++ b/crates/rlp/src/lib.rs @@ -19,7 +19,7 @@ extern crate alloc; mod decode; -pub use decode::{Decodable, Rlp}; +pub use decode::{decode_exact, Decodable, Rlp}; mod error; pub use error::{Error, Result};