Skip to content

Commit

Permalink
Do not panic on Bytes::slice_ref on empty slice (#355)
Browse files Browse the repository at this point in the history
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`.
  • Loading branch information
stepancheg authored and seanmonstar committed Jan 23, 2020
1 parent 87b75cc commit f330ef6
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 15 deletions.
6 changes: 6 additions & 0 deletions src/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
29 changes: 14 additions & 15 deletions tests/test_bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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]
Expand Down

0 comments on commit f330ef6

Please sign in to comment.