Bytes::unsplit (#182)

Add `Bytes::unsplit`, analogous to `BytesMut::unsplit`.
This commit is contained in:
Alan Somers
2018-02-26 10:19:20 -07:00
committed by Carl Lerche
parent 57ca48c364
commit a7f89104bf
2 changed files with 201 additions and 31 deletions
+58 -22
View File
@@ -804,6 +804,36 @@ impl Bytes {
mem::replace(self, result.freeze());
}
/// Combine splitted Bytes objects back as contiguous.
///
/// If `Bytes` objects were not contiguous originally, they will be extended.
///
/// # Examples
///
/// ```
/// use bytes::Bytes;
///
/// let mut buf = Bytes::with_capacity(64);
/// buf.extend_from_slice(b"aaabbbcccddd");
///
/// let splitted = buf.split_off(6);
/// assert_eq!(b"aaabbb", &buf[..]);
/// assert_eq!(b"cccddd", &splitted[..]);
///
/// buf.unsplit(splitted);
/// assert_eq!(b"aaabbbcccddd", &buf[..]);
/// ```
pub fn unsplit(&mut self, other: Bytes) {
if self.is_empty() {
*self = other;
return;
}
if let Err(other_inner) = self.inner.try_unsplit(other.inner) {
self.extend_from_slice(other_inner.as_ref());
}
}
}
impl IntoBuf for Bytes {
@@ -1087,7 +1117,7 @@ impl BytesMut {
/// ```
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
self.inner.is_empty()
}
/// Return true if the `BytesMut` uses inline allocation
@@ -1437,32 +1467,13 @@ impl BytesMut {
/// assert_eq!(b"aaabbbcccddd", &buf[..]);
/// ```
pub fn unsplit(&mut self, other: BytesMut) {
let ptr;
if other.is_empty() {
return;
}
if self.is_empty() {
*self = other;
return;
}
unsafe {
ptr = self.inner.ptr.offset(self.inner.len as isize);
}
if ptr == other.inner.ptr &&
self.inner.kind() == KIND_ARC &&
other.inner.kind() == KIND_ARC
{
debug_assert_eq!(self.inner.arc.load(Acquire),
other.inner.arc.load(Acquire));
// Contiguous blocks, just combine directly
self.inner.len += other.inner.len;
self.inner.cap += other.inner.cap;
}
else {
self.extend_from_slice(&other);
if let Err(other_inner) = self.inner.try_unsplit(other.inner) {
self.extend_from_slice(other_inner.as_ref());
}
}
}
@@ -1922,6 +1933,31 @@ impl Inner {
}
}
fn try_unsplit(&mut self, other: Inner) -> Result<(), Inner> {
let ptr;
if other.is_empty() {
return Ok(());
}
unsafe {
ptr = self.ptr.offset(self.len as isize);
}
if ptr == other.ptr &&
self.kind() == KIND_ARC &&
other.kind() == KIND_ARC
{
debug_assert_eq!(self.arc.load(Acquire),
other.arc.load(Acquire));
// Contiguous blocks, just combine directly
self.len += other.len;
self.cap += other.cap;
Ok(())
} else {
Err(other)
}
}
unsafe fn set_start(&mut self, start: usize) {
// Setting the start to 0 is a no-op, so return early if this is the
// case.
+143 -9
View File
@@ -554,7 +554,141 @@ fn partial_eq_bytesmut() {
}
#[test]
fn unsplit_basic() {
fn bytes_unsplit_basic() {
let mut buf = Bytes::with_capacity(64);
buf.extend_from_slice(b"aaabbbcccddd");
let splitted = buf.split_off(6);
assert_eq!(b"aaabbb", &buf[..]);
assert_eq!(b"cccddd", &splitted[..]);
buf.unsplit(splitted);
assert_eq!(b"aaabbbcccddd", &buf[..]);
}
#[test]
fn bytes_unsplit_empty_other() {
let mut buf = Bytes::with_capacity(64);
buf.extend_from_slice(b"aaabbbcccddd");
// empty other
let other = Bytes::new();
buf.unsplit(other);
assert_eq!(b"aaabbbcccddd", &buf[..]);
}
#[test]
fn bytes_unsplit_empty_self() {
// empty self
let mut buf = Bytes::new();
let mut other = Bytes::with_capacity(64);
other.extend_from_slice(b"aaabbbcccddd");
buf.unsplit(other);
assert_eq!(b"aaabbbcccddd", &buf[..]);
}
#[test]
fn bytes_unsplit_inline_arc() {
let mut buf = Bytes::with_capacity(8); //inline
buf.extend_from_slice(b"aaaabbbb");
let mut buf2 = Bytes::with_capacity(64);
buf2.extend_from_slice(b"ccccddddeeee");
buf2.split_off(8); //arc
buf.unsplit(buf2);
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
}
#[test]
fn bytes_unsplit_arc_inline() {
let mut buf = Bytes::with_capacity(64);
buf.extend_from_slice(b"aaaabbbbeeee");
buf.split_off(8); //arc
let mut buf2 = Bytes::with_capacity(8); //inline
buf2.extend_from_slice(b"ccccdddd");
buf.unsplit(buf2);
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
}
#[test]
fn bytes_unsplit_both_inline() {
let mut buf = Bytes::with_capacity(16); //inline
buf.extend_from_slice(b"aaaabbbbccccdddd");
let splitted = buf.split_off(8); // both inline
assert_eq!(b"aaaabbbb", &buf[..]);
assert_eq!(b"ccccdddd", &splitted[..]);
buf.unsplit(splitted);
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
}
#[test]
fn bytes_unsplit_arc_different() {
let mut buf = Bytes::with_capacity(64);
buf.extend_from_slice(b"aaaabbbbeeee");
buf.split_off(8); //arc
let mut buf2 = Bytes::with_capacity(64);
buf2.extend_from_slice(b"ccccddddeeee");
buf2.split_off(8); //arc
buf.unsplit(buf2);
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
}
#[test]
fn bytes_unsplit_arc_non_contiguous() {
let mut buf = Bytes::with_capacity(64);
buf.extend_from_slice(b"aaaabbbbeeeeccccdddd");
let mut buf2 = buf.split_off(8); //arc
let buf3 = buf2.split_off(4); //arc
buf.unsplit(buf3);
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
}
#[test]
fn bytes_unsplit_two_split_offs() {
let mut buf = Bytes::with_capacity(64);
buf.extend_from_slice(b"aaaabbbbccccdddd");
let mut buf2 = buf.split_off(8); //arc
let buf3 = buf2.split_off(4); //arc
buf2.unsplit(buf3);
buf.unsplit(buf2);
assert_eq!(b"aaaabbbbccccdddd", &buf[..]);
}
#[test]
fn bytes_unsplit_overlapping_references() {
let mut buf = Bytes::with_capacity(64);
buf.extend_from_slice(b"abcdefghijklmnopqrstuvwxyz");
let mut buf0010 = buf.slice(0, 10);
let buf1020 = buf.slice(10, 20);
let buf0515 = buf.slice(5, 15);
buf0010.unsplit(buf1020);
assert_eq!(b"abcdefghijklmnopqrst", &buf0010[..]);
assert_eq!(b"fghijklmno", &buf0515[..]);
}
#[test]
fn bytes_mut_unsplit_basic() {
let mut buf = BytesMut::with_capacity(64);
buf.extend_from_slice(b"aaabbbcccddd");
@@ -567,7 +701,7 @@ fn unsplit_basic() {
}
#[test]
fn unsplit_empty_other() {
fn bytes_mut_unsplit_empty_other() {
let mut buf = BytesMut::with_capacity(64);
buf.extend_from_slice(b"aaabbbcccddd");
@@ -579,7 +713,7 @@ fn unsplit_empty_other() {
}
#[test]
fn unsplit_empty_self() {
fn bytes_mut_unsplit_empty_self() {
// empty self
let mut buf = BytesMut::new();
@@ -591,7 +725,7 @@ fn unsplit_empty_self() {
}
#[test]
fn unsplit_inline_arc() {
fn bytes_mut_unsplit_inline_arc() {
let mut buf = BytesMut::with_capacity(8); //inline
buf.extend_from_slice(b"aaaabbbb");
@@ -605,7 +739,7 @@ fn unsplit_inline_arc() {
}
#[test]
fn unsplit_arc_inline() {
fn bytes_mut_unsplit_arc_inline() {
let mut buf = BytesMut::with_capacity(64);
buf.extend_from_slice(b"aaaabbbbeeee");
@@ -620,7 +754,7 @@ fn unsplit_arc_inline() {
}
#[test]
fn unsplit_both_inline() {
fn bytes_mut_unsplit_both_inline() {
let mut buf = BytesMut::with_capacity(16); //inline
buf.extend_from_slice(b"aaaabbbbccccdddd");
@@ -634,7 +768,7 @@ fn unsplit_both_inline() {
#[test]
fn unsplit_arc_different() {
fn bytes_mut_unsplit_arc_different() {
let mut buf = BytesMut::with_capacity(64);
buf.extend_from_slice(b"aaaabbbbeeee");
@@ -650,7 +784,7 @@ fn unsplit_arc_different() {
}
#[test]
fn unsplit_arc_non_contiguous() {
fn bytes_mut_unsplit_arc_non_contiguous() {
let mut buf = BytesMut::with_capacity(64);
buf.extend_from_slice(b"aaaabbbbeeeeccccdddd");
@@ -663,7 +797,7 @@ fn unsplit_arc_non_contiguous() {
}
#[test]
fn unsplit_two_split_offs() {
fn bytes_mut_unsplit_two_split_offs() {
let mut buf = BytesMut::with_capacity(64);
buf.extend_from_slice(b"aaaabbbbccccdddd");