From 06b94c55b0f6624845b8570f15f8decb1624e964 Mon Sep 17 00:00:00 2001
From: Carl Lerche <me@carllerche.com>
Date: Tue, 7 Mar 2017 11:28:34 -0800
Subject: [PATCH] Remove buf::Source in favor of buf::IntoBuf

The `Source` trait was essentially covering the same case as `IntoBuf`,
so remove it.

While technically a breaking change, this should not have any impact due
to:

1) There are no reverse dependencies that currently depend on `bytes`
2) Source was not supposed to be implemented externally
3) IntoBuf provides the same implementations as `Source`

Given these points, the change should be safe to apply.
---
 src/buf/buf.rs      |  28 +++++++++
 src/buf/buf_mut.rs  |  74 ++++++++++++++++++++++-
 src/buf/into_buf.rs |  32 +++++++---
 src/buf/mod.rs      |   2 -
 src/buf/source.rs   | 140 --------------------------------------------
 src/lib.rs          |   1 -
 6 files changed, 123 insertions(+), 154 deletions(-)
 delete mode 100644 src/buf/source.rs

diff --git a/src/buf/buf.rs b/src/buf/buf.rs
index a8268f7..7b26904 100644
--- a/src/buf/buf.rs
+++ b/src/buf/buf.rs
@@ -720,3 +720,31 @@ impl<T: AsRef<[u8]>> Buf for io::Cursor<T> {
         self.set_position(pos as u64);
     }
 }
+
+impl Buf for Option<[u8; 1]> {
+    fn remaining(&self) -> usize {
+        if self.is_some() {
+            1
+        } else {
+            0
+        }
+    }
+
+    fn bytes(&self) -> &[u8] {
+        self.as_ref().map(AsRef::as_ref)
+            .unwrap_or(Default::default())
+    }
+
+    fn advance(&mut self, cnt: usize) {
+        if cnt == 0 {
+            return;
+        }
+
+        if self.is_none() {
+            panic!("overflow");
+        } else {
+            assert_eq!(1, cnt);
+            *self = None;
+        }
+    }
+}
diff --git a/src/buf/buf_mut.rs b/src/buf/buf_mut.rs
index def898d..8259ccf 100644
--- a/src/buf/buf_mut.rs
+++ b/src/buf/buf_mut.rs
@@ -1,4 +1,4 @@
-use super::{Source, Writer};
+use super::{IntoBuf, Writer};
 use byteorder::ByteOrder;
 use iovec::IoVec;
 
@@ -219,8 +219,30 @@ pub trait BufMut {
     /// # Panics
     ///
     /// Panics if `self` does not have enough capacity to contain `src`.
-    fn put<S: Source>(&mut self, src: S) where Self: Sized {
-        src.copy_to_buf(self);
+    fn put<T: IntoBuf>(&mut self, src: T) where Self: Sized {
+        use super::Buf;
+
+        let mut src = src.into_buf();
+
+        assert!(self.remaining_mut() >= src.remaining());
+
+        while src.has_remaining() {
+            let l;
+
+            unsafe {
+                let s = src.bytes();
+                let d = self.bytes_mut();
+                l = cmp::min(s.len(), d.len());
+
+                ptr::copy_nonoverlapping(
+                    s.as_ptr(),
+                    d.as_mut_ptr(),
+                    l);
+            }
+
+            src.advance(l);
+            unsafe { self.advance_mut(l); }
+        }
     }
 
     /// Transfer bytes into `self` from `src` and advance the cursor by the
@@ -268,6 +290,52 @@ pub trait BufMut {
         }
     }
 
+    /// Writes an unsigned 8 bit integer to `self`.
+    ///
+    /// The current position is advanced by 1.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use bytes::BufMut;
+    ///
+    /// let mut buf = vec![];
+    /// buf.put_u8(0x01);
+    /// assert_eq!(buf, b"\x01");
+    /// ```
+    ///
+    /// # Panics
+    ///
+    /// This function panics if there is not enough remaining capacity in
+    /// `self`.
+    fn put_u8(&mut self, n: u8) {
+        let src = [n];
+        self.put_slice(&src);
+    }
+
+    /// Writes a signed 8 bit integer to `self`.
+    ///
+    /// The current position is advanced by 1.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use bytes::BufMut;
+    ///
+    /// let mut buf = vec![];
+    /// buf.put_i8(0x01);
+    /// assert_eq!(buf, b"\x01");
+    /// ```
+    ///
+    /// # Panics
+    ///
+    /// This function panics if there is not enough remaining capacity in
+    /// `self`.
+    fn put_i8(&mut self, n: i8) {
+        let src = [n as u8];
+        self.put_slice(&src)
+    }
+
     /// Writes an unsigned 16 bit integer to `self` in the specified byte order.
     ///
     /// The current position is advanced by 2.
diff --git a/src/buf/into_buf.rs b/src/buf/into_buf.rs
index 771fc09..1071908 100644
--- a/src/buf/into_buf.rs
+++ b/src/buf/into_buf.rs
@@ -79,6 +79,14 @@ impl IntoBuf for Vec<u8> {
     }
 }
 
+impl<'a> IntoBuf for &'a Vec<u8> {
+    type Buf = io::Cursor<&'a [u8]>;
+
+    fn into_buf(self) -> Self::Buf {
+        io::Cursor::new(&self[..])
+    }
+}
+
 // Kind of annoying... but this impl is required to allow passing `&'static
 // [u8]` where for<'a> &'a T: IntoBuf is required.
 impl<'a> IntoBuf for &'a &'static [u8] {
@@ -97,14 +105,6 @@ impl<'a> IntoBuf for &'a &'static str {
     }
 }
 
-impl<'a> IntoBuf for &'a Vec<u8> {
-    type Buf = io::Cursor<&'a [u8]>;
-
-    fn into_buf(self) -> Self::Buf {
-        io::Cursor::new(&self[..])
-    }
-}
-
 impl IntoBuf for String {
     type Buf = io::Cursor<Vec<u8>>;
 
@@ -120,3 +120,19 @@ impl<'a> IntoBuf for &'a String {
         self.as_bytes().into_buf()
     }
 }
+
+impl IntoBuf for u8 {
+    type Buf = Option<[u8; 1]>;
+
+    fn into_buf(self) -> Self::Buf {
+        Some([self])
+    }
+}
+
+impl IntoBuf for i8 {
+    type Buf = Option<[u8; 1]>;
+
+    fn into_buf(self) -> Self::Buf {
+        Some([self as u8; 1])
+    }
+}
diff --git a/src/buf/mod.rs b/src/buf/mod.rs
index 7d7ce22..1f74e0a 100644
--- a/src/buf/mod.rs
+++ b/src/buf/mod.rs
@@ -23,7 +23,6 @@ mod chain;
 mod into_buf;
 mod iter;
 mod reader;
-mod source;
 mod take;
 mod writer;
 
@@ -34,6 +33,5 @@ pub use self::chain::Chain;
 pub use self::into_buf::IntoBuf;
 pub use self::iter::Iter;
 pub use self::reader::Reader;
-pub use self::source::Source;
 pub use self::take::Take;
 pub use self::writer::Writer;
diff --git a/src/buf/source.rs b/src/buf/source.rs
deleted file mode 100644
index bb12057..0000000
--- a/src/buf/source.rs
+++ /dev/null
@@ -1,140 +0,0 @@
-use {Buf, BufMut, Bytes};
-
-use std::{cmp, ptr};
-
-/// A value that writes bytes from itself into a `BufMut`.
-///
-/// Values that implement `Source` are used as an argument to
-/// [`BufMut::put`](trait.BufMut.html#method.put).
-///
-/// # Examples
-///
-/// ```
-/// use bytes::{BufMut, Source};
-///
-/// struct Repeat {
-///     num: usize,
-///     str: String,
-/// }
-///
-/// impl Source for Repeat {
-///     fn copy_to_buf<B: BufMut>(self, buf: &mut B) {
-///         for _ in 0..self.num {
-///             buf.put(&self.str);
-///         }
-///     }
-/// }
-///
-/// let mut dst = vec![];
-/// dst.put(Repeat {
-///     num: 3,
-///     str: "hello".into(),
-/// });
-///
-/// assert_eq!(*dst, b"hellohellohello"[..]);
-/// ```
-pub trait Source {
-    /// Copy data from self into destination buffer
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use bytes::{BufMut, Source};
-    ///
-    /// let mut dst = vec![];
-    ///
-    /// "hello".copy_to_buf(&mut dst);
-    ///
-    /// assert_eq!(*dst, b"hello"[..]);
-    /// ```
-    ///
-    /// # Panics
-    ///
-    /// This function panis if `buf` does not have enough capacity for `self`.
-    fn copy_to_buf<B: BufMut>(self, buf: &mut B);
-}
-
-impl Source for Vec<u8> {
-    fn copy_to_buf<B: BufMut>(self, buf: &mut B) {
-        buf.put_slice(&self[..]);
-    }
-}
-
-impl<'a> Source for &'a Vec<u8> {
-    fn copy_to_buf<B: BufMut>(self, buf: &mut B) {
-        buf.put_slice(&self[..]);
-    }
-}
-
-impl<'a> Source for &'a [u8] {
-    fn copy_to_buf<B: BufMut>(self, buf: &mut B) {
-        buf.put_slice(self);
-    }
-}
-
-impl Source for String {
-    fn copy_to_buf<B: BufMut>(self, buf: &mut B) {
-        buf.put_slice(self.as_bytes());
-    }
-}
-
-impl<'a> Source for &'a String {
-    fn copy_to_buf<B: BufMut>(self, buf: &mut B) {
-        buf.put_slice(self.as_bytes());
-    }
-}
-
-impl<'a> Source for &'a str {
-    fn copy_to_buf<B: BufMut>(self, buf: &mut B) {
-        buf.put_slice(self.as_bytes());
-    }
-}
-
-impl Source for u8 {
-    fn copy_to_buf<B: BufMut>(self, buf: &mut B) {
-        let src = [self];
-        buf.put_slice(&src);
-    }
-}
-
-impl Source for i8 {
-    fn copy_to_buf<B: BufMut>(self, buf: &mut B) {
-        buf.put_slice(&[self as u8])
-    }
-}
-
-impl Source for Bytes {
-    fn copy_to_buf<B: BufMut>(self, buf: &mut B) {
-        Source::copy_to_buf(self.as_ref(), buf);
-    }
-}
-
-impl<'a> Source for &'a Bytes {
-    fn copy_to_buf<B: BufMut>(self, buf: &mut B) {
-        Source::copy_to_buf(self.as_ref(), buf);
-    }
-}
-
-impl<T: Buf> Source for T {
-    fn copy_to_buf<B: BufMut>(mut self, buf: &mut B) {
-        assert!(buf.remaining_mut() >= self.remaining());
-
-        while self.has_remaining() {
-            let l;
-
-            unsafe {
-                let s = self.bytes();
-                let d = buf.bytes_mut();
-                l = cmp::min(s.len(), d.len());
-
-                ptr::copy_nonoverlapping(
-                    s.as_ptr(),
-                    d.as_mut_ptr(),
-                    l);
-            }
-
-            self.advance(l);
-            unsafe { buf.advance_mut(l); }
-        }
-    }
-}
diff --git a/src/lib.rs b/src/lib.rs
index 13f17c5..fabba8a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -83,7 +83,6 @@ pub use buf::{
 #[deprecated(since = "0.4.1", note = "moved to `buf` module")]
 #[doc(hidden)]
 pub use buf::{
-    Source,
     Reader,
     Writer,
     Take,
-- 
GitLab