From a4b63406c7ca372331c295fe855eff21367e241a Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Thu, 23 Jan 2020 18:29:42 +0000 Subject: [PATCH] Do not panic on Bytes::slice_ref on empty slice (#355) Use case: ``` let bytes: Bytes = ... let subbytes = bytes.slice(a..b); // where a == b let slice = &subbytes[..]; let slice_bytes = bytes.slice_ref(slice); ``` Last line should not panic, because `slice` object is derived from the original `Bytes` object. Before this commit it panics, because `Bytes::slice` returns a fresh `Bytes` object when `begin == end`. --- src/bytes.rs | 6 ++++++ tests/test_bytes.rs | 29 ++++++++++++++--------------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/bytes.rs b/src/bytes.rs index d70852a..380b1c6 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -270,6 +270,12 @@ impl Bytes { /// 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 { + // Empty slice and empty Bytes may have their pointers reset + // so explicitly allow empty slice to be a subslice of any slice. + if subset.is_empty() { + return Bytes::new(); + } + let bytes_p = self.as_ptr() as usize; let bytes_len = self.len(); diff --git a/tests/test_bytes.rs b/tests/test_bytes.rs index b582627..40fcae4 100644 --- a/tests/test_bytes.rs +++ b/tests/test_bytes.rs @@ -808,6 +808,16 @@ fn slice_ref_empty() { assert_eq!(&sub[..], b""); } +#[test] +fn slice_ref_empty_subslice() { + let bytes = Bytes::from(&b"abcde"[..]); + let subbytes = bytes.slice(0..0); + let slice = &subbytes[..]; + // The `slice` object is derived from the original `bytes` object + // so `slice_ref` should work. + assert_eq!(Bytes::new(), bytes.slice_ref(slice)); +} + #[test] #[should_panic] fn slice_ref_catches_not_a_subset() { @@ -818,30 +828,19 @@ fn slice_ref_catches_not_a_subset() { } #[test] -#[should_panic] -fn slice_ref_catches_not_an_empty_subset() { +fn slice_ref_not_an_empty_subset() { let bytes = Bytes::from(&b"012345678"[..]); let slice = &b""[0..0]; - bytes.slice_ref(slice); + assert_eq!(Bytes::new(), bytes.slice_ref(slice)); } #[test] -#[should_panic] -fn empty_slice_ref_catches_not_an_empty_subset() { +fn empty_slice_ref_not_an_empty_subset() { let bytes = Bytes::new(); let slice = &b"some other slice"[0..0]; - // Protect this test against Bytes internals. - // - // This should panic *because* the slice's ptr doesn't fit in the range - // of the `bytes`. - if bytes.as_ptr() as usize == slice.as_ptr() as usize { - // don't panic, failing the test - return; - } - - bytes.slice_ref(slice); + assert_eq!(Bytes::new(), bytes.slice_ref(slice)); } #[test]