diff --git a/src/buf/mod.rs b/src/buf.rs
similarity index 91%
rename from src/buf/mod.rs
rename to src/buf.rs
index cab96c50da05660f9896227dbad1812f21f730a0..a45ed604d65877d9715aa743f190ee818c175a17 100644
--- a/src/buf/mod.rs
+++ b/src/buf.rs
@@ -2,9 +2,30 @@ use {Bytes};
 use byteorder::ByteOrder;
 use std::{cmp, io, ptr, usize};
 
-/// A trait for values that provide sequential read access to bytes.
+/// Read bytes from a buffer.
+///
+/// A buffer stores bytes in memory such that read access is infallible. The
+/// underlying storage may or may not be in contiguous memory. A `Buf` value is
+/// a cursor into the buffer. Reading from `Buf` advances the cursor position.
+///
+/// The simplest `Buf` is a `Cursor` wrapping a `[u8]`.
+///
+/// ```
+/// use bytes::Buf;
+/// use std::io::Cursor;
+///
+/// let mut buf = Cursor::new(b"hello world");
+///
+/// assert_eq!(b'h', buf.get_u8());
+/// assert_eq!(b'e', buf.get_u8());
+/// assert_eq!(b'l', buf.get_u8());
+///
+/// let mut rest = vec![];
+/// buf.copy_to(&mut rest);
+///
+/// assert_eq!(&rest[..], b"lo world");
+/// ```
 pub trait Buf {
-
     /// Returns the number of bytes that can be accessed from the Buf
     fn remaining(&self) -> usize;
 
@@ -70,16 +91,6 @@ pub trait Buf {
         }
     }
 
-    /// Gets an unsigned 8 bit integer from the `Buf` without advancing the
-    /// buffer cursor
-    fn peek_u8(&self) -> Option<u8> {
-        if self.has_remaining() {
-            Some(self.bytes()[0])
-        } else {
-            None
-        }
-    }
-
     /// Gets an unsigned 8 bit integer from the `Buf`.
     fn get_u8(&mut self) -> u8 {
         let mut buf = [0; 1];
@@ -203,7 +214,7 @@ pub trait BufMut {
     ///
     /// Panics if `self` does not have enough capacity to copy all the data
     /// from `src`
-    fn copy_from<S: Source>(&mut self, src: S) where Self: Sized {
+    fn put<S: Source>(&mut self, src: S) where Self: Sized {
         src.source(self);
     }
 
@@ -219,14 +230,14 @@ pub trait BufMut {
     ///
     /// {
     ///     let mut buf = Cursor::new(&mut dst);
-    ///     buf.copy_from_slice(b"hello");
+    ///     buf.put_slice(b"hello");
     ///
     ///     assert_eq!(1, buf.remaining_mut());
     /// }
     ///
     /// assert_eq!(b"hello\0", &dst);
     /// ```
-    fn copy_from_slice(&mut self, src: &[u8]) {
+    fn put_slice(&mut self, src: &[u8]) {
         let mut off = 0;
 
         assert!(self.remaining_mut() >= src.len(), "buffer overflow");
@@ -251,66 +262,46 @@ pub trait BufMut {
         }
     }
 
-    /// Writes the given string into self.
-    ///
-    /// # Panics
-    ///
-    /// The function panics if `self` does not have enough remaining capacity
-    /// to write the full string.
-    fn put_str(&mut self, src: &str) {
-        self.copy_from_slice(src.as_bytes());
-    }
-
-    /// Writes an unsigned 8 bit integer to the BufMut.
-    fn put_u8(&mut self, n: u8) {
-        self.copy_from_slice(&[n])
-    }
-
-    /// Writes a signed 8 bit integer to the BufMut.
-    fn put_i8(&mut self, n: i8) {
-        self.copy_from_slice(&[n as u8])
-    }
-
     /// Writes an unsigned 16 bit integer to the BufMut.
     fn put_u16<T: ByteOrder>(&mut self, n: u16) {
         let mut buf = [0; 2];
         T::write_u16(&mut buf, n);
-        self.copy_from_slice(&buf)
+        self.put_slice(&buf)
     }
 
     /// Writes a signed 16 bit integer to the BufMut.
     fn put_i16<T: ByteOrder>(&mut self, n: i16) {
         let mut buf = [0; 2];
         T::write_i16(&mut buf, n);
-        self.copy_from_slice(&buf)
+        self.put_slice(&buf)
     }
 
     /// Writes an unsigned 32 bit integer to the BufMut.
     fn put_u32<T: ByteOrder>(&mut self, n: u32) {
         let mut buf = [0; 4];
         T::write_u32(&mut buf, n);
-        self.copy_from_slice(&buf)
+        self.put_slice(&buf)
     }
 
     /// Writes a signed 32 bit integer to the BufMut.
     fn put_i32<T: ByteOrder>(&mut self, n: i32) {
         let mut buf = [0; 4];
         T::write_i32(&mut buf, n);
-        self.copy_from_slice(&buf)
+        self.put_slice(&buf)
     }
 
     /// Writes an unsigned 64 bit integer to the BufMut.
     fn put_u64<T: ByteOrder>(&mut self, n: u64) {
         let mut buf = [0; 8];
         T::write_u64(&mut buf, n);
-        self.copy_from_slice(&buf)
+        self.put_slice(&buf)
     }
 
     /// Writes a signed 64 bit integer to the BufMut.
     fn put_i64<T: ByteOrder>(&mut self, n: i64) {
         let mut buf = [0; 8];
         T::write_i64(&mut buf, n);
-        self.copy_from_slice(&buf)
+        self.put_slice(&buf)
     }
 
     /// Writes an unsigned n-bytes integer to the BufMut.
@@ -320,7 +311,7 @@ pub trait BufMut {
     fn put_uint<T: ByteOrder>(&mut self, n: u64, nbytes: usize) {
         let mut buf = [0; 8];
         T::write_uint(&mut buf, n, nbytes);
-        self.copy_from_slice(&buf[0..nbytes])
+        self.put_slice(&buf[0..nbytes])
     }
 
     /// Writes a signed n-bytes integer to the BufMut.
@@ -330,7 +321,7 @@ pub trait BufMut {
     fn put_int<T: ByteOrder>(&mut self, n: i64, nbytes: usize) {
         let mut buf = [0; 8];
         T::write_int(&mut buf, n, nbytes);
-        self.copy_from_slice(&buf[0..nbytes])
+        self.put_slice(&buf[0..nbytes])
     }
 
     /// Writes a IEEE754 single-precision (4 bytes) floating point number to
@@ -338,7 +329,7 @@ pub trait BufMut {
     fn put_f32<T: ByteOrder>(&mut self, n: f32) {
         let mut buf = [0; 4];
         T::write_f32(&mut buf, n);
-        self.copy_from_slice(&buf)
+        self.put_slice(&buf)
     }
 
     /// Writes a IEEE754 double-precision (8 bytes) floating point number to
@@ -346,7 +337,7 @@ pub trait BufMut {
     fn put_f64<T: ByteOrder>(&mut self, n: f64) {
         let mut buf = [0; 8];
         T::write_f64(&mut buf, n);
-        self.copy_from_slice(&buf)
+        self.put_slice(&buf)
     }
 
     /// Creates a "by reference" adaptor for this instance of BufMut
@@ -446,14 +437,26 @@ pub trait Source {
 
 impl<'a> Source for &'a [u8] {
     fn source<B: BufMut>(self, buf: &mut B) {
-        buf.copy_from_slice(self);
+        buf.put_slice(self);
+    }
+}
+
+impl<'a> Source for &'a str {
+    fn source<B: BufMut>(self, buf: &mut B) {
+        buf.put_slice(self.as_bytes());
     }
 }
 
 impl Source for u8 {
     fn source<B: BufMut>(self, buf: &mut B) {
         let src = [self];
-        buf.copy_from_slice(&src);
+        buf.put_slice(&src);
+    }
+}
+
+impl Source for i8 {
+    fn source<B: BufMut>(self, buf: &mut B) {
+        buf.put_slice(&[self as u8])
     }
 }
 
@@ -584,7 +587,7 @@ impl<B: BufMut + Sized> io::Write for Writer<B> {
     fn write(&mut self, src: &[u8]) -> io::Result<usize> {
         let n = cmp::min(self.buf.remaining_mut(), src.len());
 
-        self.buf.copy_from(&src[0..n]);
+        self.buf.put(&src[0..n]);
         Ok(n)
     }
 
diff --git a/src/buf/take.rs b/src/buf/take.rs
deleted file mode 100644
index f92a9933769c9f21d0ef672a1efa313ded33f8e5..0000000000000000000000000000000000000000
--- a/src/buf/take.rs
+++ /dev/null
@@ -1,182 +0,0 @@
-use {Buf, BufMut};
-use std::{cmp, fmt};
-
-/// A buffer adapter which limits the bytes read from an underlying value.
-#[derive(Debug)]
-pub struct Take<T> {
-    inner: T,
-    limit: usize,
-}
-
-/// A buffer adapter which limits the bytes written from an underlying value.
-#[derive(Debug)]
-pub struct TakeMut<T> {
-    inner: T,
-    limit: usize,
-}
-
-pub fn new<T>(inner: T, limit: usize) -> Take<T> {
-    Take {
-        inner: inner,
-        limit: limit,
-    }
-}
-
-pub fn new_mut<T>(inner: T, limit: usize) -> TakeMut<T> {
-    TakeMut {
-        inner: inner,
-        limit: limit,
-    }
-}
-
-/*
- *
- * ===== impl Take =====
- *
- */
-
-impl<T> Take<T> {
-    /// Consumes this `Take`, returning the underlying value.
-    pub fn into_inner(self) -> T {
-        self.inner
-    }
-
-    /// Gets a reference to the underlying value in this `Take`.
-    pub fn get_ref(&self) -> &T {
-        &self.inner
-    }
-
-    /// Gets a mutable reference to the underlying value in this `Take`.
-    pub fn get_mut(&mut self) -> &mut T {
-        &mut self.inner
-    }
-
-    /// Returns the maximum number of bytes that are made available from the
-    /// underlying value.
-    pub fn limit(&self) -> usize {
-        self.limit
-    }
-
-    /// Sets the maximum number of bytes that are made available from the
-    /// underlying value.
-    pub fn set_limit(&mut self, lim: usize) {
-        self.limit = lim
-    }
-}
-
-impl<T: Buf> Buf for Take<T> {
-    fn remaining(&self) -> usize {
-        cmp::min(self.inner.remaining(), self.limit)
-    }
-
-    fn bytes(&self) -> &[u8] {
-        &self.inner.bytes()[..self.limit]
-    }
-
-    fn advance(&mut self, cnt: usize) {
-        let cnt = cmp::min(cnt, self.limit);
-        self.limit -= cnt;
-        self.inner.advance(cnt);
-    }
-}
-
-impl<T: BufMut> BufMut for Take<T> {
-    fn remaining_mut(&self) -> usize {
-        self.inner.remaining_mut()
-    }
-
-    unsafe fn bytes_mut(&mut self) -> &mut [u8] {
-        self.inner.bytes_mut()
-    }
-
-    unsafe fn advance_mut(&mut self, cnt: usize) {
-        self.inner.advance_mut(cnt)
-    }
-}
-
-impl<T: BufMut> fmt::Write for Take<T> {
-    fn write_str(&mut self, s: &str) -> fmt::Result {
-        BufMut::put_str(self, s);
-        Ok(())
-    }
-
-    fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result {
-        fmt::write(self, args)
-    }
-}
-
-/*
- *
- * ===== impl TakeMut =====
- *
- */
-
-impl<T> TakeMut<T> {
-    /// Consumes this `TakeMut`, returning the underlying value.
-    pub fn into_inner(self) -> T {
-        self.inner
-    }
-
-    /// Gets a reference to the underlying value in this `TakeMut`.
-    pub fn get_ref(&self) -> &T {
-        &self.inner
-    }
-
-    /// Gets a mutable reference to the underlying value in this `TakeMut`.
-    pub fn get_mut(&mut self) -> &mut T {
-        &mut self.inner
-    }
-
-    /// Returns the maximum number of bytes that are made available from the
-    /// underlying value.
-    pub fn limit(&self) -> usize {
-        self.limit
-    }
-
-    /// Sets the maximum number of bytes that are made available from the
-    /// underlying value.
-    pub fn set_limit(&mut self, lim: usize) {
-        self.limit = lim
-    }
-}
-
-impl<T: Buf> Buf for TakeMut<T> {
-    fn remaining(&self) -> usize {
-        self.inner.remaining()
-    }
-
-    fn bytes(&self) -> &[u8] {
-        self.inner.bytes()
-    }
-
-    fn advance(&mut self, cnt: usize) {
-        self.inner.advance(cnt)
-    }
-}
-
-impl<T: BufMut> BufMut for TakeMut<T> {
-    fn remaining_mut(&self) -> usize {
-        cmp::min(self.inner.remaining_mut(), self.limit)
-    }
-
-    unsafe fn bytes_mut(&mut self) -> &mut [u8] {
-        &mut self.inner.bytes_mut()[..self.limit]
-    }
-
-    unsafe fn advance_mut(&mut self, cnt: usize) {
-        let cnt = cmp::min(cnt, self.limit);
-        self.limit -= cnt;
-        self.inner.advance_mut(cnt);
-    }
-}
-
-impl<T: BufMut> fmt::Write for TakeMut<T> {
-    fn write_str(&mut self, s: &str) -> fmt::Result {
-        BufMut::put_str(self, s);
-        Ok(())
-    }
-
-    fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result {
-        fmt::write(self, args)
-    }
-}
diff --git a/src/bytes.rs b/src/bytes.rs
index ed56618876bd2fe131fbfa0122d47c3897e1cd59..3160bbdd4738adac3f26d015604ad4200c4712bf 100644
--- a/src/bytes.rs
+++ b/src/bytes.rs
@@ -114,9 +114,9 @@ pub struct Bytes {
 ///
 /// let mut buf = BytesMut::with_capacity(64);
 ///
-/// buf.put_u8(b'h');
-/// buf.put_u8(b'e');
-/// buf.put_str("llo");
+/// buf.put(b'h');
+/// buf.put(b'e');
+/// buf.put("llo");
 ///
 /// assert_eq!(&buf[..], b"hello");
 ///
@@ -489,12 +489,24 @@ impl From<Vec<u8>> for Bytes {
     }
 }
 
+impl From<String> for Bytes {
+    fn from(src: String) -> Bytes {
+        BytesMut::from(src).freeze()
+    }
+}
+
 impl<'a> From<&'a [u8]> for Bytes {
     fn from(src: &'a [u8]) -> Bytes {
         BytesMut::from(src).freeze()
     }
 }
 
+impl<'a> From<&'a str> for Bytes {
+    fn from(src: &'a str) -> Bytes {
+        BytesMut::from(src).freeze()
+    }
+}
+
 impl PartialEq for Bytes {
     fn eq(&self, other: &Bytes) -> bool {
         self.inner.as_ref() == other.inner.as_ref()
@@ -538,7 +550,7 @@ impl BytesMut {
     /// // `bytes` contains no data, even though there is capacity
     /// assert_eq!(bytes.len(), 0);
     ///
-    /// bytes.copy_from_slice(b"hello world");
+    /// bytes.put(&b"hello world"[..]);
     ///
     /// assert_eq!(&bytes[..], b"hello world");
     /// ```
@@ -618,7 +630,7 @@ impl BytesMut {
     /// use std::thread;
     ///
     /// let mut b = BytesMut::with_capacity(64);
-    /// b.put_str("hello world");
+    /// b.put("hello world");
     /// let b1 = b.freeze();
     /// let b2 = b1.clone();
     ///
@@ -785,6 +797,63 @@ impl BytesMut {
     pub unsafe fn set_len(&mut self, len: usize) {
         self.inner.set_len(len)
     }
+
+    /// Reserves capacity for at least `additional` more bytes to be inserted
+    /// into the given `BytesMut`.
+    ///
+    /// More than `additional` bytes may be reserved in order to avoid frequent
+    /// reallocations. A call to `reserve` may result in an allocation.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use bytes::BytesMut;
+    ///
+    /// let mut b = BytesMut::from(&b"hello"[..]);
+    /// b.reserve(64);
+    /// assert!(b.capacity() >= 69);
+    /// ```
+    ///
+    /// # Panics
+    ///
+    /// Panics if the new capacity overflows usize.
+    pub fn reserve(&mut self, additional: usize) {
+        self.inner.reserve(additional)
+    }
+
+    /// Attempts to reclaim ownership of the full buffer.
+    ///
+    /// Returns `true` if the reclaim is successful.
+    ///
+    /// If the `BytesMut` handle is the only outstanding handle pointing to the
+    /// memory slice, the handle's view will be set to the full memory slice,
+    /// enabling reusing buffer space without allocating.
+    ///
+    /// Any data in the `BytesMut` handle will be copied to the start of the
+    /// memory region.
+    ///
+    /// ```rust
+    /// use bytes::BytesMut;
+    ///
+    /// let mut bytes = BytesMut::from(
+    ///     "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+    ///
+    /// // Create a new handle to the shared memory region
+    /// let a = bytes.drain_to(5);
+    ///
+    /// // Attempting to reclaim here will fail due to `a` still being in
+    /// // existence.
+    /// assert!(!bytes.try_reclaim());
+    /// assert_eq!(bytes.capacity(), 51);
+    ///
+    /// // Dropping the handle will allow reclaim to succeed.
+    /// drop(a);
+    /// assert!(bytes.try_reclaim());
+    /// assert_eq!(bytes.capacity(), 56);
+    /// ```
+    pub fn try_reclaim(&mut self) -> bool {
+        self.inner.try_reclaim()
+    }
 }
 
 impl BufMut for BytesMut {
@@ -806,7 +875,7 @@ impl BufMut for BytesMut {
     }
 
     #[inline]
-    fn copy_from_slice(&mut self, src: &[u8]) {
+    fn put_slice(&mut self, src: &[u8]) {
         assert!(self.remaining_mut() >= src.len());
 
         let len = src.len();
@@ -875,6 +944,12 @@ impl From<Vec<u8>> for BytesMut {
     }
 }
 
+impl From<String> for BytesMut {
+    fn from(src: String) -> BytesMut {
+        BytesMut::from(src.into_bytes())
+    }
+}
+
 impl<'a> From<&'a [u8]> for BytesMut {
     fn from(src: &'a [u8]) -> BytesMut {
         if src.len() <= INLINE_CAP {
@@ -894,12 +969,18 @@ impl<'a> From<&'a [u8]> for BytesMut {
             }
         } else {
             let mut buf = BytesMut::with_capacity(src.len());
-            buf.copy_from_slice(src.as_ref());
+            buf.put(src.as_ref());
             buf
         }
     }
 }
 
+impl<'a> From<&'a str> for BytesMut {
+    fn from(src: &'a str) -> BytesMut {
+        BytesMut::from(src.as_bytes())
+    }
+}
+
 impl From<Bytes> for BytesMut {
     fn from(src: Bytes) -> BytesMut {
         src.try_mut()
@@ -924,7 +1005,7 @@ impl fmt::Debug for BytesMut {
 
 impl fmt::Write for BytesMut {
     fn write_str(&mut self, s: &str) -> fmt::Result {
-        BufMut::put_str(self, s);
+        BufMut::put(self, s);
         Ok(())
     }
 
@@ -1220,6 +1301,150 @@ impl Inner {
         }
     }
 
+    #[inline]
+    fn reserve(&mut self, additional: usize) {
+        let len = self.len();
+        let rem = self.capacity() - len;
+
+        if additional <= rem {
+            // Nothing more to do
+            return;
+        }
+
+        match self.kind() {
+            Kind::Vec => {
+                unsafe {
+                    let d = &mut *self.data.get();
+
+                    // Promote this `Bytes` to an arc, and clone it
+                    let mut v = Vec::from_raw_parts(d.ptr, d.len, d.cap);
+                    v.reserve(additional);
+
+                    // Update the info
+                    d.ptr = v.as_mut_ptr();
+                    d.len = v.len();
+                    d.cap = v.capacity();
+
+                    // Drop the vec reference
+                    mem::forget(v);
+                }
+            }
+            Kind::Arc => {
+                unsafe {
+                    // Compute the new capacity
+                    let new_cap = len + additional;
+
+                    // Create a new vector to store the data
+                    let mut v = Vec::with_capacity(new_cap);
+
+                    // Copy the bytes
+                    v.extend_from_slice(self.as_ref());
+
+                    let d = &mut *self.data.get();
+
+                    d.ptr = v.as_mut_ptr();
+                    d.len = v.len();
+                    d.cap = v.capacity();
+
+                    mem::forget(v);
+
+                    // Drop the arc reference
+                    let _: Arc<UnsafeCell<Vec<u8>>> = mem::transmute(self.arc.get());
+
+                    self.arc.set(0);
+                }
+            }
+            Kind::Inline => {
+                let new_cap = len + additional;
+
+                unsafe {
+                    if new_cap <= INLINE_CAP {
+                        let dst = &mut self.data as *mut _ as *mut u8;
+                        let src = self.inline_ptr();
+
+                        ptr::copy(src, dst, len);
+
+                        let mut a = KIND_INLINE;
+                        a |= len << INLINE_LEN_OFFSET;
+
+                        self.arc.set(a);
+                    } else {
+                        let mut v = Vec::with_capacity(new_cap);
+
+                        // Copy the bytes
+                        v.extend_from_slice(self.as_ref());
+
+                        let d = &mut *self.data.get();
+
+                        d.ptr = v.as_mut_ptr();
+                        d.len = v.len();
+                        d.cap = v.capacity();
+
+                        mem::forget(v);
+
+                        self.arc.set(0);
+                    }
+                }
+            }
+            Kind::Static => unreachable!(),
+        }
+    }
+
+    /// This must take `&mut self` in order to be able to copy memory in the
+    /// inline case.
+    #[inline]
+    fn try_reclaim(&mut self) -> bool {
+        match self.kind() {
+            Kind::Inline => {
+                if self.inline_start() > 0 {
+                    // Shift the data back to the front
+                    unsafe {
+                        let len = self.inline_len();
+                        let dst = &mut self.data as *mut _ as *mut u8;
+                        let src = self.inline_ptr();
+
+                        ptr::copy(src, dst, len);
+
+                        let mut a = KIND_INLINE;
+                        a |= len << INLINE_LEN_OFFSET;
+
+                        self.arc.set(a);
+                    }
+                }
+
+                true
+            }
+            Kind::Arc => {
+                unsafe {
+                    let arc: &mut Shared = mem::transmute(&mut self.arc);
+
+                    // Check if mut safe
+                    if Arc::get_mut(arc).is_none() {
+                        return false;
+                    }
+
+                    let v = &mut *arc.get();
+                    let d = &mut *self.data.get();
+
+                    let len = v.len();
+                    let ptr = v.as_mut_ptr();
+
+                    ptr::copy(d.ptr, ptr, len);
+
+                    d.ptr = ptr;
+                    d.len = len;
+                    d.cap = v.capacity();
+
+                    true
+                }
+            }
+            Kind::Vec => {
+                true
+            }
+            Kind::Static => unreachable!(),
+        }
+    }
+
     #[inline]
     fn kind(&self) -> Kind {
         let arc = self.arc.get();
@@ -1283,6 +1508,12 @@ impl PartialEq<[u8]> for BytesMut {
     }
 }
 
+impl PartialEq<str> for BytesMut {
+    fn eq(&self, other: &str) -> bool {
+        &**self == other.as_bytes()
+    }
+}
+
 impl PartialEq<BytesMut> for [u8] {
     fn eq(&self, other: &BytesMut) -> bool {
         *other == *self
@@ -1295,12 +1526,24 @@ impl PartialEq<Vec<u8>> for BytesMut {
     }
 }
 
+impl PartialEq<String> for BytesMut {
+    fn eq(&self, other: &String) -> bool {
+        *self == &other[..]
+    }
+}
+
 impl PartialEq<BytesMut> for Vec<u8> {
     fn eq(&self, other: &BytesMut) -> bool {
         *other == *self
     }
 }
 
+impl PartialEq<BytesMut> for String {
+    fn eq(&self, other: &BytesMut) -> bool {
+        *other == *self
+    }
+}
+
 impl<'a, T: ?Sized> PartialEq<&'a T> for BytesMut
     where BytesMut: PartialEq<T>
 {
@@ -1315,36 +1558,72 @@ impl<'a> PartialEq<BytesMut> for &'a [u8] {
     }
 }
 
+impl<'a> PartialEq<BytesMut> for &'a str {
+    fn eq(&self, other: &BytesMut) -> bool {
+        *other == *self
+    }
+}
+
 impl PartialEq<[u8]> for Bytes {
     fn eq(&self, other: &[u8]) -> bool {
         self.inner.as_ref() == other
     }
 }
 
+impl PartialEq<str> for Bytes {
+    fn eq(&self, other: &str) -> bool {
+        self.inner.as_ref() == other.as_bytes()
+    }
+}
+
 impl PartialEq<Bytes> for [u8] {
     fn eq(&self, other: &Bytes) -> bool {
         *other == *self
     }
 }
 
+impl PartialEq<Bytes> for str {
+    fn eq(&self, other: &Bytes) -> bool {
+        *other == *self
+    }
+}
+
 impl PartialEq<Vec<u8>> for Bytes {
     fn eq(&self, other: &Vec<u8>) -> bool {
         *self == &other[..]
     }
 }
 
+impl PartialEq<String> for Bytes {
+    fn eq(&self, other: &String) -> bool {
+        *self == &other[..]
+    }
+}
+
 impl PartialEq<Bytes> for Vec<u8> {
     fn eq(&self, other: &Bytes) -> bool {
         *other == *self
     }
 }
 
+impl PartialEq<Bytes> for String {
+    fn eq(&self, other: &Bytes) -> bool {
+        *other == *self
+    }
+}
+
 impl<'a> PartialEq<Bytes> for &'a [u8] {
     fn eq(&self, other: &Bytes) -> bool {
         *other == *self
     }
 }
 
+impl<'a> PartialEq<Bytes> for &'a str {
+    fn eq(&self, other: &Bytes) -> bool {
+        *other == *self
+    }
+}
+
 impl<'a, T: ?Sized> PartialEq<&'a T> for Bytes
     where Bytes: PartialEq<T>
 {
diff --git a/src/lib.rs b/src/lib.rs
index 9d2a2e28fadb8ad21361ed2aeaa60a44f0163ccf..834f5b0a0b9c9a5ed62c102db3ee040574ec1251 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,4 +1,67 @@
 //! Provides abstractions for working with bytes.
+//!
+//! The `bytes` crate provides an efficient byte buffer structure
+//! ([`Bytes`](struct.Bytes.html)) and traits for working with buffer
+//! implementations ([`Buf`](trait.Buf.html), [`BufMut`](trait.BufMut.html)).
+//!
+//! # `Bytes`
+//!
+//! `Bytes` is an efficient container for storing and operating on continguous
+//! slices of memory. It is intended for use primarily in networking code, but
+//! could have applications elsewhere as well.
+//!
+//! `Bytes` values facilitate zero-copy network programming by allowing multiple
+//! `Bytes` objects to point to the same underlying memory. This is managed by
+//! using a reference count to track when the memory is no longer needed and can
+//! be freed.
+//!
+//! See the [struct docs](struct.Bytes.html) for more details.
+//!
+//! # `Buf`, `BufMut`
+//!
+//! These two traits provide read and write access to buffers. The underlying
+//! storage may or may not be in contiguous memory. For example, `Bytes` is a
+//! buffer that guarantees contiguous memory, but a
+//! [rope](https://en.wikipedia.org/wiki/Rope_(data_structure)) stores the bytes
+//! in disjoint chunks. `Buf` and `BufMut` maintain cursors tracking the current
+//! position in the underlying byte storage. When bytes are read or written, the
+//! cursor is advanced.
+//!
+//! ## Relation with `Read` and `Write`
+//!
+//! At first glance, it may seem that `Buf` and `BufMut` overlap in
+//! functionality with `std::io::Ready` and `std::io::Write`. However, they
+//! serve different purposes. A buffer is the value that is provided as an
+//! argument to `Read::read` and `Write::write`. `Read` and `Write` may then
+//! perform a syscall, which has the potential of failing. Operations on `Buf`
+//! and `BufMut` are infallible.
+//!
+//! # Example
+//!
+//! ```
+//! use bytes::{BytesMut, Buf, BufMut};
+//! use std::io::Cursor;
+//! use std::thread;
+//!
+//! // Allocate a buffer capable of holding 1024 bytes.
+//! let mut buf = BytesMut::with_capacity(1024);
+//!
+//! // Write some data
+//! buf.put("Hello world");
+//! buf.put(b'-');
+//! buf.put("goodbye");
+//!
+//! // Freeze the buffer, enabling concurrent access
+//! let b1 = buf.freeze();
+//! let b2 = b1.clone();
+//!
+//! thread::spawn(move || {
+//!     assert_eq!(&b1[..], b"Hello world-goodbye");
+//! });
+//!
+//! let mut buf = Cursor::new(b2);
+//! assert_eq!(b'H', buf.get_u8());
+//! ```
 
 #![deny(warnings, missing_docs)]
 
diff --git a/tests/test_bytes.rs b/tests/test_bytes.rs
index 521446e1930c8f8249d1d9209a70020706478f2f..1e38e5c7103320ad2d983ec4b2f0925e4278861d 100644
--- a/tests/test_bytes.rs
+++ b/tests/test_bytes.rs
@@ -1,10 +1,16 @@
 extern crate bytes;
 
-use bytes::{Bytes, BytesMut};
+use bytes::{Bytes, BytesMut, BufMut};
 
 const LONG: &'static [u8] = b"mary had a little lamb, little lamb, little lamb";
 const SHORT: &'static [u8] = b"hello world";
 
+#[cfg(target_pointer_width = "64")]
+const INLINE_CAP: usize = 8 * 3;
+
+#[cfg(target_pointer_width = "32")]
+const INNER_CAP: usize = 4 * 3;
+
 fn is_sync<T: Sync>() {}
 fn is_send<T: Send>() {}
 
@@ -193,5 +199,67 @@ fn fns_defined_for_bytes_mut() {
 
     // Iterator
     let v: Vec<u8> = bytes.iter().map(|b| *b).collect();
-    assert_eq!(&v[..], &bytes[..]);
+    assert_eq!(&v[..], bytes);
+}
+
+#[test]
+fn reserve() {
+    // Inline -> Vec
+    let mut bytes = BytesMut::with_capacity(8);
+    bytes.put("hello");
+    bytes.reserve(40);
+    assert_eq!(bytes.capacity(), 45);
+    assert_eq!(bytes, "hello");
+
+    // Inline -> Inline
+    let mut bytes = BytesMut::with_capacity(INLINE_CAP);
+    bytes.put("abcdefghijkl");
+
+    let a = bytes.drain_to(10);
+    bytes.reserve(INLINE_CAP - 3);
+    assert_eq!(INLINE_CAP, bytes.capacity());
+
+    assert_eq!(bytes, "kl");
+    assert_eq!(a, "abcdefghij");
+
+    // Vec -> Vec
+    let mut bytes = BytesMut::from(LONG);
+    bytes.reserve(64);
+    assert_eq!(bytes.capacity(), LONG.len() + 64);
+
+    // Arc -> Vec
+    let mut bytes = BytesMut::from(LONG);
+    let a = bytes.drain_to(30);
+
+    bytes.reserve(128);
+    assert_eq!(bytes.capacity(), bytes.len() + 128);
+
+    drop(a);
+}
+
+#[test]
+fn try_reclaim() {
+    // Inline w/ start at zero
+    let mut bytes = BytesMut::from(&SHORT[..]);
+    assert!(bytes.try_reclaim());
+    assert_eq!(bytes.capacity(), INLINE_CAP);
+    assert_eq!(bytes, SHORT);
+
+    // Inline w/ start not at zero
+    let mut bytes = BytesMut::from(&SHORT[..]);
+    let _ = bytes.drain_to(2);
+    assert_eq!(bytes.capacity(), INLINE_CAP - 2);
+    assert!(bytes.try_reclaim());
+    assert_eq!(bytes.capacity(), INLINE_CAP);
+    assert_eq!(bytes, &SHORT[2..]);
+
+    // Arc
+    let mut bytes = BytesMut::from(&LONG[..]);
+    let a = bytes.drain_to(2);
+    assert!(!bytes.try_reclaim());
+    assert_eq!(bytes.capacity(), LONG.len() - 2);
+
+    drop(a);
+    assert!(bytes.try_reclaim());
+    assert_eq!(bytes.capacity(), LONG.len());
 }
diff --git a/tests/test_mut_buf.rs b/tests/test_mut_buf.rs
index 56660e8c69e1cd1d4ad08b466862e16a30e363c7..d15a9209c7a12c2a4c4196eb959b49d5d737337b 100644
--- a/tests/test_mut_buf.rs
+++ b/tests/test_mut_buf.rs
@@ -15,7 +15,7 @@ fn test_vec_as_mut_buf() {
         assert!(buf.bytes_mut().len() >= 64);
     }
 
-    buf.copy_from(&b"zomg"[..]);
+    buf.put(&b"zomg"[..]);
 
     assert_eq!(&buf, b"zomg");
 
@@ -23,7 +23,7 @@ fn test_vec_as_mut_buf() {
     assert_eq!(buf.capacity(), 64);
 
     for _ in 0..16 {
-        buf.copy_from(&b"zomg"[..]);
+        buf.put(&b"zomg"[..]);
     }
 
     assert_eq!(buf.len(), 68);
@@ -32,7 +32,7 @@ fn test_vec_as_mut_buf() {
 #[test]
 fn test_put_u8() {
     let mut buf = Vec::with_capacity(8);
-    buf.put_u8(33);
+    buf.put::<u8>(33);
     assert_eq!(b"\x21", &buf[..]);
 }