From a84bb94cbfc5af859236685a3a230236d47e887f Mon Sep 17 00:00:00 2001 From: Wolfgang Welz Date: Thu, 16 Jan 2025 12:05:38 +0100 Subject: [PATCH 1/3] improve decode_raw --- crates/rlp/src/header.rs | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/crates/rlp/src/header.rs b/crates/rlp/src/header.rs index 65f2c97..f3d51e1 100644 --- a/crates/rlp/src/header.rs +++ b/crates/rlp/src/header.rs @@ -106,10 +106,15 @@ impl Header { /// Extracts the next payload from the given buffer, advancing it. /// + /// The returned `PayloadView` provides a structured view of the payload, allowing for efficient + /// parsing of nested items without unnecessary allocations. + /// /// # Errors /// - /// Returns an error if the buffer is too short, the header is invalid or one of the headers one - /// level deeper is invalid. + /// Returns an error if: + /// - The buffer is too short + /// - The header is invalid + /// - Any nested headers (for list items) are invalid #[inline] pub fn decode_raw<'a>(buf: &mut &'a [u8]) -> Result> { let Self { list, payload_length } = Self::decode(buf)?; @@ -122,17 +127,18 @@ impl Header { let mut items = alloc::vec::Vec::new(); while !payload.is_empty() { - // decode the next header without advancing in the payload - let Self { payload_length, .. } = Self::decode(&mut &payload[..])?; - // the length of the RLP encoding is the length of the header plus its payload length - // if payload length is 1 and the first byte is in [0x00, 0x7F], then there is no header - let rlp_length = if payload_length == 1 && payload[0] <= 0x7F { - 1 - } else { - payload_length + crate::length_of_length(payload_length) - }; - items.push(&payload[..rlp_length]); - payload.advance(rlp_length); + // store the start of the current item for later slice creation + let item_start = payload; + + // decode the header of the next RLP item, advancing the payload + let Self { payload_length, .. } = Self::decode(&mut payload)?; + // SAFETY: this is already checked in `decode` + unsafe { advance_unchecked(&mut payload, payload_length) }; + + // calculate the total length of the item (header + payload) by subtracting the + // remaining payload length from the initial length + let item_length = item_start.len() - payload.len(); + items.push(&item_start[..item_length]); } Ok(PayloadView::List(items)) From 7442078d1a253af4eec28d36d5af9aeb318ace76 Mon Sep 17 00:00:00 2001 From: Wolfgang Welz Date: Thu, 16 Jan 2025 12:24:08 +0100 Subject: [PATCH 2/3] add CHANGELOG --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a10b81..c612b34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- Improve `decode_raw` performance ([#34]) + ## [0.3.8] - 2024-08-05 ### Added From c0406db0ea4dcc354a8d069b2fb986e4bc5583e6 Mon Sep 17 00:00:00 2001 From: Wolfgang Welz Date: Thu, 16 Jan 2025 14:31:04 +0100 Subject: [PATCH 3/3] fix link in CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c612b34..f1c79e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improve `decode_raw` performance ([#34]) +[#34]: https://github.com/alloy-rs/rlp/pull/34 + ## [0.3.8] - 2024-08-05 ### Added