diff --git a/Cargo.toml b/Cargo.toml
index b8735422b69b35a03b018f0c84fcdcf4062a5e06..217319a0ede036453bbf2db057ada5f486b034e3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -21,6 +21,7 @@ categories = ["network-programming", "data-structures"]
 
 [dependencies]
 byteorder = "1.0.0"
+iovec = { git = "https://github.com/carllerche/iovec" }
 
 [dev-dependencies]
 tokio-core = "0.1.0"
diff --git a/src/buf/buf.rs b/src/buf/buf.rs
index 3f3dbb6e8ba5207475daec0a0580f103472f8230..0732aff145ea6f7759f854a3b4fe77eac67171c2 100644
--- a/src/buf/buf.rs
+++ b/src/buf/buf.rs
@@ -1,5 +1,6 @@
 use super::{Take, Reader, Iter, FromBuf};
 use byteorder::ByteOrder;
+use iovec::IoVec;
 
 use std::{cmp, io, ptr};
 
@@ -72,6 +73,34 @@ pub trait Buf {
     /// ```
     fn bytes(&self) -> &[u8];
 
+    /// Fills `dst` with potentially multiple slices starting at `self`'s
+    /// current position.
+    ///
+    /// If the `Buf` is backed by disjoint slices of bytes, `bytes_vec` enables
+    /// fetching more than one slice at once. `dst` is a slice of `IoVec`
+    /// references, enabling the slice to be directly used with [`writev`]
+    /// without any further conversion. The sum of the lengths of all the
+    /// buffers in `dst` will be less than or equal to `Buf::remaining()`.
+    ///
+    /// The entries in `dst` will be overwritten, but the data **contained** by
+    /// the slices **will not** be modified. If `bytes_vec` does not fill every
+    /// entry in `dst`, then `dst` is guaranteed to contain all remaining slices
+    /// in `self.
+    ///
+    /// This is a lower level function. Most operations are done with other
+    /// functions.
+    ///
+    /// [`writev`]: http://man7.org/linux/man-pages/man2/readv.2.html
+    fn bytes_vec<'a>(&'a self, dst: &mut [&'a IoVec]) -> usize {
+        if dst.is_empty() {
+            return 0;
+        }
+
+        dst[0] = self.bytes().into();
+
+        1
+    }
+
     /// Advance the internal cursor of the Buf
     ///
     /// The next call to `bytes` will return a slice starting `cnt` bytes
@@ -576,6 +605,10 @@ impl<'a, T: Buf + ?Sized> Buf for &'a mut T {
         (**self).bytes()
     }
 
+    fn bytes_vec<'b>(&'b self, dst: &mut [&'b IoVec]) -> usize {
+        (**self).bytes_vec(dst)
+    }
+
     fn advance(&mut self, cnt: usize) {
         (**self).advance(cnt)
     }
@@ -590,6 +623,10 @@ impl<T: Buf + ?Sized> Buf for Box<T> {
         (**self).bytes()
     }
 
+    fn bytes_vec<'b>(&'b self, dst: &mut [&'b IoVec]) -> usize {
+        (**self).bytes_vec(dst)
+    }
+
     fn advance(&mut self, cnt: usize) {
         (**self).advance(cnt)
     }
diff --git a/src/buf/buf_mut.rs b/src/buf/buf_mut.rs
index 2e3c141b91da260ae5ee20a16302babef87a3df1..7ecc8b2d4e92141948c450b5dd23fb28aabb9217 100644
--- a/src/buf/buf_mut.rs
+++ b/src/buf/buf_mut.rs
@@ -1,5 +1,6 @@
 use super::{Source, Writer};
 use byteorder::ByteOrder;
+use iovec::IoVec;
 
 use std::{cmp, io, ptr, usize};
 
@@ -137,6 +138,35 @@ pub trait BufMut {
     /// ```
     unsafe fn bytes_mut(&mut self) -> &mut [u8];
 
+    /// Fills `dst` with potentially multiple mutable slices starting at `self`'s
+    /// current position.
+    ///
+    /// If the `BufMut` is backed by disjoint slices of bytes, `bytes_vec_mut`
+    /// enables fetching more than one slice at once. `dst` is a slice of
+    /// mutable `IoVec` references, enabling the slice to be directly used with
+    /// [`readv`] without any further conversion. The sum of the lengths of all
+    /// the buffers in `dst` will be less than or equal to
+    /// `Buf::remaining_mut()`.
+    ///
+    /// The entries in `dst` will be overwritten, but the data **contained** by
+    /// the slices **will not** be modified. If `bytes_vec_mut` does not fill every
+    /// entry in `dst`, then `dst` is guaranteed to contain all remaining slices
+    /// in `self.
+    ///
+    /// This is a lower level function. Most operations are done with other
+    /// functions.
+    ///
+    /// [`readv`]: http://man7.org/linux/man-pages/man2/readv.2.html
+    unsafe fn bytes_vec_mut<'a>(&'a mut self, dst: &mut [&'a mut IoVec]) -> usize {
+        if dst.is_empty() {
+            return 0;
+        }
+
+        dst[0] = self.bytes_mut().into();
+
+        1
+    }
+
     /// Transfer bytes into `self` from `src` and advance the cursor by the
     /// number of bytes written.
     ///
@@ -513,6 +543,10 @@ impl<'a, T: BufMut + ?Sized> BufMut for &'a mut T {
         (**self).bytes_mut()
     }
 
+    unsafe fn bytes_vec_mut<'b>(&'b mut self, dst: &mut [&'b mut IoVec]) -> usize {
+        (**self).bytes_vec_mut(dst)
+    }
+
     unsafe fn advance_mut(&mut self, cnt: usize) {
         (**self).advance_mut(cnt)
     }
@@ -527,6 +561,10 @@ impl<T: BufMut + ?Sized> BufMut for Box<T> {
         (**self).bytes_mut()
     }
 
+    unsafe fn bytes_vec_mut<'b>(&'b mut self, dst: &mut [&'b mut IoVec]) -> usize {
+        (**self).bytes_vec_mut(dst)
+    }
+
     unsafe fn advance_mut(&mut self, cnt: usize) {
         (**self).advance_mut(cnt)
     }
diff --git a/src/bytes.rs b/src/bytes.rs
index 1ebcff19bad19340d0e05357a9a96bcfbc146114..fb70101b56cd54a3b47c9bd3ebdda00beff47a6f 100644
--- a/src/bytes.rs
+++ b/src/bytes.rs
@@ -1229,7 +1229,8 @@ impl<'a> From<&'a [u8]> for BytesMut {
             }
         } else {
             let mut buf = BytesMut::with_capacity(src.len());
-            buf.put(src.as_ref());
+            let src: &[u8] = src.as_ref();
+            buf.put(src);
             buf
         }
     }
diff --git a/src/lib.rs b/src/lib.rs
index 521f80c560ca2418bdbe4d7dbee44be28bce09a9..d62db78f97b2d1946ed1350d5a137c13c2fb7453 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -72,6 +72,7 @@
 #![doc(html_root_url = "https://docs.rs/bytes/0.4")]
 
 extern crate byteorder;
+extern crate iovec;
 
 pub mod buf;
 pub use buf::{
diff --git a/tests/test_buf.rs b/tests/test_buf.rs
index 27229e816857d9fb7f99a8cc3a7159f77fcc7b1d..5c989c34af096735834cf77d8f2c24bd02b8c834 100644
--- a/tests/test_buf.rs
+++ b/tests/test_buf.rs
@@ -1,7 +1,9 @@
 extern crate bytes;
 extern crate byteorder;
+extern crate iovec;
 
 use bytes::Buf;
+use iovec::IoVec;
 use std::io::Cursor;
 
 #[test]
@@ -46,3 +48,11 @@ fn test_get_u16_buffer_underflow() {
     let mut buf = Cursor::new(b"\x21");
     buf.get_u16::<byteorder::BigEndian>();
 }
+
+#[test]
+fn test_bufs_vec() {
+    let buf = Cursor::new(b"hello world");
+    let mut dst: [&IoVec; 2] = Default::default();
+
+    assert_eq!(1, buf.bytes_vec(&mut dst[..]));
+}
diff --git a/tests/test_buf_mut.rs b/tests/test_buf_mut.rs
index d15a9209c7a12c2a4c4196eb959b49d5d737337b..fe2e9c8b96e8b811b6f160bf2d5fded4dd039355 100644
--- a/tests/test_buf_mut.rs
+++ b/tests/test_buf_mut.rs
@@ -1,7 +1,9 @@
 extern crate bytes;
 extern crate byteorder;
+extern crate iovec;
 
 use bytes::{BufMut, BytesMut};
+use iovec::IoVec;
 use std::usize;
 use std::fmt::Write;
 
@@ -56,3 +58,15 @@ fn test_clone() {
     buf.write_str(" of our emergecy broadcast system").unwrap();
     assert!(buf != buf2);
 }
+
+#[test]
+fn test_bufs_vec_mut() {
+    use std::mem;
+
+    let mut buf = BytesMut::from(&b"hello world"[..]);
+
+    unsafe {
+        let mut dst: [&mut IoVec; 2] = mem::zeroed();
+        assert_eq!(1, buf.bytes_vec_mut(&mut dst[..]));
+    }
+}