Repository: 3Hren/msgpack-rust
Pull request #216 (2019-09-03 13:20:23)

Add serde Ext support for rmpv and rmps

unrealhoang: Thank you for your very detailed review. I will fix it all and try to look at the serde_derive support.

unrealhoang: I have to change Serde Data Model of Ext to a newtype struct named `_ExtStruct`, so the serde representation of Ext become `_ExtStruct((i8, Bytes))`.
This is because, for `Value` and `ValueRef`, which rely on `deserialize_any` to visit the correct type, there's currently no way to communicate the seq's name from deserializer to visitor.
daboross: @kornelski This looks good to me. If you're good with the addition, I'm good with merging it.

Patch:
diff --git a/rmp-serde/src/decode.rs b/rmp-serde/src/decode.rs
index 41c41c4..288c230 100644
--- a/rmp-serde/src/decode.rs
+++ b/rmp-serde/src/decode.rs
@@ -14,6 +14,8 @@ use rmp;
 use rmp::Marker;
 use rmp::decode::{self, MarkerReadError, DecodeStringError, ValueReadError, NumValueReadError};
 
+use crate::MSGPACK_EXT_STRUCT_NAME;
+
 /// Enum representing errors that can occur while decoding MessagePack data.
 #[derive(Debug)]
 pub enum Error {
@@ -249,6 +251,13 @@ impl<'de, R: ReadSlice<'de>> Deserializer<R> {
         self.rd.read_slice(len as usize).map_err(Error::InvalidDataRead)
     }
 
+    fn read_ext<V>(&mut self, len: u32, visitor: V) -> Result<V::Value, Error>
+        where V: Visitor<'de>
+    {
+        let ext_de = ExtDeserializer::new(self, len);
+        visitor.visit_newtype_struct(ext_de)
+    }
+
     fn read_array<V>(&mut self, len: u32, visitor: V) -> Result<V::Value, Error>
         where V: Visitor<'de>
     {
@@ -283,6 +292,99 @@ fn read_u32<R: Read>(rd: &mut R) -> Result<u32, Error> {
     rd.read_u32::<byteorder::BigEndian>().map_err(Error::InvalidDataRead)
 }
 
+#[derive(Debug)]
+enum ExtDeserializerState {
+    New,
+    ReadTag,
+    ReadBinary
+}
+
+#[derive(Debug)]
+struct ExtDeserializer<'a, R: 'a> {
+    rd: &'a mut R,
+    len: u32,
+    state: ExtDeserializerState
+}
+
+impl<'de, 'a, R: ReadSlice<'de> + 'a> ExtDeserializer<'a, R> {
+    fn new(d: &'a mut Deserializer<R>, len: u32) -> Self {
+        ExtDeserializer {
+            rd: &mut d.rd,
+            len,
+            state: ExtDeserializerState::New,
+        }
+    }
+}
+
+impl<'de, 'a, R: ReadSlice<'de> + 'a> de::Deserializer<'de> for ExtDeserializer<'a, R> {
+    type Error = Error;
+
+    #[inline]
+    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+        where V: Visitor<'de>
+    {
+        visitor.visit_seq(self)
+    }
+
+    forward_to_deserialize_any! {
+        bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
+        seq bytes byte_buf map unit_struct newtype_struct
+        struct identifier tuple enum ignored_any tuple_struct
+    }
+}
+
+impl<'de, 'a, R: ReadSlice<'de> + 'a> de::SeqAccess<'de> for ExtDeserializer<'a, R> {
+    type Error = Error;
+
+    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
+    where
+        T: DeserializeSeed<'de>,
+    {
+        match self.state {
+            ExtDeserializerState::New | ExtDeserializerState::ReadTag => Ok(Some(seed.deserialize(self)?)),
+            ExtDeserializerState::ReadBinary => Ok(None)
+        }
+    }
+}
+
+
+/// Deserializer for Ext SeqAccess
+impl<'de, 'a, R: ReadSlice<'de> + 'a> de::Deserializer<'de> for &mut ExtDeserializer<'a, R> {
+    type Error = Error;
+
+    #[inline]
+    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+        where V: Visitor<'de>
+    {
+        match self.state {
+            ExtDeserializerState::New => {
+                let tag = rmp::decode::read_data_i8(self.rd)?;
+                self.state = ExtDeserializerState::ReadTag;
+                visitor.visit_i8(tag)
+            }
+            ExtDeserializerState::ReadTag => {
+                let data = self.rd.read_slice(self.len as usize).map_err(Error::InvalidDataRead)?;
+                self.state = ExtDeserializerState::ReadBinary;
+                match data {
+                    Reference::Borrowed(bytes) => {
+                        visitor.visit_borrowed_bytes(bytes)
+                    }
+                    Reference::Copied(bytes) => {
+                        visitor.visit_bytes(bytes)
+                    }
+                }
+            }
+            ExtDeserializerState::ReadBinary => unreachable!()
+        }
+    }
+
+    forward_to_deserialize_any! {
+        bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
+        seq bytes byte_buf map unit_struct newtype_struct
+        tuple_struct struct identifier tuple enum ignored_any
+    }
+}
+
 impl<'de, 'a, R: ReadSlice<'de>> serde::Deserializer<'de> for &'a mut Deserializer<R> {
     type Error = Error;
 
@@ -359,8 +461,39 @@ impl<'de, 'a, R: ReadSlice<'de>> serde::Deserializer<'de> for &'a mut Deserializ
                 let len = read_u32(&mut self.rd)?;
                 self.read_bytes(len, visitor)
             }
+            Marker::FixExt1 => {
+                let len = 1 as usize;
+                self.read_ext(len as u32, visitor)
+            }
+            Marker::FixExt2 => {
+                let len = 2 as usize;
+                self.read_ext(len as u32, visitor)
+            }
+            Marker::FixExt4 => {
+                let len = 4 as usize;
+                self.read_ext(len as u32, visitor)
+            }
+            Marker::FixExt8 => {
+                let len = 8 as usize;
+                self.read_ext(len as u32, visitor)
+            }
+            Marker::FixExt16 => {
+                let len = 16 as usize;
+                self.read_ext(len as u32, visitor)
+            }
+            Marker::Ext8 => {
+                let len = read_u8(&mut self.rd)?;
+                self.read_ext(len as u32, visitor)
+            }
+            Marker::Ext16 => {
+                let len = read_u16(&mut self.rd)?;
+                self.read_ext(len as u32, visitor)
+            }
+            Marker::Ext32 => {
+                let len = read_u32(&mut self.rd)?;
+                self.read_ext(len as u32, visitor)
+            }
             Marker::Reserved => Err(Error::TypeMismatch(Marker::Reserved)),
-            marker => Err(Error::TypeMismatch(marker)),
         }
     }
 
@@ -391,9 +524,48 @@ impl<'de, 'a, R: ReadSlice<'de>> serde::Deserializer<'de> for &'a mut Deserializ
         }
     }
 
-    fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value, Error>
+    fn deserialize_newtype_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value, Error>
         where V: Visitor<'de>
     {
+        if name == MSGPACK_EXT_STRUCT_NAME {
+            let marker = match self.marker.take() {
+                Some(marker) => marker,
+                None => rmp::decode::read_marker(&mut self.rd)?,
+            };
+            let len = match marker {
+                Marker::FixExt1 => {
+                    1 as u32
+                }
+                Marker::FixExt2 => {
+                    2 as u32
+                }
+                Marker::FixExt4 => {
+                    4 as u32
+                }
+                Marker::FixExt8 => {
+                    8 as u32
+                }
+                Marker::FixExt16 => {
+                    16 as u32
+                }
+                Marker::Ext8 => {
+                    read_u8(&mut self.rd)? as u32
+                }
+                Marker::Ext16 => {
+                    read_u16(&mut self.rd)? as u32
+                }
+                Marker::Ext32 => {
+                    read_u32(&mut self.rd)? as u32
+                }
+                _ => {
+                    return Err(Error::TypeMismatch(marker))
+                }
+            };
+
+            let ext_de = ExtDeserializer::new(self, len);
+            return visitor.visit_newtype_struct(ext_de);
+        }
+
         visitor.visit_newtype_struct(self)
     }
 
@@ -469,7 +641,7 @@ impl<'de, 'a, R: ReadSlice<'de>> serde::Deserializer<'de> for &'a mut Deserializ
     forward_to_deserialize_any! {
         bool u8 u16 u32 u64 i8 i16 i32 i64 char
         str string bytes byte_buf unit seq map
-        tuple_struct struct identifier tuple
+        struct identifier tuple tuple_struct
         ignored_any
     }
 }
diff --git a/rmp-serde/src/encode.rs b/rmp-serde/src/encode.rs
index 444ffc2..83af8e9 100644
--- a/rmp-serde/src/encode.rs
+++ b/rmp-serde/src/encode.rs
@@ -16,6 +16,7 @@ use crate::config::{
     DefaultConfig, SerializerConfig, StructMapConfig, StructTupleConfig, VariantIntegerConfig,
     VariantStringConfig,
 };
+use crate::MSGPACK_EXT_STRUCT_NAME;
 
 /// This type represents all possible errors that can occur when serializing or
 /// deserializing MessagePack data.
@@ -25,6 +26,8 @@ pub enum Error {
     InvalidValueWrite(ValueWriteError),
     /// Failed to serialize struct, sequence or map, because its length is unknown.
     UnknownLength,
+    /// Invalid Data model, i.e. Serialize trait is not implmented correctly
+    InvalidDataModel(&'static str),
     /// Depth limit exceeded
     DepthLimitExceeded,
     /// Catchall for syntax error messages.
@@ -38,6 +41,7 @@ impl error::Error for Error {
             Error::UnknownLength => {
                 "attempt to serialize struct, sequence or map with unknown length"
             }
+            Error::InvalidDataModel(_) => "serialize data model is invalid",
             Error::DepthLimitExceeded => "depth limit exceeded",
             Error::Syntax(..) => "syntax error",
         }
@@ -47,6 +51,7 @@ impl error::Error for Error {
         match *self {
             Error::InvalidValueWrite(ref err) => Some(err),
             Error::UnknownLength => None,
+            Error::InvalidDataModel(_) => None,
             Error::DepthLimitExceeded => None,
             Error::Syntax(..) => None,
         }
@@ -60,6 +65,7 @@ impl Display for Error {
             Error::UnknownLength => {
                 f.write_str("attempt to serialize struct, sequence or map with unknown length")
             }
+            Error::InvalidDataModel(r) => write!(f, "serialize data model is invalid: {}", r),
             Error::DepthLimitExceeded => f.write_str("depth limit exceeded"),
             Error::Syntax(ref msg) => f.write_str(msg),
         }
@@ -117,6 +123,7 @@ pub struct Serializer<W, C> {
     depth: usize,
 }
 
+
 impl<W: Write, C> Serializer<W, C> {
     /// Gets a reference to the underlying writer.
     pub fn get_ref(&self) -> &W {
@@ -263,6 +270,20 @@ pub struct Compound<'a, W: 'a, C: 'a> {
     se: &'a mut Serializer<W, C>,
 }
 
+#[derive(Debug)]
+pub struct ExtFieldSerializer<'a, W> {
+    wr: &'a mut W,
+    tag: Option<i8>,
+    finish: bool
+}
+
+/// Represents MessagePack serialization implementation for Ext.
+#[derive(Debug)]
+pub struct ExtSerializer<'a, W> {
+    fields_se: ExtFieldSerializer<'a, W>,
+    tuple_received: bool
+}
+
 impl<'a, W: Write + 'a, C: SerializerConfig> SerializeSeq for Compound<'a, W, C> {
     type Ok = ();
     type Error = Error;
@@ -339,7 +360,7 @@ impl<'a, W: Write + 'a, C: SerializerConfig> SerializeStruct for Compound<'a, W,
     fn serialize_field<T: ?Sized + Serialize>(&mut self, key: &'static str, value: &T) ->
         Result<(), Self::Error>
     {
-        C::write_struct_field(self.se, key, value)
+        C::write_struct_field(&mut *self.se, key, value)
     }
 
     fn end(self) -> Result<Self::Ok, Self::Error> {
@@ -354,7 +375,7 @@ impl<'a, W: Write + 'a, C: SerializerConfig> SerializeStructVariant for Compound
     fn serialize_field<T: ?Sized + Serialize>(&mut self, key: &'static str, value: &T) ->
         Result<(), Self::Error>
     {
-        C::write_struct_field(self.se, key, value)
+        C::write_struct_field(&mut *self.se, key, value)
     }
 
     fn end(self) -> Result<Self::Ok, Self::Error> {
@@ -472,7 +493,14 @@ where
         self.serialize_unit()
     }
 
-    fn serialize_newtype_struct<T: ?Sized + serde::Serialize>(self, _name: &'static str, value: &T) -> Result<(), Self::Error> {
+    fn serialize_newtype_struct<T: ?Sized + serde::Serialize>(self, name: &'static str, value: &T) -> Result<(), Self::Error> {
+        if name == MSGPACK_EXT_STRUCT_NAME {
+            let mut ext_se = ExtSerializer::new(self);
+            value.serialize(&mut ext_se)?;
+
+            return ext_se.end();
+        }
+
         // Encode as if it's inner type.
         value.serialize(self)
     }
@@ -502,16 +530,18 @@ where
     fn serialize_tuple_struct(self, _name: &'static str, len: usize) ->
         Result<Self::SerializeTupleStruct, Self::Error>
     {
-        self.serialize_tuple(len)
+        encode::write_array_len(&mut self.wr, len as u32)?;
+
+        self.compound()
     }
 
-    fn serialize_tuple_variant(self,  name: &'static str,  idx: u32,  variant: &'static str,  len: usize) ->
+    fn serialize_tuple_variant(self, _name: &'static str, idx: u32, variant: &'static str, len: usize) ->
         Result<Self::SerializeTupleVariant, Error>
     {
         // encode as a map from variant idx to a sequence of its attributed data, like: {idx => [v1,...,vN]}
         encode::write_map_len(&mut self.wr, 1)?;
         C::write_variant_ident(self, idx, variant)?;
-        self.serialize_tuple_struct(name, len)
+        self.serialize_tuple(len)
     }
 
     fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Error> {
@@ -541,6 +571,377 @@ where
     }
 }
 
+impl<'a, W: Write + 'a> serde::Serializer for &mut ExtFieldSerializer<'a, W> {
+    type Ok = ();
+    type Error = Error;
+
+    type SerializeSeq = serde::ser::Impossible<(), Error>;
+    type SerializeTuple = serde::ser::Impossible<(), Error>;
+    type SerializeTupleStruct = serde::ser::Impossible<(), Error>;
+    type SerializeTupleVariant = serde::ser::Impossible<(), Error>;
+    type SerializeMap = serde::ser::Impossible<(), Error>;
+    type SerializeStruct = serde::ser::Impossible<(), Error>;
+    type SerializeStructVariant = serde::ser::Impossible<(), Error>;
+
+    #[inline]
+    fn serialize_i8(self, value: i8) -> Result<Self::Ok, Self::Error> {
+        if self.tag.is_none() {
+            self.tag.replace(value);
+            Ok(())
+        } else {
+            Err(Error::InvalidDataModel("expected i8 and bytes, unexpected second i8"))
+        }
+    }
+
+    #[inline]
+    fn serialize_bytes(self, val: &[u8]) -> Result<Self::Ok, Self::Error> {
+        if let Some(tag) = self.tag.take() {
+            encode::write_ext_meta(self.wr, val.len() as u32, tag)?;
+            self.wr
+                .write_all(val)
+                .map_err(|err| Error::InvalidValueWrite(ValueWriteError::InvalidDataWrite(err)))?;
+
+            self.finish = true;
+
+            Ok(())
+        } else {
+            Err(Error::InvalidDataModel("expected i8 and bytes, received bytes first"))
+        }
+    }
+
+    #[inline]
+    fn serialize_bool(self, _val: bool) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, bool unexpected"))
+    }
+
+    #[inline]
+    fn serialize_i16(self, _val: i16) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, i16 unexpected"))
+    }
+
+    #[inline]
+    fn serialize_i32(self, _val: i32) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, i32 unexpected"))
+    }
+
+    #[inline]
+    fn serialize_i64(self, _val: i64) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, i64 unexpected"))
+    }
+
+    #[inline]
+    fn serialize_u8(self, _val: u8) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, u8 unexpected"))
+    }
+
+    #[inline]
+    fn serialize_u16(self, _val: u16) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, u16 unexpected"))
+    }
+
+    #[inline]
+    fn serialize_u32(self, _val: u32) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, u32 unexpected"))
+    }
+
+    #[inline]
+    fn serialize_u64(self, _val: u64) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, u64 unexpected"))
+    }
+
+    #[inline]
+    fn serialize_f32(self, _val: f32) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, f32 unexpected"))
+    }
+
+    #[inline]
+    fn serialize_f64(self, _val: f64) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, f64 unexpected"))
+    }
+
+    #[inline]
+    fn serialize_char(self, _val: char) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, char unexpected"))
+    }
+
+    #[inline]
+    fn serialize_str(self, _val: &str) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, str unexpected"))
+    }
+
+    #[inline]
+    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, unit unexpected"))
+    }
+
+    #[inline]
+    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, unit struct unexpected"))
+    }
+
+    #[inline]
+    fn serialize_unit_variant(self, _name: &'static str, _idx: u32, _variant: &'static str) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, unit variant unexpected"))
+    }
+
+    #[inline]
+    fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, _value: &T) -> Result<Self::Ok, Self::Error>
+        where T: Serialize
+    {
+        Err(Error::InvalidDataModel("expected i8 and bytes, newtype struct unexpected"))
+    }
+
+    fn serialize_newtype_variant<T: ?Sized>(self, _name: &'static str, _idx: u32, _variant: &'static str, _value: &T) -> Result<Self::Ok, Self::Error>
+        where T: Serialize
+    {
+        Err(Error::InvalidDataModel("expected i8 and bytes, newtype variant unexpected"))
+    }
+
+    #[inline]
+    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, none unexpected"))
+    }
+
+    #[inline]
+    fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok, Self::Error>
+        where T: Serialize
+    {
+        Err(Error::InvalidDataModel("expected i8 and bytes, some unexpected"))
+    }
+
+    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, seq unexpected"))
+    }
+
+    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, tuple unexpected"))
+    }
+
+    fn serialize_tuple_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeTupleStruct, Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, tuple struct unexpected"))
+    }
+
+    fn serialize_tuple_variant(self, _name: &'static str, _idx: u32, _variant: &'static str, _len: usize) -> Result<Self::SerializeTupleVariant, Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, tuple variant unexpected"))
+    }
+
+    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, map unexpected"))
+    }
+
+    fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct, Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, struct unexpected"))
+    }
+
+    fn serialize_struct_variant(self, _name: &'static str, _idx: u32, _variant: &'static str, _len: usize) -> Result<Self::SerializeStructVariant, Error> {
+        Err(Error::InvalidDataModel("expected i8 and bytes, struct variant unexpected"))
+    }
+}
+
+impl<'a, W: Write + 'a> serde::ser::Serializer for &mut ExtSerializer<'a, W> {
+    type Ok = ();
+    type Error = Error;
+
+    type SerializeSeq = serde::ser::Impossible<(), Error>;
+    type SerializeTuple = Self;
+    type SerializeTupleStruct = serde::ser::Impossible<(), Error>;
+    type SerializeTupleVariant = serde::ser::Impossible<(), Error>;
+    type SerializeMap = serde::ser::Impossible<(), Error>;
+    type SerializeStruct = serde::ser::Impossible<(), Error>;
+    type SerializeStructVariant = serde::ser::Impossible<(), Error>;
+
+
+    #[inline]
+    fn serialize_bytes(self, _val: &[u8]) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected tuple, received bytes"))
+    }
+
+    #[inline]
+    fn serialize_bool(self, _val: bool) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected tuple, received bool"))
+    }
+
+    #[inline]
+    fn serialize_i8(self, _value: i8) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected tuple, received i8"))
+    }
+
+    #[inline]
+    fn serialize_i16(self, _val: i16) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected tuple, received i16"))
+    }
+
+    #[inline]
+    fn serialize_i32(self, _val: i32) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected tuple, received i32"))
+    }
+
+    #[inline]
+    fn serialize_i64(self, _val: i64) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected tuple, received i64"))
+    }
+
+    #[inline]
+    fn serialize_u8(self, _val: u8) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected tuple, received u8"))
+    }
+
+    #[inline]
+    fn serialize_u16(self, _val: u16) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected tuple, received u16"))
+    }
+
+    #[inline]
+    fn serialize_u32(self, _val: u32) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected tuple, received u32"))
+    }
+
+    #[inline]
+    fn serialize_u64(self, _val: u64) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected tuple, received u64"))
+    }
+
+    #[inline]
+    fn serialize_f32(self, _val: f32) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected tuple, received f32"))
+    }
+
+    #[inline]
+    fn serialize_f64(self, _val: f64) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected tuple, received f64"))
+    }
+
+    #[inline]
+    fn serialize_char(self, _val: char) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected tuple, received char"))
+    }
+
+    #[inline]
+    fn serialize_str(self, _val: &str) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected tuple, received str"))
+    }
+
+    #[inline]
+    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected tuple, received unit"))
+    }
+
+    #[inline]
+    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected tuple, received unit_struct"))
+    }
+
+    #[inline]
+    fn serialize_unit_variant(self, _name: &'static str, _idx: u32, _variant: &'static str) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected tuple, received unit_variant"))
+    }
+
+    #[inline]
+    fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, _value: &T) -> Result<Self::Ok, Self::Error>
+        where T: Serialize
+    {
+        Err(Error::InvalidDataModel("expected tuple, received newtype_struct"))
+    }
+
+    fn serialize_newtype_variant<T: ?Sized>(self, _name: &'static str, _idx: u32, _variant: &'static str, _value: &T) -> Result<Self::Ok, Self::Error>
+        where T: Serialize
+    {
+        Err(Error::InvalidDataModel("expected tuple, received newtype_variant"))
+    }
+
+    #[inline]
+    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
+        Err(Error::InvalidDataModel("expected tuple, received none"))
+    }
+
+    #[inline]
+    fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok, Self::Error>
+        where T: Serialize
+    {
+        Err(Error::InvalidDataModel("expected tuple, received some"))
+    }
+
+    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
+        Err(Error::InvalidDataModel("expected tuple, received seq"))
+    }
+
+    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Error> {
+        // FIXME check len
+        self.tuple_received = true;
+
+        Ok(self)
+    }
+
+    fn serialize_tuple_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeTupleStruct, Error> {
+        Err(Error::InvalidDataModel("expected tuple, received tuple_struct"))
+    }
+
+    fn serialize_tuple_variant(self, _name: &'static str, _idx: u32, _variant: &'static str, _len: usize) -> Result<Self::SerializeTupleVariant, Error> {
+        Err(Error::InvalidDataModel("expected tuple, received tuple_variant"))
+    }
+
+    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Error> {
+        Err(Error::InvalidDataModel("expected tuple, received map"))
+    }
+
+    fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct, Error> {
+        Err(Error::InvalidDataModel("expected tuple, received struct"))
+    }
+
+    fn serialize_struct_variant(self, _name: &'static str, _idx: u32, _variant: &'static str, _len: usize) -> Result<Self::SerializeStructVariant, Error> {
+        Err(Error::InvalidDataModel("expected tuple, received struct_variant"))
+    }
+}
+
+impl<'a, W: Write + 'a> SerializeTuple for &mut ExtSerializer<'a, W> {
+    type Ok = ();
+    type Error = Error;
+
+    fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error> {
+        value.serialize(&mut self.fields_se)
+    }
+
+    fn end(self) -> Result<Self::Ok, Self::Error> {
+        Ok(())
+    }
+}
+
+
+impl<'a, W: Write + 'a> ExtSerializer<'a, W> {
+    fn new<C>(ser: &'a mut Serializer<W, C>) -> Self {
+        Self {
+            fields_se: ExtFieldSerializer::new(ser),
+            tuple_received: false
+        }
+    }
+
+    fn end(self) -> Result<(), Error> {
+        if !self.tuple_received {
+            Err(Error::InvalidDataModel("expected tuple, received nothing"))
+        } else {
+            self.fields_se.end()
+        }
+    }
+}
+
+impl<'a, W: Write + 'a> ExtFieldSerializer<'a, W> {
+    fn new<C>(ser: &'a mut Serializer<W, C>) -> Self {
+        Self {
+           wr: UnderlyingWrite::get_mut(ser),
+           tag: None,
+           finish: false
+        }
+    }
+
+    fn end(self) -> Result<(), Error> {
+        if self.finish {
+            Ok(())
+        } else {
+            Err(Error::InvalidDataModel("expected i8 and bytes"))
+        }
+    }
+}
+
 /// Serialize the given data structure as MessagePack into the I/O stream.
 /// This function uses compact representation - structures as arrays
 ///
diff --git a/rmp-serde/src/lib.rs b/rmp-serde/src/lib.rs
index cea7eac..75112ef 100644
--- a/rmp-serde/src/lib.rs
+++ b/rmp-serde/src/lib.rs
@@ -79,6 +79,21 @@ pub mod config;
 pub mod decode;
 pub mod encode;
 
+/// Name of Serde newtype struct to Represent Msgpack's Ext
+/// Msgpack Ext: Ext(tag, binary)
+/// Serde data model: _ExtStruct((tag, binary))
+/// Example Serde impl for custom type:
+///
+/// ```ignore
+/// #[derive(Debug, PartialEq, Serialize, Deserialize)]
+/// #[serde(rename = "_ExtStruct")]
+/// struct ExtStruct((i8, serde_bytes::ByteBuf));
+///
+/// test_round(ExtStruct((2, serde_bytes::ByteBuf::from(vec![5]))),
+///            Value::Ext(2, vec![5]));
+/// ```
+pub const MSGPACK_EXT_STRUCT_NAME: &'static str = "_ExtStruct";
+
 /// Helper that allows both to encode and decode strings no matter whether they contain valid or
 /// invalid UTF-8.
 ///
diff --git a/rmpv/src/ext/de.rs b/rmpv/src/ext/de.rs
index 8fcb1a1..0210e36 100644
--- a/rmpv/src/ext/de.rs
+++ b/rmpv/src/ext/de.rs
@@ -2,6 +2,7 @@ use std::fmt::{self, Display, Formatter};
 use std::iter::ExactSizeIterator;
 use std::slice::Iter;
 use std::vec::IntoIter;
+use std::borrow::Cow;
 
 use serde::{self, Deserialize, Deserializer};
 use serde::de::{self, DeserializeSeed, IntoDeserializer, SeqAccess, Unexpected, Visitor};
@@ -9,6 +10,7 @@ use serde::de::{self, DeserializeSeed, IntoDeserializer, SeqAccess, Unexpected,
 use crate::{Integer, IntPriv, Utf8String, Utf8StringRef, Value, ValueRef};
 
 use super::{Error, ValueExt};
+use crate::MSGPACK_EXT_STRUCT_NAME;
 
 pub fn from_value<T>(val: Value) -> Result<T, Error>
     where T: for<'de> Deserialize<'de>
@@ -115,6 +117,13 @@ impl<'de> Deserialize<'de> for Value {
                 Ok(Value::Binary(v.to_owned()))
             }
 
+            #[inline]
+            fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
+                where E: de::Error
+            {
+                Ok(Value::Binary(v))
+            }
+
             #[inline]
             fn visit_map<V>(self, mut visitor: V) -> Result<Value, V::Error>
                 where V: de::MapAccess<'de>
@@ -132,6 +141,34 @@ impl<'de> Deserialize<'de> for Value {
 
                 Ok(Value::Map(pairs))
             }
+
+            #[inline]
+            fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+                where D: Deserializer<'de>,
+            {
+                struct ExtValueVisitor;
+                impl<'de> serde::de::Visitor<'de> for ExtValueVisitor {
+                    type Value = Value;
+
+                    fn expecting(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
+                        "a valid MessagePack Ext".fmt(fmt)
+                    }
+
+                    #[inline]
+                    fn visit_seq<V>(self, mut seq: V) -> Result<Value, V::Error>
+                        where V: SeqAccess<'de>
+                    {
+                        let tag = seq.next_element()?
+                            .ok_or_else(|| de::Error::invalid_length(0, &self))?;
+                        let bytes: serde_bytes::ByteBuf = seq.next_element()?
+                            .ok_or_else(|| de::Error::invalid_length(1, &self))?;
+
+                        Ok(Value::Ext(tag, bytes.to_vec()))
+                    }
+                }
+
+                deserializer.deserialize_tuple(2, ExtValueVisitor)
+            }
         }
 
         de.deserialize_any(ValueVisitor)
@@ -234,6 +271,34 @@ impl<'de> Deserialize<'de> for ValueRef<'de> {
 
                 Ok(ValueRef::Map(vec))
             }
+
+            #[inline]
+            fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+                where D: Deserializer<'de>,
+            {
+                struct ExtValueRefVisitor;
+                impl<'de> serde::de::Visitor<'de> for ExtValueRefVisitor {
+                    type Value = ValueRef<'de>;
+
+                    fn expecting(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
+                        "a valid MessagePack Ext".fmt(fmt)
+                    }
+
+                    #[inline]
+                    fn visit_seq<V>(self, mut seq: V) -> Result<ValueRef<'de>, V::Error>
+                        where V: SeqAccess<'de>
+                    {
+                        let tag = seq.next_element()?
+                            .ok_or_else(|| de::Error::invalid_length(0, &"invalid ext sequence"))?;
+                        let bytes: &[u8] = seq.next_element()?
+                            .ok_or_else(|| de::Error::invalid_length(1, &"invalid ext sequence"))?;
+
+                        Ok(ValueRef::Ext(tag, bytes))
+                    }
+                }
+
+                deserializer.deserialize_tuple(2, ExtValueRefVisitor)
+            }
         }
 
         de.deserialize_any(ValueVisitor)
@@ -285,13 +350,9 @@ impl<'de> Deserializer<'de> for Value {
                     Err(de::Error::invalid_length(len, &"fewer elements in map"))
                 }
             }
-            Value::Ext(..) => {
-                // TODO: [i8, [u8]] can be represented as:
-                //      - (0i8, Vec<u8>),
-                //      - struct F(i8, Vec<u8>),
-                //      - struct F {ty: i8, val: Vec<u8>}
-                //      - enum F{ A(Vec<u8>), B { name: Vec<u8> } }
-                unimplemented!();
+            Value::Ext(tag, data) => {
+                let de = ExtDeserializer::new_owned(tag, data);
+                visitor.visit_newtype_struct(de)
             }
         }
     }
@@ -311,9 +372,21 @@ impl<'de> Deserializer<'de> for Value {
     }
 
     #[inline]
-    fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value, Self::Error>
+    fn deserialize_newtype_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value, Self::Error>
         where V: Visitor<'de>
     {
+        if name == MSGPACK_EXT_STRUCT_NAME {
+            match self {
+                Value::Ext(tag, data) => {
+                    let ext_de = ExtDeserializer::new_owned(tag, data);
+                    return visitor.visit_newtype_struct(ext_de);
+                }
+                other => {
+                    return Err(de::Error::invalid_type(other.unexpected(), &"expected Ext"))
+                }
+            }
+        }
+
         visitor.visit_newtype_struct(self)
     }
 
@@ -376,8 +449,9 @@ impl<'de> Deserializer<'de> for ValueRef<'de> {
                     Err(de::Error::invalid_length(len, &"fewer elements in map"))
                 }
             }
-            ValueRef::Ext(..) => {
-                unimplemented!();
+            ValueRef::Ext(tag, data) => {
+                let de = ExtDeserializer::new_ref(tag, data);
+                visitor.visit_newtype_struct(de)
             }
         }
     }
@@ -397,9 +471,21 @@ impl<'de> Deserializer<'de> for ValueRef<'de> {
     }
 
     #[inline]
-    fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value, Self::Error>
+    fn deserialize_newtype_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value, Self::Error>
         where V: Visitor<'de>
     {
+        if name == MSGPACK_EXT_STRUCT_NAME {
+            match self {
+                ValueRef::Ext(tag, data) => {
+                    let ext_de = ExtDeserializer::new_ref(tag, data);
+                    return visitor.visit_newtype_struct(ext_de);
+                }
+                other => {
+                    return Err(de::Error::invalid_type(other.unexpected(), &"expected Ext"))
+                }
+            }
+        }
+
         visitor.visit_newtype_struct(self)
     }
 
@@ -462,8 +548,9 @@ impl<'de> Deserializer<'de> for &'de ValueRef<'de> {
                     Err(de::Error::invalid_length(len, &"fewer elements in map"))
                 }
             }
-            ValueRef::Ext(..) => {
-                unimplemented!();
+            ValueRef::Ext(tag, data) => {
+                let de = ExtDeserializer::new_ref(tag, data);
+                visitor.visit_newtype_struct(de)
             }
         }
     }
@@ -505,9 +592,21 @@ impl<'de> Deserializer<'de> for &'de ValueRef<'de> {
     }
 
     #[inline]
-    fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value, Self::Error>
+    fn deserialize_newtype_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value, Self::Error>
         where V: Visitor<'de>
     {
+        if name == MSGPACK_EXT_STRUCT_NAME {
+            match self {
+                ValueRef::Ext(tag, data) => {
+                    let ext_de = ExtDeserializer::new_ref(*tag, data);
+                    return visitor.visit_newtype_struct(ext_de);
+                }
+                other => {
+                    return Err(de::Error::invalid_type(other.unexpected(), &"expected Ext"))
+                }
+            }
+        }
+
         visitor.visit_newtype_struct(self)
     }
 
@@ -534,6 +633,89 @@ impl<'de> Deserializer<'de> for &'de ValueRef<'de> {
     }
 }
 
+struct ExtDeserializer<'de> {
+    tag: Option<i8>,
+    data: Option<Cow<'de, [u8]>>,
+}
+
+impl<'de> ExtDeserializer<'de> {
+    fn new_owned(tag: i8, data: Vec<u8>) -> Self {
+        ExtDeserializer {
+            tag: Some(tag),
+            data: Some(Cow::Owned(data)),
+        }
+    }
+
+    fn new_ref(tag: i8, data: &'de [u8]) -> Self {
+        ExtDeserializer {
+            tag: Some(tag),
+            data: Some(Cow::Borrowed(data)),
+        }
+    }
+}
+
+impl<'de> SeqAccess<'de> for ExtDeserializer<'de> {
+    type Error = Error;
+
+    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
+    where
+        T: DeserializeSeed<'de>,
+    {
+        if self.tag.is_some() || self.data.is_some() {
+            return Ok(Some(seed.deserialize(self)?));
+        }
+
+        Ok(None)
+    }
+}
+
+/// Deserializer for Ext (expecting sequence)
+impl<'a, 'de: 'a> Deserializer<'de> for ExtDeserializer<'de> {
+    type Error = Error;
+
+    #[inline]
+    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+        where V: Visitor<'de>
+    {
+        visitor.visit_seq(self)
+    }
+
+    forward_to_deserialize_any! {
+        bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
+        seq bytes byte_buf map unit_struct newtype_struct
+        struct identifier tuple enum ignored_any tuple_struct
+    }
+}
+
+/// Deserializer for Ext SeqAccess elements
+impl<'a, 'de: 'a> Deserializer<'de> for &'a mut ExtDeserializer<'de> {
+    type Error = Error;
+
+    #[inline]
+    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+        where V: Visitor<'de>
+    {
+        if self.tag.is_some() {
+            let tag = self.tag.take().unwrap();
+            visitor.visit_i8(tag)
+        } else if self.data.is_some() {
+            let data = self.data.take().unwrap();
+            match data {
+                Cow::Owned(data) => visitor.visit_byte_buf(data),
+                Cow::Borrowed(data) => visitor.visit_borrowed_bytes(data)
+            }
+        } else {
+            unreachable!("ext seq only has two elements");
+        }
+    }
+
+    forward_to_deserialize_any! {
+        bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
+        seq bytes byte_buf map unit_struct newtype_struct
+        tuple_struct struct identifier tuple enum ignored_any
+    }
+}
+
 struct SeqDeserializer<I> {
     iter: I,
 }
diff --git a/rmpv/src/ext/se.rs b/rmpv/src/ext/se.rs
index 86a0892..3411619 100644
--- a/rmpv/src/ext/se.rs
+++ b/rmpv/src/ext/se.rs
@@ -1,12 +1,13 @@
 use std::fmt::Display;
 
 use serde::Serialize;
-use serde::ser::{self, SerializeSeq, SerializeTuple, SerializeTupleStruct, SerializeMap, SerializeStruct};
+use serde::ser::{self, SerializeTupleStruct, SerializeSeq, SerializeTuple, SerializeMap, SerializeStruct};
 use serde_bytes::Bytes;
 
 use crate::{Integer, IntPriv, Value};
 
 use super::Error;
+use crate::MSGPACK_EXT_STRUCT_NAME;
 
 impl Serialize for Value {
     fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
@@ -45,10 +46,8 @@ impl Serialize for Value {
                 state.end()
             }
             Value::Ext(ty, ref buf) => {
-                let mut state = s.serialize_seq(Some(2))?;
-                state.serialize_element(&ty)?;
-                state.serialize_element(buf)?;
-                state.end()
+                let value = (ty, Bytes::new(&buf[..]));
+                s.serialize_newtype_struct(MSGPACK_EXT_STRUCT_NAME, &value)
             }
         }
     }
@@ -181,10 +180,17 @@ impl ser::Serializer for Serializer {
     }
 
     #[inline]
-    fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, value: &T) -> Result<Self::Ok, Self::Error>
+    fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<Self::Ok, Self::Error>
         where T: Serialize
     {
-        Ok(to_value(value)?)
+        if name == MSGPACK_EXT_STRUCT_NAME {
+            let mut ext_se = ExtSerializer::new();
+            value.serialize(&mut ext_se)?;
+
+            return ext_se.value();
+        }
+
+        to_value(value)
     }
 
     fn serialize_newtype_variant<T: ?Sized>(self, _name: &'static str, idx: u32, _variant: &'static str, value: &T) -> Result<Self::Ok, Self::Error>
@@ -221,7 +227,7 @@ impl ser::Serializer for Serializer {
     }
 
     fn serialize_tuple_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeTupleStruct, Error> {
-        self.serialize_seq(Some(len))
+        self.serialize_tuple(len)
     }
 
     fn serialize_tuple_variant(self, _name: &'static str, idx: u32, _variant: &'static str, len: usize) -> Result<Self::SerializeTupleVariant, Error> {
@@ -253,6 +259,385 @@ impl ser::Serializer for Serializer {
     }
 }
 
+pub struct ExtSerializer {
+    fields_se: Option<ExtFieldSerializer>
+}
+
+impl ser::Serializer for &mut ExtSerializer {
+    type Ok = ();
+    type Error = Error;
+
+    type SerializeSeq = ser::Impossible<(), Error>;
+    type SerializeTuple = Self;
+    type SerializeTupleStruct = ser::Impossible<(), Error>;
+    type SerializeTupleVariant = ser::Impossible<(), Error>;
+    type SerializeMap = ser::Impossible<(), Error>;
+    type SerializeStruct = ser::Impossible<(), Error>;
+    type SerializeStructVariant = ser::Impossible<(), Error>;
+
+
+    #[inline]
+    fn serialize_bytes(self, _val: &[u8]) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received bytes"))
+    }
+
+    #[inline]
+    fn serialize_bool(self, _val: bool) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received bool"))
+    }
+
+    #[inline]
+    fn serialize_i8(self, _value: i8) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received i8"))
+    }
+
+    #[inline]
+    fn serialize_i16(self, _val: i16) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received i16"))
+    }
+
+    #[inline]
+    fn serialize_i32(self, _val: i32) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received i32"))
+    }
+
+    #[inline]
+    fn serialize_i64(self, _val: i64) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received i64"))
+    }
+
+    #[inline]
+    fn serialize_u8(self, _val: u8) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received u8"))
+    }
+
+    #[inline]
+    fn serialize_u16(self, _val: u16) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received u16"))
+    }
+
+    #[inline]
+    fn serialize_u32(self, _val: u32) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received u32"))
+    }
+
+    #[inline]
+    fn serialize_u64(self, _val: u64) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received u64"))
+    }
+
+    #[inline]
+    fn serialize_f32(self, _val: f32) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received f32"))
+    }
+
+    #[inline]
+    fn serialize_f64(self, _val: f64) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received f64"))
+    }
+
+    #[inline]
+    fn serialize_char(self, _val: char) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received char"))
+    }
+
+    #[inline]
+    fn serialize_str(self, _val: &str) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received str"))
+    }
+
+    #[inline]
+    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received unit"))
+    }
+
+    #[inline]
+    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received unit_struct"))
+    }
+
+    #[inline]
+    fn serialize_unit_variant(self, _name: &'static str, _idx: u32, _variant: &'static str) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received unit_variant"))
+    }
+
+    #[inline]
+    fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, _value: &T) -> Result<Self::Ok, Self::Error>
+        where T: Serialize
+    {
+        Err(<Error as ser::Error>::custom("expected tuple, received newtype_struct"))
+    }
+
+    fn serialize_newtype_variant<T: ?Sized>(self, _name: &'static str, _idx: u32, _variant: &'static str, _value: &T) -> Result<Self::Ok, Self::Error>
+        where T: Serialize
+    {
+        Err(<Error as ser::Error>::custom("expected tuple, received newtype_variant"))
+    }
+
+    #[inline]
+    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received none"))
+    }
+
+    #[inline]
+    fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok, Self::Error>
+        where T: Serialize
+    {
+        Err(<Error as ser::Error>::custom("expected tuple, received some"))
+    }
+
+    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received seq"))
+    }
+
+    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Error> {
+        // FIXME check len
+        self.fields_se = Some(ExtFieldSerializer::new());
+
+        Ok(self)
+    }
+
+    fn serialize_tuple_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeTupleStruct, Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received tuple_struct"))
+    }
+
+    fn serialize_tuple_variant(self, _name: &'static str, _idx: u32, _variant: &'static str, _len: usize) -> Result<Self::SerializeTupleVariant, Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received tuple_variant"))
+    }
+
+    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received map"))
+    }
+
+    fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct, Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received struct"))
+    }
+
+    fn serialize_struct_variant(self, _name: &'static str, _idx: u32, _variant: &'static str, _len: usize) -> Result<Self::SerializeStructVariant, Error> {
+        Err(<Error as ser::Error>::custom("expected tuple, received struct_variant"))
+    }
+}
+
+impl SerializeTuple for &mut ExtSerializer {
+    type Ok = ();
+    type Error = Error;
+
+    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+        where T: Serialize
+    {
+        match self.fields_se {
+            Some(ref mut se) => value.serialize(&mut *se),
+            None => unreachable!()
+        }
+    }
+
+    fn end(self) -> Result<(), Error> {
+        Ok(())
+    }
+}
+
+pub struct ExtFieldSerializer {
+    tag: Option<i8>,
+    binary: Option<Vec<u8>>,
+}
+
+impl ser::Serializer for &mut ExtFieldSerializer {
+    type Ok = ();
+    type Error = Error;
+
+    type SerializeSeq = ser::Impossible<(), Error>;
+    type SerializeTuple = ser::Impossible<(), Error>;
+    type SerializeTupleStruct = ser::Impossible<(), Error>;
+    type SerializeTupleVariant = ser::Impossible<(), Error>;
+    type SerializeMap = ser::Impossible<(), Error>;
+    type SerializeStruct = ser::Impossible<(), Error>;
+    type SerializeStructVariant = ser::Impossible<(), Error>;
+
+    #[inline]
+    fn serialize_i8(self, value: i8) -> Result<Self::Ok, Self::Error> {
+        if self.tag.is_none() {
+            self.tag.replace(value);
+            Ok(())
+        } else {
+            Err(<Error as ser::Error>::custom("exptected i8 and bytes, received second i8"))
+        }
+    }
+
+    #[inline]
+    fn serialize_bytes(self, val: &[u8]) -> Result<Self::Ok, Self::Error> {
+        if self.binary.is_none() {
+            self.binary.replace(val.to_vec());
+
+            Ok(())
+        } else {
+            Err(<Error as ser::Error>::custom("expected i8 and bytes, received second bytes"))
+        }
+    }
+
+
+    #[inline]
+    fn serialize_bool(self, _val: bool) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received bool"))
+    }
+
+    #[inline]
+    fn serialize_i16(self, _val: i16) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received i16"))
+    }
+
+    #[inline]
+    fn serialize_i32(self, _val: i32) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received i32"))
+    }
+
+    #[inline]
+    fn serialize_i64(self, _val: i64) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received i64"))
+    }
+
+    #[inline]
+    fn serialize_u8(self, _val: u8) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received u8"))
+    }
+
+    #[inline]
+    fn serialize_u16(self, _val: u16) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received u16"))
+    }
+
+    #[inline]
+    fn serialize_u32(self, _val: u32) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received u32"))
+    }
+
+    #[inline]
+    fn serialize_u64(self, _val: u64) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received u64"))
+    }
+
+    #[inline]
+    fn serialize_f32(self, _val: f32) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received f32"))
+    }
+
+    #[inline]
+    fn serialize_f64(self, _val: f64) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received f64"))
+    }
+
+    #[inline]
+    fn serialize_char(self, _val: char) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received char"))
+    }
+
+    #[inline]
+    fn serialize_str(self, _val: &str) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received str"))
+    }
+
+    #[inline]
+    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received unit"))
+    }
+
+    #[inline]
+    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received unit_struct"))
+    }
+
+    #[inline]
+    fn serialize_unit_variant(self, _name: &'static str, _idx: u32, _variant: &'static str) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received unit_variant"))
+    }
+
+    #[inline]
+    fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, _value: &T) -> Result<Self::Ok, Self::Error>
+        where T: Serialize
+    {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received newtype_struct"))
+    }
+
+    fn serialize_newtype_variant<T: ?Sized>(self, _name: &'static str, _idx: u32, _variant: &'static str, _value: &T) -> Result<Self::Ok, Self::Error>
+        where T: Serialize
+    {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received newtype_variant"))
+    }
+
+    #[inline]
+    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received none"))
+    }
+
+    #[inline]
+    fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok, Self::Error>
+        where T: Serialize
+    {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received some"))
+    }
+
+    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received seq"))
+    }
+
+    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received tuple"))
+    }
+
+    fn serialize_tuple_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeTupleStruct, Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received tuple_struct"))
+    }
+
+    fn serialize_tuple_variant(self, _name: &'static str, _idx: u32, _variant: &'static str, _len: usize) -> Result<Self::SerializeTupleVariant, Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received tuple_variant"))
+    }
+
+    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received map"))
+    }
+
+    fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct, Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received struct"))
+    }
+
+    fn serialize_struct_variant(self, _name: &'static str, _idx: u32, _variant: &'static str, _len: usize) -> Result<Self::SerializeStructVariant, Error> {
+        Err(<Error as ser::Error>::custom("expected i8 and bytes, received struct_variant"))
+    }
+}
+
+
+impl ExtSerializer {
+    fn new() -> Self {
+        Self {
+            fields_se: None
+        }
+    }
+
+    fn value(self) -> Result<Value, Error> {
+        match self.fields_se {
+            Some(fields_se) => fields_se.value(),
+            None => Err(<Error as ser::Error>::custom("expected tuple, received nothing"))
+        }
+    }
+}
+
+impl ExtFieldSerializer {
+    fn new() -> Self {
+        Self {
+            tag: None,
+            binary: None
+        }
+    }
+
+    fn value(self) -> Result<Value, Error> {
+        match (self.tag, self.binary) {
+            (Some(tag), Some(binary)) => Ok(Value::Ext(tag, binary)),
+            (Some(_), None) => Err(<Error as ser::Error>::custom("expected i8 and bytes, received i8 only")),
+            (None, Some(_)) => Err(<Error as ser::Error>::custom("expected i8 and bytes, received bytes only")),
+            (None, None) => Err(<Error as ser::Error>::custom("expected i8 and bytes, received nothing")),
+        }
+    }
+}
+
 #[doc(hidden)]
 pub struct SerializeVec {
     vec: Vec<Value>,
diff --git a/rmpv/src/lib.rs b/rmpv/src/lib.rs
index 09caeba..3da4e6e 100644
--- a/rmpv/src/lib.rs
+++ b/rmpv/src/lib.rs
@@ -30,6 +30,21 @@ enum IntPriv {
     NegInt(i64),
 }
 
+/// Name of Serde newtype struct to Represent Msgpack's Ext
+/// Msgpack Ext: Ext(tag, binary)
+/// Serde data model: _ExtStruct((tag, binary))
+/// Example Serde impl for custom type:
+///
+/// ```ignore
+/// #[derive(Debug, PartialEq, Serialize, Deserialize)]
+/// #[serde(rename = "_ExtStruct")]
+/// struct ExtStruct((i8, serde_bytes::ByteBuf));
+///
+/// test_round(ExtStruct((2, serde_bytes::ByteBuf::from(vec![5]))),
+///            Value::Ext(2, vec![5]));
+/// ```
+pub const MSGPACK_EXT_STRUCT_NAME: &'static str = "_ExtStruct";
+
 /// Represents a MessagePack integer, whether signed or unsigned.
 ///
 /// A `Value` or `ValueRef` that contains integer can be constructed using `From` trait.


Test patch:
diff --git a/rmpv-tests/tests/de_ref.rs b/rmpv-tests/tests/de_ref.rs
index fd07a9d..fd67510 100644
--- a/rmpv-tests/tests/de_ref.rs
+++ b/rmpv-tests/tests/de_ref.rs
@@ -256,3 +256,48 @@ fn pass_from_slice() {
     assert_eq!(ValueRef::Array(vec![ValueRef::from("John"), ValueRef::from("Smith"), ValueRef::from(42)]),
         rmps::from_slice(&buf[..]).unwrap());
 }
+
+#[test]
+fn pass_from_ext() {
+    #[derive(Debug, PartialEq)]
+    struct ExtRefStruct<'a>(i8, &'a [u8]);
+
+    struct ExtRefStructVisitor;
+
+    impl<'de> serde::de::Deserialize<'de> for ExtRefStruct<'de> {
+        fn deserialize<D>(deserializer: D) -> Result<ExtRefStruct<'de>, D::Error>
+            where D: serde::Deserializer<'de>,
+        {
+            let visitor = ExtRefStructVisitor;
+            deserializer.deserialize_any(visitor)
+        }
+    }
+
+    impl<'de> serde::de::Visitor<'de> for ExtRefStructVisitor {
+        type Value = ExtRefStruct<'de>;
+
+        fn expecting(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
+            write!(fmt, "a sequence of tag & binary")
+        }
+
+        fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+            where D: serde::de::Deserializer<'de>,
+        {
+            deserializer.deserialize_tuple(2, self)
+        }
+
+        fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
+            where A: serde::de::SeqAccess<'de>
+        {
+            let tag: i8 = seq.next_element()?
+                .ok_or_else(|| serde::de::Error::invalid_length(0, &self))?;
+            let data: &[u8] = seq.next_element()?
+                .ok_or_else(|| serde::de::Error::invalid_length(1, &self))?;
+
+            Ok(ExtRefStruct(tag, data))
+        }
+    }
+
+    assert_eq!(ExtRefStruct(42, &[255]),
+        deserialize_from(ValueRef::Ext(42, &[255])).unwrap());
+}
diff --git a/rmpv-tests/tests/decode.rs b/rmpv-tests/tests/decode.rs
index 9f6f981..d27c71d 100644
--- a/rmpv-tests/tests/decode.rs
+++ b/rmpv-tests/tests/decode.rs
@@ -240,3 +240,49 @@ fn pass_enum_from_value() {
     assert_eq!(Enum::Struct { name: "John".into(), age: 42 },
         from_value(Value::Array(vec![Value::from(3), Value::Array(vec![Value::from("John"), Value::from(42)])])).unwrap());
 }
+
+#[test]
+fn pass_tuple_struct_from_ext() {
+    #[derive(Debug, PartialEq)]
+    struct ExtStruct(i8, Vec<u8>);
+
+    struct ExtStructVisitor;
+
+    impl<'de> serde::de::Visitor<'de> for ExtStructVisitor {
+        type Value = ExtStruct;
+
+        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
+            formatter.write_str("msgpack ext")
+        }
+
+        fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+            where D: serde::de::Deserializer<'de>,
+        {
+            deserializer.deserialize_tuple(2, self)
+        }
+
+        fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
+            where A: serde::de::SeqAccess<'de>,
+        {
+
+            let tag = seq.next_element()?
+                .ok_or_else(|| serde::de::Error::invalid_length(0, &self))?;
+            let bytes: serde_bytes::ByteBuf = seq.next_element()?
+                .ok_or_else(|| serde::de::Error::invalid_length(1, &self))?;
+
+            Ok(ExtStruct(tag, bytes.to_vec()))
+        }
+    }
+
+    impl<'de> serde::de::Deserialize<'de> for ExtStruct {
+        fn deserialize<D>(deserializer: D) -> Result<ExtStruct, D::Error>
+        where
+            D: serde::Deserializer<'de>,
+        {
+            deserializer.deserialize_any(ExtStructVisitor)
+        }
+    }
+
+    assert_eq!(ExtStruct(42, vec![255]),
+        from_value(Value::Ext(42, vec![255])).unwrap());
+}
diff --git a/rmpv-tests/tests/encode.rs b/rmpv-tests/tests/encode.rs
index 7967dba..f549812 100644
--- a/rmpv-tests/tests/encode.rs
+++ b/rmpv-tests/tests/encode.rs
@@ -246,3 +246,15 @@ fn pass_enum_to_value() {
     assert_eq!(Value::Array(vec![Value::from(3), Value::Array(vec![Value::from("John"), Value::from(42)])]),
         to_value(Enum::Struct { name: "John".into(), age: 42 }).unwrap());
 }
+
+#[test]
+fn pass_ext_struct_to_value() {
+    use serde_bytes::ByteBuf;
+
+    #[derive(Debug, PartialEq, Serialize)]
+    #[serde(rename = "_ExtStruct")]
+    struct ExtStruct((i8, ByteBuf));
+
+    assert_eq!(Value::Ext(5, vec![10]),
+        to_value(ExtStruct((5, ByteBuf::from(vec![10])))).unwrap());
+}
diff --git a/rmpv-tests/tests/round.rs b/rmpv-tests/tests/round.rs
index 0f3ce25..7a2111f 100644
--- a/rmpv-tests/tests/round.rs
+++ b/rmpv-tests/tests/round.rs
@@ -109,3 +109,92 @@ fn pass_newtype_struct() {
 
     test_round(Newtype("John".into()), Value::from("John"));
 }
+
+#[test]
+fn pass_ext_struct() {
+    #[derive(Debug, PartialEq)]
+    enum ExtStruct {
+        One(u8),
+        Two(u8)
+    }
+
+    struct ExtStructVisitor;
+
+    use serde::de::Unexpected;
+    use serde_bytes::ByteBuf;
+
+    impl Serialize for ExtStruct {
+        fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
+            where S: serde::ser::Serializer
+        {
+            let value = match self {
+                ExtStruct::One(data) => {
+                    let tag = 1 as i8;
+                    let byte_buf = ByteBuf::from(vec![*data]);
+
+                    (tag, byte_buf)
+                }
+                ExtStruct::Two(data) => {
+                    let tag = 2 as i8;
+                    let byte_buf = ByteBuf::from(vec![*data]);
+
+                    (tag, byte_buf)
+                }
+            };
+            s.serialize_newtype_struct(rmps::MSGPACK_EXT_STRUCT_NAME, &value)
+        }
+    }
+
+    impl<'de> serde::de::Visitor<'de> for ExtStructVisitor {
+        type Value = ExtStruct;
+
+        fn expecting(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
+            write!(fmt, "a sequence of tag & binary")
+        }
+
+        fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+            where D: serde::de::Deserializer<'de>,
+        {
+            deserializer.deserialize_tuple(2, self)
+        }
+
+        fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
+            where A: serde::de::SeqAccess<'de>
+        {
+            let tag: i8 = seq.next_element()?
+                .ok_or_else(|| serde::de::Error::invalid_length(0, &self))?;
+            let data: ByteBuf = seq.next_element()?
+                .ok_or_else(|| serde::de::Error::invalid_length(1, &self))?;
+
+            if tag == 1 {
+                Ok(ExtStruct::One(data[0]))
+            } else if tag == 2 {
+                Ok(ExtStruct::Two(data[0]))
+            } else {
+                let unexp = Unexpected::Signed(tag as i64);
+                Err(serde::de::Error::invalid_value(unexp, &self))
+            }
+        }
+    }
+
+    impl<'de> serde::de::Deserialize<'de> for ExtStruct {
+        fn deserialize<D>(deserializer: D) -> Result<ExtStruct, D::Error>
+            where D: serde::Deserializer<'de>,
+        {
+            let visitor = ExtStructVisitor;
+            deserializer.deserialize_newtype_struct(rmps::MSGPACK_EXT_STRUCT_NAME, visitor)
+        }
+    }
+
+    test_round(ExtStruct::One(5), Value::Ext(1, vec![5]));
+}
+
+#[test]
+fn pass_derive_serde_ext_struct() {
+    #[derive(Debug, PartialEq, Serialize, Deserialize)]
+    #[serde(rename = "_ExtStruct")]
+    struct ExtStruct((i8, serde_bytes::ByteBuf));
+
+    test_round(ExtStruct((2, serde_bytes::ByteBuf::from(vec![5]))),
+               Value::Ext(2, vec![5]));
+}