Skip to content

Commit 2ba859b

Browse files
Wollacmattsse
andauthored
feat: add function to decode an entire slice (#23)
* implement decode_full * add tests * add CHANGELOG * add PR number * Update crates/rlp/src/decode.rs Co-authored-by: Matthias Seitz <[email protected]> * revert CHANGELOG changes * fix imports * add CHANGELOG * remove TrailingBytes to avoid breaking change --------- Co-authored-by: Matthias Seitz <[email protected]>
1 parent d3df251 commit 2ba859b

File tree

3 files changed

+45
-2
lines changed

3 files changed

+45
-2
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- `decode_exact` function ([#23])
13+
14+
### Fixed
15+
1016
- Fix `RlpEncodableWrapper` doc ([#22])
1117

1218
[#22]: https://github.com/alloy-rs/rlp/pull/22
19+
[#23]: https://github.com/alloy-rs/rlp/pull/23
1320

1421
## [0.3.7] - 2024-06-29
1522

crates/rlp/src/decode.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,25 @@ mod std_impl {
176176
}
177177
}
178178

179+
/// Decodes the entire input, ensuring no trailing bytes remain.
180+
///
181+
/// # Errors
182+
///
183+
/// Returns an error if the encoding is invalid or if data remains after decoding the RLP item.
184+
#[inline]
185+
pub fn decode_exact<T: Decodable>(bytes: impl AsRef<[u8]>) -> Result<T> {
186+
let mut buf = bytes.as_ref();
187+
let out = T::decode(&mut buf)?;
188+
189+
// check if there are any remaining bytes after decoding
190+
if !buf.is_empty() {
191+
// TODO: introduce a new variant TrailingBytes to better distinguish this error
192+
return Err(Error::UnexpectedLength);
193+
}
194+
195+
Ok(out)
196+
}
197+
179198
/// Left-pads a slice to a statically known size array.
180199
///
181200
/// # Errors
@@ -212,7 +231,7 @@ fn slice_to_array<const N: usize>(slice: &[u8]) -> Result<[u8; N]> {
212231
#[cfg(test)]
213232
mod tests {
214233
use super::*;
215-
use crate::Encodable;
234+
use crate::{encode, Encodable};
216235
use core::fmt::Debug;
217236
use hex_literal::hex;
218237

@@ -356,4 +375,21 @@ mod tests {
356375
check_decode::<u8, _>([(Err(Error::InputTooShort), &hex!("82")[..])]);
357376
check_decode::<u64, _>([(Err(Error::InputTooShort), &hex!("82")[..])]);
358377
}
378+
379+
#[test]
380+
fn rlp_full() {
381+
fn check_decode_exact<T: Decodable + Encodable + PartialEq + Debug>(input: T) {
382+
let encoded = encode(&input);
383+
assert_eq!(decode_exact::<T>(&encoded), Ok(input));
384+
assert_eq!(
385+
decode_exact::<T>([encoded, vec![0x00]].concat()),
386+
Err(Error::UnexpectedLength)
387+
);
388+
}
389+
390+
check_decode_exact::<String>("".into());
391+
check_decode_exact::<String>("test1234".into());
392+
check_decode_exact::<Vec<u64>>(vec![]);
393+
check_decode_exact::<Vec<u64>>(vec![0; 4]);
394+
}
359395
}

crates/rlp/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
extern crate alloc;
2020

2121
mod decode;
22-
pub use decode::{Decodable, Rlp};
22+
pub use decode::{decode_exact, Decodable, Rlp};
2323

2424
mod error;
2525
pub use error::{Error, Result};

0 commit comments

Comments
 (0)