From b26f291d93b269a4c3ba9a6f8b47e1eeccb1d7de Mon Sep 17 00:00:00 2001
From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Date: Mon, 16 Jan 2017 16:55:13 +0100
Subject: [PATCH] add missing `Vec<u8>` deserialization hint to `Deserializer`

---
 serde/src/bytes.rs          |  2 +-
 serde/src/de/mod.rs         | 13 ++++++++++++-
 serde/src/de/value.rs       | 24 ++++++++++++------------
 serde/src/macros.rs         |  3 +++
 serde_test/src/de.rs        |  5 +++++
 serde_test/src/token.rs     |  1 +
 testing/tests/test_bytes.rs |  2 ++
 7 files changed, 36 insertions(+), 14 deletions(-)

diff --git a/serde/src/bytes.rs b/serde/src/bytes.rs
index 574a673d..8402b4bd 100644
--- a/serde/src/bytes.rs
+++ b/serde/src/bytes.rs
@@ -234,7 +234,7 @@ mod bytebuf {
         fn deserialize<D>(deserializer: D) -> Result<ByteBuf, D::Error>
             where D: de::Deserializer
         {
-            deserializer.deserialize_bytes(ByteBufVisitor)
+            deserializer.deserialize_byte_buf(ByteBufVisitor)
         }
     }
 }
diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs
index af488dd4..f6307eab 100644
--- a/serde/src/de/mod.rs
+++ b/serde/src/de/mod.rs
@@ -174,6 +174,9 @@ pub enum Type {
 
     /// Represents a `&[u8]` type.
     Bytes,
+
+    /// Represents a `Vec<u8>` type.
+    ByteBuf,
 }
 
 impl fmt::Display for Type {
@@ -212,6 +215,7 @@ impl fmt::Display for Type {
             Type::UnitVariant    => "unit variant",
             Type::NewtypeVariant => "newtype variant",
             Type::Bytes          => "bytes",
+            Type::ByteBuf        => "bytes buf",
         };
         display.fmt(formatter)
     }
@@ -343,12 +347,19 @@ pub trait Deserializer {
                                      visitor: V) -> Result<V::Value, Self::Error>
         where V: Visitor;
 
-    /// This method hints that the `Deserialize` type is expecting a `Vec<u8>`. This allows
+    /// This method hints that the `Deserialize` type is expecting a `&[u8]`. This allows
     /// deserializers that provide a custom byte vector serialization to properly deserialize the
     /// type.
     fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
         where V: Visitor;
 
+    /// This method hints that the `Deserialize` type is expecting a `Vec<u8>`. This allows
+    /// deserializers that provide a custom byte vector serialization to properly deserialize the
+    /// type and prevent needless intermediate allocations that would occur when going through
+    /// `&[u8]`.
+    fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+        where V: Visitor;
+
     /// This method hints that the `Deserialize` type is expecting a map of values. This allows
     /// deserializers to parse sequences that aren't tagged as maps.
     fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs
index 52342cec..c6472474 100644
--- a/serde/src/de/value.rs
+++ b/serde/src/de/value.rs
@@ -181,7 +181,7 @@ impl<E> de::Deserializer for UnitDeserializer<E>
     forward_to_deserialize! {
         bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
         unit seq seq_fixed_size bytes map unit_struct newtype_struct
-        tuple_struct struct struct_field tuple enum ignored_any
+        tuple_struct struct struct_field tuple enum ignored_any byte_buf
     }
 
     fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -223,7 +223,7 @@ macro_rules! primitive_deserializer {
                 bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str
                 string unit option seq seq_fixed_size bytes map unit_struct
                 newtype_struct tuple_struct struct struct_field tuple enum
-                ignored_any
+                ignored_any byte_buf
             }
 
             fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -288,7 +288,7 @@ impl<'a, E> de::Deserializer for StrDeserializer<'a, E>
     forward_to_deserialize! {
         bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
         unit option seq seq_fixed_size bytes map unit_struct newtype_struct
-        tuple_struct struct struct_field tuple ignored_any
+        tuple_struct struct struct_field tuple ignored_any byte_buf
     }
 }
 
@@ -346,7 +346,7 @@ impl<E> de::Deserializer for StringDeserializer<E>
     forward_to_deserialize! {
         bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
         unit option seq seq_fixed_size bytes map unit_struct newtype_struct
-        tuple_struct struct struct_field tuple ignored_any
+        tuple_struct struct struct_field tuple ignored_any byte_buf
     }
 }
 
@@ -408,7 +408,7 @@ impl<'a, E> de::Deserializer for CowStrDeserializer<'a, E>
     forward_to_deserialize! {
         bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
         unit option seq seq_fixed_size bytes map unit_struct newtype_struct
-        tuple_struct struct struct_field tuple ignored_any
+        tuple_struct struct struct_field tuple ignored_any byte_buf
     }
 }
 
@@ -469,7 +469,7 @@ impl<I, T, E> de::Deserializer for SeqDeserializer<I, E>
     forward_to_deserialize! {
         bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
         unit option seq seq_fixed_size bytes map unit_struct newtype_struct
-        tuple_struct struct struct_field tuple enum ignored_any
+        tuple_struct struct struct_field tuple enum ignored_any byte_buf
     }
 }
 
@@ -572,7 +572,7 @@ impl<V_, E> de::Deserializer for SeqVisitorDeserializer<V_, E>
     forward_to_deserialize! {
         bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
         unit option seq seq_fixed_size bytes map unit_struct newtype_struct
-        tuple_struct struct struct_field tuple enum ignored_any
+        tuple_struct struct struct_field tuple enum ignored_any byte_buf
     }
 }
 
@@ -675,7 +675,7 @@ impl<I, K, V, E> de::Deserializer for MapDeserializer<I, K, V, E>
     forward_to_deserialize! {
         bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
         unit option bytes map unit_struct newtype_struct tuple_struct struct
-        struct_field tuple enum ignored_any
+        struct_field tuple enum ignored_any byte_buf
     }
 }
 
@@ -772,7 +772,7 @@ impl<A, B, E> de::Deserializer for PairDeserializer<A, B, E>
     forward_to_deserialize! {
         bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
         unit option bytes map unit_struct newtype_struct tuple_struct struct
-        struct_field tuple enum ignored_any
+        struct_field tuple enum ignored_any byte_buf
     }
 
     fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -901,7 +901,7 @@ impl<V_, E> de::Deserializer for MapVisitorDeserializer<V_, E>
     forward_to_deserialize! {
         bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
         unit option seq seq_fixed_size bytes map unit_struct newtype_struct
-        tuple_struct struct struct_field tuple enum ignored_any
+        tuple_struct struct struct_field tuple enum ignored_any byte_buf
     }
 }
 
@@ -934,7 +934,7 @@ impl<'a, E> de::Deserializer for BytesDeserializer<'a, E>
     forward_to_deserialize! {
         bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
         unit option seq seq_fixed_size bytes map unit_struct newtype_struct
-        tuple_struct struct struct_field tuple enum ignored_any
+        tuple_struct struct struct_field tuple enum ignored_any byte_buf
     }
 }
 
@@ -970,7 +970,7 @@ impl<E> de::Deserializer for ByteBufDeserializer<E>
     forward_to_deserialize! {
         bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
         unit option seq seq_fixed_size bytes map unit_struct newtype_struct
-        tuple_struct struct struct_field tuple enum ignored_any
+        tuple_struct struct struct_field tuple enum ignored_any byte_buf
     }
 }
 
diff --git a/serde/src/macros.rs b/serde/src/macros.rs
index 2580980f..44718108 100644
--- a/serde/src/macros.rs
+++ b/serde/src/macros.rs
@@ -92,6 +92,9 @@ macro_rules! forward_to_deserialize_helper {
     (bytes) => {
         forward_to_deserialize_method!{deserialize_bytes()}
     };
+    (byte_buf) => {
+        forward_to_deserialize_method!{deserialize_byte_buf()}
+    };
     (map) => {
         forward_to_deserialize_method!{deserialize_map()}
     };
diff --git a/serde_test/src/de.rs b/serde_test/src/de.rs
index 80ba9e80..849bdf27 100644
--- a/serde_test/src/de.rs
+++ b/serde_test/src/de.rs
@@ -160,6 +160,10 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
         where __V: de::Visitor {
         self.deserialize(visitor)
     }
+    fn deserialize_byte_buf<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
+        where __V: de::Visitor {
+        self.deserialize(visitor)
+    }
     fn deserialize_ignored_any<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
         where __V: de::Visitor {
         self.deserialize(visitor)
@@ -250,6 +254,7 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
             Some(Token::Str(v)) => visitor.visit_str(v),
             Some(Token::String(v)) => visitor.visit_string(v),
             Some(Token::Bytes(v)) => visitor.visit_bytes(v),
+            Some(Token::ByteBuf(v)) => visitor.visit_byte_buf(v),
             Some(Token::Option(false)) => visitor.visit_none(),
             Some(Token::Option(true)) => visitor.visit_some(self),
             Some(Token::Unit) => visitor.visit_unit(),
diff --git a/serde_test/src/token.rs b/serde_test/src/token.rs
index e4b3a825..b8bd23c6 100644
--- a/serde_test/src/token.rs
+++ b/serde_test/src/token.rs
@@ -17,6 +17,7 @@ pub enum Token<'a> {
     Str(&'a str),
     String(String),
     Bytes(&'a [u8]),
+    ByteBuf(Vec<u8>),
 
     Option(bool),
 
diff --git a/testing/tests/test_bytes.rs b/testing/tests/test_bytes.rs
index 6968f900..86067627 100644
--- a/testing/tests/test_bytes.rs
+++ b/testing/tests/test_bytes.rs
@@ -15,6 +15,7 @@ fn test_bytes() {
 fn test_byte_buf() {
     let empty = ByteBuf::new();
     assert_tokens(&empty, &[Token::Bytes(b"")]);
+    assert_de_tokens(&empty, &[Token::ByteBuf(Vec::new())]);
     assert_de_tokens(&empty, &[Token::Str("")]);
     assert_de_tokens(&empty, &[Token::String(String::new())]);
     assert_de_tokens(&empty, &[
@@ -28,6 +29,7 @@ fn test_byte_buf() {
 
     let buf = ByteBuf::from(vec![65, 66, 67]);
     assert_tokens(&buf, &[Token::Bytes(b"ABC")]);
+    assert_de_tokens(&buf, &[Token::ByteBuf(vec![65, 66, 67])]);
     assert_de_tokens(&buf, &[Token::Str("ABC")]);
     assert_de_tokens(&buf, &[Token::String("ABC".to_owned())]);
     assert_de_tokens(&buf, &[