From 469a117da728a3fd437963055e95791132ce2885 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Thu, 31 May 2018 12:22:46 -0500 Subject: [PATCH 1/2] Add a slice_ref function for Bytes (#198) This lets us take Bytes and a &[u8] slice that is contained in it, and create a new Bytes that corresponds to that subset slice. https://github.com/carllerche/bytes/issues/198 --- src/bytes.rs | 41 ++++++++++++++++++++++++++++++++++ tests/test_bytes.rs | 54 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/src/bytes.rs b/src/bytes.rs index 89244dd40..dd0997a64 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -576,6 +576,47 @@ impl Bytes { self.slice(0, end) } + /// Returns a slice of self that is equivalent to the given `subset`. + /// + /// When processing a `Bytes` buffer with other tools, one often + /// gets a `&[u8]` which is in fact a slice of the `Bytes`, i.e. a + /// subset of it. This function turns that `&[u8]` into another + /// `Bytes`, as if one had called `self.slice()` with the offsets + /// that correspond to `subset`. + /// + /// This operation is `O(1)`. + /// + /// # Examples + /// + /// ``` + /// use bytes::Bytes; + /// + /// let bytes = Bytes::from(&b"012345678"[..]); + /// let as_slice = bytes.as_ref(); + /// let subset = &as_slice[2..6]; + /// let subslice = bytes.slice_ref(&subset); + /// assert_eq!(&subslice[..], b"2345"); + /// ``` + /// + /// # Panics + /// + /// Requires that the given `sub` slice is in fact contained + /// within the `Bytes` buffer; otherwise this function will panic. + pub fn slice_ref(&self, subset: &[u8]) -> Bytes { + let bytes_p = self.as_ptr() as usize; + let bytes_len = self.len(); + + let sub_p = subset.as_ptr() as usize; + let sub_len = subset.len(); + + assert!(sub_p >= bytes_p); + assert!(sub_p + sub_len <= bytes_p + bytes_len); + + let sub_offset = sub_p - bytes_p; + + self.slice(sub_offset, sub_offset + sub_len) + } + /// Splits the bytes into two at the given index. /// /// Afterwards `self` contains elements `[0, at)`, and the returned `Bytes` diff --git a/tests/test_bytes.rs b/tests/test_bytes.rs index c0cba6b76..4cf340e6a 100644 --- a/tests/test_bytes.rs +++ b/tests/test_bytes.rs @@ -717,3 +717,57 @@ fn from_iter_no_size_hint() { assert_eq!(&actual[..], &expect[..]); } + +fn test_slice_ref(bytes: &Bytes, start: usize, end: usize, expected: &[u8]) { + let slice = &(bytes.as_ref()[start..end]); + let sub = bytes.slice_ref(&slice); + assert_eq!(&sub[..], expected); +} + +#[test] +fn slice_ref_works() { + let bytes = Bytes::from(&b"012345678"[..]); + + test_slice_ref(&bytes, 0, 0, b""); + test_slice_ref(&bytes, 0, 3, b"012"); + test_slice_ref(&bytes, 2, 6, b"2345"); + test_slice_ref(&bytes, 7, 9, b"78"); + test_slice_ref(&bytes, 9, 9, b""); +} + + +#[test] +fn slice_ref_empty() { + let bytes = Bytes::from(&b""[..]); + let slice = &(bytes.as_ref()[0..0]); + + let sub = bytes.slice_ref(&slice); + assert_eq!(&sub[..], b""); +} + +#[test] +#[should_panic] +fn slice_ref_catches_not_a_subset() { + let bytes = Bytes::from(&b"012345678"[..]); + let slice = &b"012345"[0..4]; + + bytes.slice_ref(slice); +} + +#[test] +#[should_panic] +fn slice_ref_catches_not_an_empty_subset() { + let bytes = Bytes::from(&b"012345678"[..]); + let slice = &b""[0..0]; + + bytes.slice_ref(slice); +} + +#[test] +#[should_panic] +fn empty_slice_ref_catches_not_an_empty_subset() { + let bytes = Bytes::from(&b""[..]); + let slice = &b""[0..0]; + + bytes.slice_ref(slice); +} From f8bbac3eeadcaed599c419d52d3205ea1ba4e250 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Fri, 31 Aug 2018 10:55:22 -0700 Subject: [PATCH 2/2] Reformat doc.. mostly to bump CI --- src/bytes.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/bytes.rs b/src/bytes.rs index dd0997a64..1cc168f1c 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -578,11 +578,10 @@ impl Bytes { /// Returns a slice of self that is equivalent to the given `subset`. /// - /// When processing a `Bytes` buffer with other tools, one often - /// gets a `&[u8]` which is in fact a slice of the `Bytes`, i.e. a - /// subset of it. This function turns that `&[u8]` into another - /// `Bytes`, as if one had called `self.slice()` with the offsets - /// that correspond to `subset`. + /// When processing a `Bytes` buffer with other tools, one often gets a + /// `&[u8]` which is in fact a slice of the `Bytes`, i.e. a subset of it. + /// This function turns that `&[u8]` into another `Bytes`, as if one had + /// called `self.slice()` with the offsets that correspond to `subset`. /// /// This operation is `O(1)`. /// @@ -600,8 +599,8 @@ impl Bytes { /// /// # Panics /// - /// Requires that the given `sub` slice is in fact contained - /// within the `Bytes` buffer; otherwise this function will panic. + /// Requires that the given `sub` slice is in fact contained within the + /// `Bytes` buffer; otherwise this function will panic. pub fn slice_ref(&self, subset: &[u8]) -> Bytes { let bytes_p = self.as_ptr() as usize; let bytes_len = self.len();