diff --git a/serde/Cargo.toml b/serde/Cargo.toml index f162ea31..4bacc0ad 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -26,3 +26,6 @@ unstable-testing = ["clippy", "unstable", "std"] [dependencies] clippy = { version = "^0.*", optional = true } + +[dev-dependencies] +serde_derive = "0.9.0-rc3" diff --git a/serde/src/bytes.rs b/serde/src/bytes.rs index 10e95eb8..8f914839 100644 --- a/serde/src/bytes.rs +++ b/serde/src/bytes.rs @@ -1,4 +1,20 @@ -//! Helper module to enable serializing bytes more efficiently +//! Wrapper types to enable optimized handling of `&[u8]` and `Vec`. +//! +//! Without specialization, Rust forces us to treat `&[u8]` just like any other +//! slice and `Vec` just like any other vector. In reality this particular +//! slice and vector can often be serialized and deserialized in a more +//! efficient, compact representation in many formats. +//! +//! When working with such a format, you can opt into specialized handling of +//! `&[u8]` by wrapping it in `bytes::Bytes` and `Vec` by wrapping it in +//! `bytes::ByteBuf`. +//! +//! Rust support for specialization is being tracked in +//! [rust-lang/rust#31844][specialization]. Once it lands in the stable compiler +//! we will be deprecating these wrapper types in favor of optimizing `&[u8]` +//! and `Vec` out of the box. +//! +//! [specialization]: https://github.com/rust-lang/rust/issues/31844 use core::{ops, fmt, char, iter, slice}; use core::fmt::Write; @@ -6,14 +22,36 @@ use core::fmt::Write; use ser; #[cfg(any(feature = "std", feature = "collections"))] -pub use self::bytebuf::{ByteBuf, ByteBufVisitor}; +pub use self::bytebuf::ByteBuf; + +#[cfg(any(feature = "std", feature = "collections"))] +#[doc(hidden)] // does anybody need this? +pub use self::bytebuf::ByteBufVisitor; #[cfg(feature = "collections")] use collections::Vec; /////////////////////////////////////////////////////////////////////////////// -/// `Bytes` wraps a `&[u8]` in order to serialize into a byte array. +/// Wraps a `&[u8]` in order to serialize in an efficient way. Does not support +/// deserialization. +/// +/// ```rust +/// # #[macro_use] extern crate serde_derive; +/// # extern crate serde; +/// # use std::net::IpAddr; +/// # +/// use serde::bytes::Bytes; +/// +/// # #[allow(dead_code)] +/// #[derive(Serialize)] +/// struct Packet<'a> { +/// destination: IpAddr, +/// payload: Bytes<'a>, +/// } +/// # +/// # fn main() {} +/// ``` #[derive(Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)] pub struct Bytes<'a> { bytes: &'a [u8], @@ -86,7 +124,25 @@ mod bytebuf { #[cfg(feature = "collections")] use collections::{String, Vec}; - /// `ByteBuf` wraps a `Vec` and serializes as a byte array. + /// Wraps a `Vec` in order to serialize and deserialize in an efficient + /// way. + /// + /// ```rust + /// # #[macro_use] extern crate serde_derive; + /// # extern crate serde; + /// # use std::net::IpAddr; + /// # + /// use serde::bytes::ByteBuf; + /// + /// # #[allow(dead_code)] + /// #[derive(Serialize, Deserialize)] + /// struct Packet { + /// destination: IpAddr, + /// payload: ByteBuf, + /// } + /// # + /// # fn main() {} + /// ``` #[derive(Clone, Default, Eq, Hash, PartialEq, PartialOrd, Ord)] pub struct ByteBuf { bytes: Vec, diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index 3a51ead5..e45b20af 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -1,4 +1,98 @@ -//! Generic deserialization framework. +//! Generic data structure deserialization framework. +//! +//! The two most important traits in this module are `Deserialize` and +//! `Deserializer`. +//! +//! - **A type that implements `Deserialize` is a data structure** that can be +//! deserialized from any data format supported by Serde, and conversely +//! - **A type that implements `Deserializer` is a data format** that can +//! deserialize any data structure supported by Serde. +//! +//! # The Deserialize trait +//! +//! Serde provides `Deserialize` implementations for many Rust primitive and +//! standard library types. The complete list is below. All of these can be +//! deserialized using Serde out of the box. +//! +//! Additionally, Serde provides a procedural macro called `serde_derive` to +//! automatically generate `Deserialize` implementations for structs and enums +//! in your program. See the [codegen section of the manual][codegen] for how to +//! use this. +//! +//! In rare cases it may be necessary to implement `Deserialize` manually for +//! some type in your program. See the [Implementing +//! `Deserialize`][impl-deserialize] section of the manual for more about this. +//! +//! Third-party crates may provide `Deserialize` implementations for types that +//! they expose. For example the `linked-hash-map` crate provides a +//! `LinkedHashMap` type that is deserializable by Serde because the crate +//! provides an implementation of `Deserialize` for it. +//! +//! # The Deserializer trait +//! +//! `Deserializer` implementations are provided by third-party crates, for +//! example [`serde_json`][serde_json], [`serde_yaml`][serde_yaml] and +//! [`bincode`][bincode]. +//! +//! A partial list of well-maintained formats is given on the [Serde +//! website][data-formats]. +//! +//! # Implementations of Deserialize provided by Serde +//! +//! This is a slightly different set of types than what is supported for +//! serialization. Some types can be serialized by Serde but not deserialized. +//! One example is `&str`. +//! +//! - **Primitive types**: +//! - bool +//! - isize, i8, i16, i32, i64 +//! - usize, u8, u16, u32, u64 +//! - f32, f64 +//! - char +//! - **Compound types**: +//! - [T; 0] through [T; 32] +//! - tuples up to size 16 +//! - **Common standard library types**: +//! - String +//! - Option\ +//! - Result\ +//! - PhantomData\ +//! - **Wrapper types**: +//! - Box\ +//! - Box\<[T]\> +//! - Box\ +//! - Rc\ +//! - Arc\ +//! - Cow\<'a, T\> +//! - **Collection types**: +//! - BTreeMap\ +//! - BTreeSet\ +//! - BinaryHeap\ +//! - HashMap\ +//! - HashSet\ +//! - LinkedList\ +//! - VecDeque\ +//! - Vec\ +//! - EnumSet\ (unstable) +//! - **Miscellaneous standard library types**: +//! - Duration +//! - Path +//! - PathBuf +//! - NonZero\ (unstable) +//! - **Net types**: +//! - IpAddr +//! - Ipv4Addr +//! - Ipv6Addr +//! - SocketAddr +//! - SocketAddrV4 +//! - SocketAddrV6 +//! +//! [codegen]: https://serde.rs/codegen.html +//! [impl-deserialize]: https://serde.rs/impl-deserialize.html +//! [serde_json]: https://github.com/serde-rs/json +//! [serde_yaml]: https://github.com/dtolnay/serde-yaml +//! [bincode]: https://github.com/TyOverby/bincode +//! [data-formats]: https://serde.rs/#data-formats #[cfg(feature = "std")] use std::error; @@ -13,6 +107,7 @@ use core::marker::PhantomData; /////////////////////////////////////////////////////////////////////////////// +#[doc(hidden)] pub mod impls; pub mod value; mod from_primitive; @@ -38,6 +133,30 @@ pub mod private; /// and inherit the default behavior for the other methods. pub trait Error: Sized + error::Error { /// Raised when there is general error when deserializing a type. + /// + /// The message should not be capitalized and should not end with a period. + /// + /// ```rust + /// # use serde::de::{Deserialize, Deserializer, Error}; + /// # use std::str::FromStr; + /// # #[allow(dead_code)] + /// # struct IpAddr; + /// # impl FromStr for IpAddr { + /// # type Err = String; + /// # fn from_str(_: &str) -> Result { unimplemented!() } + /// # } + /// impl Deserialize for IpAddr { + /// fn deserialize(deserializer: D) -> Result + /// where D: Deserializer + /// { + /// let s = try!(String::deserialize(deserializer)); + /// match s.parse() { + /// Ok(s) => Ok(s), + /// Err(err) => Err(Error::custom(err)), + /// } + /// } + /// } + /// ``` fn custom(msg: T) -> Self; /// Raised when a `Deserialize` receives a type different from what it was @@ -201,6 +320,7 @@ pub trait Error: Sized + error::Error { /// ```rust /// # use serde::de::{Error, Unexpected, Visitor}; /// # use std::fmt; +/// # #[allow(dead_code)] /// # struct Example; /// # impl Visitor for Example { /// # type Value = (); @@ -309,9 +429,10 @@ impl<'a> fmt::Display for Unexpected<'a> { /// /// This is used as an argument to the `invalid_type`, `invalid_value`, and /// `invalid_length` methods of the `Error` trait to build error messages. The -/// message should complete the sentence "This Visitor expects to receive ...", -/// for example the message could be "an integer between 0 and 64". The message -/// should not be capitalized and should not end with a period. +/// message should be a noun or noun phrase that completes the sentence "This +/// Visitor expects to receive ...", for example the message could be "an +/// integer between 0 and 64". The message should not be capitalized and should +/// not end with a period. /// /// Within the context of a `Visitor` implementation, the `Visitor` itself /// (`&self`) is an implementation of this trait. @@ -319,6 +440,7 @@ impl<'a> fmt::Display for Unexpected<'a> { /// ```rust /// # use serde::de::{Error, Unexpected, Visitor}; /// # use std::fmt; +/// # #[allow(dead_code)] /// # struct Example; /// # impl Visitor for Example { /// # type Value = (); @@ -337,6 +459,7 @@ impl<'a> fmt::Display for Unexpected<'a> { /// /// ```rust /// # use serde::de::{Error, Unexpected}; +/// # #[allow(dead_code)] /// # fn example() -> Result<(), E> { /// # let v = true; /// return Err(Error::invalid_type(Unexpected::Bool(v), &"a negative integer")); @@ -368,9 +491,37 @@ impl<'a> Display for Expected + 'a { /////////////////////////////////////////////////////////////////////////////// -/// `Deserialize` represents a type that can be deserialized. +/// An implementation of this trait is a **data structure** that can be +/// deserialized from any data format supported by Serde. +/// +/// Serde provides `Deserialize` implementations for many Rust primitive and +/// standard library types. The complete list is [here][de]. All of these can +/// be deserialized using Serde out of the box. +/// +/// Additionally, Serde provides a procedural macro called `serde_derive` to +/// automatically generate `Deserialize` implementations for structs and enums +/// in your program. See the [codegen section of the manual][codegen] for how to +/// use this. +/// +/// In rare cases it may be necessary to implement `Deserialize` manually for +/// some type in your program. See the [Implementing +/// `Deserialize`][impl-deserialize] section of the manual for more about this. +/// +/// Third-party crates may provide `Deserialize` implementations for types that +/// they expose. For example the `linked-hash-map` crate provides a +/// `LinkedHashMap` type that is deserializable by Serde because the crate +/// provides an implementation of `Deserialize` for it. +/// +/// [de]: https://docs.serde.rs/serde/de/index.html +/// [codegen]: https://serde.rs/codegen.html +/// [impl-deserialize]: https://serde.rs/impl-deserialize.html pub trait Deserialize: Sized { - /// Deserialize this value given this `Deserializer`. + /// Deserialize this value from the given Serde deserializer. + /// + /// See the [Implementing `Deserialize`][impl-deserialize] section of the + /// manual for more information about how to implement this method. + /// + /// [impl-deserialize]: https://serde.rs/impl-deserialize.html fn deserialize(deserializer: D) -> Result where D: Deserializer; } @@ -390,7 +541,9 @@ pub trait Deserialize: Sized { /// /// ```rust /// # use serde::Deserialize; +/// # #[allow(dead_code)] /// # enum Error {} +/// # #[allow(dead_code)] /// fn func() -> Result /// # { unimplemented!() } /// ``` @@ -400,9 +553,14 @@ pub trait Deserialize: Sized { /// /// ```rust /// # use serde::de::DeserializeSeed; +/// # #[allow(dead_code)] /// # enum Error {} +/// # #[allow(dead_code)] /// fn func_seed(seed: T) -> Result -/// # { unimplemented!() } +/// # { +/// # let _ = seed; +/// # unimplemented!() +/// # } /// ``` /// /// In practice the majority of deserialization is stateless. An API expecting a @@ -500,9 +658,11 @@ pub trait Deserialize: Sized { /// # } /// } /// +/// # #[allow(dead_code)] /// # fn example(deserializer: D) -> Result<(), D::Error> { /// let visitor = FlattenedVecVisitor(PhantomData); /// let flattened: Vec = deserializer.deserialize_seq(visitor)?; +/// # let _ = flattened; /// # Ok(()) } /// ``` pub trait DeserializeSeed: Sized { @@ -530,192 +690,279 @@ impl DeserializeSeed for PhantomData /////////////////////////////////////////////////////////////////////////////// -/// `Deserializer` is a trait that can deserialize values by threading a `Visitor` trait through a -/// value. It supports two entry point styles which enables different kinds of deserialization. +/// An implementation of this trait is a **data format** that can deserialize +/// any data structure supported by Serde. /// -/// 1) The `deserialize` method. File formats like JSON embed the type of its construct in its file -/// format. This allows the `Deserializer` to deserialize into a generic type like -/// `json::Value`, which can represent all JSON types. +/// The role of this trait is to define the deserialization half of the Serde +/// data model, which is a way to categorize every Rust data type into one of 30 +/// possible types. Each method of the `Serializer` trait corresponds to one of +/// the types of the data model. /// -/// 2) The `deserialize_*` methods. File formats like bincode do not embed in its format how to -/// decode its values. It relies instead on the `Deserialize` type to hint to the `Deserializer` -/// with the `deserialize_*` methods how it should parse the next value. One downside though to -/// only supporting the `deserialize_*` types is that it does not allow for deserializing into a -/// generic `json::Value`-esque type. +/// Implementations of `Deserialize` map themselves into this data model by +/// passing to the `Deserializer` a `Visitor` implementation that can receive +/// these various types. +/// +/// The types that make up the Serde data model are: +/// +/// - 15 primitive types: +/// - bool +/// - isize, i8, i16, i32, i64 +/// - usize, u8, u16, u32, u64 +/// - f32, f64 +/// - char +/// - string +/// - byte array - [u8] +/// - option +/// - either none or some value +/// - unit +/// - unit is the type of () in Rust +/// - unit_struct +/// - for example `struct Unit` or `PhantomData` +/// - unit_variant +/// - the `E::A` and `E::B` in `enum E { A, B }` +/// - newtype_struct +/// - for example `struct Millimeters(u8)` +/// - newtype_variant +/// - the `E::N` in `enum E { N(u8) }` +/// - seq +/// - a dynamically sized sequence of values, for example `Vec` or +/// `HashSet` +/// - seq_fixed_size +/// - a statically sized sequence of values for which the size will be known +/// at deserialization time without looking at the serialized data, for +/// example `[u64; 10]` +/// - tuple +/// - for example `(u8,)` or `(String, u64, Vec)` +/// - tuple_struct +/// - for example `struct Rgb(u8, u8, u8)` +/// - tuple_variant +/// - the `E::T` in `enum E { T(u8, u8) }` +/// - map +/// - for example `BTreeMap` +/// - struct +/// - a key-value pairing in which the keys will be known at deserialization +/// time without looking at the serialized data, for example `struct S { r: +/// u8, g: u8, b: u8 }` +/// - struct_variant +/// - the `E::S` in `enum E { S { r: u8, g: u8, b: u8 } }` +/// +/// The `Deserializer` trait supports two entry point styles which enables +/// different kinds of deserialization. +/// +/// 1. The `deserialize` method. Self-describing data formats like JSON are able +/// to look at the serialized data and tell what it represents. For example +/// the JSON deserializer may see an opening curly brace (`{`) and know that +/// it is seeing a map. If the data format supports +/// `Deserializer::deserialize`, it will drive the Visitor using whatever +/// type it sees in the input. JSON uses this approach when deserializing +/// `serde_json::Value` which is an enum that can represent any JSON +/// document. Without knowing what is in a JSON document, we can deserialize +/// it to `serde_json::Value` by going through `Deserializer::deserialize`. +/// +/// 2. The various `deserialize_*` methods. Non-self-describing formats like +/// Bincode need to be told what is in the input in order to deserialize it. +/// The `deserialize_*` methods are hints to the deserializer for how to +/// interpret the next piece of input. Non-self-describing formats are not +/// able to deserialize something like `serde_json::Value` which relies on +/// `Deserializer::deserialize`. +/// +/// When implementing `Deserialize`, you should avoid relying on +/// `Deserializer::deserialize` unless you need to be told by the Deserializer +/// what type is in the input. Know that relying on `Deserializer::deserialize` +/// means your data type will be able to deserialize from self-describing +/// formats only, ruling out Bincode and many others. pub trait Deserializer: Sized { - /// The error type that can be returned if some error occurs during deserialization. + /// The error type that can be returned if some error occurs during + /// deserialization. type Error: Error; - /// This method walks a visitor through a value as it is being deserialized. + /// Require the `Deserializer` to figure out how to drive the visitor based + /// on what data type is in the input. + /// + /// When implementing `Deserialize`, you should avoid relying on + /// `Deserializer::deserialize` unless you need to be told by the + /// Deserializer what type is in the input. Know that relying on + /// `Deserializer::deserialize` means your data type will be able to + /// deserialize from self-describing formats only, ruling out Bincode and + /// many others. fn deserialize(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting a `bool` value. + /// Hint that the `Deserialize` type is expecting a `bool` value. fn deserialize_bool(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting an `usize` value. - /// A reasonable default is to forward to `deserialize_u64`. + /// Hint that the `Deserialize` type is expecting a `usize` value. fn deserialize_usize(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting an `u8` value. - /// A reasonable default is to forward to `deserialize_u64`. + /// Hint that the `Deserialize` type is expecting a `u8` value. fn deserialize_u8(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting an `u16` value. - /// A reasonable default is to forward to `deserialize_u64`. + /// Hint that the `Deserialize` type is expecting a `u16` value. fn deserialize_u16(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting an `u32` value. - /// A reasonable default is to forward to `deserialize_u64`. + /// Hint that the `Deserialize` type is expecting a `u32` value. fn deserialize_u32(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting an `u64` value. + /// Hint that the `Deserialize` type is expecting a `u64` value. fn deserialize_u64(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting an `isize` value. - /// A reasonable default is to forward to `deserialize_i64`. + /// Hint that the `Deserialize` type is expecting an `isize` value. fn deserialize_isize(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting an `i8` value. - /// A reasonable default is to forward to `deserialize_i64`. + /// Hint that the `Deserialize` type is expecting an `i8` value. fn deserialize_i8(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting an `i16` value. - /// A reasonable default is to forward to `deserialize_i64`. + /// Hint that the `Deserialize` type is expecting an `i16` value. fn deserialize_i16(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting an `i32` value. - /// A reasonable default is to forward to `deserialize_i64`. + /// Hint that the `Deserialize` type is expecting an `i32` value. fn deserialize_i32(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting an `i64` value. + /// Hint that the `Deserialize` type is expecting an `i64` value. fn deserialize_i64(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting a `f32` value. - /// A reasonable default is to forward to `deserialize_f64`. + /// Hint that the `Deserialize` type is expecting a `f32` value. fn deserialize_f32(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting a `f64` value. + /// Hint that the `Deserialize` type is expecting a `f64` value. fn deserialize_f64(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting a `char` value. + /// Hint that the `Deserialize` type is expecting a `char` value. fn deserialize_char(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting a `&str` value. + /// Hint that the `Deserialize` type is expecting a string value and does + /// not benefit from taking ownership of buffered data owned by the + /// `Deserializer`. + /// + /// If the `Visitor` would benefit from taking ownership of `String` data, + /// indiciate this to the `Deserializer` by using `deserialize_string` + /// instead. fn deserialize_str(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting a `String` value. + /// Hint that the `Deserialize` type is expecting a string value and would + /// benefit from taking ownership of buffered data owned by the + /// `Deserializer`. + /// + /// If the `Visitor` would not benefit from taking ownership of `String` + /// data, indicate that to the `Deserializer` by using `deserialize_str` + /// instead. fn deserialize_string(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting an `unit` value. - fn deserialize_unit(self, visitor: V) -> Result - where V: Visitor; - - /// This method hints that the `Deserialize` type is expecting an `Option` value. This allows - /// deserializers that encode an optional value as a nullable value to convert the null value - /// into a `None`, and a regular value as `Some(value)`. - fn deserialize_option(self, visitor: V) -> Result - where V: Visitor; - - /// This method hints that the `Deserialize` type is expecting a sequence value. This allows - /// deserializers to parse sequences that aren't tagged as sequences. - fn deserialize_seq(self, visitor: V) -> Result - where V: Visitor; - - /// This method hints that the `Deserialize` type is expecting a fixed size array. This allows - /// deserializers to parse arrays that aren't tagged as arrays. - fn deserialize_seq_fixed_size(self, - len: usize, - visitor: V) -> Result - where V: Visitor; - - /// This method hints that the `Deserialize` type is expecting a `&[u8]`. This allows - /// deserializers that provide a custom byte vector serialization to properly deserialize the - /// type. + /// Hint that the `Deserialize` type is expecting a byte array and does not + /// benefit from taking ownership of buffered data owned by the + /// `Deserializer`. + /// + /// If the `Visitor would benefit from taking ownership of `Vec` data, + /// indicate this to the `Deserializer` by using `deserialize_byte_buf` + /// instead. fn deserialize_bytes(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting a `Vec`. This allows - /// deserializers that provide a custom byte vector serialization to properly deserialize the - /// type and prevent needless intermediate allocations that would occur when going through - /// `&[u8]`. + /// Hint that the `Deserialize` type is expecting a byte array and would + /// benefit from taking ownership of buffered data owned by the + /// `Deserializer`. + /// + /// If the `Visitor` would not benefit from taking ownership of `Vec` + /// data, indicate that to the `Deserializer` by using `deserialize_bytes` + /// instead. fn deserialize_byte_buf(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting a map of values. This allows - /// deserializers to parse sequences that aren't tagged as maps. - fn deserialize_map(self, visitor: V) -> Result + /// Hint that the `Deserialize` type is expecting an optional value. + /// + /// This allows deserializers that encode an optional value as a nullable + /// value to convert the null value into `None` and a regular value into + /// `Some(value)`. + fn deserialize_option(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting a unit struct. This allows - /// deserializers to a unit struct that aren't tagged as a unit struct. + /// Hint that the `Deserialize` type is expecting a unit value. + fn deserialize_unit(self, visitor: V) -> Result + where V: Visitor; + + /// Hint that the `Deserialize` type is expecting a unit struct with a + /// particular name. fn deserialize_unit_struct(self, name: &'static str, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting a newtype struct. This allows - /// deserializers to a newtype struct that aren't tagged as a newtype struct. - /// A reasonable default is to simply deserialize the expected value directly. + /// Hint that the `Deserialize` type is expecting a newtype struct with a + /// particular name. fn deserialize_newtype_struct(self, name: &'static str, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting a tuple struct. This allows - /// deserializers to parse sequences that aren't tagged as sequences. + /// Hint that the `Deserialize` type is expecting a sequence of values. + fn deserialize_seq(self, visitor: V) -> Result + where V: Visitor; + + /// Hint that the `Deserialize` type is expecting a sequence of values and + /// knows how many values there are without looking at the serialized data. + fn deserialize_seq_fixed_size(self, + len: usize, + visitor: V) -> Result + where V: Visitor; + + /// Hint that the `Deserialize` type is expecting a tuple value with a + /// particular number of elements. + fn deserialize_tuple(self, len: usize, visitor: V) -> Result + where V: Visitor; + + /// Hint that the `Deserialize` type is expecting a tuple struct with a + /// particular name and number of fields. fn deserialize_tuple_struct(self, name: &'static str, len: usize, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting a struct. This allows - /// deserializers to parse sequences that aren't tagged as maps. + /// Hint that the `Deserialize` type is expecting a map of key-value pairs. + fn deserialize_map(self, visitor: V) -> Result + where V: Visitor; + + /// Hint that the `Deserialize` type is expecting a struct with a particular + /// name and fields. fn deserialize_struct(self, name: &'static str, fields: &'static [&'static str], visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting some sort of struct field - /// name. This allows deserializers to choose between &str, usize, or &[u8] to properly - /// deserialize a struct field. + /// Hint that the `Deserialize` type is expecting the name of a struct + /// field. fn deserialize_struct_field(self, visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type is expecting a tuple value. This allows - /// deserializers that provide a custom tuple serialization to properly deserialize the type. - fn deserialize_tuple(self, len: usize, visitor: V) -> Result - where V: Visitor; - - /// This method hints that the `Deserialize` type is expecting an enum value. This allows - /// deserializers that provide a custom enumeration serialization to properly deserialize the - /// type. + /// Hint that the `Deserialize` type is expecting an enum value with a + /// particular name and possible variants. fn deserialize_enum(self, name: &'static str, variants: &'static [&'static str], visitor: V) -> Result where V: Visitor; - /// This method hints that the `Deserialize` type needs to deserialize a value whose type + /// Hint that the `Deserialize` type needs to deserialize a value whose type /// doesn't matter because it is ignored. + /// + /// Deserializers for non-self-describing formats may not support this mode. fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor; } @@ -729,6 +976,7 @@ pub trait Deserializer: Sized { /// # use std::fmt; /// /// A visitor that deserializes a long string - a string containing at least /// /// some minimum number of bytes. +/// # #[allow(dead_code)] /// struct LongString { /// min: usize, /// } @@ -764,6 +1012,7 @@ pub trait Visitor: Sized { /// /// ```rust /// # use std::fmt; + /// # #[allow(dead_code)] /// # struct S { max: usize } /// # impl serde::de::Visitor for S { /// # type Value = (); @@ -774,98 +1023,98 @@ pub trait Visitor: Sized { /// ``` fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result; - /// `visit_bool` deserializes a `bool` into a `Value`. + /// Deserialize a `bool` into a `Value`. fn visit_bool(self, v: bool) -> Result where E: Error, { Err(Error::invalid_type(Unexpected::Bool(v), &self)) } - /// `visit_isize` deserializes a `isize` into a `Value`. + /// Deserialize an `isize` into a `Value`. fn visit_isize(self, v: isize) -> Result where E: Error, { self.visit_i64(v as i64) } - /// `visit_i8` deserializes a `i8` into a `Value`. + /// Deserialize an `i8` into a `Value`. fn visit_i8(self, v: i8) -> Result where E: Error, { self.visit_i64(v as i64) } - /// `visit_i16` deserializes a `i16` into a `Value`. + /// Deserialize an `i16` into a `Value`. fn visit_i16(self, v: i16) -> Result where E: Error, { self.visit_i64(v as i64) } - /// `visit_i32` deserializes a `i32` into a `Value`. + /// Deserialize an `i32` into a `Value`. fn visit_i32(self, v: i32) -> Result where E: Error, { self.visit_i64(v as i64) } - /// `visit_i64` deserializes a `i64` into a `Value`. + /// Deserialize an `i64` into a `Value`. fn visit_i64(self, v: i64) -> Result where E: Error, { Err(Error::invalid_type(Unexpected::Signed(v), &self)) } - /// `visit_usize` deserializes a `usize` into a `Value`. + /// Deserialize a `usize` into a `Value`. fn visit_usize(self, v: usize) -> Result where E: Error, { self.visit_u64(v as u64) } - /// `visit_u8` deserializes a `u8` into a `Value`. + /// Deserialize a `u8` into a `Value`. fn visit_u8(self, v: u8) -> Result where E: Error, { self.visit_u64(v as u64) } - /// `visit_u16` deserializes a `u16` into a `Value`. + /// Deserialize a `u16` into a `Value`. fn visit_u16(self, v: u16) -> Result where E: Error, { self.visit_u64(v as u64) } - /// `visit_u32` deserializes a `u32` into a `Value`. + /// Deserialize a `u32` into a `Value`. fn visit_u32(self, v: u32) -> Result where E: Error, { self.visit_u64(v as u64) } - /// `visit_u64` deserializes a `u64` into a `Value`. + /// Deserialize a `u64` into a `Value`. fn visit_u64(self, v: u64) -> Result where E: Error, { Err(Error::invalid_type(Unexpected::Unsigned(v), &self)) } - /// `visit_f32` deserializes a `f32` into a `Value`. + /// Deserialize a `f32` into a `Value`. fn visit_f32(self, v: f32) -> Result where E: Error, { self.visit_f64(v as f64) } - /// `visit_f64` deserializes a `f64` into a `Value`. + /// Deserialize a `f64` into a `Value`. fn visit_f64(self, v: f64) -> Result where E: Error, { Err(Error::invalid_type(Unexpected::Float(v), &self)) } - /// `visit_char` deserializes a `char` into a `Value`. + /// Deserialize a `char` into a `Value`. #[inline] fn visit_char(self, v: char) -> Result where E: Error, @@ -873,16 +1122,36 @@ pub trait Visitor: Sized { self.visit_str(::utils::encode_utf8(v).as_str()) } - /// `visit_str` deserializes a `&str` into a `Value`. + /// Deserialize a `&str` into a `Value`. + /// + /// This method allows the `Deserializer` to avoid a copy by retaining + /// ownership of any buffered data. `Deserialize` implementations that do + /// not benefit from taking ownership of `String` data should indicate that + /// to the deserializer by using `Deserializer::deserialize_str` rather than + /// `Deserializer::deserialize_string`. + /// + /// It is never correct to implement `visit_string` without implementing + /// `visit_str`. Implement neither, both, or just `visit_str`. fn visit_str(self, v: &str) -> Result where E: Error, { Err(Error::invalid_type(Unexpected::Str(v), &self)) } - /// `visit_string` deserializes a `String` into a `Value`. This allows a deserializer to avoid - /// a copy if it is deserializing a string from a `String` type. By default it passes a `&str` - /// to the `visit_str` method. + /// Deserialize a `String` into a `Value`. + /// + /// This method allows the `Visitor` to avoid a copy by taking ownership of + /// a string created by the `Deserializer`. `Deserialize` implementations + /// that benefit from taking ownership of `String` data should indicate that + /// to the deserializer by using `Deserializer::deserialize_string` rather + /// than `Deserializer::deserialize_str`, although not every deserializer + /// will honor such a request. + /// + /// It is never correct to implement `visit_string` without implementing + /// `visit_str`. Implement neither, both, or just `visit_str`. + /// + /// The default implementation forwards to `visit_str` and then drops the + /// `String`. #[inline] #[cfg(any(feature = "std", feature = "collections"))] fn visit_string(self, v: String) -> Result @@ -891,21 +1160,21 @@ pub trait Visitor: Sized { self.visit_str(&v) } - /// `visit_unit` deserializes a `()` into a `Value`. + /// Deserialize a `()` into a `Value`. fn visit_unit(self) -> Result where E: Error, { Err(Error::invalid_type(Unexpected::Unit, &self)) } - /// `visit_none` deserializes a none value into a `Value`. + /// Deserialize an absent optional `Value`. fn visit_none(self) -> Result where E: Error, { Err(Error::invalid_type(Unexpected::Option, &self)) } - /// `visit_some` deserializes a value into a `Value`. + /// Deserialize a present optional `Value`. fn visit_some(self, deserializer: D) -> Result where D: Deserializer, { @@ -913,7 +1182,7 @@ pub trait Visitor: Sized { Err(Error::invalid_type(Unexpected::Option, &self)) } - /// `visit_newtype_struct` deserializes a value into a `Value`. + /// Deserialize `Value` as a newtype struct. fn visit_newtype_struct(self, deserializer: D) -> Result where D: Deserializer, { @@ -921,7 +1190,7 @@ pub trait Visitor: Sized { Err(Error::invalid_type(Unexpected::NewtypeStruct, &self)) } - /// `visit_seq` deserializes a `SeqVisitor` into a `Value`. + /// Deserialize `Value` as a sequence of elements. fn visit_seq(self, visitor: V) -> Result where V: SeqVisitor, { @@ -929,7 +1198,7 @@ pub trait Visitor: Sized { Err(Error::invalid_type(Unexpected::Seq, &self)) } - /// `visit_map` deserializes a `MapVisitor` into a `Value`. + /// Deserialize `Value` as a key-value map. fn visit_map(self, visitor: V) -> Result where V: MapVisitor, { @@ -937,7 +1206,7 @@ pub trait Visitor: Sized { Err(Error::invalid_type(Unexpected::Map, &self)) } - /// `visit_enum` deserializes a `EnumVisitor` into a `Value`. + /// Deserialize `Value` as an enum. fn visit_enum(self, visitor: V) -> Result where V: EnumVisitor, { @@ -945,7 +1214,16 @@ pub trait Visitor: Sized { Err(Error::invalid_type(Unexpected::Enum, &self)) } - /// `visit_bytes` deserializes a `&[u8]` into a `Value`. + /// Deserialize a `&[u8]` into a `Value`. + /// + /// This method allows the `Deserializer` to avoid a copy by retaining + /// ownership of any buffered data. `Deserialize` implementations that do + /// not benefit from taking ownership of `Vec` data should indicate that + /// to the deserializer by using `Deserializer::deserialize_bytes` rather + /// than `Deserializer::deserialize_byte_buf`. + /// + /// It is never correct to implement `visit_byte_buf` without implementing + /// `visit_bytes`. Implement neither, both, or just `visit_bytes`. fn visit_bytes(self, v: &[u8]) -> Result where E: Error, { @@ -953,7 +1231,21 @@ pub trait Visitor: Sized { Err(Error::invalid_type(Unexpected::Bytes(v), &self)) } - /// `visit_byte_buf` deserializes a `Vec` into a `Value`. + /// Deserialize a `Vec` into a `Value`. + /// + /// This method allows the `Visitor` to avoid a copy by taking ownership of + /// a byte buffer created by the `Deserializer`. `Deserialize` + /// implementations that benefit from taking ownership of `Vec` data + /// should indicate that to the deserializer by using + /// `Deserializer::deserialize_byte_buf` rather than + /// `Deserializer::deserialize_bytes`, although not every deserializer will + /// honor such a request. + /// + /// It is never correct to implement `visit_byte_buf` without implementing + /// `visit_bytes`. Implement neither, both, or just `visit_bytes`. + /// + /// The default implementation forwards to `visit_bytes` and then drops the + /// `Vec`. #[cfg(any(feature = "std", feature = "collections"))] fn visit_byte_buf(self, v: Vec) -> Result where E: Error, @@ -966,10 +1258,11 @@ pub trait Visitor: Sized { /// `SeqVisitor` visits each item in a sequence. /// -/// This is a trait that a `Deserializer` passes to a `Visitor` implementation, which deserializes -/// each item in a sequence. +/// This is a trait that a `Deserializer` passes to a `Visitor` implementation, +/// which deserializes each item in a sequence. pub trait SeqVisitor { - /// The error type that can be returned if some error occurs during deserialization. + /// The error type that can be returned if some error occurs during + /// deserialization. type Error: Error; /// This returns `Ok(Some(value))` for the next value in the sequence, or @@ -984,8 +1277,7 @@ pub trait SeqVisitor { /// `Ok(None)` if there are no more remaining items. /// /// This method exists as a convenience for `Deserialize` implementations. - /// `SeqVisitor` implementations should not need to override the default - /// behavior. + /// `SeqVisitor` implementations should not override the default behavior. #[inline] fn visit(&mut self) -> Result, Self::Error> where T: Deserialize @@ -1029,7 +1321,8 @@ impl<'a, V> SeqVisitor for &'a mut V where V: SeqVisitor { /// /// This is a trait that a `Deserializer` passes to a `Visitor` implementation. pub trait MapVisitor { - /// The error type that can be returned if some error occurs during deserialization. + /// The error type that can be returned if some error occurs during + /// deserialization. type Error: Error; /// This returns `Ok(Some(key))` for the next key in the map, or `Ok(None)` @@ -1073,8 +1366,7 @@ pub trait MapVisitor { /// if there are no more remaining entries. /// /// This method exists as a convenience for `Deserialize` implementations. - /// `MapVisitor` implementations should not need to override the default - /// behavior. + /// `MapVisitor` implementations should not override the default behavior. #[inline] fn visit_key(&mut self) -> Result, Self::Error> where K: Deserialize @@ -1085,8 +1377,7 @@ pub trait MapVisitor { /// This returns a `Ok(value)` for the next value in the map. /// /// This method exists as a convenience for `Deserialize` implementations. - /// `MapVisitor` implementations should not need to override the default - /// behavior. + /// `MapVisitor` implementations should not override the default behavior. #[inline] fn visit_value(&mut self) -> Result where V: Deserialize @@ -1098,8 +1389,7 @@ pub trait MapVisitor { /// the map, or `Ok(None)` if there are no more remaining items. /// /// This method exists as a convenience for `Deserialize` implementations. - /// `MapVisitor` implementations should not need to override the default - /// behavior. + /// `MapVisitor` implementations should not override the default behavior. #[inline] fn visit(&mut self) -> Result, Self::Error> where K: Deserialize, @@ -1174,7 +1464,8 @@ impl<'a, V_> MapVisitor for &'a mut V_ where V_: MapVisitor { /// to the `Deserialize` in order to identify which variant of an enum to /// deserialize. pub trait EnumVisitor: Sized { - /// The error type that can be returned if some error occurs during deserialization. + /// The error type that can be returned if some error occurs during + /// deserialization. type Error: Error; /// The `Visitor` that will be used to deserialize the content of the enum /// variant. @@ -1190,8 +1481,7 @@ pub trait EnumVisitor: Sized { /// `visit_variant` is called to identify which variant to deserialize. /// /// This method exists as a convenience for `Deserialize` implementations. - /// `EnumVisitor` implementations should not need to override the default - /// behavior. + /// `EnumVisitor` implementations should not override the default behavior. #[inline] fn visit_variant(self) -> Result<(V, Self::Variant), Self::Error> where V: Deserialize @@ -1204,25 +1494,48 @@ pub trait EnumVisitor: Sized { /// passed to the `Deserialize` to deserialize the content of a particular enum /// variant. pub trait VariantVisitor: Sized { - /// The error type that can be returned if some error occurs during deserialization. + /// The error type that can be returned if some error occurs during + /// deserialization. Must match the error type of our `EnumVisitor`. type Error: Error; - /// `visit_unit` is called when deserializing a variant with no values. + /// Called when deserializing a variant with no values. + /// + /// If the data contains a different type of variant, the following + /// `invalid_type` error should be constructed: + /// + /// ```rust,ignore + /// fn visit_unit(self) -> Result<(), Self::Error> { + /// // What the data actually contained; suppose it is a tuple variant. + /// let unexp = Unexpected::TupleVariant; + /// Err(de::Error::invalid_type(unexp, &"unit variant")) + /// } + /// ``` fn visit_unit(self) -> Result<(), Self::Error>; - /// `visit_newtype` is called when deserializing a variant with a single value. - /// A good default is often to use the `visit_tuple` method to deserialize a `(value,)`. + /// Called when deserializing a variant with a single value. /// /// `Deserialize` implementations should typically use /// `VariantVisitor::visit_newtype` instead. + /// + /// If the data contains a different type of variant, the following + /// `invalid_type` error should be constructed: + /// + /// ```rust,ignore + /// fn visit_newtype_seed(self, _seed: T) -> Result + /// where T: de::DeserializeSeed + /// { + /// // What the data actually contained; suppose it is a unit variant. + /// let unexp = Unexpected::UnitVariant; + /// Err(de::Error::invalid_type(unexp, &"newtype variant")) + /// } + /// ``` fn visit_newtype_seed(self, seed: T) -> Result where T: DeserializeSeed; - /// `visit_newtype` is called when deserializing a variant with a single value. - /// A good default is often to use the `visit_tuple` method to deserialize a `(value,)`. + /// Called when deserializing a variant with a single value. /// /// This method exists as a convenience for `Deserialize` implementations. - /// `VariantVisitor` implementations should not need to override the default + /// `VariantVisitor` implementations should not override the default /// behavior. #[inline] fn visit_newtype(self) -> Result @@ -1231,17 +1544,47 @@ pub trait VariantVisitor: Sized { self.visit_newtype_seed(PhantomData) } - /// `visit_tuple` is called when deserializing a tuple-like variant. - /// If no tuple variants are expected, yield a - /// `Err(serde::de::Error::invalid_type(serde::de::Type::TupleVariant))` + /// Called when deserializing a tuple-like variant. + /// + /// The `len` is the number of fields expected in the tuple variant. + /// + /// If the data contains a different type of variant, the following + /// `invalid_type` error should be constructed: + /// + /// ```rust,ignore + /// fn visit_tuple(self, + /// _len: usize, + /// _visitor: V) -> Result + /// where V: Visitor + /// { + /// // What the data actually contained; suppose it is a unit variant. + /// let unexp = Unexpected::UnitVariant; + /// Err(Error::invalid_type(unexp, &"tuple variant")) + /// } + /// ``` fn visit_tuple(self, len: usize, visitor: V) -> Result where V: Visitor; - /// `visit_struct` is called when deserializing a struct-like variant. - /// If no struct variants are expected, yield a - /// `Err(serde::de::Error::invalid_type(serde::de::Type::StructVariant))` + /// Called when deserializing a struct-like variant. + /// + /// The `fields` are the names of the fields of the struct variant. + /// + /// If the data contains a different type of variant, the following + /// `invalid_type` error should be constructed: + /// + /// ```rust,ignore + /// fn visit_struct(self, + /// _fields: &'static [&'static str], + /// _visitor: V) -> Result + /// where V: Visitor + /// { + /// // What the data actually contained; suppose it is a unit variant. + /// let unexp = Unexpected::UnitVariant; + /// Err(Error::invalid_type(unexp, &"struct variant")) + /// } + /// ``` fn visit_struct(self, fields: &'static [&'static str], visitor: V) -> Result @@ -1255,6 +1598,8 @@ pub trait VariantVisitor: Sized { /// - expected `a` /// - expected `a` or `b` /// - expected one of `a`, `b`, `c` +/// +/// The slice of names must not be empty. struct OneOf { names: &'static [&'static str], } diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index 71bb353b..38f99394 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -975,16 +975,16 @@ mod private { } fn visit_tuple(self, - _len: usize, - _visitor: V) -> Result + _len: usize, + _visitor: V) -> Result where V: de::Visitor { Err(de::Error::invalid_type(Unexpected::UnitVariant, &"tuple variant")) } fn visit_struct(self, - _fields: &'static [&'static str], - _visitor: V) -> Result + _fields: &'static [&'static str], + _visitor: V) -> Result where V: de::Visitor { Err(de::Error::invalid_type(Unexpected::UnitVariant, &"struct variant")) diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 77a04932..6144fb15 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -1,13 +1,63 @@ -//! Serde Serialization Framework +//! # Serde //! -//! Serde is a powerful framework that enables serialization libraries to generically serialize -//! Rust data structures without the overhead of runtime type information. In many situations, the -//! handshake protocol between serializers and serializees can be completely optimized away, -//! leaving serde to perform roughly the same speed as a hand written serializer for a specific -//! type. +//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data +//! structures efficiently and generically. //! -//! For a detailed tutorial on the different ways to use serde please check out the -//! [github repository](https://github.com/serde-rs/serde) +//! The Serde ecosystem consists of data structures that know how to serialize +//! and deserialize themselves along with data formats that know how to +//! serialize and deserialize other things. Serde provides the layer by which +//! these two groups interact with each other, allowing any supported data +//! structure to be serialized and deserialized using any supported data format. +//! +//! See the Serde website https://serde.rs/ for additional documentation and +//! usage examples. +//! +//! ### Design +//! +//! Where many other languages rely on runtime reflection for serializing data, +//! Serde is instead built on Rust's powerful trait system. A data structure +//! that knows how to serialize and deserialize itself is one that implements +//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's code +//! generation to automatically derive implementations at compile time). This +//! avoids any overhead of reflection or runtime type information. In fact in +//! many situations the interaction between data structure and data format can +//! be completely optimized away by the Rust compiler, leaving Serde +//! serialization to perform roughly the same speed as a handwritten serializer +//! for the specific selection of data structure and data format. +//! +//! ### Data formats +//! +//! The following is a partial list of data formats that have been implemented +//! for Serde by the community. +//! +//! - [JSON](https://github.com/serde-rs/json), the ubiquitous JavaScript Object +//! Notation used by many HTTP APIs. +//! - [Bincode](https://github.com/TyOverby/bincode), a compact binary format +//! used for IPC within the Servo rendering engine. +//! - [CBOR](https://github.com/pyfisch/cbor), a Concise Binary Object +//! Representation designed for small message size without the need for +//! version negotiation. +//! - [YAML](https://github.com/dtolnay/serde-yaml), a popular human-friendly +//! configuration language that ain't markup language. +//! - [MessagePack](https://github.com/3Hren/msgpack-rust), an efficient binary +//! format that resembles a compact JSON. +//! - [TOML](https://github.com/alexcrichton/toml-rs), a minimal configuration +//! format used by [Cargo](http://doc.crates.io/manifest.html). +//! - [Pickle](https://github.com/birkenfeld/serde-pickle), a format common in +//! the Python world. +//! - [Hjson](https://github.com/laktak/hjson-rust), a variant of JSON designed +//! to be readable and writable by humans. +//! - [BSON](https://github.com/zonyitoo/bson-rs), the data storage and network +//! transfer format used by MongoDB. +//! - [URL](https://github.com/nox/serde_urlencoded), the x-www-form-urlencoded +//! format. +//! - [XML](https://github.com/serde-rs/xml), the flexible machine-friendly W3C +//! standard. *(deserialization only)* +//! - [Envy](https://github.com/softprops/envy), a way to deserialize +//! environment variables into Rust structs. *(deserialization only)* +//! - [Redis](https://github.com/OneSignal/serde-redis), deserialize values from +//! Redis when using [redis-rs](https://crates.io/crates/redis). +//! *(deserialization only)* #![doc(html_root_url="https://docs.serde.rs")] #![cfg_attr(not(feature = "std"), no_std)] @@ -45,6 +95,7 @@ mod macros; pub mod bytes; pub mod de; #[cfg(feature = "std")] +#[doc(hidden)] pub mod iter; pub mod ser; #[cfg_attr(feature = "std", doc(hidden))] diff --git a/serde/src/macros.rs b/serde/src/macros.rs index 44718108..0a8416ac 100644 --- a/serde/src/macros.rs +++ b/serde/src/macros.rs @@ -124,28 +124,70 @@ macro_rules! forward_to_deserialize_helper { }; } -/// Helper to forward `Deserializer` methods to `Deserializer::deserialize`. -/// Every given method ignores all arguments and forwards to `deserialize`. -/// Note that `deserialize_enum` simply returns an `Error::invalid_type`; a -/// better approach is tracked in [serde-rs/serde#521][1]. +// Super explicit first paragraph because this shows up at the top level and +// trips up people who are just looking for basic Serialize / Deserialize +// documentation. +// +/// Helper macro when implementing the `Deserializer` part of a new data format +/// for Serde. /// -/// ```rust,ignore +/// Some `Deserializer` implementations for self-describing formats do not care +/// what hint the `Visitor` gives them, they just want to blindly call the +/// `Visitor` method corresponding to the data they can tell is in the input. +/// This requires repetitive implementations of all the `Deserializer` trait +/// methods. +/// +/// ```rust +/// # #[macro_use] extern crate serde; +/// # use serde::de::{value, Deserializer, Visitor}; +/// # pub struct MyDeserializer; +/// # impl Deserializer for MyDeserializer { +/// # type Error = value::Error; +/// # fn deserialize(self, _: V) -> Result +/// # where V: Visitor +/// # { unimplemented!() } +/// # +/// #[inline] +/// fn deserialize_bool(self, visitor: V) -> Result +/// where V: Visitor +/// { +/// self.deserialize(visitor) +/// } +/// # forward_to_deserialize! { +/// # usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string +/// # unit option seq seq_fixed_size bytes byte_buf map unit_struct +/// # newtype_struct tuple_struct struct struct_field tuple enum ignored_any +/// # } +/// # } +/// # fn main() {} +/// ``` +/// +/// The `forward_to_deserialize!` macro implements these simple forwarding +/// methods so that they forward directly to `Deserializer::deserialize`. You +/// can choose which methods to forward. +/// +/// ```rust +/// # #[macro_use] extern crate serde; +/// # use serde::de::{value, Deserializer, Visitor}; +/// # pub struct MyDeserializer; /// impl Deserializer for MyDeserializer { +/// # type Error = value::Error; /// fn deserialize(self, visitor: V) -> Result /// where V: Visitor /// { /// /* ... */ +/// # let _ = visitor; +/// # unimplemented!() /// } /// /// forward_to_deserialize! { -/// bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string -/// unit option seq seq_fixed_size bytes map unit_struct newtype_struct -/// tuple_struct struct struct_field tuple enum ignored_any +/// bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str +/// string unit option seq seq_fixed_size bytes byte_buf map unit_struct +/// newtype_struct tuple_struct struct struct_field tuple enum ignored_any /// } /// } +/// # fn main() {} /// ``` -/// -/// [1]: https://github.com/serde-rs/serde/issues/521 #[macro_export] macro_rules! forward_to_deserialize { ($($func:ident)*) => { diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index 734337e9..c08f56ec 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -1,9 +1,3 @@ -//! Implementations for all of Rust's builtin types. Tuples implement the `Serialize` trait if they -//! have at most 16 fields. Arrays implement the `Serialize` trait if their length is 32 or less. -//! You can always forward array serialization to slice serialization, which works for any length. -//! Long tuples are best replaced by tuple structs, for which you can use `derive(Serialize)`. In -//! that case the number of fields is irrelevant. - #[cfg(feature = "std")] use std::borrow::Cow; #[cfg(all(feature = "collections", not(feature = "std")))] @@ -772,7 +766,7 @@ impl Serialize for path::Path { { match self.to_str() { Some(s) => s.serialize(serializer), - None => Err(Error::custom("Path contains invalid UTF-8 characters")), + None => Err(Error::custom("path contains invalid UTF-8 characters")), } } } diff --git a/serde/src/ser/mod.rs b/serde/src/ser/mod.rs index f755579d..1fa47114 100644 --- a/serde/src/ser/mod.rs +++ b/serde/src/ser/mod.rs @@ -1,14 +1,97 @@ -//! Generic serialization framework. -//! # For Developers who want to serialize objects -//! Implement the `Serialize` trait for the type of objects you want to serialize. Call methods of -//! the `serializer` object. For which methods to call and how to do so, look at the documentation -//! of the `Serializer` trait. +//! Generic data structure serialization framework. //! -//! # For Serialization Format Developers -//! Implement the `Serializer` trait for a structure that contains fields that enable it to write -//! the serialization result to your target. When a method's argument is an object of type -//! `Serialize`, you can either forward the serializer object (`self`) or create a new one, -//! depending on the quirks of your format. +//! The two most important traits in this module are `Serialize` and +//! `Serializer`. +//! +//! - **A type that implements `Serialize` is a data structure** that can be +//! serialized to any data format supported by Serde, and conversely +//! - **A type that implements `Serializer` is a data format** that can +//! serialize any data structure supported by Serde. +//! +//! # The Serialize trait +//! +//! Serde provides `Serialize` implementations for many Rust primitive and +//! standard library types. The complete list is below. All of these can be +//! serialized using Serde out of the box. +//! +//! Additionally, Serde provides a procedural macro called `serde_derive` to +//! automatically generate `Serialize` implementations for structs and enums in +//! your program. See the [codegen section of the manual][codegen] for how to +//! use this. +//! +//! In rare cases it may be necessary to implement `Serialize` manually for some +//! type in your program. See the [Implementing `Serialize`][impl-serialize] +//! section of the manual for more about this. +//! +//! Third-party crates may provide `Serialize` implementations for types that +//! they expose. For example the `linked-hash-map` crate provides a +//! `LinkedHashMap` type that is serializable by Serde because the crate +//! provides an implementation of `Serialize` for it. +//! +//! # The Serializer trait +//! +//! `Serializer` implementations are provided by third-party crates, for example +//! [`serde_json`][serde_json], [`serde_yaml`][serde_yaml] and +//! [`bincode`][bincode]. +//! +//! A partial list of well-maintained formats is given on the [Serde +//! website][data-formats]. +//! +//! # Implementations of Serialize provided by Serde +//! +//! - **Primitive types**: +//! - bool +//! - isize, i8, i16, i32, i64 +//! - usize, u8, u16, u32, u64 +//! - f32, f64 +//! - char +//! - str +//! - &T and &mut T +//! - **Compound types**: +//! - [T] +//! - [T; 0] through [T; 32] +//! - tuples up to size 16 +//! - **Common standard library types**: +//! - String +//! - Option\ +//! - Result\ +//! - PhantomData\ +//! - **Wrapper types**: +//! - Box\ +//! - Rc\ +//! - Arc\ +//! - Cow\<'a, T\> +//! - **Collection types**: +//! - BTreeMap\ +//! - BTreeSet\ +//! - BinaryHeap\ +//! - HashMap\ +//! - HashSet\ +//! - LinkedList\ +//! - VecDeque\ +//! - Vec\ +//! - EnumSet\ (unstable) +//! - Range\ (unstable) +//! - RangeInclusive\ (unstable) +//! - **Miscellaneous standard library types**: +//! - Duration +//! - Path +//! - PathBuf +//! - NonZero\ (unstable) +//! - **Net types**: +//! - IpAddr +//! - Ipv4Addr +//! - Ipv6Addr +//! - SocketAddr +//! - SocketAddrV4 +//! - SocketAddrV6 +//! +//! [codegen]: https://serde.rs/codegen.html +//! [impl-serialize]: https://serde.rs/impl-serialize.html +//! [serde_json]: https://github.com/serde-rs/json +//! [serde_yaml]: https://github.com/dtolnay/serde-yaml +//! [bincode]: https://github.com/TyOverby/bincode +//! [data-formats]: https://serde.rs/#data-formats #[cfg(feature = "std")] use std::error; @@ -20,52 +103,146 @@ use core::cell::RefCell; use core::fmt::Display; -pub mod impls; +mod impls; /////////////////////////////////////////////////////////////////////////////// -/// `Error` is a trait that allows a `Serialize` to generically create a -/// `Serializer` error. +/// Trait used by `Serialize` implementations to generically construct errors +/// belonging to the `Serializer` against which they are currently running. pub trait Error: Sized + error::Error { - /// Raised when there is a general error when serializing a type. + /// Raised when a `Serialize` implementation encounters a general error + /// while serializing a type. + /// + /// The message should not be capitalized and should not end with a period. + /// + /// For example, a filesystem `Path` may refuse to serialize itself if it + /// contains invalid UTF-8 data. + /// + /// ```rust + /// # use serde::ser::{Serialize, Serializer, Error}; + /// # struct Path; + /// # impl Path { fn to_str(&self) -> Option<&str> { unimplemented!() } } + /// impl Serialize for Path { + /// fn serialize(&self, serializer: S) -> Result + /// where S: Serializer + /// { + /// match self.to_str() { + /// Some(s) => s.serialize(serializer), + /// None => Err(Error::custom("path contains invalid UTF-8 characters")), + /// } + /// } + /// } + /// ``` fn custom(msg: T) -> Self; } /////////////////////////////////////////////////////////////////////////////// -/// A trait that describes a type that can be serialized by a `Serializer`. +/// An implementation of this trait is a **data structure** that can be +/// serialized into any data format supported by Serde. +/// +/// Serde provides `Serialize` implementations for many Rust primitive and +/// standard library types. The complete list is [here][ser]. All of these can +/// be serialized using Serde out of the box. +/// +/// Additionally, Serde provides a procedural macro called `serde_derive` to +/// automatically generate `Serialize` implementations for structs and enums in +/// your program. See the [codegen section of the manual][codegen] for how to +/// use this. +/// +/// In rare cases it may be necessary to implement `Serialize` manually for some +/// type in your program. See the [Implementing `Serialize`][impl-serialize] +/// section of the manual for more about this. +/// +/// Third-party crates may provide `Serialize` implementations for types that +/// they expose. For example the `linked-hash-map` crate provides a +/// `LinkedHashMap` type that is serializable by Serde because the crate +/// provides an implementation of `Serialize` for it. +/// +/// [ser]: https://docs.serde.rs/serde/ser/index.html +/// [codegen]: https://serde.rs/codegen.html +/// [impl-serialize]: https://serde.rs/impl-serialize.html pub trait Serialize { - /// Serializes this value into this serializer. + /// Serialize this value into the given Serde serializer. + /// + /// See the [Implementing `Serialize`][impl-serialize] section of the manual + /// for more information about how to implement this method. + /// + /// [impl-serialize]: https://serde.rs/impl-serialize.html fn serialize(&self, serializer: S) -> Result where S: Serializer; } /////////////////////////////////////////////////////////////////////////////// -/// A trait that describes a type that can serialize a stream of values into the underlying format. +/// An implementation of this trait is a **data format** that can serialize any +/// data structure supported by Serde. /// -/// # For `Serialize` Developers -/// Non-aggregate types like integers and strings can be serialized directly by calling the -/// appropriate function. For Aggregate types there's an initial `serialize_T` method that yields -/// a State object that you should not interact with. For each part of the aggregate there's a -/// `serialize_T_elt` method that allows you to pass values or key/value pairs. The types of the -/// values or the keys may change between calls, but the serialization format may not necessarily -/// accept it. The `serialize_T_elt` method also takes a mutable reference to the state object. -/// Make sure that you always use the same state object and only the state object that was returned -/// by the `serialize_T` method. Finally, when your object is done, call the `serialize_T_end` -/// method and pass the state object by value +/// The role of this trait is to define the serialization half of the Serde data +/// model, which is a way to categorize every Rust data structure into one of 30 +/// possible types. Each method of the `Serializer` trait corresponds to one of +/// the types of the data model. /// -/// # For Serialization Format Developers -/// If your format has different situations where it accepts different types, create a -/// `Serializer` for each situation. You can create the sub-`Serializer` in one of the aggregate -/// `serialize_T` methods and return it as a state object. Remember to also set the corresponding -/// associated type `TState`. In the `serialize_T_elt` methods you will be given a mutable -/// reference to that state. You do not need to do any additional checks for the correctness of the -/// state object, as it is expected that the user will not modify it. Due to the generic nature -/// of the `Serialize` impls, modifying the object is impossible on stable Rust. +/// Implementations of `Serialize` map themselves into this data model by +/// invoking exactly one of the `Serializer` methods. +/// +/// The types that make up the Serde data model are: +/// +/// - 15 primitive types: +/// - bool +/// - isize, i8, i16, i32, i64 +/// - usize, u8, u16, u32, u64 +/// - f32, f64 +/// - char +/// - string +/// - byte array - [u8] +/// - option +/// - either none or some value +/// - unit +/// - unit is the type of () in Rust +/// - unit_struct +/// - for example `struct Unit` or `PhantomData` +/// - unit_variant +/// - the `E::A` and `E::B` in `enum E { A, B }` +/// - newtype_struct +/// - for example `struct Millimeters(u8)` +/// - newtype_variant +/// - the `E::N` in `enum E { N(u8) }` +/// - seq +/// - a dynamically sized sequence of values, for example `Vec` or +/// `HashSet` +/// - seq_fixed_size +/// - a statically sized sequence of values for which the size will be known +/// at deserialization time without looking at the serialized data, for +/// example `[u64; 10]` +/// - tuple +/// - for example `(u8,)` or `(String, u64, Vec)` +/// - tuple_struct +/// - for example `struct Rgb(u8, u8, u8)` +/// - tuple_variant +/// - the `E::T` in `enum E { T(u8, u8) }` +/// - map +/// - for example `BTreeMap` +/// - struct +/// - a key-value pairing in which the keys will be known at deserialization +/// time without looking at the serialized data, for example `struct S { r: +/// u8, g: u8, b: u8 }` +/// - struct_variant +/// - the `E::S` in `enum E { S { r: u8, g: u8, b: u8 } }` +/// +/// Many Serde serializers produce text or binary data as output, for example +/// JSON or Bincode. This is not a requirement of the `Serializer` trait, and +/// there are serializers that do not produce text or binary output. One example +/// is the `serde_json::value::Serializer` (distinct from the main `serde_json` +/// serializer) that produces a `serde_json::Value` data structure in memory as +/// output. pub trait Serializer { - /// Trickery to enforce correct use of the `Serialize` trait. Every - /// `Serializer` should set `Ok = ()`. + /// The output type produced by this `Serializer` during successful + /// serialization. Most serializers that produce text or binary output + /// should set `Ok = ()` and serialize into an `io::Write` or buffer + /// contained within the `Serializer` instance. Serializers that build + /// in-memory data structures may be simplified by using `Ok` to propagate + /// the data structure around. type Ok; /// The error type when some error occurs during serialization. @@ -99,75 +276,99 @@ pub trait Serializer { /// content of the struct variant. type SerializeStructVariant: SerializeStructVariant; - /// Serializes a `bool` value. + /// Serialize a `bool` value. fn serialize_bool(self, v: bool) -> Result; - /// Serializes an `isize` value. If the format does not differentiate - /// between `isize` and `i64`, a reasonable implementation would be to cast - /// the value to `i64` and forward to `serialize_i64`. + /// Serialize an `isize` value. + /// + /// If the format does not differentiate between `isize` and `i64`, a + /// reasonable implementation would be to cast the value to `i64` and + /// forward to `serialize_i64`. fn serialize_isize(self, v: isize) -> Result; - /// Serializes an `i8` value. If the format does not differentiate between - /// `i8` and `i64`, a reasonable implementation would be to cast the value - /// to `i64` and forward to `serialize_i64`. + /// Serialize an `i8` value. + /// + /// If the format does not differentiate between `i8` and `i64`, a + /// reasonable implementation would be to cast the value to `i64` and + /// forward to `serialize_i64`. fn serialize_i8(self, v: i8) -> Result; - /// Serializes an `i16` value. If the format does not differentiate between - /// `i16` and `i64`, a reasonable implementation would be to cast the value - /// to `i64` and forward to `serialize_i64`. + /// Serialize an `i16` value. + /// + /// If the format does not differentiate between `i16` and `i64`, a + /// reasonable implementation would be to cast the value to `i64` and + /// forward to `serialize_i64`. fn serialize_i16(self, v: i16) -> Result; - /// Serializes an `i32` value. If the format does not differentiate between - /// `i32` and `i64`, a reasonable implementation would be to cast the value - /// to `i64` and forward to `serialize_i64`. + /// Serialize an `i32` value. + /// + /// If the format does not differentiate between `i32` and `i64`, a + /// reasonable implementation would be to cast the value to `i64` and + /// forward to `serialize_i64`. fn serialize_i32(self, v: i32) -> Result; - /// Serializes an `i64` value. + /// Serialize an `i64` value. fn serialize_i64(self, v: i64) -> Result; - /// Serializes a `usize` value. If the format does not differentiate between - /// `usize` and `u64`, a reasonable implementation would be to cast the - /// value to `u64` and forward to `serialize_u64`. + /// Serialize a `usize` value. + /// + /// If the format does not differentiate between `usize` and `u64`, a + /// reasonable implementation would be to cast the value to `u64` and + /// forward to `serialize_u64`. fn serialize_usize(self, v: usize) -> Result; - /// Serializes a `u8` value. If the format does not differentiate between - /// `u8` and `u64`, a reasonable implementation would be to cast the value - /// to `u64` and forward to `serialize_u64`. + /// Serialize a `u8` value. + /// + /// If the format does not differentiate between `u8` and `u64`, a + /// reasonable implementation would be to cast the value to `u64` and + /// forward to `serialize_u64`. fn serialize_u8(self, v: u8) -> Result; - /// Serializes a `u16` value. If the format does not differentiate between - /// `u16` and `u64`, a reasonable implementation would be to cast the value - /// to `u64` and forward to `serialize_u64`. + /// Serialize a `u16` value. + /// + /// If the format does not differentiate between `u16` and `u64`, a + /// reasonable implementation would be to cast the value to `u64` and + /// forward to `serialize_u64`. fn serialize_u16(self, v: u16) -> Result; - /// Serializes a `u32` value. If the format does not differentiate between - /// `u32` and `u64`, a reasonable implementation would be to cast the value - /// to `u64` and forward to `serialize_u64`. + /// Serialize a `u32` value. + /// + /// If the format does not differentiate between `u32` and `u64`, a + /// reasonable implementation would be to cast the value to `u64` and + /// forward to `serialize_u64`. fn serialize_u32(self, v: u32) -> Result; - /// `Serializes a `u64` value. + /// Serialize a `u64` value. fn serialize_u64(self, v: u64) -> Result; - /// Serializes an `f32` value. If the format does not differentiate between - /// `f32` and `f64`, a reasonable implementation would be to cast the value - /// to `f64` and forward to `serialize_f64`. + /// Serialize an `f32` value. + /// + /// If the format does not differentiate between `f32` and `f64`, a + /// reasonable implementation would be to cast the value to `f64` and + /// forward to `serialize_f64`. fn serialize_f32(self, v: f32) -> Result; - /// Serializes an `f64` value. + /// Serialize an `f64` value. fn serialize_f64(self, v: f64) -> Result; - /// Serializes a character. If the format does not support characters, - /// it is reasonable to serialize it as a single element `str` or a `u32`. + /// Serialize a character. + /// + /// If the format does not support characters, it is reasonable to serialize + /// it as a single element `str` or a `u32`. fn serialize_char(self, v: char) -> Result; - /// Serializes a `&str`. + /// Serialize a `&str`. fn serialize_str(self, value: &str) -> Result; + /// Serialize a chunk of raw byte data. + /// /// Enables serializers to serialize byte slices more compactly or more /// efficiently than other types of slices. If no efficient implementation /// is available, a reasonable implementation would be to forward to - /// `serialize_seq`. If forwarded, the implementation looks usually just like this: - /// ```rust + /// `serialize_seq`. If forwarded, the implementation looks usually just + /// like this: + /// + /// ```rust,ignore /// let mut seq = self.serialize_seq(Some(value.len()))?; /// for b in value { /// seq.serialize_element(b)?; @@ -176,19 +377,40 @@ pub trait Serializer { /// ``` fn serialize_bytes(self, value: &[u8]) -> Result; - /// Serializes a `()` value. It's reasonable to just not serialize anything. + /// Serialize a `None` value. + fn serialize_none(self) -> Result; + + /// Serialize a `Some(T)` value. + fn serialize_some( + self, + value: &T, + ) -> Result; + + /// Serialize a `()` value. fn serialize_unit(self) -> Result; - /// Serializes a unit struct value. A reasonable implementation would be to - /// forward to `serialize_unit`. + /// Serialize a unit struct like `struct Unit` or `PhantomData`. + /// + /// A reasonable implementation would be to forward to `serialize_unit`. fn serialize_unit_struct( self, name: &'static str, ) -> Result; - /// Serializes a unit variant, otherwise known as a variant with no - /// arguments. A reasonable implementation would be to forward to - /// `serialize_unit`. + /// Serialize a unit variant like `E::A` in `enum E { A, B }`. + /// + /// The `name` is the name of the enum, the `variant_index` is the index of + /// this variant within the enum, and the `variant` is the name of the + /// variant. + /// + /// A reasonable implementation would be to forward to `serialize_unit`. + /// + /// ```rust,ignore + /// match *self { + /// E::A => serializer.serialize_unit_variant("E", 0, "A"), + /// E::B => serializer.serialize_unit_variant("E", 1, "B"), + /// } + /// ``` fn serialize_unit_variant( self, name: &'static str, @@ -196,19 +418,32 @@ pub trait Serializer { variant: &'static str, ) -> Result; - /// Allows a tuple struct with a single element, also known as a newtype - /// struct, to be more efficiently serialized than a tuple struct with - /// multiple items. A reasonable implementation would be to forward to - /// `serialize_tuple_struct` or to just serialize the inner value without wrapping. + /// Serialize a newtype struct like `struct Millimeters(u8)`. + /// + /// Serializers are encouraged to treat newtype structs as insignificant + /// wrappers around the data they contain. A reasonable implementation would + /// be to forward to `value.serialize(self)`. + /// + /// ```rust,ignore + /// serializer.serialize_newtype_struct("Millimeters", &self.0) + /// ``` fn serialize_newtype_struct( self, name: &'static str, value: &T, ) -> Result; - /// Allows a variant with a single item to be more efficiently serialized - /// than a variant with multiple items. A reasonable implementation would be - /// to forward to `serialize_tuple_variant`. + /// Serialize a newtype variant like `E::N` in `enum E { N(u8) }`. + /// + /// The `name` is the name of the enum, the `variant_index` is the index of + /// this variant within the enum, and the `variant` is the name of the + /// variant. The `value` is the data contained within this newtype variant. + /// + /// ```rust,ignore + /// match *self { + /// E::N(ref n) => serializer.serialize_newtype_variant("E", 0, "N", n), + /// } + /// ``` fn serialize_newtype_variant( self, name: &'static str, @@ -217,53 +452,96 @@ pub trait Serializer { value: &T, ) -> Result; - /// Serializes a `None` value. - fn serialize_none(self) -> Result; - - /// Serializes a `Some(...)` value. - fn serialize_some( - self, - value: &T, - ) -> Result; - - /// Begins to serialize a sequence. This call must be followed by zero or - /// more calls to `serialize_seq_elt`, then a call to `serialize_seq_end`. + /// Begin to serialize a dynamically sized sequence. This call must be + /// followed by zero or more calls to `serialize_element`, then a call to + /// `end`. + /// + /// The argument is the number of elements in the sequence, which may or may + /// not be computable before the sequence is iterated. Some serializers only + /// support sequences whose length is known up front. + /// + /// ```rust,ignore + /// let mut seq = serializer.serialize_seq(Some(self.len()))?; + /// for element in self { + /// seq.serialize_element(element)?; + /// } + /// seq.end() + /// ``` fn serialize_seq( self, len: Option, ) -> Result; - /// Begins to serialize a sequence whose length will be known at - /// deserialization time. This call must be followed by zero or more calls - /// to `serialize_seq_elt`, then a call to `serialize_seq_end`. A reasonable - /// implementation would be to forward to `serialize_seq`. + /// Begin to serialize a statically sized sequence whose length will be + /// known at deserialization time without looking at the serialized data. + /// This call must be followed by zero or more calls to `serialize_element`, + /// then a call to `end`. + /// + /// ```rust,ignore + /// let mut seq = serializer.serialize_seq_fixed_size(self.len())?; + /// for element in self { + /// seq.serialize_element(element)?; + /// } + /// seq.end() + /// ``` fn serialize_seq_fixed_size( self, size: usize, ) -> Result; - /// Begins to serialize a tuple. This call must be followed by zero or more - /// calls to `serialize_tuple_elt`, then a call to `serialize_tuple_end`. A - /// reasonable implementation would be to forward to `serialize_seq`. + /// Begin to serialize a tuple. This call must be followed by zero or more + /// calls to `serialize_field`, then a call to `end`. + /// + /// ```rust,ignore + /// let mut tup = serializer.serialize_tuple(3)?; + /// tup.serialize_field(&self.0)?; + /// tup.serialize_field(&self.1)?; + /// tup.serialize_field(&self.2)?; + /// tup.end() + /// ``` fn serialize_tuple( self, len: usize, ) -> Result; - /// Begins to serialize a tuple struct. This call must be followed by zero - /// or more calls to `serialize_tuple_struct_elt`, then a call to - /// `serialize_tuple_struct_end`. A reasonable implementation would be to - /// forward to `serialize_tuple`. + /// Begin to serialize a tuple struct like `struct Rgb(u8, u8, u8)`. This + /// call must be followed by zero or more calls to `serialize_field`, then a + /// call to `end`. + /// + /// The `name` is the name of the tuple struct and the `len` is the number + /// of data fields that will be serialized. + /// + /// ```rust,ignore + /// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?; + /// ts.serialize_field(&self.0)?; + /// ts.serialize_field(&self.1)?; + /// ts.serialize_field(&self.2)?; + /// ts.end() + /// ``` fn serialize_tuple_struct( self, name: &'static str, len: usize, ) -> Result; - /// Begins to serialize a tuple variant. This call must be followed by zero - /// or more calls to `serialize_tuple_variant_elt`, then a call to - /// `serialize_tuple_variant_end`. A reasonable implementation would be to - /// forward to `serialize_tuple_struct`. + /// Begin to serialize a tuple variant like `E::T` in `enum E { T(u8, u8) + /// }`. This call must be followed by zero or more calls to + /// `serialize_field`, then a call to `end`. + /// + /// The `name` is the name of the enum, the `variant_index` is the index of + /// this variant within the enum, the `variant` is the name of the variant, + /// and the `len` is the number of data fields that will be serialized. + /// + /// ```rust,ignore + /// match *self { + /// E::T(ref a, ref b) => { + /// let mut tv = serializer.serialize_tuple_variant("E", 0, "T", 2)?; + /// tv.serialize_field(a)?; + /// tv.serialize_field(b)?; + /// tv.end() + /// } + /// } + /// ``` fn serialize_tuple_variant( self, name: &'static str, @@ -272,25 +550,65 @@ pub trait Serializer { len: usize, ) -> Result; - /// Begins to serialize a map. This call must be followed by zero or more - /// calls to `serialize_map_key` and `serialize_map_value`, then a call to - /// `serialize_map_end`. + /// Begin to serialize a map. This call must be followed by zero or more + /// calls to `serialize_key` and `serialize_value`, then a call to `end`. + /// + /// The argument is the number of elements in the map, which may or may not + /// be computable before the map is iterated. Some serializers only support + /// maps whose length is known up front. + /// + /// ```rust,ignore + /// let mut map = serializer.serialize_map(Some(self.len()))?; + /// for (k, v) in self { + /// map.serialize_key(k)?; + /// map.serialize_value(v)?; + /// } + /// map.end() + /// ``` fn serialize_map( self, len: Option, ) -> Result; - /// Begins to serialize a struct. This call must be followed by zero or more - /// calls to `serialize_struct_elt`, then a call to `serialize_struct_end`. + /// Begin to serialize a struct like `struct Rgb { r: u8, g: u8, b: u8 }`. + /// This call must be followed by zero or more calls to `serialize_field`, + /// then a call to `end`. + /// + /// The `name` is the name of the struct and the `len` is the number of + /// data fields that will be serialized. + /// + /// ```rust,ignore + /// let mut struc = serializer.serialize_struct("Rgb", 3)?; + /// struc.serialize_field("r", &self.r)?; + /// struc.serialize_field("g", &self.g)?; + /// struc.serialize_field("b", &self.b)?; + /// struc.end() + /// ``` fn serialize_struct( self, name: &'static str, len: usize, ) -> Result; - /// Begins to serialize a struct variant. This call must be followed by zero - /// or more calls to `serialize_struct_variant_elt`, then a call to - /// `serialize_struct_variant_end`. + /// Begin to serialize a struct variant like `E::S` in `enum E { S { r: u8, + /// g: u8, b: u8 } }`. This call must be followed by zero or more calls to + /// `serialize_field`, then a call to `end`. + /// + /// The `name` is the name of the enum, the `variant_index` is the index of + /// this variant within the enum, the `variant` is the name of the variant, + /// and the `len` is the number of data fields that will be serialized. + /// + /// ```rust,ignore + /// match *self { + /// E::S { ref r, ref g, ref b } => { + /// let mut sv = serializer.serialize_struct_variant("E", 0, "S", 3)?; + /// sv.serialize_field("r", r)?; + /// sv.serialize_field("g", g)?; + /// sv.serialize_field("b", b)?; + /// sv.end() + /// } + /// } + /// ``` fn serialize_struct_variant( self, name: &'static str, @@ -302,76 +620,115 @@ pub trait Serializer { /// Returned from `Serializer::serialize_seq` and /// `Serializer::serialize_seq_fixed_size`. +/// +/// ```rust,ignore +/// let mut seq = serializer.serialize_seq(Some(self.len()))?; +/// for element in self { +/// seq.serialize_element(element)?; +/// } +/// seq.end() +/// ``` pub trait SerializeSeq { - /// Trickery to enforce correct use of the `Serialize` trait. Every - /// `SerializeSeq` should set `Ok = ()`. + /// Must match the `Ok` type of our `Serializer`. type Ok; - /// The error type when some error occurs during serialization. + /// Must match the `Error` type of our `Serializer`. type Error: Error; - /// Serializes a sequence element. + /// Serialize a sequence element. fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error>; - /// Finishes serializing a sequence. + /// Finish serializing a sequence. fn end(self) -> Result; } /// Returned from `Serializer::serialize_tuple`. +/// +/// ```rust,ignore +/// let mut tup = serializer.serialize_tuple(3)?; +/// tup.serialize_field(&self.0)?; +/// tup.serialize_field(&self.1)?; +/// tup.serialize_field(&self.2)?; +/// tup.end() +/// ``` pub trait SerializeTuple { - /// Trickery to enforce correct use of the `Serialize` trait. Every - /// `SerializeTuple` should set `Ok = ()`. + /// Must match the `Ok` type of our `Serializer`. type Ok; - /// The error type when some error occurs during serialization. + /// Must match the `Error` type of our `Serializer`. type Error: Error; - /// Serializes a tuple element. + /// Serialize a tuple element. fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error>; - /// Finishes serializing a tuple. + /// Finish serializing a tuple. fn end(self) -> Result; } /// Returned from `Serializer::serialize_tuple_struct`. +/// +/// ```rust,ignore +/// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?; +/// ts.serialize_field(&self.0)?; +/// ts.serialize_field(&self.1)?; +/// ts.serialize_field(&self.2)?; +/// ts.end() +/// ``` pub trait SerializeTupleStruct { - /// Trickery to enforce correct use of the `Serialize` trait. Every - /// `SerializeTupleStruct` should set `Ok = ()`. + /// Must match the `Ok` type of our `Serializer`. type Ok; - /// The error type when some error occurs during serialization. + /// Must match the `Error` type of our `Serializer`. type Error: Error; - /// Serializes a tuple struct element. + /// Serialize a tuple struct field. fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error>; - /// Finishes serializing a tuple struct. + /// Finish serializing a tuple struct. fn end(self) -> Result; } /// Returned from `Serializer::serialize_tuple_variant`. +/// +/// ```rust,ignore +/// match *self { +/// E::T(ref a, ref b) => { +/// let mut tv = serializer.serialize_tuple_variant("E", 0, "T", 2)?; +/// tv.serialize_field(a)?; +/// tv.serialize_field(b)?; +/// tv.end() +/// } +/// } +/// ``` pub trait SerializeTupleVariant { - /// Trickery to enforce correct use of the `Serialize` trait. Every - /// `SerializeTupleVariant` should set `Ok = ()`. + /// Must match the `Ok` type of our `Serializer`. type Ok; - /// The error type when some error occurs during serialization. + /// Must match the `Error` type of our `Serializer`. type Error: Error; - /// Serializes a tuple variant element. + /// Serialize a tuple variant field. fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error>; - /// Finishes serializing a tuple variant. + /// Finish serializing a tuple variant. fn end(self) -> Result; } /// Returned from `Serializer::serialize_map`. +/// +/// ```rust,ignore +/// let mut map = serializer.serialize_map(Some(self.len()))?; +/// for (k, v) in self { +/// map.serialize_key(k)?; +/// map.serialize_value(v)?; +/// } +/// map.end() +/// ``` pub trait SerializeMap { - /// Trickery to enforce correct use of the `Serialize` trait. Every - /// `SerializeMap` should set `Ok = ()`. + /// Must match the `Ok` type of our `Serializer`. type Ok; - /// The error type when some error occurs during serialization. + /// Must match the `Error` type of our `Serializer`. type Error: Error; /// Serialize a map key. @@ -380,52 +737,71 @@ pub trait SerializeMap { /// Serialize a map value. fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error>; - /// Finishes serializing a map. + /// Finish serializing a map. fn end(self) -> Result; } /// Returned from `Serializer::serialize_struct`. +/// +/// ```rust,ignore +/// let mut struc = serializer.serialize_struct("Rgb", 3)?; +/// struc.serialize_field("r", &self.r)?; +/// struc.serialize_field("g", &self.g)?; +/// struc.serialize_field("b", &self.b)?; +/// struc.end() +/// ``` pub trait SerializeStruct { - /// Trickery to enforce correct use of the `Serialize` trait. Every - /// `SerializeStruct` should set `Ok = ()`. + /// Must match the `Ok` type of our `Serializer`. type Ok; - /// The error type when some error occurs during serialization. + /// Must match the `Error` type of our `Serializer`. type Error: Error; - /// Serializes a struct field. + /// Serialize a struct field. fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>; - /// Finishes serializing a struct. + /// Finish serializing a struct. fn end(self) -> Result; } /// Returned from `Serializer::serialize_struct_variant`. +/// +/// ```rust,ignore +/// match *self { +/// E::S { ref r, ref g, ref b } => { +/// let mut sv = serializer.serialize_struct_variant("E", 0, "S", 3)?; +/// sv.serialize_field("r", r)?; +/// sv.serialize_field("g", g)?; +/// sv.serialize_field("b", b)?; +/// sv.end() +/// } +/// } +/// ``` pub trait SerializeStructVariant { - /// Trickery to enforce correct use of the `Serialize` trait. Every - /// `SerializeStructVariant` should set `Ok = ()`. + /// Must match the `Ok` type of our `Serializer`. type Ok; - /// The error type when some error occurs during serialization. + /// Must match the `Error` type of our `Serializer`. type Error: Error; - /// Serialize a struct variant element. + /// Serialize a struct variant field. fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>; - /// Finishes serializing a struct variant. + /// Finish serializing a struct variant. fn end(self) -> Result; } -/// A wrapper type for iterators that implements `Serialize` for iterators whose items implement -/// `Serialize`. Don't use multiple times. Create new versions of this with the `iterator` function -/// every time you want to serialize an iterator. +/// A wrapper type for iterators that implements `Serialize` for iterators whose +/// items implement `Serialize`. Don't use multiple times. Create new versions +/// of this with the `serde::ser::iterator` function every time you want to +/// serialize an iterator. #[cfg(feature = "unstable")] pub struct Iterator(RefCell>) where ::Item: Serialize, I: IntoIterator; -/// Creates a temporary type that can be passed to any function expecting a `Serialize` and will -/// serialize the given iterator as a sequence +/// Create a wrapper type that can be passed to any function expecting a +/// `Serialize` and will serialize the given iterator as a sequence. #[cfg(feature = "unstable")] pub fn iterator(iter: I) -> Iterator where ::Item: Serialize, diff --git a/testing/tests/test_ser.rs b/testing/tests/test_ser.rs index 25df26d1..4d8e0f0e 100644 --- a/testing/tests/test_ser.rs +++ b/testing/tests/test_ser.rs @@ -432,7 +432,7 @@ fn test_cannot_serialize_paths() { assert_ser_tokens_error( &Path::new(path), &[], - Error::Message("Path contains invalid UTF-8 characters".to_owned())); + Error::Message("path contains invalid UTF-8 characters".to_owned())); let mut path_buf = PathBuf::new(); path_buf.push(path); @@ -440,7 +440,7 @@ fn test_cannot_serialize_paths() { assert_ser_tokens_error( &path_buf, &[], - Error::Message("Path contains invalid UTF-8 characters".to_owned())); + Error::Message("path contains invalid UTF-8 characters".to_owned())); } #[test]