diff --git a/src/bytes.rs b/src/bytes.rs
index cf398154172c9c450cdd1aed83f0133b04942c78..287ab8874c899a5f80c7c23260cffe76f3987b03 100644
--- a/src/bytes.rs
+++ b/src/bytes.rs
@@ -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.
diff --git a/tests/test_bytes.rs b/tests/test_bytes.rs
index 15c315748367403aad4b81a8fbe258e11c218a3d..c75de1f200bd499f739de0489988165c8162ebfb 100644
--- a/tests/test_bytes.rs
+++ b/tests/test_bytes.rs
@@ -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");