diff --git a/src/byte_str.rs b/src/byte_str.rs
index ee420cf6659fe2059544ce0e5076a9f27e78814d..831c9c51d8d6a09caaf18cf9e58922ac2626ba33 100644
--- a/src/byte_str.rs
+++ b/src/byte_str.rs
@@ -1,5 +1,5 @@
-use {alloc, Bytes, ByteBuf, ROByteBuf};
-use traits::{Buf, MutBuf, MutBufExt, ByteStr};
+use {alloc, Bytes, ByteBuf, ROByteBuf, Rope};
+use traits::{Buf, MutBuf, MutBufExt, ByteStr, ToBytes};
 use std::{cmp, ops};
 
 /*
@@ -53,8 +53,8 @@ impl ByteStr for SeqByteStr {
         }
     }
 
-    fn concat<B: ByteStr>(&self, _other: B) -> Bytes {
-        unimplemented!();
+    fn concat<B: ByteStr+'static>(&self, other: &B) -> Bytes {
+        Rope::of(self.clone()).concat(other)
     }
 
     fn len(&self) -> usize {
@@ -75,7 +75,9 @@ impl ByteStr for SeqByteStr {
 
         Bytes::of(bytes)
     }
+}
 
+impl ToBytes for SeqByteStr {
     fn to_bytes(self) -> Bytes {
         Bytes::of(self)
     }
@@ -159,8 +161,8 @@ impl ByteStr for SmallByteStr {
         SmallByteStrBuf { small: self.clone() }
     }
 
-    fn concat<B: ByteStr>(&self, _other: B) -> Bytes {
-        unimplemented!();
+    fn concat<B: ByteStr+'static>(&self, other: &B) -> Bytes {
+        Rope::of(self.clone()).concat(other)
     }
 
     fn len(&self) -> usize {
@@ -174,7 +176,9 @@ impl ByteStr for SmallByteStr {
     fn split_at(&self, _mid: usize) -> (Bytes, Bytes) {
         unimplemented!();
     }
+}
 
+impl ToBytes for SmallByteStr {
     fn to_bytes(self) -> Bytes {
         Bytes::of(self)
     }
diff --git a/src/bytes.rs b/src/bytes.rs
index 963fdb8135f55de811aa11f304308f5cce21e758..149a4d85c1e800e48276cabf1eb84b790278af61 100644
--- a/src/bytes.rs
+++ b/src/bytes.rs
@@ -1,4 +1,5 @@
-use {Buf, ByteStr, ByteBuf, SmallByteStr};
+use {ByteBuf, SmallByteStr};
+use traits::{Buf, ByteStr, ToBytes};
 use std::{fmt, mem, ops, ptr};
 use std::any::{Any, TypeId};
 use std::raw::TraitObject;
@@ -136,8 +137,8 @@ impl ByteStr for Bytes {
         self.obj().buf()
     }
 
-    fn concat<B: ByteStr+'static>(&self, other: B) -> Bytes {
-        self.obj().concat(Bytes::of(other))
+    fn concat<B: ByteStr+'static>(&self, other: &B) -> Bytes {
+        self.obj().concat(&Bytes::of(other.clone()))
     }
 
     fn len(&self) -> usize {
@@ -151,7 +152,9 @@ impl ByteStr for Bytes {
     fn split_at(&self, mid: usize) -> (Bytes, Bytes) {
         self.obj().split_at(mid)
     }
+}
 
+impl ToBytes for Bytes {
     fn to_bytes(self) -> Bytes {
         self
     }
@@ -203,7 +206,7 @@ trait ByteStrPriv {
 
     fn clone(&self) -> Bytes;
 
-    fn concat(&self, other: Bytes) -> Bytes;
+    fn concat(&self, other: &Bytes) -> Bytes;
 
     fn drop(&mut self);
 
@@ -228,7 +231,7 @@ impl<B: ByteStr + 'static> ByteStrPriv for B {
         Bytes::of(self.clone())
     }
 
-    fn concat(&self, other: Bytes) -> Bytes {
+    fn concat(&self, other: &Bytes) -> Bytes {
         self.concat(other)
     }
 
diff --git a/src/lib.rs b/src/lib.rs
index c4ce64efb5822504fee29ccefd9e59fca88fb87d..adb35b85a7138ee2f5e3689bb99594806c90bfd1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -24,7 +24,7 @@ mod slice;
 
 pub mod traits {
     //! All traits are re-exported here to allow glob imports.
-    pub use {Buf, BufExt, MutBuf, MutBufExt, ByteStr};
+    pub use {Buf, BufExt, MutBuf, MutBufExt, ByteStr, ToBytes};
 }
 
 const MAX_CAPACITY: usize = u32::MAX as usize;
@@ -198,7 +198,7 @@ pub trait MutBufExt {
 /// An immutable sequence of bytes. Operations will not mutate the original
 /// value. Since only immutable access is permitted, operations do not require
 /// copying (though, sometimes copying will happen as an optimization).
-pub trait ByteStr : Clone + Sized + Send + Sync + ops::Index<usize, Output=u8> {
+pub trait ByteStr : Clone + Sized + Send + Sync + ToBytes + ops::Index<usize, Output=u8> {
 
     // Until HKT lands, the buf must be bound by 'static
     type Buf: Buf+'static;
@@ -209,7 +209,7 @@ pub trait ByteStr : Clone + Sized + Send + Sync + ops::Index<usize, Output=u8> {
 
     /// Returns a new `Bytes` value representing the concatenation of `self`
     /// with the given `Bytes`.
-    fn concat<B: ByteStr+'static>(&self, other: B) -> Bytes;
+    fn concat<B: ByteStr+'static>(&self, other: &B) -> Bytes;
 
     /// Returns the number of bytes in the ByteStr
     fn len(&self) -> usize;
@@ -249,12 +249,75 @@ pub trait ByteStr : Clone + Sized + Send + Sync + ops::Index<usize, Output=u8> {
     fn split_at(&self, mid: usize) -> (Bytes, Bytes) {
         (self.slice_to(mid), self.slice_from(mid))
     }
+}
+
+impl<B1: ByteStr, B2: ByteStr> cmp::PartialEq<B2> for B1 {
+    fn eq(&self, other: &B2) -> bool {
+        if self.len() != other.len() {
+            return false;
+        }
+
+        let mut buf1 = self.buf();
+        let mut buf2 = self.buf();
+
+        while buf1.has_remaining() {
+            let len;
+
+            {
+                let b1 = buf1.bytes();
+                let b2 = buf2.bytes();
+
+                len = cmp::min(b1.len(), b2.len());
+
+                if b1[..len] != b2[..len] {
+                    return false;
+                }
+            }
+
+            buf1.advance(len);
+            buf2.advance(len);
+        }
+
+        true
+    }
+
+    fn ne(&self, other: &B2) -> bool {
+        return !self.eq(other)
+    }
+}
+
+macro_rules! impl_eq {
+    ($ty:ty) => {
+        impl cmp::Eq for $ty {}
+    }
+}
 
+impl_eq!(Bytes);
+
+/*
+ *
+ * ===== ToBytes =====
+ *
+ */
+
+pub trait ToBytes {
     /// Consumes the value and returns a `Bytes` instance containing
     /// identical bytes
     fn to_bytes(self) -> Bytes;
 }
 
+impl<'a> ToBytes for &'a [u8] {
+    fn to_bytes(self) -> Bytes {
+        Bytes::from_slice(self)
+    }
+}
+
+impl<'a> ToBytes for &'a Vec<u8> {
+    fn to_bytes(self) -> Bytes {
+        self.as_slice().to_bytes()
+    }
+}
+
 /*
  *
  * ===== *Ext impls =====
@@ -351,8 +414,33 @@ impl<'a> Source for &'a Vec<u8> {
 impl<'a> Source for &'a Bytes {
     type Error = BufError;
 
-    fn fill<B: MutBuf>(self, _buf: &mut B) -> Result<usize, BufError> {
-        unimplemented!();
+    fn fill<B: MutBuf>(self, dst: &mut B) -> Result<usize, BufError> {
+        let mut src = self.buf();
+        let mut res = 0;
+
+        while src.has_remaining() && dst.has_remaining() {
+            let mut l;
+
+            {
+                let s = src.bytes();
+                let d = dst.mut_bytes();
+                l = cmp::min(s.len(), d.len());
+
+                unsafe {
+                    ptr::copy_nonoverlapping(
+                        d.as_mut_ptr(),
+                        s.as_ptr(),
+                        l);
+                }
+            }
+
+            src.advance(l);
+            dst.advance(l);
+
+            res += l;
+        }
+
+        Ok(res)
     }
 }
 
diff --git a/src/rope.rs b/src/rope.rs
index 6cae0a632ca468788d7eb73b874059693e3fb2de..180859e94358b91805246b26e8eba2c8bf4fc8bf 100644
--- a/src/rope.rs
+++ b/src/rope.rs
@@ -1,5 +1,5 @@
 use {Bytes, ByteBuf, Source, BufError};
-use traits::*;
+use traits::{Buf, ByteStr, MutBuf, MutBufExt, ToBytes};
 use std::{cmp, mem, ops};
 use std::sync::Arc;
 
@@ -98,9 +98,9 @@ impl ByteStr for Rope {
         RopeBuf::new(self.clone())
     }
 
-    fn concat<B: ByteStr+'static>(&self, other: B) -> Bytes {
+    fn concat<B: ByteStr+'static>(&self, other: &B) -> Bytes {
         let left = Bytes::of(self.clone());
-        let right = Bytes::of(other);
+        let right = Bytes::of(other.clone());
         Bytes::of(concat(left, right))
     }
 
@@ -146,7 +146,9 @@ impl ByteStr for Rope {
 
         Bytes::of(Rope::new(left_slice, right_slice))
     }
+}
 
+impl ToBytes for Rope {
     fn to_bytes(self) -> Bytes {
         Bytes::of(self)
     }
diff --git a/test/test_rope.rs b/test/test_rope.rs
index af7870eeeca48ae92832363e6983f47ed7051e78..27070cf807ba89e6235f19ff446da29c444b8498 100644
--- a/test/test_rope.rs
+++ b/test/test_rope.rs
@@ -69,7 +69,7 @@ pub fn test_rope_concat_two_byte_str() {
     let left = Rope::from_slice(TEST_BYTES_1);
     let right = Rope::from_slice(TEST_BYTES_2);
 
-    let both = left.concat(right);
+    let both = left.concat(&right);
 
     assert_eq!(both.len(), TEST_BYTES_1.len() + TEST_BYTES_2.len());
 
@@ -88,3 +88,17 @@ pub fn test_slice_parity() {
 
     // stuff
 }
+
+#[test]
+pub fn test_rope_equality() {
+    let a = &b"Mary had a little lamb, its fleece was white as snow; ".to_bytes()
+        .concat(&b"And everywhere that Mary went, the lamb was sure to go.".to_bytes());
+
+    let b = &b"Mary had a little lamb, ".to_bytes()
+        .concat(&b"its fleece was white as snow; ".to_bytes())
+        .concat(
+            &b"And everywhere that Mary went, ".to_bytes()
+                .concat(&b"the lamb was sure to go.".to_bytes()));
+
+    assert_eq!(a, b);
+}