| // this module is based on the content module in serde::private::ser |
| use serde::ser::{self, Serialize, Serializer}; |
| use std::cmp::Ordering; |
| use std::marker::PhantomData; |
| |
| /// Represents variable typed content. |
| /// |
| /// This is used for the serialization system to represent values |
| /// before the actual snapshots are written and is also exposed to |
| /// dynamic redaction functions. |
| /// |
| /// Some enum variants are intentionally not exposed to user code. |
| /// It's generally recommended to construct content objects by |
| /// using the [`From`](std::convert::From) trait and by using the |
| /// accessor methods to assert on it. |
| /// |
| /// While matching on the content is possible in theory it is |
| /// recommended against. The reason for this is that the content |
| /// enum holds variants that can "wrap" values where it's not |
| /// expected. For instance if a field holds an `Option<String>` |
| /// you cannot use pattern matching to extract the string as it |
| /// will be contained in an internal `Some` variant that is not |
| /// exposed. On the other hand the `as_str` method will |
| /// automatically resolve such internal wrappers. |
| /// |
| /// If you do need to pattern match you should use the |
| /// `resolve_inner` method to resolve such internal wrappers. |
| #[derive(Debug, Clone, PartialEq, PartialOrd)] |
| pub enum Content { |
| Bool(bool), |
| |
| U8(u8), |
| U16(u16), |
| U32(u32), |
| U64(u64), |
| U128(u128), |
| |
| I8(i8), |
| I16(i16), |
| I32(i32), |
| I64(i64), |
| I128(i128), |
| |
| F32(f32), |
| F64(f64), |
| |
| Char(char), |
| String(String), |
| Bytes(Vec<u8>), |
| |
| #[doc(hidden)] |
| None, |
| #[doc(hidden)] |
| Some(Box<Content>), |
| |
| #[doc(hidden)] |
| Unit, |
| #[doc(hidden)] |
| UnitStruct(&'static str), |
| #[doc(hidden)] |
| UnitVariant(&'static str, u32, &'static str), |
| #[doc(hidden)] |
| NewtypeStruct(&'static str, Box<Content>), |
| #[doc(hidden)] |
| NewtypeVariant(&'static str, u32, &'static str, Box<Content>), |
| |
| Seq(Vec<Content>), |
| #[doc(hidden)] |
| Tuple(Vec<Content>), |
| #[doc(hidden)] |
| TupleStruct(&'static str, Vec<Content>), |
| #[doc(hidden)] |
| TupleVariant(&'static str, u32, &'static str, Vec<Content>), |
| Map(Vec<(Content, Content)>), |
| #[doc(hidden)] |
| Struct(&'static str, Vec<(&'static str, Content)>), |
| #[doc(hidden)] |
| StructVariant( |
| &'static str, |
| u32, |
| &'static str, |
| Vec<(&'static str, Content)>, |
| ), |
| } |
| |
| #[derive(PartialEq, PartialOrd, Debug)] |
| pub enum Key<'a> { |
| Bool(bool), |
| U64(u64), |
| I64(i64), |
| F64(f64), |
| U128(u128), |
| I128(i128), |
| Str(&'a str), |
| Bytes(&'a [u8]), |
| Other, |
| } |
| |
| impl<'a> Eq for Key<'a> {} |
| |
| impl<'a> Ord for Key<'a> { |
| fn cmp(&self, other: &Self) -> Ordering { |
| self.partial_cmp(other).unwrap_or(Ordering::Less) |
| } |
| } |
| |
| macro_rules! impl_from { |
| ($ty:ty, $newty:ident) => { |
| impl From<$ty> for Content { |
| fn from(value: $ty) -> Content { |
| Content::$newty(value) |
| } |
| } |
| }; |
| } |
| |
| impl_from!(bool, Bool); |
| impl_from!(u8, U8); |
| impl_from!(u16, U16); |
| impl_from!(u32, U32); |
| impl_from!(u64, U64); |
| impl_from!(u128, U128); |
| impl_from!(i8, I8); |
| impl_from!(i16, I16); |
| impl_from!(i32, I32); |
| impl_from!(i64, I64); |
| impl_from!(i128, I128); |
| impl_from!(f32, F32); |
| impl_from!(f64, F64); |
| impl_from!(char, Char); |
| impl_from!(String, String); |
| impl_from!(Vec<u8>, Bytes); |
| |
| impl From<()> for Content { |
| fn from(_value: ()) -> Content { |
| Content::Unit |
| } |
| } |
| |
| impl<'a> From<&'a str> for Content { |
| fn from(value: &'a str) -> Content { |
| Content::String(value.to_string()) |
| } |
| } |
| |
| impl<'a> From<&'a [u8]> for Content { |
| fn from(value: &'a [u8]) -> Content { |
| Content::Bytes(value.to_vec()) |
| } |
| } |
| |
| impl Content { |
| /// This resolves the innermost content in a chain of |
| /// wrapped content. |
| /// |
| /// For instance if you encounter an `Option<Option<String>>` |
| /// field the content will be wrapped twice in an internal |
| /// option wrapper. If you need to pattern match you will |
| /// need in some situations to first resolve the inner value |
| /// before such matching can take place as there is no exposed |
| /// way to match on these wrappers. |
| /// |
| /// This method does not need to be called for the `as_` |
| /// methods which resolve automatically. |
| pub fn resolve_inner(&self) -> &Content { |
| match *self { |
| Content::Some(ref v) |
| | Content::NewtypeStruct(_, ref v) |
| | Content::NewtypeVariant(_, _, _, ref v) => v.resolve_inner(), |
| ref other => other, |
| } |
| } |
| |
| /// Mutable version of [`resolve_inner`](Self::resolve_inner). |
| pub fn resolve_inner_mut(&mut self) -> &mut Content { |
| match *self { |
| Content::Some(ref mut v) |
| | Content::NewtypeStruct(_, ref mut v) |
| | Content::NewtypeVariant(_, _, _, ref mut v) => v.resolve_inner_mut(), |
| ref mut other => other, |
| } |
| } |
| |
| /// Returns the value as string |
| pub fn as_str(&self) -> Option<&str> { |
| match self.resolve_inner() { |
| Content::String(ref s) => Some(s.as_str()), |
| _ => None, |
| } |
| } |
| |
| /// Returns the value as bytes |
| pub fn as_bytes(&self) -> Option<&[u8]> { |
| match self.resolve_inner() { |
| Content::Bytes(ref b) => Some(&*b), |
| _ => None, |
| } |
| } |
| |
| /// Returns the value as slice of content values. |
| pub fn as_slice(&self) -> Option<&[Content]> { |
| match self.resolve_inner() { |
| Content::Seq(ref v) | Content::Tuple(ref v) | Content::TupleVariant(_, _, _, ref v) => { |
| Some(&v[..]) |
| } |
| _ => None, |
| } |
| } |
| |
| /// Returns true if the value is nil. |
| pub fn is_nil(&self) -> bool { |
| if let Content::None | Content::Unit = self.resolve_inner() { |
| true |
| } else { |
| false |
| } |
| } |
| |
| pub(crate) fn as_key(&self) -> Key<'_> { |
| match *self.resolve_inner() { |
| Content::Bool(val) => Key::Bool(val), |
| Content::Char(val) => Key::U64(val as u64), |
| Content::U16(val) => Key::U64(val.into()), |
| Content::U32(val) => Key::U64(val.into()), |
| Content::U64(val) => Key::U64(val), |
| Content::U128(val) => Key::U128(val), |
| Content::I16(val) => Key::I64(val.into()), |
| Content::I32(val) => Key::I64(val.into()), |
| Content::I64(val) => Key::I64(val), |
| Content::I128(val) => Key::I128(val), |
| Content::F32(val) => Key::F64(val.into()), |
| Content::F64(val) => Key::F64(val), |
| Content::String(ref val) => Key::Str(&val.as_str()), |
| Content::Bytes(ref val) => Key::Bytes(&val[..]), |
| _ => Key::Other, |
| } |
| } |
| |
| /// Returns the value as bool |
| pub fn as_bool(&self) -> Option<bool> { |
| match *self.resolve_inner() { |
| Content::Bool(val) => Some(val), |
| _ => None, |
| } |
| } |
| |
| /// Returns the value as u64 |
| pub fn as_u64(&self) -> Option<u64> { |
| match *self.resolve_inner() { |
| Content::U8(v) => Some(u64::from(v)), |
| Content::U16(v) => Some(u64::from(v)), |
| Content::U32(v) => Some(u64::from(v)), |
| Content::U64(v) => Some(v), |
| Content::U128(v) => { |
| let rv = v as u64; |
| if rv as u128 == v { |
| Some(rv) |
| } else { |
| None |
| } |
| } |
| Content::I8(v) if v >= 0 => Some(v as u64), |
| Content::I16(v) if v >= 0 => Some(v as u64), |
| Content::I32(v) if v >= 0 => Some(v as u64), |
| Content::I64(v) if v >= 0 => Some(v as u64), |
| Content::I128(v) => { |
| let rv = v as u64; |
| if rv as i128 == v { |
| Some(rv) |
| } else { |
| None |
| } |
| } |
| _ => None, |
| } |
| } |
| |
| /// Returns the value as u128 |
| pub fn as_u128(&self) -> Option<u128> { |
| match *self.resolve_inner() { |
| Content::U128(v) => Some(v), |
| Content::I128(v) if v >= 0 => Some(v as u128), |
| _ => self.as_u64().map(u128::from), |
| } |
| } |
| |
| /// Returns the value as i64 |
| pub fn as_i64(&self) -> Option<i64> { |
| match *self.resolve_inner() { |
| Content::U8(v) => Some(i64::from(v)), |
| Content::U16(v) => Some(i64::from(v)), |
| Content::U32(v) => Some(i64::from(v)), |
| Content::U64(v) => { |
| let rv = v as i64; |
| if rv as u64 == v { |
| Some(rv) |
| } else { |
| None |
| } |
| } |
| Content::U128(v) => { |
| let rv = v as i64; |
| if rv as u128 == v { |
| Some(rv) |
| } else { |
| None |
| } |
| } |
| Content::I8(v) => Some(i64::from(v)), |
| Content::I16(v) => Some(i64::from(v)), |
| Content::I32(v) => Some(i64::from(v)), |
| Content::I64(v) => Some(v), |
| Content::I128(v) => { |
| let rv = v as i64; |
| if rv as i128 == v { |
| Some(rv) |
| } else { |
| None |
| } |
| } |
| _ => None, |
| } |
| } |
| |
| /// Returns the value as i128 |
| pub fn as_i128(&self) -> Option<i128> { |
| match *self.resolve_inner() { |
| Content::U128(v) => { |
| let rv = v as i128; |
| if rv as u128 == v { |
| Some(rv) |
| } else { |
| None |
| } |
| } |
| Content::I128(v) => Some(v), |
| _ => self.as_i64().map(i128::from), |
| } |
| } |
| |
| /// Returns the value as f64 |
| pub fn as_f64(&self) -> Option<f64> { |
| match *self.resolve_inner() { |
| Content::F32(v) => Some(f64::from(v)), |
| Content::F64(v) => Some(v), |
| _ => None, |
| } |
| } |
| |
| pub(crate) fn sort_maps(&mut self) { |
| self.walk(&mut |content| { |
| if let Content::Map(ref mut items) = content { |
| items.sort_by(|a, b| a.0.as_key().cmp(&b.0.as_key())); |
| } |
| true |
| }) |
| } |
| |
| /// Recursively walks the content structure mutably. |
| /// |
| /// The callback is invoked for every content in the tree. |
| pub fn walk<F: FnMut(&mut Content) -> bool>(&mut self, visit: &mut F) { |
| if !visit(self) { |
| return; |
| } |
| |
| match *self { |
| Content::Some(ref mut inner) => { |
| Self::walk(&mut *inner, visit); |
| } |
| Content::NewtypeStruct(_, ref mut inner) => { |
| Self::walk(&mut *inner, visit); |
| } |
| Content::NewtypeVariant(_, _, _, ref mut inner) => { |
| Self::walk(&mut *inner, visit); |
| } |
| Content::Seq(ref mut vec) => { |
| for inner in vec.iter_mut() { |
| Self::walk(inner, visit); |
| } |
| } |
| Content::Map(ref mut vec) => { |
| for inner in vec.iter_mut() { |
| Self::walk(&mut inner.0, visit); |
| Self::walk(&mut inner.1, visit); |
| } |
| } |
| Content::Struct(_, ref mut vec) => { |
| for inner in vec.iter_mut() { |
| Self::walk(&mut inner.1, visit); |
| } |
| } |
| Content::StructVariant(_, _, _, ref mut vec) => { |
| for inner in vec.iter_mut() { |
| Self::walk(&mut inner.1, visit); |
| } |
| } |
| Content::Tuple(ref mut vec) => { |
| for inner in vec.iter_mut() { |
| Self::walk(inner, visit); |
| } |
| } |
| Content::TupleStruct(_, ref mut vec) => { |
| for inner in vec.iter_mut() { |
| Self::walk(inner, visit); |
| } |
| } |
| Content::TupleVariant(_, _, _, ref mut vec) => { |
| for inner in vec.iter_mut() { |
| Self::walk(inner, visit); |
| } |
| } |
| _ => {} |
| } |
| } |
| } |
| |
| impl Serialize for Content { |
| fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> |
| 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::U128(u) => serializer.serialize_u128(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::I128(i) => serializer.serialize_i128(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::Tuple(ref elements) => { |
| use serde::ser::SerializeTuple; |
| let mut tuple = serializer.serialize_tuple(elements.len())?; |
| for e in elements { |
| tuple.serialize_element(e)?; |
| } |
| tuple.end() |
| } |
| Content::TupleStruct(n, ref fields) => { |
| use serde::ser::SerializeTupleStruct; |
| let mut ts = serializer.serialize_tuple_struct(n, fields.len())?; |
| for f in fields { |
| ts.serialize_field(f)?; |
| } |
| ts.end() |
| } |
| Content::TupleVariant(n, i, v, ref fields) => { |
| use serde::ser::SerializeTupleVariant; |
| let mut tv = serializer.serialize_tuple_variant(n, i, v, fields.len())?; |
| for f in fields { |
| tv.serialize_field(f)?; |
| } |
| tv.end() |
| } |
| Content::Map(ref entries) => { |
| use serde::ser::SerializeMap; |
| let mut map = serializer.serialize_map(Some(entries.len()))?; |
| for &(ref k, ref v) in entries { |
| map.serialize_entry(k, v)?; |
| } |
| map.end() |
| } |
| Content::Struct(n, ref fields) => { |
| use serde::ser::SerializeStruct; |
| let mut s = serializer.serialize_struct(n, fields.len())?; |
| for &(k, ref v) in fields { |
| s.serialize_field(k, v)?; |
| } |
| s.end() |
| } |
| Content::StructVariant(n, i, v, ref fields) => { |
| use serde::ser::SerializeStructVariant; |
| let mut sv = serializer.serialize_struct_variant(n, i, v, fields.len())?; |
| for &(k, ref v) in fields { |
| sv.serialize_field(k, v)?; |
| } |
| sv.end() |
| } |
| } |
| } |
| } |
| |
| pub struct ContentSerializer<E> { |
| error: PhantomData<E>, |
| } |
| |
| impl<E> ContentSerializer<E> { |
| pub fn new() -> Self { |
| ContentSerializer { error: PhantomData } |
| } |
| } |
| |
| impl<E> Serializer for ContentSerializer<E> |
| where |
| E: ser::Error, |
| { |
| type Ok = Content; |
| type Error = E; |
| |
| type SerializeSeq = SerializeSeq<E>; |
| type SerializeTuple = SerializeTuple<E>; |
| type SerializeTupleStruct = SerializeTupleStruct<E>; |
| type SerializeTupleVariant = SerializeTupleVariant<E>; |
| type SerializeMap = SerializeMap<E>; |
| type SerializeStruct = SerializeStruct<E>; |
| type SerializeStructVariant = SerializeStructVariant<E>; |
| |
| fn serialize_bool(self, v: bool) -> Result<Content, E> { |
| Ok(Content::Bool(v)) |
| } |
| |
| fn serialize_i8(self, v: i8) -> Result<Content, E> { |
| Ok(Content::I8(v)) |
| } |
| |
| fn serialize_i16(self, v: i16) -> Result<Content, E> { |
| Ok(Content::I16(v)) |
| } |
| |
| fn serialize_i32(self, v: i32) -> Result<Content, E> { |
| Ok(Content::I32(v)) |
| } |
| |
| fn serialize_i64(self, v: i64) -> Result<Content, E> { |
| Ok(Content::I64(v)) |
| } |
| |
| fn serialize_i128(self, v: i128) -> Result<Content, E> { |
| Ok(Content::I128(v)) |
| } |
| |
| fn serialize_u8(self, v: u8) -> Result<Content, E> { |
| Ok(Content::U8(v)) |
| } |
| |
| fn serialize_u16(self, v: u16) -> Result<Content, E> { |
| Ok(Content::U16(v)) |
| } |
| |
| fn serialize_u32(self, v: u32) -> Result<Content, E> { |
| Ok(Content::U32(v)) |
| } |
| |
| fn serialize_u64(self, v: u64) -> Result<Content, E> { |
| Ok(Content::U64(v)) |
| } |
| |
| fn serialize_u128(self, v: u128) -> Result<Content, E> { |
| Ok(Content::U128(v)) |
| } |
| |
| fn serialize_f32(self, v: f32) -> Result<Content, E> { |
| Ok(Content::F32(v)) |
| } |
| |
| fn serialize_f64(self, v: f64) -> Result<Content, E> { |
| Ok(Content::F64(v)) |
| } |
| |
| fn serialize_char(self, v: char) -> Result<Content, E> { |
| Ok(Content::Char(v)) |
| } |
| |
| fn serialize_str(self, value: &str) -> Result<Content, E> { |
| Ok(Content::String(value.to_owned())) |
| } |
| |
| fn serialize_bytes(self, value: &[u8]) -> Result<Content, E> { |
| Ok(Content::Bytes(value.to_owned())) |
| } |
| |
| fn serialize_none(self) -> Result<Content, E> { |
| Ok(Content::None) |
| } |
| |
| fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Content, E> |
| where |
| T: Serialize, |
| { |
| Ok(Content::Some(Box::new(value.serialize(self)?))) |
| } |
| |
| fn serialize_unit(self) -> Result<Content, E> { |
| Ok(Content::Unit) |
| } |
| |
| fn serialize_unit_struct(self, name: &'static str) -> Result<Content, E> { |
| Ok(Content::UnitStruct(name)) |
| } |
| |
| fn serialize_unit_variant( |
| self, |
| name: &'static str, |
| variant_index: u32, |
| variant: &'static str, |
| ) -> Result<Content, E> { |
| Ok(Content::UnitVariant(name, variant_index, variant)) |
| } |
| |
| fn serialize_newtype_struct<T: ?Sized>( |
| self, |
| name: &'static str, |
| value: &T, |
| ) -> Result<Content, E> |
| where |
| T: Serialize, |
| { |
| Ok(Content::NewtypeStruct( |
| name, |
| Box::new(value.serialize(self)?), |
| )) |
| } |
| |
| fn serialize_newtype_variant<T: ?Sized>( |
| self, |
| name: &'static str, |
| variant_index: u32, |
| variant: &'static str, |
| value: &T, |
| ) -> Result<Content, E> |
| where |
| T: Serialize, |
| { |
| Ok(Content::NewtypeVariant( |
| name, |
| variant_index, |
| variant, |
| Box::new(value.serialize(self)?), |
| )) |
| } |
| |
| fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, E> { |
| Ok(SerializeSeq { |
| elements: Vec::with_capacity(len.unwrap_or(0)), |
| error: PhantomData, |
| }) |
| } |
| |
| fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, E> { |
| Ok(SerializeTuple { |
| elements: Vec::with_capacity(len), |
| error: PhantomData, |
| }) |
| } |
| |
| fn serialize_tuple_struct( |
| self, |
| name: &'static str, |
| len: usize, |
| ) -> Result<Self::SerializeTupleStruct, E> { |
| Ok(SerializeTupleStruct { |
| name, |
| fields: Vec::with_capacity(len), |
| error: PhantomData, |
| }) |
| } |
| |
| fn serialize_tuple_variant( |
| self, |
| name: &'static str, |
| variant_index: u32, |
| variant: &'static str, |
| len: usize, |
| ) -> Result<Self::SerializeTupleVariant, E> { |
| Ok(SerializeTupleVariant { |
| name, |
| variant_index, |
| variant, |
| fields: Vec::with_capacity(len), |
| error: PhantomData, |
| }) |
| } |
| |
| fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, E> { |
| Ok(SerializeMap { |
| entries: Vec::with_capacity(len.unwrap_or(0)), |
| key: None, |
| error: PhantomData, |
| }) |
| } |
| |
| fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeStruct, E> { |
| Ok(SerializeStruct { |
| name, |
| fields: Vec::with_capacity(len), |
| error: PhantomData, |
| }) |
| } |
| |
| fn serialize_struct_variant( |
| self, |
| name: &'static str, |
| variant_index: u32, |
| variant: &'static str, |
| len: usize, |
| ) -> Result<Self::SerializeStructVariant, E> { |
| Ok(SerializeStructVariant { |
| name, |
| variant_index, |
| variant, |
| fields: Vec::with_capacity(len), |
| error: PhantomData, |
| }) |
| } |
| } |
| |
| pub struct SerializeSeq<E> { |
| elements: Vec<Content>, |
| error: PhantomData<E>, |
| } |
| |
| impl<E> ser::SerializeSeq for SerializeSeq<E> |
| where |
| E: ser::Error, |
| { |
| type Ok = Content; |
| type Error = E; |
| |
| fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), E> |
| where |
| T: Serialize, |
| { |
| let value = value.serialize(ContentSerializer::<E>::new())?; |
| self.elements.push(value); |
| Ok(()) |
| } |
| |
| fn end(self) -> Result<Content, E> { |
| Ok(Content::Seq(self.elements)) |
| } |
| } |
| |
| pub struct SerializeTuple<E> { |
| elements: Vec<Content>, |
| error: PhantomData<E>, |
| } |
| |
| impl<E> ser::SerializeTuple for SerializeTuple<E> |
| where |
| E: ser::Error, |
| { |
| type Ok = Content; |
| type Error = E; |
| |
| fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), E> |
| where |
| T: Serialize, |
| { |
| let value = value.serialize(ContentSerializer::<E>::new())?; |
| self.elements.push(value); |
| Ok(()) |
| } |
| |
| fn end(self) -> Result<Content, E> { |
| Ok(Content::Tuple(self.elements)) |
| } |
| } |
| |
| pub struct SerializeTupleStruct<E> { |
| name: &'static str, |
| fields: Vec<Content>, |
| error: PhantomData<E>, |
| } |
| |
| impl<E> ser::SerializeTupleStruct for SerializeTupleStruct<E> |
| where |
| E: ser::Error, |
| { |
| type Ok = Content; |
| type Error = E; |
| |
| fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), E> |
| where |
| T: Serialize, |
| { |
| let value = value.serialize(ContentSerializer::<E>::new())?; |
| self.fields.push(value); |
| Ok(()) |
| } |
| |
| fn end(self) -> Result<Content, E> { |
| Ok(Content::TupleStruct(self.name, self.fields)) |
| } |
| } |
| |
| pub struct SerializeTupleVariant<E> { |
| name: &'static str, |
| variant_index: u32, |
| variant: &'static str, |
| fields: Vec<Content>, |
| error: PhantomData<E>, |
| } |
| |
| impl<E> ser::SerializeTupleVariant for SerializeTupleVariant<E> |
| where |
| E: ser::Error, |
| { |
| type Ok = Content; |
| type Error = E; |
| |
| fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), E> |
| where |
| T: Serialize, |
| { |
| let value = value.serialize(ContentSerializer::<E>::new())?; |
| self.fields.push(value); |
| Ok(()) |
| } |
| |
| fn end(self) -> Result<Content, E> { |
| Ok(Content::TupleVariant( |
| self.name, |
| self.variant_index, |
| self.variant, |
| self.fields, |
| )) |
| } |
| } |
| |
| pub struct SerializeMap<E> { |
| entries: Vec<(Content, Content)>, |
| key: Option<Content>, |
| error: PhantomData<E>, |
| } |
| |
| impl<E> ser::SerializeMap for SerializeMap<E> |
| where |
| E: ser::Error, |
| { |
| type Ok = Content; |
| type Error = E; |
| |
| fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), E> |
| where |
| T: Serialize, |
| { |
| let key = key.serialize(ContentSerializer::<E>::new())?; |
| self.key = Some(key); |
| Ok(()) |
| } |
| |
| fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), E> |
| where |
| T: Serialize, |
| { |
| let key = self |
| .key |
| .take() |
| .expect("serialize_value called before serialize_key"); |
| let value = value.serialize(ContentSerializer::<E>::new())?; |
| self.entries.push((key, value)); |
| Ok(()) |
| } |
| |
| fn end(self) -> Result<Content, E> { |
| Ok(Content::Map(self.entries)) |
| } |
| |
| fn serialize_entry<K: ?Sized, V: ?Sized>(&mut self, key: &K, value: &V) -> Result<(), E> |
| where |
| K: Serialize, |
| V: Serialize, |
| { |
| let key = key.serialize(ContentSerializer::<E>::new())?; |
| let value = value.serialize(ContentSerializer::<E>::new())?; |
| self.entries.push((key, value)); |
| Ok(()) |
| } |
| } |
| |
| pub struct SerializeStruct<E> { |
| name: &'static str, |
| fields: Vec<(&'static str, Content)>, |
| error: PhantomData<E>, |
| } |
| |
| impl<E> ser::SerializeStruct for SerializeStruct<E> |
| where |
| E: ser::Error, |
| { |
| type Ok = Content; |
| type Error = E; |
| |
| fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), E> |
| where |
| T: Serialize, |
| { |
| let value = value.serialize(ContentSerializer::<E>::new())?; |
| self.fields.push((key, value)); |
| Ok(()) |
| } |
| |
| fn end(self) -> Result<Content, E> { |
| Ok(Content::Struct(self.name, self.fields)) |
| } |
| } |
| |
| pub struct SerializeStructVariant<E> { |
| name: &'static str, |
| variant_index: u32, |
| variant: &'static str, |
| fields: Vec<(&'static str, Content)>, |
| error: PhantomData<E>, |
| } |
| |
| impl<E> ser::SerializeStructVariant for SerializeStructVariant<E> |
| where |
| E: ser::Error, |
| { |
| type Ok = Content; |
| type Error = E; |
| |
| fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), E> |
| where |
| T: Serialize, |
| { |
| let value = value.serialize(ContentSerializer::<E>::new())?; |
| self.fields.push((key, value)); |
| Ok(()) |
| } |
| |
| fn end(self) -> Result<Content, E> { |
| Ok(Content::StructVariant( |
| self.name, |
| self.variant_index, |
| self.variant, |
| self.fields, |
| )) |
| } |
| } |