Repository: pyfisch/cbor (rust)

Issue:
Serde 0.8!
Serde v0.8 is now out. We should update cbor to work with it.

Pull request:
Update to Serde 0.8
Closes #16 

Patch:
diff --git a/Cargo.toml b/Cargo.toml
index c628004..f83f222 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,8 +11,8 @@ keywords = ["serde", "cbor", "serialization"]
 
 [dependencies]
 byteorder = "0.5"
-serde = "0.7.0"
-serde_macros = { version="0.7.0", optional=true }
+serde = "0.8.0"
+serde_macros = { version="0.8.0", optional=true }
 
 [features]
 unstable = ["serde_macros"]
diff --git a/src/de.rs b/src/de.rs
index b1cb5c7..ac29709 100644
--- a/src/de.rs
+++ b/src/de.rs
@@ -10,6 +10,15 @@ use super::error::{Error, Result};
 
 const MAX_SEQ_LEN: u64 = 524288;
 
+macro_rules! forward_deserialize {
+    ($($name:ident;)*) => {
+        $(#[inline]
+        fn $name<V: Visitor>(&mut self, visitor: V) -> Result<V::Value> {
+            self.deserialize(visitor)
+        })*
+    }
+}
+
 /// A structure that deserializes CBOR into Rust values.
 pub struct Deserializer<R: Read> {
     reader: R,
@@ -191,7 +200,30 @@ impl<R: Read> Deserializer<R> {
 
 impl<R: Read> de::Deserializer for Deserializer<R> {
     type Error = Error;
-
+    forward_deserialize!(
+        deserialize_bool;
+        deserialize_isize;
+        deserialize_i8;
+        deserialize_i16;
+        deserialize_i32;
+        deserialize_i64;
+        deserialize_usize;
+        deserialize_u8;
+        deserialize_u16;
+        deserialize_u32;
+        deserialize_u64;
+        deserialize_f32;
+        deserialize_f64;
+        deserialize_char;
+        deserialize_str;
+        deserialize_string;
+        deserialize_unit;
+        deserialize_seq;
+        deserialize_bytes;
+        deserialize_map;
+        deserialize_struct_field;
+        deserialize_ignored_any;
+    );
     #[inline]
     fn deserialize<V: Visitor>(&mut self, visitor: V) -> Result<V::Value> {
         if self.first.is_none() {
@@ -239,6 +271,26 @@ impl<R: Read> de::Deserializer for Deserializer<R> {
         };
         visitor.visit(CompositeVisitor::new(self, items))
     }
+    fn deserialize_seq_fixed_size<V>(&mut self, _len: usize, visitor: V) -> Result<V::Value>
+            where V: Visitor {
+        self.deserialize(visitor)
+    }
+    fn deserialize_unit_struct<V>(&mut self, _name: &'static str, visitor: V) -> Result<V::Value>
+            where V: Visitor {
+        self.deserialize(visitor)
+    }
+    fn deserialize_struct<V>(&mut self, _name: &'static str, _fields: &'static [&'static str],
+            visitor: V) -> Result<V::Value> where V: Visitor {
+        self.deserialize(visitor)
+    }
+    fn deserialize_tuple_struct<V>(&mut self, _name: &'static str, _len: usize, visitor: V)
+            -> Result<V::Value> where V: Visitor {
+        self.deserialize(visitor)
+    }
+    fn deserialize_tuple<V>(&mut self, _len: usize, visitor: V)
+            -> Result<V::Value> where V: Visitor {
+        self.deserialize(visitor)
+    }
 }
 
 impl<R: Read> Read for Deserializer<R> {
diff --git a/src/lib.rs b/src/lib.rs
index e9ce150..a679a4f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -119,7 +119,7 @@ extern crate serde;
 
 pub use de::{from_slice, from_reader};
 pub use error::{Error, Result};
-pub use ser::{to_vec, to_writer, to_vec_sd, to_writer_sd};
+pub use ser::{to_vec};
 pub use value::{Value, ObjectKey};
 
 pub mod de;
diff --git a/src/ser.rs b/src/ser.rs
index e52a945..290a629 100644
--- a/src/ser.rs
+++ b/src/ser.rs
@@ -3,242 +3,530 @@
 use std::io::Write;
 
 use byteorder::{BigEndian, WriteBytesExt};
-use serde::ser::{self, Serialize, SeqVisitor, MapVisitor};
+use serde::ser::{self, Serialize};
 
-use super::error::{Error, Result};
+use {Error, Result};
 
 /// A structure for serializing Rust values into CBOR.
 pub struct Serializer<W: Write> {
     writer: W,
+    packed: bool,
 }
 
 impl<W: Write> Serializer<W> {
     /// Creates a new CBOR serializer.
-    #[inline]
     pub fn new(writer: W) -> Serializer<W> {
-        Serializer { writer: writer }
+        Serializer {
+            writer: writer,
+            packed: false,
+        }
+    }
+    
+    /// Creates a new packed CBOR serializer.
+    ///
+    /// In packed mode all struct field names and enum variant names
+    /// are not serialized instead the index position of the field
+    /// is used.
+    pub fn packed(writer: W) -> Serializer<W> {
+        Serializer {
+            writer: writer,
+            packed: true
+        }
+    }
+    
+    /// Writes the CBOR self-describe tag to the stream.
+    ///
+    /// Tagging allows a decoder to distinguish different file formats
+    /// based on their content without other information.
+    pub fn self_describe(&mut self) -> Result<()> {
+        try!(self.writer.write_u8(6 << 5 | 25));
+        try!(self.writer.write_u16::<BigEndian>(55799));
+        Ok(())
+    }
+    
+    #[inline]
+    fn write_type_u8(&mut self, major: u8, additional: u8) -> Result<()> {
+        if additional > 23 {
+            try!(self.writer.write_u8(major << 5 | 24));
+            try!(self.writer.write_u8(additional));
+        } else {
+            try!(self.writer.write_u8(major << 5 | additional));
+        }
+        Ok(())
+    }
+    
+    #[inline]
+    fn write_type_u16(&mut self, major: u8, additional: u16) -> Result<()> {
+        if additional > ::std::u8::MAX as u16 {
+            try!(self.writer.write_u8(major << 5 | 25));
+            try!(self.writer.write_u16::<BigEndian>(additional));
+        } else {
+            try!(self.write_type_u8(major, additional as u8));
+        }
+        Ok(())
+    }
+    
+    #[inline]
+    fn write_type_u32(&mut self, major: u8, additional: u32) -> Result<()> {
+        if additional > ::std::u16::MAX as u32 {
+            try!(self.writer.write_u8(major << 5 | 26));
+            try!(self.writer.write_u32::<BigEndian>(additional));
+        } else {
+            try!(self.write_type_u16(major, additional as u16));
+        }
+        Ok(())
     }
 
     #[inline]
-    fn compact_type(&mut self, major_type: u8, v: u64) -> Result<()> {
-        if v <= 23 {
-            self.writer.write_u8(major_type << 5 | v as u8)
-        } else if v <= ::std::u8::MAX as u64 {
-            self.writer
-                .write_u8(major_type << 5 | 0x18)
-                .and_then(|()| self.writer.write_u8(v as u8))
-        } else if v <= ::std::u16::MAX as u64 {
-            self.writer
-                .write_u8(major_type << 5 | 0x19)
-                .and_then(|()| self.writer.write_u16::<BigEndian>(v as u16))
-        } else if v <= ::std::u32::MAX as u64 {
-            self.writer
-                .write_u8(major_type << 5 | 0x1a)
-                .and_then(|()| self.writer.write_u32::<BigEndian>(v as u32))
+    fn write_type_u64(&mut self, major: u8, additional: u64) -> Result<()> {
+        if additional > ::std::u32::MAX as u64 {
+            try!(self.writer.write_u8(major << 5 | 27));
+            try!(self.writer.write_u64::<BigEndian>(additional));
         } else {
-            self.writer
-                .write_u8(major_type << 5 | 0x1b)
-                .and_then(|()| self.writer.write_u64::<BigEndian>(v))
+            try!(self.write_type_u32(major, additional as u32));
         }
-        .map_err(From::from)
+        Ok(())
     }
+    
+    #[inline]
+    fn write_collection_start(&mut self, major: u8, len: Option<usize>) -> Result<CollectionState> {
+        if let Some(len) = len {
+            try!(self.write_type_u64(major, len as u64));
+            Ok(CollectionState::Fixed)
+        } else {
+            try!(self.writer.write_u8(major << 5 | 31));
+            Ok(CollectionState::Indefinite)
+        }
+    }
+
+    #[inline]
+    fn write_collection_end(&mut self, state: CollectionState) -> Result<()> {
+        match state {
+            CollectionState::Fixed => Ok(()),
+            CollectionState::Indefinite => self.writer.write_u8(0xff).map_err(From::from),
+        }
+    }
+}
+
+/// A collection like an array or map may have a fixed or indefinite length.
+pub enum CollectionState {
+    /// Fixed collections end after all elements were serialized.
+    Fixed,
+    /// Indefinite collections are terminated by a stop code after the last element.
+    Indefinite,
+}
+
+/// Structs are record types. They are serialized as key value pairs.
+///
+/// The keys are either strings or indexes denoting the position in the struct.
+/// In `packed` serialization indexes are used to preserve space.
+///
+/// To keep track of the current index a counter is stored in this state.
+pub struct StructState {
+    counter: usize
 }
 
 impl<W: Write> ser::Serializer for Serializer<W> {
     type Error = Error;
-
+    type SeqState = CollectionState;
+    type TupleState = ();
+    type TupleStructState = ();
+    type TupleVariantState = ();
+    type MapState = CollectionState;
+    type StructState = StructState;
+    type StructVariantState = StructState;
+    
     #[inline]
     fn serialize_bool(&mut self, v: bool) -> Result<()> {
-        self.writer
-            .write_u8(if v {
-                0xf5
-            } else {
-                0xf4
-            })
-            .map_err(From::from)
+        self.writer.write_u8(
+            match v {
+                false => 7 << 5 | 20,
+                true => 7 << 5 | 21,
+            }).map_err(From::from)
     }
+    
+    #[inline]
+    fn serialize_isize(&mut self, v: isize) -> Result<()> {
+        self.serialize_i64(v as i64)
+    }
+    
+    #[inline]
+    fn serialize_i8(&mut self, v: i8) -> Result<()> {
+        if v < 0 {
+            self.write_type_u8(1, -(v + 1) as u8)
+        } else {
+            self.serialize_u8(v as u8)
+        }
+    }
+    
+    #[inline]
+    fn serialize_i16(&mut self, v: i16) -> Result<()> {
+        if v < 0 {
+            self.write_type_u16(1, -(v + 1) as u16)
+        } else {
+            self.serialize_u16(v as u16)
+        }
+    }
+    
+    #[inline]
+    fn serialize_i32(&mut self, v: i32) -> Result<()> {
+        if v < 0 {
+            self.write_type_u32(1, -(v + 1) as u32)
+        } else {
+            self.serialize_u32(v as u32)
+        }
+    }
+    
     #[inline]
     fn serialize_i64(&mut self, v: i64) -> Result<()> {
-        if v >= 0 {
-            self.serialize_u64(v as u64)
+        if v < 0 {
+            self.write_type_u64(1, -(v + 1) as u64)
         } else {
-            self.compact_type(1, (-v) as u64 - 1)
+            self.serialize_u64(v as u64)
         }
     }
+    
+    #[inline]
+    fn serialize_usize(&mut self, v: usize) -> Result<()> {
+        self.serialize_u64(v as u64)
+    }
+    
+    #[inline]
+    fn serialize_u8(&mut self, v: u8) -> Result<()> {
+        self.write_type_u8(0, v)
+    }
+    
+    #[inline]
+    fn serialize_u16(&mut self, v: u16) -> Result<()> {
+        self.write_type_u16(0, v)
+    }
+    
+    #[inline]
+    fn serialize_u32(&mut self, v: u32) -> Result<()> {
+        self.write_type_u32(0, v)
+    }
+    
     #[inline]
     fn serialize_u64(&mut self, v: u64) -> Result<()> {
-        self.compact_type(0, v)
+        self.write_type_u64(0, v)
     }
+    
+    #[inline]
+    fn serialize_f32(&mut self, v: f32) -> Result<()> {
+        // TODO: Encode to f16
+        if v.is_infinite() && v.is_sign_positive() {
+            self.writer.write_all(&[0xf9, 0x7c, 0x00])
+        } else if v.is_infinite() && v.is_sign_negative() {
+            self.writer.write_all(&[0xf9, 0xfc, 0x00])
+        } else if v.is_nan() {
+            self.writer.write_all(&[0xf9, 0x7e, 0x00])
+        } else {
+            self.writer
+                .write_u8(7 << 5 | 26)
+                .and_then(|()| self.writer.write_f32::<BigEndian>(v))
+        }.map_err(From::from)
+    }
+    
     #[inline]
     fn serialize_f64(&mut self, v: f64) -> Result<()> {
         // TODO: Encode to f16
         if v.is_infinite() && v.is_sign_positive() {
-            self.writer.write_all(&[0xf9, 0x7c, 0x00]).map_err(From::from)
+            self.writer.write_all(&[0xf9, 0x7c, 0x00])
         } else if v.is_infinite() && v.is_sign_negative() {
-            self.writer.write_all(&[0xf9, 0xfc, 0x00]).map_err(From::from)
+            self.writer.write_all(&[0xf9, 0xfc, 0x00])
         } else if v.is_nan() {
-            self.writer.write_all(&[0xf9, 0x7e, 0x00]).map_err(From::from)
+            self.writer.write_all(&[0xf9, 0x7e, 0x00])
         } else if v as f32 as f64 == v {
             self.writer
-                .write_u8(0xfa)
+                .write_u8(7 << 5 | 26)
                 .and_then(|()| self.writer.write_f32::<BigEndian>(v as f32))
-                .map_err(From::from)
         } else {
             self.writer
-                .write_u8(0xfb)
+                .write_u8(7 << 5 | 27)
                 .and_then(|()| self.writer.write_f64::<BigEndian>(v))
-                .map_err(From::from)
-        }
+        }.map_err(From::from)
+    }
+    
+    #[inline]
+    fn serialize_char(&mut self, v: char) -> Result<()> {
+        // TODO: Avoid allocation. rust-lang/rust#27784
+        let mut s = String::new();
+        s.push(v);
+        self.serialize_str(s.as_str())
     }
+    
     #[inline]
     fn serialize_str(&mut self, value: &str) -> Result<()> {
-        self.compact_type(3, value.len() as u64)
-            .and_then(|()| self.writer.write_all(value.as_bytes()).map_err(From::from))
+        try!(self.write_type_u64(3, value.len() as u64));
+        self.writer.write_all(value.as_bytes()).map_err(From::from)
+    }
+    
+    #[inline]
+    fn serialize_bytes(&mut self, value: &[u8]) -> Result<()> {
+        try!(self.write_type_u64(2, value.len() as u64));
+        self.writer.write_all(value).map_err(From::from)
     }
+    
     #[inline]
     fn serialize_unit(&mut self) -> Result<()> {
-        self.writer.write_u8(0xf6).map_err(From::from)
+        self.writer.write_u8(7 << 5 | 22).map_err(From::from)
+    }
+    
+    #[inline]
+    fn serialize_unit_struct(&mut self, _name: &'static str) -> Result<()> {
+        self.serialize_unit()
+    }
+    
+    #[inline]
+    fn serialize_unit_variant(&mut self,
+                              _name: &'static str,
+                              variant_index: usize,
+                              variant: &'static str) -> Result<()> {
+        if !self.packed {
+            self.serialize_str(variant)
+        } else {
+            self.serialize_usize(variant_index)
+        }
+    }
+    
+    #[inline]
+    fn serialize_newtype_struct<T: Serialize>(&mut self, 
+                                              _name: &'static str,
+                                              value: T) -> Result<()> {
+        value.serialize(self)
+    }
+    
+    #[inline]
+    fn serialize_newtype_variant<T: Serialize>(&mut self,
+                                               name: &'static str,
+                                               variant_index: usize,
+                                               variant: &'static str,
+                                               value: T) -> Result<()> {
+        try!(self.writer.write_u8(4 << 5 | 2));
+        try!(self.serialize_unit_variant(name, variant_index, variant));
+        value.serialize(self)
     }
+    
     #[inline]
     fn serialize_none(&mut self) -> Result<()> {
         self.serialize_unit()
     }
+    
     #[inline]
-    fn serialize_some<V>(&mut self, value: V) -> Result<()>
-        where V: Serialize
-    {
+    fn serialize_some<T: Serialize>(&mut self, value: T) -> Result<()> {
         value.serialize(self)
     }
+    
     #[inline]
-    fn serialize_seq<V>(&mut self, mut visitor: V) -> Result<()>
-        where V: SeqVisitor
-    {
-        if let Some(len) = visitor.len() {
-            try!(self.compact_type(4, len as u64));
-            while let Some(()) = try!(visitor.visit(self)) {
-            }
-            Ok(())
-        } else {
-            try!(self.writer.write_u8(0x9f));
-            while let Some(()) = try!(visitor.visit(self)) {
-            }
-            self.writer.write_u8(0xff).map_err(From::from)
-        }
+    fn serialize_seq(&mut self, len: Option<usize>) -> Result<CollectionState> {
+        self.write_collection_start(4, len)
     }
+    
     #[inline]
-    fn serialize_seq_elt<T>(&mut self, value: T) -> Result<()>
-        where T: Serialize
-    {
+    fn serialize_seq_elt<T: Serialize>(&mut self,
+                                       _state: &mut Self::SeqState,
+                                       value: T) -> Result<()> {
         value.serialize(self)
     }
+    
     #[inline]
-    fn serialize_map<V>(&mut self, mut visitor: V) -> Result<()>
-        where V: MapVisitor
-    {
-        if let Some(len) = visitor.len() {
-            try!(self.compact_type(5, len as u64));
-            while let Some(()) = try!(visitor.visit(self)) {
-            }
-            Ok(())
-        } else {
-            try!(self.writer.write_u8(0xbf));
-            while let Some(()) = try!(visitor.visit(self)) {
-            }
-            self.writer.write_u8(0xff).map_err(From::from)
-        }
+    fn serialize_seq_end(&mut self, state: CollectionState) -> Result<()> {
+        self.write_collection_end(state)
     }
+    
     #[inline]
-    fn serialize_map_elt<K, V>(&mut self, key: K, value: V) -> Result<()>
-        where K: Serialize,
-              V: Serialize
-    {
-        key.serialize(self).and_then(|()| value.serialize(self))
+    fn serialize_seq_fixed_size(&mut self, size: usize) -> Result<CollectionState> {
+        self.serialize_seq(Some(size))
     }
+    
     #[inline]
-    fn serialize_unit_variant(&mut self, _name: &'static str,
-                              _variant_index: usize, 
-                              variant: &'static str) -> Result<()> {
-        self.serialize_str(variant)
+    fn serialize_tuple(&mut self, len: usize) -> Result<()> {
+        self.write_type_u64(4, len as u64)
+    }
+
+    #[inline]
+    fn serialize_tuple_elt<T: Serialize>(&mut self,
+                                         _state: &mut (),
+                                         value: T) -> Result<()> {
+        value.serialize(self)
+    }
+
+    #[inline]
+    fn serialize_tuple_end(&mut self, _state: ()) -> Result<()> {
+        Ok(())
+    }
+
+    #[inline]
+    fn serialize_tuple_struct(&mut self, _name: &'static str, len: usize) -> Result<()> {
+        self.serialize_tuple(len)
+    }
+
+    #[inline]
+    fn serialize_tuple_struct_elt<T: Serialize>(&mut self,
+                                         _state: &mut (),
+                                         value: T) -> Result<()> {
+        value.serialize(self)
     }
+    
     #[inline]
-    fn serialize_newtype_struct<T>(&mut self,
-                                   _name: &'static str,
-                                   value: T) -> Result<()>
-        where T: ser::Serialize,
-    {
+    fn serialize_tuple_struct_end(&mut self, _state: ()) -> Result<()> {
+        Ok(())
+    }
+    
+    #[inline]
+    fn serialize_tuple_variant(&mut self,
+                               name: &'static str,
+                               variant_index: usize,
+                               variant: &'static str,
+                               len: usize) -> Result<()> {
+        try!(self.write_type_u64(4, (len + 1) as u64));
+        self.serialize_unit_variant(name, variant_index, variant)
+    }
+    
+    #[inline]
+    fn serialize_tuple_variant_elt<T: Serialize>(&mut self, _state: &mut (), value: T) -> Result<()> {
         value.serialize(self)
     }
+    
+    #[inline]
+    fn serialize_tuple_variant_end(&mut self, _state: ()) -> Result<()> {
+        Ok(())
+    }
+    
     #[inline]
-    fn serialize_newtype_variant<T>(&mut self, _name: &'static str,
-            _variant_index: usize, variant: &'static str, value: T) 
-            -> Result<()> where T: Serialize {
-        try!(self.writer.write_u8(0x82));
-        try!(self.serialize_str(variant));
+    fn serialize_map(&mut self, len: Option<usize>) -> Result<Self::MapState> {
+        self.write_collection_start(5, len)
+    }
+
+    #[inline]
+    fn serialize_map_key<T: Serialize>(&mut self,
+                                       _state: &mut CollectionState,
+                                       key: T) -> Result<()> {
+        key.serialize(self)
+    }
+
+    #[inline]
+    fn serialize_map_value<T: Serialize>(&mut self,
+                                         _state: &mut CollectionState,
+                                         value: T) -> Result<()> {
         value.serialize(self)
     }
+
+    #[inline]
+    fn serialize_map_end(&mut self, state: CollectionState) -> Result<()> {
+        self.write_collection_end(state)
+    }
+    
     #[inline]
-    fn serialize_tuple_variant<V>(&mut self, _name: &'static str,
-            _variant_index: usize, variant: &'static str, mut visitor: V)
-            -> Result<()> where V: SeqVisitor {
-        if let Some(len) = visitor.len() {
-            try!(self.compact_type(4, len as u64 + 1));
-            try!(self.serialize_str(variant));
-            while let Some(()) = try!(visitor.visit(self)) {
-            }
-            Ok(())
+    fn serialize_struct(&mut self, _name: &'static str, len: usize) -> Result<StructState> {
+        try!(self.write_type_u64(5, len as u64));
+        Ok(StructState {
+            counter: 0
+        })
+    }
+    
+    #[inline]
+    fn serialize_struct_elt<V: Serialize>(&mut self,
+                                          state: &mut StructState,
+                                          key: &'static str,
+                                          value: V) -> Result<()> {
+        if !self.packed {
+            try!(self.serialize_str(key));
         } else {
-            try!(self.writer.write_u8(0x9f));
-            try!(self.serialize_str(variant));
-            while let Some(()) = try!(visitor.visit(self)) {
-            }
-            self.writer.write_u8(0xff).map_err(From::from)
+            try!(self.serialize_usize(state.counter));
         }
+        try!(value.serialize(self));
+        state.counter += 1;
+        Ok(())
     }
+    
     #[inline]
-    fn serialize_tuple_variant_elt<T>(&mut self, value: T) -> Result<()>
-            where T: Serialize {
-        value.serialize(self)
+    fn serialize_struct_end(&mut self, _state: StructState) -> Result<()> {
+        Ok(())
     }
+    
     #[inline]
-    fn serialize_struct_variant<V: MapVisitor>(&mut self,
-            _name: &'static str,
-            _variant_index: usize,
-            variant: &'static str,
-            visitor: V)
-             -> Result<()> {
-        try!(self.writer.write_u8(0x82));
-        try!(self.serialize_str(variant));
-        self.serialize_map(visitor)
+    fn serialize_struct_variant(&mut self,
+                                name: &'static str,
+                                variant_index: usize,
+                                variant: &'static str,
+                                len: usize) -> Result<StructState> {
+        try!(self.writer.write_u8(4 << 5 | 2));
+        try!(self.serialize_unit_variant(name, variant_index, variant));
+        try!(self.write_type_u64(5, len as u64));
+        Ok(StructState {
+            counter: 0
+        })
     }
+
+    #[inline]
+    fn serialize_struct_variant_elt<V: Serialize>(&mut self,
+                                                  state: &mut StructState,
+                                                  key: &'static str,
+                                                  value: V) -> Result<()> {
+        if !self.packed {
+            try!(self.serialize_str(key));
+        } else {
+            try!(self.serialize_usize(state.counter));
+        }
+        try!(value.serialize(self));
+        state.counter += 1;
+        Ok(())
+    }
+    
+    #[inline]
+    fn serialize_struct_variant_end(&mut self, _state: StructState) -> Result<()> {
+        Ok(())
+    }
+}
+
+/// Serializes a value to a writer.
+pub fn to_writer<W: Write, T: Serialize>(mut writer: &mut W, value: &T) -> Result<()> {
+    value.serialize(&mut Serializer::new(&mut writer))
+}
+
+/// Serializes a value to a writer and add a CBOR self-describe tag.
+pub fn to_writer_sd<W: Write, T: Serialize>(mut writer: &mut W, value: &T) -> Result<()> {
+    let mut ser = Serializer::new(&mut writer);
+    try!(ser.self_describe());
+    value.serialize(&mut ser)
 }
 
-/// Encodes the specified struct into a writer.
-#[inline]
-pub fn to_writer<W: Write, T: ser::Serialize>(writer: &mut W, value: &T) -> Result<()> {
-    let mut ser = Serializer::new(writer);
-    value.serialize(&mut ser).map_err(From::from)
+/// Serializes a value without names to a writer.
+pub fn to_writer_packed<W: Write, T: Serialize>(mut writer: &mut W, value: &T) -> Result<()> {
+    value.serialize(&mut Serializer::packed(&mut writer))
 }
 
-/// Encodes the specified struct into a writer with a leading self-describe tag.
-#[inline]
-pub fn to_writer_sd<W: Write, T: ser::Serialize>(writer: &mut W, value: &T) -> Result<()> {
-    try!(writer.write_all(&[0xd9, 0xd9, 0xf7]));
-    let mut ser = Serializer::new(writer);
-    value.serialize(&mut ser).map_err(From::from)
+/// Serializes a value without names to a writer and add a CBOR self-describe tag.
+pub fn to_writer_packed_sd<W: Write, T: Serialize>(mut writer: &mut W, value: &T) -> Result<()> {
+    let mut ser = Serializer::packed(&mut writer);
+    try!(ser.self_describe());
+    value.serialize(&mut ser)
 }
 
-/// Encodes the specified struct into a `Vec<u8>`.
-#[inline]
+/// Serializes a value to a vector.
 pub fn to_vec<T: Serialize>(value: &T) -> Result<Vec<u8>> {
-    let mut writer = Vec::new();
-    try!(to_writer(&mut writer, value));
-    Ok(writer)
+    let mut vec = Vec::new();
+    try!(to_writer(&mut vec, value));
+    Ok(vec)
 }
 
-/// Encodes the specified struct into a `Vec<u8>` with a leading self-describe tag.
-#[inline]
+/// Serializes a value to a vector and add a CBOR self-describe tag.
 pub fn to_vec_sd<T: Serialize>(value: &T) -> Result<Vec<u8>> {
-    let mut writer = Vec::new();
-    try!(to_writer_sd(&mut writer, value));
-    Ok(writer)
+    let mut vec = Vec::new();
+    try!(to_writer_sd(&mut vec, value));
+    Ok(vec)
+}
+
+/// Serializes a value without names to a vector.
+pub fn to_vec_packed<T: Serialize>(value: &T) -> Result<Vec<u8>> {
+    let mut vec = Vec::new();
+    try!(to_writer_packed(&mut vec, value));
+    Ok(vec)
+}
+/// Serializes a value without names to a vector and add a CBOR self-describe tag.
+pub fn to_vec_packed_sd<T: Serialize>(value: &T) -> Result<Vec<u8>> {
+    let mut vec = Vec::new();
+    try!(to_writer_packed_sd(&mut vec, value));
+    Ok(vec)
 }


Test patch:
diff --git a/tests/de.rs b/tests/de.rs
index ff7453b..919ce8b 100644
--- a/tests/de.rs
+++ b/tests/de.rs
@@ -2,7 +2,7 @@ extern crate serde_cbor;
 
 use std::collections::HashMap;
 
-use serde_cbor::{Value, ObjectKey, error, de};
+use serde_cbor::{to_vec, Value, ObjectKey, error, de};
 
 #[test]
 fn test_string1() {
@@ -177,9 +177,7 @@ fn test_kietaub_file() {
 fn test_option_roundtrip() {
     let obj1 = Some(10u32);
 
-    let mut v = vec![];
-    assert!(serde_cbor::ser::to_writer(&mut v, &obj1).is_ok());
-    println!("{:?}", v);
+    let v = to_vec(&obj1).unwrap();
     let obj2: Result<Option<u32>, _> = serde_cbor::de::from_reader(&v[..]);
     println!("{:?}", obj2);
 
@@ -190,8 +188,7 @@ fn test_option_roundtrip() {
 fn test_option_none_roundtrip() {
     let obj1 = None;
 
-    let mut v = vec![];
-    assert!(serde_cbor::ser::to_writer(&mut v, &obj1).is_ok());
+    let v = to_vec(&obj1).unwrap();
     println!("{:?}", v);
     let obj2: Result<Option<u32>, _> = serde_cbor::de::from_reader(&v[..]);
 
diff --git a/tests/ser.rs b/tests/ser.rs
index 957ae8e..7adeef1 100644
--- a/tests/ser.rs
+++ b/tests/ser.rs
@@ -3,7 +3,9 @@ extern crate serde_cbor;
 
 use std::collections::HashMap;
 
-use serde_cbor::{to_vec, to_vec_sd, from_slice};
+use serde::Serializer;
+use serde_cbor::{to_vec, from_slice};
+use serde_cbor::ser;
 
 #[test]
 fn test_string() {
@@ -81,6 +83,11 @@ fn test_integer() {
 
 #[test]
 fn test_self_describing() {
-    let vec = to_vec_sd(&0).unwrap();
-    assert_eq!(vec, b"\xd9\xd9\xf7\x00");
+    let mut vec = Vec::new();
+    {
+        let mut serializer = ser::Serializer::new(&mut vec);
+        serializer.self_describe().unwrap();
+        serializer.serialize_u64(9).unwrap();
+    }
+    assert_eq!(vec, b"\xd9\xd9\xf7\x09");
 }