Repository: 3Hren/msgpack-rust
Pull request #257 (2020-09-12 04:29:44)

Add config to choose binary vs human-readable, for Serializer and Deserializer
Add a defaulted type parameter to `Deserializer` and all its auxiliary
types, threading the config ZSTs through. Delegate
`Serializer::is_human_readable` and `Deserializer::is_human_readable` to
the config. Test round-tripping for the new config variants this
introduces.


Patch:
diff --git a/rmp-serde/Cargo.toml b/rmp-serde/Cargo.toml
index 87fd684..76e4786 100644
--- a/rmp-serde/Cargo.toml
+++ b/rmp-serde/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "rmp-serde"
-version = "0.14.4"
+version = "0.15.0"
 authors = ["Evgeny Safronov <division494@gmail.com>"]
 license = "MIT"
 description = "Serde bindings for RMP"
diff --git a/rmp-serde/src/config.rs b/rmp-serde/src/config.rs
index 1aa3018..442423d 100644
--- a/rmp-serde/src/config.rs
+++ b/rmp-serde/src/config.rs
@@ -21,7 +21,7 @@ mod sealed {
     ///
     /// This hack disallows external implementations and usage of SerializerConfig and thus
     /// allows us to change SerializerConfig methods freely without breaking backwards compatibility.
-    pub trait SerializerConfig {
+    pub trait SerializerConfig: Copy {
         fn write_struct_len<S>(ser: &mut S, len: usize) -> Result<(), Error>
         where
             S: UnderlyingWrite,
@@ -44,12 +44,20 @@ mod sealed {
         where
             S: UnderlyingWrite,
             for<'a> &'a mut S: Serializer<Ok = (), Error = Error>;
+
+        /// Determines the value of `Serializer::is_human_readable` and
+        /// `Deserializer::is_human_readable`.
+        fn is_human_readable() -> bool;
     }
 }
 
-/// The default serializer configuration.
+/// The default serializer/deserializer configuration.
 ///
-/// This writes structs as a tuple, without field names, and enum variants as integers.
+/// This configuration:
+/// - Writes structs as a tuple, without field names
+/// - Writes enum variants as integers
+/// - Writes and reads types as binary, not human-readable
+//
 /// This is the most compact representation.
 #[derive(Copy, Clone, Debug)]
 pub struct DefaultConfig;
@@ -85,6 +93,10 @@ impl sealed::SerializerConfig for DefaultConfig {
     {
         ser.serialize_u32(variant_index)
     }
+
+    fn is_human_readable() -> bool {
+        false
+    }
 }
 
 /// Config wrapper, that overrides struct serialization by packing as a map with field names.
@@ -139,6 +151,10 @@ where
     {
         C::write_variant_ident(ser, variant_index, variant)
     }
+
+    fn is_human_readable() -> bool {
+        C::is_human_readable()
+    }
 }
 
 /// Config wrapper that overrides struct serlization by packing as a tuple without field
@@ -187,6 +203,10 @@ where
     {
         C::write_variant_ident(ser, variant_index, variant)
     }
+
+    fn is_human_readable() -> bool {
+        C::is_human_readable()
+    }
 }
 
 /// Config wrapper, that overrides enum serialization by serializing enum variant names as strings.
@@ -235,6 +255,10 @@ where
     {
         ser.serialize_str(variant)
     }
+
+    fn is_human_readable() -> bool {
+        C::is_human_readable()
+    }
 }
 
 /// Config wrapper that overrides enum variant serialization by packing enum names as their integer indices.
@@ -280,4 +304,109 @@ where
     {
         ser.serialize_u32(variant_index)
     }
+
+    fn is_human_readable() -> bool {
+        C::is_human_readable()
+    }
+}
+
+/// Config wrapper that overrides `Serializer::is_human_readable` and
+/// `Deserializer::is_human_readable` to return `true`.
+#[derive(Copy, Clone, Debug)]
+pub struct HumanReadableConfig<C>(C);
+
+impl<C> HumanReadableConfig<C> {
+    /// Creates a `HumanReadableConfig` inheriting unchanged configuration options from the given configuration.
+    pub fn new(inner: C) -> Self {
+        Self(inner)
+    }
+}
+
+impl<C> sealed::SerializerConfig for HumanReadableConfig<C>
+where
+    C: sealed::SerializerConfig,
+{
+    fn write_struct_len<S>(ser: &mut S, len: usize) -> Result<(), Error>
+    where
+        S: UnderlyingWrite,
+        for<'a> &'a mut S: Serializer<Ok = (), Error = Error>,
+    {
+        C::write_struct_len(ser, len)
+    }
+
+    fn write_struct_field<S, T>(ser: &mut S, key: &'static str, value: &T) -> Result<(), Error>
+    where
+        S: UnderlyingWrite,
+        for<'a> &'a mut S: Serializer<Ok = (), Error = Error>,
+        T: ?Sized + Serialize,
+    {
+        C::write_struct_field(ser, key, value)
+    }
+
+    fn write_variant_ident<S>(
+        ser: &mut S,
+        variant_index: u32,
+        variant: &'static str,
+    ) -> Result<(), Error>
+    where
+        S: UnderlyingWrite,
+        for<'a> &'a mut S: Serializer<Ok = (), Error = Error>,
+    {
+        C::write_variant_ident(ser, variant_index, variant)
+    }
+
+    fn is_human_readable() -> bool {
+        true
+    }
+}
+
+
+/// Config wrapper that overrides `Serializer::is_human_readable` and
+/// `Deserializer::is_human_readable` to return `false`.
+#[derive(Copy, Clone, Debug)]
+pub struct BinaryConfig<C>(C);
+
+impl<C> BinaryConfig<C> {
+    /// Creates a `BinaryConfig` inheriting unchanged configuration options from the given configuration.
+    pub fn new(inner: C) -> Self {
+        Self(inner)
+    }
+}
+
+impl<C> sealed::SerializerConfig for BinaryConfig<C>
+where
+    C: sealed::SerializerConfig,
+{
+    fn write_struct_len<S>(ser: &mut S, len: usize) -> Result<(), Error>
+    where
+        S: UnderlyingWrite,
+        for<'a> &'a mut S: Serializer<Ok = (), Error = Error>,
+    {
+        C::write_struct_len(ser, len)
+    }
+
+    fn write_struct_field<S, T>(ser: &mut S, key: &'static str, value: &T) -> Result<(), Error>
+    where
+        S: UnderlyingWrite,
+        for<'a> &'a mut S: Serializer<Ok = (), Error = Error>,
+        T: ?Sized + Serialize,
+    {
+        C::write_struct_field(ser, key, value)
+    }
+
+    fn write_variant_ident<S>(
+        ser: &mut S,
+        variant_index: u32,
+        variant: &'static str,
+    ) -> Result<(), Error>
+    where
+        S: UnderlyingWrite,
+        for<'a> &'a mut S: Serializer<Ok = (), Error = Error>,
+    {
+        C::write_variant_ident(ser, variant_index, variant)
+    }
+
+    fn is_human_readable() -> bool {
+        false
+    }
 }
diff --git a/rmp-serde/src/decode.rs b/rmp-serde/src/decode.rs
index 85113e4..59230b3 100644
--- a/rmp-serde/src/decode.rs
+++ b/rmp-serde/src/decode.rs
@@ -15,6 +15,7 @@ use rmp::Marker;
 use rmp::decode::{self, MarkerReadError, DecodeStringError, ValueReadError, NumValueReadError};
 
 use crate::MSGPACK_EXT_STRUCT_NAME;
+use crate::config::{DefaultConfig, SerializerConfig, HumanReadableConfig, BinaryConfig};
 
 /// Enum representing errors that can occur while decoding MessagePack data.
 #[derive(Debug)]
@@ -145,13 +146,14 @@ impl<'a> From<DecodeStringError<'a>> for Error {
 /// All instances of `ErrorKind::Interrupted` are handled by this function and the underlying
 /// operation is retried.
 #[derive(Debug)]
-pub struct Deserializer<R> {
+pub struct Deserializer<R, C = DefaultConfig> {
     rd: R,
+    config: C,
     marker: Option<Marker>,
     depth: usize,
 }
 
-impl<R: Read> Deserializer<ReadReader<R>> {
+impl<R: Read> Deserializer<ReadReader<R>, DefaultConfig> {
     #[doc(hidden)]
     #[deprecated(note="use `Deserializer::new` instead")]
     pub fn from_read(rd: R) -> Self {
@@ -162,12 +164,15 @@ impl<R: Read> Deserializer<ReadReader<R>> {
     pub fn new(rd: R) -> Self {
         Self {
             rd: ReadReader::new(rd),
+            config: DefaultConfig,
             // Cached marker in case of deserializing optional values.
             marker: None,
             depth: 1024,
         }
     }
+}
 
+impl<R: Read, C> Deserializer<ReadReader<R>, C> {
     /// Gets a reference to the underlying reader in this decoder.
     pub fn get_ref(&self) -> &R {
         &self.rd.rd
@@ -184,6 +189,38 @@ impl<R: Read> Deserializer<ReadReader<R>> {
     }
 }
 
+impl<R: Read, C: SerializerConfig> Deserializer<R, C> {
+    /// Consumes this deserializer and returns a new one, which will deserialize types with
+    /// human-readable representations (`Deserializer::is_human_readable` will return `true`).
+    ///
+    /// This is primarily useful if you need to interoperate with serializations produced by older
+    /// versions of `rmp-serde`.
+    pub fn with_human_readable(self) -> Deserializer<R, HumanReadableConfig<C>> {
+        let Deserializer { rd, config, marker, depth } = self;
+        Deserializer {
+            rd,
+            config: HumanReadableConfig::new(config),
+            marker,
+            depth,
+        }
+    }
+
+    /// Consumes this deserializer and returns a new one, which will deserialize types with
+    /// binary representations (`Deserializer::is_human_readable` will return `false`).
+    ///
+    /// This is the default MessagePack deserialization mechanism, consuming the most compact
+    /// representation.
+    pub fn with_binary(self) -> Deserializer<R, BinaryConfig<C>> {
+        let Deserializer { rd, config, marker, depth } = self;
+        Deserializer {
+            rd,
+            config: BinaryConfig::new(config),
+            marker,
+            depth,
+        }
+    }
+}
+
 impl<R: AsRef<[u8]>> Deserializer<ReadReader<Cursor<R>>> {
     /// Returns the current position of this deserializer, i.e. how many bytes were read.
     pub fn position(&self) -> u64 {
@@ -199,6 +236,7 @@ impl<'de, R> Deserializer<ReadRefReader<'de, R>>
     pub fn from_read_ref(rd: &'de R) -> Self {
         Deserializer {
             rd: ReadRefReader::new(rd),
+            config: DefaultConfig,
             marker: None,
             depth: 1024,
         }
@@ -210,7 +248,7 @@ impl<'de, R> Deserializer<ReadRefReader<'de, R>>
     }
 }
 
-impl<'de, R: ReadSlice<'de>> Deserializer<R> {
+impl<'de, R: ReadSlice<'de>, C: SerializerConfig> Deserializer<R, C> {
     /// Changes the maximum nesting depth that is allowed
     pub fn set_max_depth(&mut self, depth: usize) {
         self.depth = depth;
@@ -300,23 +338,25 @@ enum ExtDeserializerState {
 }
 
 #[derive(Debug)]
-struct ExtDeserializer<'a, R> {
+struct ExtDeserializer<'a, R, C> {
     rd: &'a mut R,
+    config: C,
     len: u32,
     state: ExtDeserializerState
 }
 
-impl<'de, 'a, R: ReadSlice<'de> + 'a> ExtDeserializer<'a, R> {
-    fn new(d: &'a mut Deserializer<R>, len: u32) -> Self {
+impl<'de, 'a, R: ReadSlice<'de> + 'a, C: SerializerConfig> ExtDeserializer<'a, R, C> {
+    fn new(d: &'a mut Deserializer<R, C>, len: u32) -> Self {
         ExtDeserializer {
             rd: &mut d.rd,
+            config: d.config,
             len,
             state: ExtDeserializerState::New,
         }
     }
 }
 
-impl<'de, 'a, R: ReadSlice<'de> + 'a> de::Deserializer<'de> for ExtDeserializer<'a, R> {
+impl<'de, 'a, R: ReadSlice<'de> + 'a, C: SerializerConfig> de::Deserializer<'de> for ExtDeserializer<'a, R, C> {
     type Error = Error;
 
     #[inline]
@@ -333,7 +373,7 @@ impl<'de, 'a, R: ReadSlice<'de> + 'a> de::Deserializer<'de> for ExtDeserializer<
     }
 }
 
-impl<'de, 'a, R: ReadSlice<'de> + 'a> de::SeqAccess<'de> for ExtDeserializer<'a, R> {
+impl<'de, 'a, R: ReadSlice<'de> + 'a, C: SerializerConfig> de::SeqAccess<'de> for ExtDeserializer<'a, R, C> {
     type Error = Error;
 
     fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
@@ -349,7 +389,7 @@ impl<'de, 'a, R: ReadSlice<'de> + 'a> de::SeqAccess<'de> for ExtDeserializer<'a,
 
 
 /// Deserializer for Ext SeqAccess
-impl<'de, 'a, R: ReadSlice<'de> + 'a> de::Deserializer<'de> for &mut ExtDeserializer<'a, R> {
+impl<'de, 'a, R: ReadSlice<'de> + 'a, C: SerializerConfig> de::Deserializer<'de> for &mut ExtDeserializer<'a, R, C> {
     type Error = Error;
 
     #[inline]
@@ -385,9 +425,13 @@ impl<'de, 'a, R: ReadSlice<'de> + 'a> de::Deserializer<'de> for &mut ExtDeserial
     }
 }
 
-impl<'de, 'a, R: ReadSlice<'de>> serde::Deserializer<'de> for &'a mut Deserializer<R> {
+impl<'de, 'a, R: ReadSlice<'de>, C: SerializerConfig> serde::Deserializer<'de> for &'a mut Deserializer<R, C> {
     type Error = Error;
 
+    fn is_human_readable(&self) -> bool {
+        C::is_human_readable()
+    }
+
     fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
         where V: Visitor<'de>
     {
@@ -646,13 +690,13 @@ impl<'de, 'a, R: ReadSlice<'de>> serde::Deserializer<'de> for &'a mut Deserializ
     }
 }
 
-struct SeqAccess<'a, R> {
-    de: &'a mut Deserializer<R>,
+struct SeqAccess<'a, R, C> {
+    de: &'a mut Deserializer<R, C>,
     left: usize,
 }
 
-impl<'a, R: 'a> SeqAccess<'a, R> {
-    fn new(de: &'a mut Deserializer<R>, len: usize) -> Self {
+impl<'a, R: 'a, C> SeqAccess<'a, R, C> {
+    fn new(de: &'a mut Deserializer<R, C>, len: usize) -> Self {
         SeqAccess {
             de,
             left: len,
@@ -660,7 +704,7 @@ impl<'a, R: 'a> SeqAccess<'a, R> {
     }
 }
 
-impl<'de, 'a, R: ReadSlice<'de> + 'a> de::SeqAccess<'de> for SeqAccess<'a, R> {
+impl<'de, 'a, R: ReadSlice<'de> + 'a, C: SerializerConfig> de::SeqAccess<'de> for SeqAccess<'a, R, C> {
     type Error = Error;
 
     fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
@@ -679,13 +723,13 @@ impl<'de, 'a, R: ReadSlice<'de> + 'a> de::SeqAccess<'de> for SeqAccess<'a, R> {
     }
 }
 
-struct MapAccess<'a, R> {
-    de: &'a mut Deserializer<R>,
+struct MapAccess<'a, R, C> {
+    de: &'a mut Deserializer<R, C>,
     left: usize,
 }
 
-impl<'a, R: 'a> MapAccess<'a, R> {
-    fn new(de: &'a mut Deserializer<R>, len: usize) -> Self {
+impl<'a, R: 'a, C> MapAccess<'a, R, C> {
+    fn new(de: &'a mut Deserializer<R, C>, len: usize) -> Self {
         MapAccess {
             de,
             left: len,
@@ -693,7 +737,7 @@ impl<'a, R: 'a> MapAccess<'a, R> {
     }
 }
 
-impl<'de, 'a, R: ReadSlice<'de> + 'a> de::MapAccess<'de> for MapAccess<'a, R> {
+impl<'de, 'a, R: ReadSlice<'de> + 'a, C: SerializerConfig> de::MapAccess<'de> for MapAccess<'a, R, C> {
     type Error = Error;
 
     fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
@@ -718,19 +762,19 @@ impl<'de, 'a, R: ReadSlice<'de> + 'a> de::MapAccess<'de> for MapAccess<'a, R> {
     }
 }
 
-struct VariantAccess<'a, R> {
-    de: &'a mut Deserializer<R>,
+struct VariantAccess<'a, R, C> {
+    de: &'a mut Deserializer<R, C>,
 }
 
-impl<'a, R: 'a> VariantAccess<'a, R> {
-    pub fn new(de: &'a mut Deserializer<R>) -> Self {
+impl<'a, R: 'a, C> VariantAccess<'a, R, C> {
+    pub fn new(de: &'a mut Deserializer<R, C>) -> Self {
         VariantAccess {
             de,
         }
     }
 }
 
-impl<'de, 'a, R: ReadSlice<'de>> de::EnumAccess<'de> for VariantAccess<'a, R> {
+impl<'de, 'a, R: ReadSlice<'de>, C: SerializerConfig> de::EnumAccess<'de> for VariantAccess<'a, R, C> {
     type Error = Error;
     type Variant = Self;
 
@@ -741,7 +785,7 @@ impl<'de, 'a, R: ReadSlice<'de>> de::EnumAccess<'de> for VariantAccess<'a, R> {
     }
 }
 
-impl<'de, 'a, R: ReadSlice<'de>> de::VariantAccess<'de> for VariantAccess<'a, R> {
+impl<'de, 'a, R: ReadSlice<'de>, C: SerializerConfig> de::VariantAccess<'de> for VariantAccess<'a, R, C> {
     type Error = Error;
 
     fn unit_variant(self) -> Result<(), Error> {
diff --git a/rmp-serde/src/encode.rs b/rmp-serde/src/encode.rs
index 736835d..33306ed 100644
--- a/rmp-serde/src/encode.rs
+++ b/rmp-serde/src/encode.rs
@@ -14,7 +14,7 @@ use rmp::encode::ValueWriteError;
 
 use crate::config::{
     DefaultConfig, SerializerConfig, StructMapConfig, StructTupleConfig, VariantIntegerConfig,
-    VariantStringConfig,
+    VariantStringConfig, HumanReadableConfig, BinaryConfig,
 };
 use crate::MSGPACK_EXT_STRUCT_NAME;
 
@@ -195,7 +195,7 @@ impl<'a, W: Write + 'a, C> Serializer<W, C> {
 impl<W: Write, C> Serializer<W, C> {
     /// Consumes this serializer returning the new one, which will serialize structs as a map.
     ///
-    /// This is used, when you the default struct serialization as a tuple does not fit your
+    /// This is used, when the default struct serialization as a tuple does not fit your
     /// requirements.
     pub fn with_struct_map(self) -> Serializer<W, StructMapConfig<C>> {
         let Serializer { wr, depth, config } = self;
@@ -222,7 +222,7 @@ impl<W: Write, C> Serializer<W, C> {
 
     /// Consumes this serializer returning the new one, which will serialize enum variants as strings.
     ///
-    /// This is used, when you the default struct serialization as integers does not fit your
+    /// This is used, when the default struct serialization as integers does not fit your
     /// requirements.
     pub fn with_string_variants(self) -> Serializer<W, VariantStringConfig<C>> {
         let Serializer { wr, depth, config } = self;
@@ -246,6 +246,36 @@ impl<W: Write, C> Serializer<W, C> {
             config: VariantIntegerConfig::new(config),
         }
     }
+
+    /// Consumes this serializer returning the new one, which will serialize some types in
+    /// human-readable representations (`Serializer::is_human_readable` will return `true`). Note
+    /// that the overall representation is still binary, but some types such as IP addresses will
+    /// be saved as human-readable strings.
+    ///
+    /// This is primarily useful if you need to interoperate with serializations produced by older
+    /// versions of `rmp-serde`.
+    pub fn with_human_readable(self) -> Serializer<W, HumanReadableConfig<C>> {
+        let Serializer { wr, depth, config } = self;
+        Serializer {
+            wr,
+            depth,
+            config: HumanReadableConfig::new(config),
+        }
+    }
+
+    /// Consumes this serializer returning the new one, which will serialize types as binary
+    /// (`Serializer::is_human_readable` will return `false`).
+    ///
+    /// This is the default MessagePack serialization mechanism, emitting the most compact
+    /// representation.
+    pub fn with_binary(self) -> Serializer<W, BinaryConfig<C>> {
+        let Serializer { wr, depth, config } = self;
+        Serializer {
+            wr,
+            depth,
+            config: BinaryConfig::new(config),
+        }
+    }
 }
 
 impl<W: Write, C> UnderlyingWrite for Serializer<W, C> {
@@ -400,6 +430,10 @@ where
     type SerializeStruct = Compound<'a, W, C>;
     type SerializeStructVariant = Compound<'a, W, C>;
 
+    fn is_human_readable(&self) -> bool {
+        C::is_human_readable()
+    }
+
     fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
         encode::write_bool(&mut self.wr, v)
             .map_err(|err| Error::InvalidValueWrite(ValueWriteError::InvalidMarkerWrite(err)))


Test patch:
diff --git a/rmp-serde/tests/round.rs b/rmp-serde/tests/round.rs
index e502335..67cd263 100644
--- a/rmp-serde/tests/round.rs
+++ b/rmp-serde/tests/round.rs
@@ -7,6 +7,7 @@ use std::io::Cursor;
 use serde::{Deserialize, Serialize};
 use rmps::{Deserializer, Serializer};
 use rmps::config::{DefaultConfig, SerializerConfig};
+use rmps::decode::ReadReader;
 
 #[test]
 fn round_trip_option() {
@@ -448,22 +449,64 @@ fn roundtrip_some_failures() {
 
 #[cfg(test)]
 fn assert_roundtrips<T: PartialEq + std::fmt::Debug + Serialize + for<'a> Deserialize<'a>>(val: T) {
-    assert_roundtrips_config(&val, "default", |s| s);
-    assert_roundtrips_config(&val, ".with_struct_map()", |s| s.with_struct_map());
-    assert_roundtrips_config(&val, ".with_string_variants()", |s| {
-        s.with_string_variants()
-    });
-    assert_roundtrips_config(&val, ".with_struct_map().with_string_variants()", |s| {
-        s.with_struct_map().with_string_variants()
-    });
+    assert_roundtrips_config(&val, "default", |s| s, |d| d);
+    assert_roundtrips_config(&val, ".with_struct_map()", |s| s.with_struct_map(), |d| d);
+    assert_roundtrips_config(
+        &val,
+        ".with_string_variants()",
+        |s| s.with_string_variants(),
+        |d| d,
+    );
+    assert_roundtrips_config(
+        &val,
+        ".with_struct_map().with_string_variants()",
+        |s| s.with_struct_map().with_string_variants(),
+        |d| d,
+    );
+    assert_roundtrips_config(
+        &val,
+        ".with_human_readable()",
+        |s| s.with_human_readable(),
+        |d| d.with_human_readable(),
+    );
+    assert_roundtrips_config(
+        &val,
+        ".with_human_readable().with_struct_map()",
+        |s| s.with_human_readable().with_struct_map(),
+        |d| d.with_human_readable(),
+    );
+    assert_roundtrips_config(
+        &val,
+        ".with_human_readable().with_string_variants()",
+        |s| s.with_human_readable().with_string_variants(),
+        |d| d.with_human_readable(),
+    );
+    assert_roundtrips_config(
+        &val,
+        ".with_human_readable().with_struct_map().with_string_variants()",
+        |s| {
+            s.with_human_readable()
+                .with_struct_map()
+                .with_string_variants()
+        },
+        |d| d.with_human_readable(),
+    );
 }
 
 #[cfg(test)]
-fn assert_roundtrips_config<T, CSF, C>(val: &T, desc: &str, config_serializer: CSF)
-where
+fn assert_roundtrips_config<T, CSF, SC, CDF, DC>(
+    val: &T,
+    desc: &str,
+    config_serializer: CSF,
+    config_deserializer: CDF,
+) where
     T: PartialEq + std::fmt::Debug + Serialize + for<'a> Deserialize<'a>,
-    CSF: FnOnce(Serializer<Vec<u8>, DefaultConfig>) -> Serializer<Vec<u8>, C>,
-    C: SerializerConfig,
+    CSF: FnOnce(Serializer<Vec<u8>, DefaultConfig>) -> Serializer<Vec<u8>, SC>,
+    SC: SerializerConfig,
+    CDF: FnOnce(
+        Deserializer<ReadReader<&[u8]>, DefaultConfig>,
+    ) -> Deserializer<ReadReader<&[u8]>, DC>,
+    DC: SerializerConfig,
 {
     let mut serializer = config_serializer(Serializer::new(Vec::new()));
     if let Err(e) = val.serialize(&mut serializer) {
@@ -474,7 +517,7 @@ where
     }
     let serialized = serializer.into_inner();
 
-    let mut deserializer = Deserializer::new(serialized.as_slice());
+    let mut deserializer = config_deserializer(Deserializer::new(serialized.as_slice()));
     let val2: T = match T::deserialize(&mut deserializer) {
         Ok(t) => t,
         Err(e) => {
diff --git a/rmpv-tests/Cargo.toml b/rmpv-tests/Cargo.toml
index 5b314e8..48e7354 100644
--- a/rmpv-tests/Cargo.toml
+++ b/rmpv-tests/Cargo.toml
@@ -8,7 +8,7 @@ edition = "2018"
 [dependencies]
 serde = "1"
 serde_derive = "1"
-rmp-serde = { version = "0.14", path = "../rmp-serde" }
+rmp-serde = { version = "0.15", path = "../rmp-serde" }
 rmpv = { features = ["with-serde"], path = "../rmpv" }
 
 [dev-dependencies]