Skip to content

Commit

Permalink
Copy around the readme examples
Browse files Browse the repository at this point in the history
  • Loading branch information
dtolnay committed Jul 25, 2017
1 parent 3aa9f83 commit 2abc142
Show file tree
Hide file tree
Showing 4 changed files with 321 additions and 0 deletions.
103 changes: 103 additions & 0 deletions src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,39 @@ use serde;
use any::Any;
use error::Error;

/// Deserialize a value of type `T` from the given trait object.
///
/// ```rust
/// extern crate erased_serde;
/// extern crate serde_json;
/// extern crate serde_cbor;
///
/// use std::collections::BTreeMap as Map;
///
/// use erased_serde::Deserializer;
///
/// fn main() {
/// static JSON: &'static [u8] = br#"{"A": 65, "B": 66}"#;
/// static CBOR: &'static [u8] = &[162, 97, 65, 24, 65, 97, 66, 24, 66];
///
/// // Construct some deserializers.
/// let json = &mut serde_json::de::Deserializer::from_slice(JSON);
/// let cbor = &mut serde_cbor::de::Deserializer::new(CBOR);
///
/// // The values in this map are boxed trait objects, which is not possible
/// // with the normal serde::Deserializer because of object safety.
/// let mut formats: Map<&str, Box<Deserializer>> = Map::new();
/// formats.insert("json", Box::new(Deserializer::erase(json)));
/// formats.insert("cbor", Box::new(Deserializer::erase(cbor)));
///
/// // Pick a Deserializer out of the formats map.
/// let format = formats.get_mut("json").unwrap();
///
/// let data: Map<String, usize> = erased_serde::deserialize(format).unwrap();
///
/// println!("{}", data["A"] + data["B"]);
/// }
/// ```
pub fn deserialize<'de, T>(deserializer: &mut Deserializer<'de>) -> Result<T, Error>
where T: serde::Deserialize<'de>
{
Expand All @@ -17,6 +50,43 @@ pub trait DeserializeSeed<'de> {
fn erased_deserialize_seed(&mut self, &mut Deserializer<'de>) -> Result<Out, Error>;
}

/// An object-safe equivalent of Serde's `Deserializer` trait.
///
/// Any implementation of Serde's `Deserializer` can be converted to an
/// `&erased_serde::Deserializer` or `Box<erased_serde::Deserializer>` trait
/// object using `erased_serde::Deserializer::erase`.
///
/// ```rust
/// extern crate erased_serde;
/// extern crate serde_json;
/// extern crate serde_cbor;
///
/// use std::collections::BTreeMap as Map;
///
/// use erased_serde::Deserializer;
///
/// fn main() {
/// static JSON: &'static [u8] = br#"{"A": 65, "B": 66}"#;
/// static CBOR: &'static [u8] = &[162, 97, 65, 24, 65, 97, 66, 24, 66];
///
/// // Construct some deserializers.
/// let json = &mut serde_json::de::Deserializer::from_slice(JSON);
/// let cbor = &mut serde_cbor::de::Deserializer::new(CBOR);
///
/// // The values in this map are boxed trait objects, which is not possible
/// // with the normal serde::Deserializer because of object safety.
/// let mut formats: Map<&str, Box<Deserializer>> = Map::new();
/// formats.insert("json", Box::new(Deserializer::erase(json)));
/// formats.insert("cbor", Box::new(Deserializer::erase(cbor)));
///
/// // Pick a Deserializer out of the formats map.
/// let format = formats.get_mut("json").unwrap();
///
/// let data: Map<String, usize> = erased_serde::deserialize(format).unwrap();
///
/// println!("{}", data["A"] + data["B"]);
/// }
/// ```
pub trait Deserializer<'de> {
fn erased_deserialize_any(&mut self, &mut Visitor<'de>) -> Result<Out, Error>;
fn erased_deserialize_bool(&mut self, &mut Visitor<'de>) -> Result<Out, Error>;
Expand Down Expand Up @@ -92,6 +162,39 @@ pub trait EnumAccess<'de> {
}

impl<'de> Deserializer<'de> {
/// Convert any Serde `Deserializer` to a trait object.
///
/// ```rust
/// extern crate erased_serde;
/// extern crate serde_json;
/// extern crate serde_cbor;
///
/// use std::collections::BTreeMap as Map;
///
/// use erased_serde::Deserializer;
///
/// fn main() {
/// static JSON: &'static [u8] = br#"{"A": 65, "B": 66}"#;
/// static CBOR: &'static [u8] = &[162, 97, 65, 24, 65, 97, 66, 24, 66];
///
/// // Construct some deserializers.
/// let json = &mut serde_json::de::Deserializer::from_slice(JSON);
/// let cbor = &mut serde_cbor::de::Deserializer::new(CBOR);
///
/// // The values in this map are boxed trait objects, which is not possible
/// // with the normal serde::Deserializer because of object safety.
/// let mut formats: Map<&str, Box<Deserializer>> = Map::new();
/// formats.insert("json", Box::new(Deserializer::erase(json)));
/// formats.insert("cbor", Box::new(Deserializer::erase(cbor)));
///
/// // Pick a Deserializer out of the formats map.
/// let format = formats.get_mut("json").unwrap();
///
/// let data: Map<String, usize> = erased_serde::deserialize(format).unwrap();
///
/// println!("{}", data["A"] + data["B"]);
/// }
/// ```
pub fn erase<D>(deserializer: D) -> erase::Deserializer<D>
where D: serde::Deserializer<'de>
{
Expand Down
1 change: 1 addition & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::fmt::{self, Display};

use serde;

/// Error when a `Serializer` or `Deserializer` trait object fails.
#[derive(Debug)]
pub struct Error {
msg: String,
Expand Down
90 changes: 90 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,93 @@
//! This crate provides type-erased versions of Serde's `Serialize`, `Serializer`
//! and `Deserializer` traits that can be used as [trait
//! objects](https://doc.rust-lang.org/book/trait-objects.html).
//!
//! The usual Serde `Serialize`, `Serializer` and `Deserializer` traits cannot
//! be used as trait objects like `&Serialize` or boxed trait objects like
//! `Box<Serialize>` because of Rust's ["object safety"
//! rules](http://huonw.github.io/blog/2015/01/object-safety/). In particular,
//! all three traits contain generic methods which cannot be made into a trait
//! object.
//!
//! **The traits in this crate work seamlessly with any existing Serde
//! `Serialize` and `Deserialize` type and any existing Serde `Serializer` and
//! `Deserializer` format.**
//!
//! ## Serialization
//!
//! ```rust
//! extern crate erased_serde;
//! extern crate serde_json;
//! extern crate serde_cbor;
//!
//! use std::collections::BTreeMap as Map;
//! use std::io;
//!
//! use erased_serde::{Serialize, Serializer};
//!
//! fn main() {
//! // Construct some serializers.
//! let json = &mut serde_json::ser::Serializer::new(io::stdout());
//! let cbor = &mut serde_cbor::ser::Serializer::new(io::stdout());
//!
//! // The values in this map are boxed trait objects. Ordinarily this would not
//! // be possible with serde::Serializer because of object safety, but type
//! // erasure makes it possible with erased_serde::Serializer.
//! let mut formats: Map<&str, Box<Serializer>> = Map::new();
//! formats.insert("json", Box::new(Serializer::erase(json)));
//! formats.insert("cbor", Box::new(Serializer::erase(cbor)));
//!
//! // These are boxed trait objects as well. Same thing here - type erasure
//! // makes this possible.
//! let mut values: Map<&str, Box<Serialize>> = Map::new();
//! values.insert("vec", Box::new(vec!["a", "b"]));
//! values.insert("int", Box::new(65536));
//!
//! // Pick a Serializer out of the formats map.
//! let format = formats.get_mut("json").unwrap();
//!
//! // Pick a Serialize out of the values map.
//! let value = values.get("vec").unwrap();
//!
//! // This line prints `["a","b"]` to stdout.
//! value.erased_serialize(format).unwrap();
//! }
//! ```
//!
//! ## Deserialization
//!
//! ```rust
//! extern crate erased_serde;
//! extern crate serde_json;
//! extern crate serde_cbor;
//!
//! use std::collections::BTreeMap as Map;
//!
//! use erased_serde::Deserializer;
//!
//! fn main() {
//! static JSON: &'static [u8] = br#"{"A": 65, "B": 66}"#;
//! static CBOR: &'static [u8] = &[162, 97, 65, 24, 65, 97, 66, 24, 66];
//!
//! // Construct some deserializers.
//! let json = &mut serde_json::de::Deserializer::from_slice(JSON);
//! let cbor = &mut serde_cbor::de::Deserializer::new(CBOR);
//!
//! // The values in this map are boxed trait objects, which is not possible
//! // with the normal serde::Deserializer because of object safety.
//! let mut formats: Map<&str, Box<Deserializer>> = Map::new();
//! formats.insert("json", Box::new(Deserializer::erase(json)));
//! formats.insert("cbor", Box::new(Deserializer::erase(cbor)));
//!
//! // Pick a Deserializer out of the formats map.
//! let format = formats.get_mut("json").unwrap();
//!
//! let data: Map<String, usize> = erased_serde::deserialize(format).unwrap();
//!
//! println!("{}", data["A"] + data["B"]);
//! }
//! ```

extern crate serde;

mod any;
Expand Down
127 changes: 127 additions & 0 deletions src/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,97 @@ use error::Error;

// TRAITS //////////////////////////////////////////////////////////////////////

/// An object-safe equivalent of Serde's `Serialize` trait.
///
/// Any implementation of Serde's `Serialize` converts seamlessly to an
/// `&erased_serde::Serialize` or `Box<erased_serde::Serialize>` trait object.
///
/// ```rust
/// extern crate erased_serde;
/// extern crate serde_json;
/// extern crate serde_cbor;
///
/// use std::collections::BTreeMap as Map;
/// use std::io;
///
/// use erased_serde::{Serialize, Serializer};
///
/// fn main() {
/// // Construct some serializers.
/// let json = &mut serde_json::ser::Serializer::new(io::stdout());
/// let cbor = &mut serde_cbor::ser::Serializer::new(io::stdout());
///
/// // The values in this map are boxed trait objects. Ordinarily this would not
/// // be possible with serde::Serializer because of object safety, but type
/// // erasure makes it possible with erased_serde::Serializer.
/// let mut formats: Map<&str, Box<Serializer>> = Map::new();
/// formats.insert("json", Box::new(Serializer::erase(json)));
/// formats.insert("cbor", Box::new(Serializer::erase(cbor)));
///
/// // These are boxed trait objects as well. Same thing here - type erasure
/// // makes this possible.
/// let mut values: Map<&str, Box<Serialize>> = Map::new();
/// values.insert("vec", Box::new(vec!["a", "b"]));
/// values.insert("int", Box::new(65536));
///
/// // Pick a Serializer out of the formats map.
/// let format = formats.get_mut("json").unwrap();
///
/// // Pick a Serialize out of the values map.
/// let value = values.get("vec").unwrap();
///
/// // This line prints `["a","b"]` to stdout.
/// value.erased_serialize(format).unwrap();
/// }
/// ```
pub trait Serialize {
fn erased_serialize(&self, &mut Serializer) -> Result<Ok, Error>;
}

/// An object-safe equivalent of Serde's `Serializer` trait.
///
/// Any implementation of Serde's `Serializer` can be converted to an
/// `&erased_serde::Serializer` or `Box<erased_serde::Serializer>` trait object
/// using `erased_serde::Serializer::erase`.
///
/// ```rust
/// extern crate erased_serde;
/// extern crate serde_json;
/// extern crate serde_cbor;
///
/// use std::collections::BTreeMap as Map;
/// use std::io;
///
/// use erased_serde::{Serialize, Serializer};
///
/// fn main() {
/// // Construct some serializers.
/// let json = &mut serde_json::ser::Serializer::new(io::stdout());
/// let cbor = &mut serde_cbor::ser::Serializer::new(io::stdout());
///
/// // The values in this map are boxed trait objects. Ordinarily this would not
/// // be possible with serde::Serializer because of object safety, but type
/// // erasure makes it possible with erased_serde::Serializer.
/// let mut formats: Map<&str, Box<Serializer>> = Map::new();
/// formats.insert("json", Box::new(Serializer::erase(json)));
/// formats.insert("cbor", Box::new(Serializer::erase(cbor)));
///
/// // These are boxed trait objects as well. Same thing here - type erasure
/// // makes this possible.
/// let mut values: Map<&str, Box<Serialize>> = Map::new();
/// values.insert("vec", Box::new(vec!["a", "b"]));
/// values.insert("int", Box::new(65536));
///
/// // Pick a Serializer out of the formats map.
/// let format = formats.get_mut("json").unwrap();
///
/// // Pick a Serialize out of the values map.
/// let value = values.get("vec").unwrap();
///
/// // This line prints `["a","b"]` to stdout.
/// value.erased_serialize(format).unwrap();
/// }
/// ```
pub trait Serializer {
fn erased_serialize_bool(&mut self, bool) -> Result<Ok, Error>;
fn erased_serialize_i8(&mut self, i8) -> Result<Ok, Error>;
Expand Down Expand Up @@ -47,6 +134,46 @@ pub trait Serializer {
}

impl Serializer {
/// Convert any Serde `Serializer` to a trait object.
///
/// ```rust
/// extern crate erased_serde;
/// extern crate serde_json;
/// extern crate serde_cbor;
///
/// use std::collections::BTreeMap as Map;
/// use std::io;
///
/// use erased_serde::{Serialize, Serializer};
///
/// fn main() {
/// // Construct some serializers.
/// let json = &mut serde_json::ser::Serializer::new(io::stdout());
/// let cbor = &mut serde_cbor::ser::Serializer::new(io::stdout());
///
/// // The values in this map are boxed trait objects. Ordinarily this would not
/// // be possible with serde::Serializer because of object safety, but type
/// // erasure makes it possible with erased_serde::Serializer.
/// let mut formats: Map<&str, Box<Serializer>> = Map::new();
/// formats.insert("json", Box::new(Serializer::erase(json)));
/// formats.insert("cbor", Box::new(Serializer::erase(cbor)));
///
/// // These are boxed trait objects as well. Same thing here - type erasure
/// // makes this possible.
/// let mut values: Map<&str, Box<Serialize>> = Map::new();
/// values.insert("vec", Box::new(vec!["a", "b"]));
/// values.insert("int", Box::new(65536));
///
/// // Pick a Serializer out of the formats map.
/// let format = formats.get_mut("json").unwrap();
///
/// // Pick a Serialize out of the values map.
/// let value = values.get("vec").unwrap();
///
/// // This line prints `["a","b"]` to stdout.
/// value.erased_serialize(format).unwrap();
/// }
/// ```
pub fn erase<S>(serializer: S) -> erase::Serializer<S>
where S: serde::Serializer,
S::Ok: 'static,
Expand Down

0 comments on commit 2abc142

Please sign in to comment.