From 4da77e420009ca031758b98e546f0fa8e3031f58 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 24 Feb 2017 11:43:55 -0800 Subject: [PATCH] Serialize to Content --- serde/src/de/content.rs | 1 - serde/src/ser/content.rs | 635 +++++++++++++++++++++++++++++++++++++++ serde/src/ser/mod.rs | 2 + serde/src/ser/private.rs | 73 ++++- 4 files changed, 699 insertions(+), 12 deletions(-) create mode 100644 serde/src/ser/content.rs diff --git a/serde/src/de/content.rs b/serde/src/de/content.rs index 8fd9e6ec..7e1f3cd0 100644 --- a/serde/src/de/content.rs +++ b/serde/src/de/content.rs @@ -29,7 +29,6 @@ use de::{self, Deserialize, DeserializeSeed, Deserializer, Visitor, SeqVisitor, /// Not public API. Use serde-value instead. #[derive(Debug)] pub enum Content { - // Don't mind the PhantomData, just need to use E somewhere. Bool(bool), U8(u8), diff --git a/serde/src/ser/content.rs b/serde/src/ser/content.rs new file mode 100644 index 00000000..1e73ae7e --- /dev/null +++ b/serde/src/ser/content.rs @@ -0,0 +1,635 @@ +use core::marker::PhantomData; + +#[cfg(all(not(feature = "std"), feature = "collections"))] +use collections::{String, Vec}; + +#[cfg(all(feature = "alloc", not(feature = "std")))] +use alloc::boxed::Box; + +#[cfg(feature = "collections")] +use collections::borrow::ToOwned; + +use ser::{self, Serialize, Serializer}; + +pub struct SerializeTupleVariantAsMapValue { + map: M, + name: &'static str, + fields: Vec, +} + +impl SerializeTupleVariantAsMapValue { + pub fn new(map: M, name: &'static str, len: usize) -> Self { + SerializeTupleVariantAsMapValue { + map: map, + name: name, + fields: Vec::with_capacity(len), + } + } +} + +impl ser::SerializeTupleVariant for SerializeTupleVariantAsMapValue + where M: ser::SerializeMap +{ + type Ok = M::Ok; + type Error = M::Error; + + fn serialize_field(&mut self, + value: &T) + -> Result<(), M::Error> + { + let value = try!(value.serialize(ContentSerializer::::new())); + self.fields.push(value); + Ok(()) + } + + fn end(mut self) -> Result { + try!(self.map.serialize_value(&Content::TupleStruct(self.name, self.fields))); + self.map.end() + } +} + +pub struct SerializeStructVariantAsMapValue { + map: M, + name: &'static str, + fields: Vec<(&'static str, Content)>, +} + +impl SerializeStructVariantAsMapValue { + pub fn new(map: M, name: &'static str, len: usize) -> Self { + SerializeStructVariantAsMapValue { + map: map, + name: name, + fields: Vec::with_capacity(len), + } + } +} + +impl ser::SerializeStructVariant for SerializeStructVariantAsMapValue + where M: ser::SerializeMap +{ + type Ok = M::Ok; + type Error = M::Error; + + fn serialize_field(&mut self, + key: &'static str, + value: &T) + -> Result<(), M::Error> + { + let value = try!(value.serialize(ContentSerializer::::new())); + self.fields.push((key, value)); + Ok(()) + } + + fn end(mut self) -> Result { + try!(self.map.serialize_value(&Content::Struct(self.name, self.fields))); + self.map.end() + } +} + +#[derive(Debug)] +enum Content { + Bool(bool), + + U8(u8), + U16(u16), + U32(u32), + U64(u64), + + I8(i8), + I16(i16), + I32(i32), + I64(i64), + + F32(f32), + F64(f64), + + Char(char), + String(String), + Bytes(Vec), + + None, + Some(Box), + + Unit, + UnitStruct(&'static str), + UnitVariant(&'static str, usize, &'static str), + NewtypeStruct(&'static str, Box), + NewtypeVariant(&'static str, usize, &'static str, Box), + + Seq(Vec), + SeqFixedSize(Vec), + Tuple(Vec), + TupleStruct(&'static str, Vec), + TupleVariant(&'static str, usize, &'static str, Vec), + Map(Vec<(Content, Content)>), + Struct(&'static str, Vec<(&'static str, Content)>), + StructVariant(&'static str, usize, &'static str, Vec<(&'static str, Content)>), +} + +impl Serialize for Content { + fn serialize(&self, serializer: S) -> Result + where S: Serializer + { + match *self { + Content::Bool(b) => serializer.serialize_bool(b), + Content::U8(u) => serializer.serialize_u8(u), + Content::U16(u) => serializer.serialize_u16(u), + Content::U32(u) => serializer.serialize_u32(u), + Content::U64(u) => serializer.serialize_u64(u), + Content::I8(i) => serializer.serialize_i8(i), + Content::I16(i) => serializer.serialize_i16(i), + Content::I32(i) => serializer.serialize_i32(i), + Content::I64(i) => serializer.serialize_i64(i), + Content::F32(f) => serializer.serialize_f32(f), + Content::F64(f) => serializer.serialize_f64(f), + Content::Char(c) => serializer.serialize_char(c), + Content::String(ref s) => serializer.serialize_str(s), + Content::Bytes(ref b) => serializer.serialize_bytes(b), + Content::None => serializer.serialize_none(), + Content::Some(ref c) => serializer.serialize_some(&**c), + Content::Unit => serializer.serialize_unit(), + Content::UnitStruct(n) => serializer.serialize_unit_struct(n), + Content::UnitVariant(n, i, v) => serializer.serialize_unit_variant(n, i, v), + Content::NewtypeStruct(n, ref c) => serializer.serialize_newtype_struct(n, &**c), + Content::NewtypeVariant(n, i, v, ref c) => serializer.serialize_newtype_variant(n, i, v, &**c), + Content::Seq(ref elements) => elements.serialize(serializer), + Content::SeqFixedSize(ref elements) => { + use ser::SerializeSeq; + let mut seq = try!(serializer.serialize_seq_fixed_size(elements.len())); + for e in elements { + try!(seq.serialize_element(e)); + } + seq.end() + } + Content::Tuple(ref elements) => { + use ser::SerializeTuple; + let mut tuple = try!(serializer.serialize_tuple(elements.len())); + for e in elements { + try!(tuple.serialize_element(e)); + } + tuple.end() + } + Content::TupleStruct(n, ref fields) => { + use ser::SerializeTupleStruct; + let mut ts = try!(serializer.serialize_tuple_struct(n, fields.len())); + for f in fields { + try!(ts.serialize_field(f)); + } + ts.end() + } + Content::TupleVariant(n, i, v, ref fields) => { + use ser::SerializeTupleVariant; + let mut tv = try!(serializer.serialize_tuple_variant(n, i, v, fields.len())); + for f in fields { + try!(tv.serialize_field(f)); + } + tv.end() + } + Content::Map(ref entries) => { + use ser::SerializeMap; + let mut map = try!(serializer.serialize_map(Some(entries.len()))); + for &(ref k, ref v) in entries { + try!(map.serialize_entry(k, v)); + } + map.end() + } + Content::Struct(n, ref fields) => { + use ser::SerializeStruct; + let mut s = try!(serializer.serialize_struct(n, fields.len())); + for &(ref k, ref v) in fields { + try!(s.serialize_field(k, v)); + } + s.end() + } + Content::StructVariant(n, i, v, ref fields) => { + use ser::SerializeStructVariant; + let mut sv = try!(serializer.serialize_struct_variant(n, i, v, fields.len())); + for &(ref k, ref v) in fields { + try!(sv.serialize_field(k, v)); + } + sv.end() + } + } + } +} + +struct ContentSerializer { + error: PhantomData, +} + +impl ContentSerializer { + fn new() -> Self { + ContentSerializer { + error: PhantomData, + } + } +} + +impl Serializer for ContentSerializer + where E: ser::Error +{ + type Ok = Content; + type Error = E; + + type SerializeSeq = SerializeSeq; + type SerializeTuple = SerializeTuple; + type SerializeTupleStruct = SerializeTupleStruct; + type SerializeTupleVariant = SerializeTupleVariant; + type SerializeMap = SerializeMap; + type SerializeStruct = SerializeStruct; + type SerializeStructVariant = SerializeStructVariant; + + fn serialize_bool(self, v: bool) -> Result { + Ok(Content::Bool(v)) + } + + fn serialize_i8(self, v: i8) -> Result { + Ok(Content::I8(v)) + } + + fn serialize_i16(self, v: i16) -> Result { + Ok(Content::I16(v)) + } + + fn serialize_i32(self, v: i32) -> Result { + Ok(Content::I32(v)) + } + + fn serialize_i64(self, v: i64) -> Result { + Ok(Content::I64(v)) + } + + fn serialize_u8(self, v: u8) -> Result { + Ok(Content::U8(v)) + } + + fn serialize_u16(self, v: u16) -> Result { + Ok(Content::U16(v)) + } + + fn serialize_u32(self, v: u32) -> Result { + Ok(Content::U32(v)) + } + + fn serialize_u64(self, v: u64) -> Result { + Ok(Content::U64(v)) + } + + fn serialize_f32(self, v: f32) -> Result { + Ok(Content::F32(v)) + } + + fn serialize_f64(self, v: f64) -> Result { + Ok(Content::F64(v)) + } + + fn serialize_char(self, v: char) -> Result { + Ok(Content::Char(v)) + } + + fn serialize_str(self, value: &str) -> Result { + Ok(Content::String(value.to_owned())) + } + + fn serialize_bytes(self, value: &[u8]) -> Result { + Ok(Content::Bytes(value.to_owned())) + } + + fn serialize_none(self) -> Result { + Ok(Content::None) + } + + fn serialize_some(self, + value: &T) + -> Result { + Ok(Content::Some(Box::new(try!(value.serialize(self))))) + } + + fn serialize_unit(self) -> Result { + Ok(Content::Unit) + } + + fn serialize_unit_struct(self, + name: &'static str) + -> Result { + Ok(Content::UnitStruct(name)) + } + + fn serialize_unit_variant(self, + name: &'static str, + variant_index: usize, + variant: &'static str) + -> Result { + Ok(Content::UnitVariant(name, variant_index, variant)) + } + + fn serialize_newtype_struct(self, + name: &'static str, + value: &T) + -> Result { + Ok(Content::NewtypeStruct(name, Box::new(try!(value.serialize(self))))) + } + + fn serialize_newtype_variant(self, + name: &'static str, + variant_index: usize, + variant: &'static str, + value: &T) + -> Result { + Ok(Content::NewtypeVariant(name, variant_index, variant, Box::new(try!(value.serialize(self))))) + } + + fn serialize_seq(self, + len: Option) + -> Result { + Ok(SerializeSeq { + fixed_size: false, + elements: Vec::with_capacity(len.unwrap_or(0)), + error: PhantomData, + }) + } + + fn serialize_seq_fixed_size(self, + size: usize) + -> Result { + Ok(SerializeSeq { + fixed_size: true, + elements: Vec::with_capacity(size), + error: PhantomData, + }) + } + + fn serialize_tuple(self, + len: usize) + -> Result { + Ok(SerializeTuple { + elements: Vec::with_capacity(len), + error: PhantomData, + }) + } + + fn serialize_tuple_struct(self, + name: &'static str, + len: usize) + -> Result { + Ok(SerializeTupleStruct { + name: name, + fields: Vec::with_capacity(len), + error: PhantomData, + }) + } + + fn serialize_tuple_variant(self, + name: &'static str, + variant_index: usize, + variant: &'static str, + len: usize) + -> Result { + Ok(SerializeTupleVariant { + name: name, + variant_index: variant_index, + variant: variant, + fields: Vec::with_capacity(len), + error: PhantomData, + }) + } + + fn serialize_map(self, + len: Option) + -> Result { + Ok(SerializeMap { + entries: Vec::with_capacity(len.unwrap_or(0)), + key: None, + error: PhantomData, + }) + } + + fn serialize_struct(self, + name: &'static str, + len: usize) + -> Result { + Ok(SerializeStruct { + name: name, + fields: Vec::with_capacity(len), + error: PhantomData, + }) + } + + fn serialize_struct_variant(self, + name: &'static str, + variant_index: usize, + variant: &'static str, + len: usize) + -> Result { + Ok(SerializeStructVariant { + name: name, + variant_index: variant_index, + variant: variant, + fields: Vec::with_capacity(len), + error: PhantomData, + }) + } +} + +struct SerializeSeq { + fixed_size: bool, + elements: Vec, + error: PhantomData, +} + +impl ser::SerializeSeq for SerializeSeq + where E: ser::Error +{ + type Ok = Content; + type Error = E; + + fn serialize_element(&mut self, + value: &T) + -> Result<(), E> { + let value = try!(value.serialize(ContentSerializer::::new())); + self.elements.push(value); + Ok(()) + } + + fn end(self) -> Result { + Ok(if self.fixed_size { + Content::SeqFixedSize(self.elements) + } else { + Content::Seq(self.elements) + }) + } +} + +struct SerializeTuple { + elements: Vec, + error: PhantomData, +} + +impl ser::SerializeTuple for SerializeTuple + where E: ser::Error +{ + type Ok = Content; + type Error = E; + + fn serialize_element(&mut self, + value: &T) + -> Result<(), E> { + let value = try!(value.serialize(ContentSerializer::::new())); + self.elements.push(value); + Ok(()) + } + + fn end(self) -> Result { + Ok(Content::Tuple(self.elements)) + } +} + +struct SerializeTupleStruct { + name: &'static str, + fields: Vec, + error: PhantomData, +} + +impl ser::SerializeTupleStruct for SerializeTupleStruct + where E: ser::Error +{ + type Ok = Content; + type Error = E; + + fn serialize_field(&mut self, + value: &T) + -> Result<(), E> { + let value = try!(value.serialize(ContentSerializer::::new())); + self.fields.push(value); + Ok(()) + } + + fn end(self) -> Result { + Ok(Content::TupleStruct(self.name, self.fields)) + } +} + +struct SerializeTupleVariant { + name: &'static str, + variant_index: usize, + variant: &'static str, + fields: Vec, + error: PhantomData, +} + +impl ser::SerializeTupleVariant for SerializeTupleVariant + where E: ser::Error +{ + type Ok = Content; + type Error = E; + + fn serialize_field(&mut self, + value: &T) + -> Result<(), E> { + let value = try!(value.serialize(ContentSerializer::::new())); + self.fields.push(value); + Ok(()) + } + + fn end(self) -> Result { + Ok(Content::TupleVariant(self.name, self.variant_index, self.variant, self.fields)) + } +} + +struct SerializeMap { + entries: Vec<(Content, Content)>, + key: Option, + error: PhantomData, +} + +impl ser::SerializeMap for SerializeMap + where E: ser::Error +{ + type Ok = Content; + type Error = E; + + fn serialize_key(&mut self, + key: &T) + -> Result<(), E> { + let key = try!(key.serialize(ContentSerializer::::new())); + self.key = Some(key); + Ok(()) + } + + fn serialize_value(&mut self, + value: &T) + -> Result<(), E> { + let key = self.key.take().expect("serialize_value called before serialize_key"); + let value = try!(value.serialize(ContentSerializer::::new())); + self.entries.push((key, value)); + Ok(()) + } + + fn end(self) -> Result { + Ok(Content::Map(self.entries)) + } + + fn serialize_entry(&mut self, + key: &K, + value: &V) + -> Result<(), E> { + let key = try!(key.serialize(ContentSerializer::::new())); + let value = try!(value.serialize(ContentSerializer::::new())); + self.entries.push((key, value)); + Ok(()) + } +} + +struct SerializeStruct { + name: &'static str, + fields: Vec<(&'static str, Content)>, + error: PhantomData, +} + +impl ser::SerializeStruct for SerializeStruct + where E: ser::Error +{ + type Ok = Content; + type Error = E; + + fn serialize_field(&mut self, + key: &'static str, + value: &T) + -> Result<(), E> { + let value = try!(value.serialize(ContentSerializer::::new())); + self.fields.push((key, value)); + Ok(()) + } + + fn end(self) -> Result { + Ok(Content::Struct(self.name, self.fields)) + } +} + +struct SerializeStructVariant { + name: &'static str, + variant_index: usize, + variant: &'static str, + fields: Vec<(&'static str, Content)>, + error: PhantomData, +} + +impl ser::SerializeStructVariant for SerializeStructVariant + where E: ser::Error +{ + type Ok = Content; + type Error = E; + + fn serialize_field(&mut self, + key: &'static str, + value: &T) + -> Result<(), E> { + let value = try!(value.serialize(ContentSerializer::::new())); + self.fields.push((key, value)); + Ok(()) + } + + fn end(self) -> Result { + Ok(Content::StructVariant(self.name, self.variant_index, self.variant, self.fields)) + } +} diff --git a/serde/src/ser/mod.rs b/serde/src/ser/mod.rs index 369d68b6..38f9ec7b 100644 --- a/serde/src/ser/mod.rs +++ b/serde/src/ser/mod.rs @@ -107,6 +107,8 @@ mod impossible; // Helpers used by generated code. Not public API. #[doc(hidden)] pub mod private; +#[cfg(any(feature = "std", feature = "collections"))] +mod content; pub use self::impossible::Impossible; diff --git a/serde/src/ser/private.rs b/serde/src/ser/private.rs index 9ee92684..f0754862 100644 --- a/serde/src/ser/private.rs +++ b/serde/src/ser/private.rs @@ -1,6 +1,9 @@ use core::fmt::{self, Display}; -use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct}; +use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct, Impossible}; + +#[cfg(any(feature = "std", feature = "collections"))] +use ser::content::{SerializeTupleVariantAsMapValue, SerializeStructVariantAsMapValue}; /// Not public API. pub fn serialize_tagged_newtype(serializer: S, @@ -43,6 +46,7 @@ enum Unsupported { Sequence, Tuple, TupleStruct, + #[cfg(not(any(feature = "std", feature = "collections")))] Enum, } @@ -61,6 +65,7 @@ impl Display for Unsupported { Unsupported::Sequence => formatter.write_str("a sequence"), Unsupported::Tuple => formatter.write_str("a tuple"), Unsupported::TupleStruct => formatter.write_str("a tuple struct"), + #[cfg(not(any(feature = "std", feature = "collections")))] Unsupported::Enum => formatter.write_str("an enum"), } } @@ -98,13 +103,21 @@ impl Serializer for TaggedSerializer type Ok = S::Ok; type Error = S::Error; - type SerializeSeq = S::SerializeSeq; - type SerializeTuple = S::SerializeTuple; - type SerializeTupleStruct = S::SerializeTupleStruct; - type SerializeTupleVariant = S::SerializeTupleVariant; + type SerializeSeq = Impossible; + type SerializeTuple = Impossible; + type SerializeTupleStruct = Impossible; type SerializeMap = S::SerializeMap; type SerializeStruct = S::SerializeStruct; - type SerializeStructVariant = S::SerializeStructVariant; + + #[cfg(not(any(feature = "std", feature = "collections")))] + type SerializeTupleVariant = Impossible; + #[cfg(any(feature = "std", feature = "collections"))] + type SerializeTupleVariant = SerializeTupleVariantAsMapValue; + + #[cfg(not(any(feature = "std", feature = "collections")))] + type SerializeStructVariant = Impossible; + #[cfg(any(feature = "std", feature = "collections"))] + type SerializeStructVariant = SerializeStructVariantAsMapValue; fn serialize_bool(self, _: bool) -> Result { Err(self.bad_type(Unsupported::Boolean)) @@ -183,9 +196,12 @@ impl Serializer for TaggedSerializer fn serialize_unit_variant(self, _: &'static str, _: usize, - _: &'static str) + inner_variant: &'static str) -> Result { - Err(self.bad_type(Unsupported::Enum)) + let mut map = try!(self.delegate.serialize_map(Some(2))); + try!(map.serialize_entry(self.tag, self.variant_name)); + try!(map.serialize_entry(inner_variant, &())); + map.end() } fn serialize_newtype_struct(self, @@ -200,12 +216,15 @@ impl Serializer for TaggedSerializer fn serialize_newtype_variant(self, _: &'static str, _: usize, - _: &'static str, - _: &T) + inner_variant: &'static str, + inner_value: &T) -> Result where T: Serialize { - Err(self.bad_type(Unsupported::Enum)) + let mut map = try!(self.delegate.serialize_map(Some(2))); + try!(map.serialize_entry(self.tag, self.variant_name)); + try!(map.serialize_entry(inner_variant, inner_value)); + map.end() } fn serialize_seq(self, _: Option) -> Result { @@ -227,15 +246,31 @@ impl Serializer for TaggedSerializer Err(self.bad_type(Unsupported::TupleStruct)) } + #[cfg(not(any(feature = "std", feature = "collections")))] fn serialize_tuple_variant(self, _: &'static str, _: usize, _: &'static str, _: usize) -> Result { + // Lack of push-based serialization means we need to buffer the content + // of the tuple variant, so it requires std. Err(self.bad_type(Unsupported::Enum)) } + #[cfg(any(feature = "std", feature = "collections"))] + fn serialize_tuple_variant(self, + _: &'static str, + _: usize, + inner_variant: &'static str, + len: usize) + -> Result { + let mut map = try!(self.delegate.serialize_map(Some(2))); + try!(map.serialize_entry(self.tag, self.variant_name)); + try!(map.serialize_key(inner_variant)); + Ok(SerializeTupleVariantAsMapValue::new(map, inner_variant, len)) + } + fn serialize_map(self, len: Option) -> Result { let mut map = try!(self.delegate.serialize_map(len.map(|len| len + 1))); try!(map.serialize_entry(self.tag, self.variant_name)); @@ -251,12 +286,28 @@ impl Serializer for TaggedSerializer Ok(state) } + #[cfg(not(any(feature = "std", feature = "collections")))] fn serialize_struct_variant(self, _: &'static str, _: usize, _: &'static str, _: usize) -> Result { + // Lack of push-based serialization means we need to buffer the content + // of the struct variant, so it requires std. Err(self.bad_type(Unsupported::Enum)) } + + #[cfg(any(feature = "std", feature = "collections"))] + fn serialize_struct_variant(self, + _: &'static str, + _: usize, + inner_variant: &'static str, + len: usize) + -> Result { + let mut map = try!(self.delegate.serialize_map(Some(2))); + try!(map.serialize_entry(self.tag, self.variant_name)); + try!(map.serialize_key(inner_variant)); + Ok(SerializeStructVariantAsMapValue::new(map, inner_variant, len)) + } }