From 4f4e81cf739632b83e303fea965b62f65de052d4 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Tue, 19 Nov 2019 17:47:17 +0100 Subject: [PATCH 1/2] Introduce Rlp::at_with_offset. --- rlp/src/rlpin.rs | 14 ++++++++++++-- rlp/tests/tests.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/rlp/src/rlpin.rs b/rlp/src/rlpin.rs index dd2ee9826..960af6a7a 100644 --- a/rlp/src/rlpin.rs +++ b/rlp/src/rlpin.rs @@ -189,6 +189,15 @@ impl<'a> Rlp<'a> { pub fn at<'view>(&'view self, index: usize) -> Result, DecoderError> where 'a: 'view, + { + let (rlp, _offset) = self.at_with_offset(index)?; + Ok(rlp) + } + + pub fn at_with_offset<'view>(&'view self, index: usize) + -> Result<(Rlp<'a>, usize), DecoderError> + where + 'a: 'view, { if !self.is_list() { return Err(DecoderError::RlpExpectedToBeList); @@ -211,11 +220,12 @@ impl<'a> Rlp<'a> { let (bytes, consumed) = Rlp::consume_items(bytes, indexes_to_skip)?; // update the cache - self.offset_cache.set(Some(OffsetCache::new(index, bytes_consumed + consumed))); + let offset = bytes_consumed + consumed; + self.offset_cache.set(Some(OffsetCache::new(index, offset))); // construct new rlp let found = BasicDecoder::payload_info(bytes)?; - Ok(Rlp::new(&bytes[0..found.header_len + found.value_len])) + Ok((Rlp::new(&bytes[0..found.header_len + found.value_len]), offset)) } pub fn is_null(&self) -> bool { diff --git a/rlp/tests/tests.rs b/rlp/tests/tests.rs index 84a090e09..6f51b9bd3 100644 --- a/rlp/tests/tests.rs +++ b/rlp/tests/tests.rs @@ -53,6 +53,35 @@ fn rlp_at() { } } +#[test] +fn rlp_at_with_offset() { + let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']; + { + let rlp = Rlp::new(&data); + assert!(rlp.is_list()); + let animals: Vec = rlp.as_list().unwrap(); + assert_eq!(animals, vec!["cat".to_owned(), "dog".to_owned()]); + + let (cat, cat_offset) = rlp.at_with_offset(0).unwrap(); + assert!(cat.is_data()); + assert_eq!(cat_offset, 1); + assert_eq!(cat.as_raw(), &[0x83, b'c', b'a', b't']); + assert_eq!(cat.as_val::().unwrap(), "cat".to_owned()); + + let (dog, dog_offset) = rlp.at_with_offset(1).unwrap(); + assert!(dog.is_data()); + assert_eq!(dog_offset, 5); + assert_eq!(dog.as_raw(), &[0x83, b'd', b'o', b'g']); + assert_eq!(dog.as_val::().unwrap(), "dog".to_owned()); + + let (cat_again, cat_offset) = rlp.at_with_offset(0).unwrap(); + assert!(cat_again.is_data()); + assert_eq!(cat_offset, 1); + assert_eq!(cat_again.as_raw(), &[0x83, b'c', b'a', b't']); + assert_eq!(cat_again.as_val::().unwrap(), "cat".to_owned()); + } +} + #[test] fn rlp_at_err() { let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o']; From 46b7272113c87158dfdfe1f6f4113dd1becd3cc2 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Wed, 20 Nov 2019 13:24:07 +0100 Subject: [PATCH 2/2] Method docs for Rlp::at and Rlp::at_with_offset. --- rlp/src/rlpin.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/rlp/src/rlpin.rs b/rlp/src/rlpin.rs index 960af6a7a..5dd3730b6 100644 --- a/rlp/src/rlpin.rs +++ b/rlp/src/rlpin.rs @@ -186,6 +186,9 @@ impl<'a> Rlp<'a> { } } + /// Returns an Rlp item in a list at the given index. + /// + /// Returns an error if this Rlp is not a list or if the index is out of range. pub fn at<'view>(&'view self, index: usize) -> Result, DecoderError> where 'a: 'view, @@ -194,6 +197,10 @@ impl<'a> Rlp<'a> { Ok(rlp) } + /// Returns an Rlp item in a list at the given index along with the byte offset into the + /// raw data slice. + /// + /// Returns an error if this Rlp is not a list or if the index is out of range. pub fn at_with_offset<'view>(&'view self, index: usize) -> Result<(Rlp<'a>, usize), DecoderError> where