//! Replace only top-level fields during serialization. This avoids cloning or turning //! large embedded payloads into JSON values and automatically preserves future fields. use serde::ser::{Serialize, SerializeMap, SerializeStruct, Serializer}; use serde_json::{Map, Value}; pub(super) fn replace(value: &T, fields: Map) -> serde_json::Result { value.serialize(Replace(fields)) } struct Replace(Map); struct Fields { replacements: Map, values: Map, } impl Fields { fn field(&mut self, key: &str, value: &T) -> serde_json::Result<()> { let value = match self.replacements.remove(key) { Some(value) => value, None => serde_json::to_value(value)?, }; self.values.insert(key.to_owned(), value); Ok(()) } } impl SerializeStruct for Fields { type Ok = Value; type Error = serde_json::Error; fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> { self.field(key, value) } fn end(self) -> Result { Ok(Value::Object(self.values)) } } impl SerializeMap for Fields { type Ok = Value; type Error = serde_json::Error; fn serialize_key(&mut self, _key: &T) -> Result<(), Self::Error> { Err(serde::ser::Error::custom("metadata requires map entries")) } fn serialize_value(&mut self, _value: &T) -> Result<(), Self::Error> { Err(serde::ser::Error::custom("metadata requires map entries")) } fn serialize_entry(&mut self, key: &K, value: &V) -> Result<(), Self::Error> { let key = serde_json::to_value(key)?; let key = key.as_str().ok_or_else(|| ::custom("metadata key must be a string"))?; self.field(key, value) } fn end(self) -> Result { Ok(Value::Object(self.values)) } } macro_rules! forward { ($($name:ident($($arg:ident: $ty:ty),*);)*) => {$( fn $name(self, $($arg: $ty),*) -> Result { serde_json::value::Serializer.$name($($arg),*) } )*}; } impl Serializer for Replace { type Ok = Value; type Error = serde_json::Error; type SerializeSeq = ::SerializeSeq; type SerializeTuple = ::SerializeTuple; type SerializeTupleStruct = ::SerializeTupleStruct; type SerializeTupleVariant = ::SerializeTupleVariant; type SerializeMap = Fields; type SerializeStruct = Fields; type SerializeStructVariant = ::SerializeStructVariant; forward! { serialize_bool(v: bool); serialize_i8(v: i8); serialize_i16(v: i16); serialize_i32(v: i32); serialize_i64(v: i64); serialize_u8(v: u8); serialize_u16(v: u16); serialize_u32(v: u32); serialize_u64(v: u64); serialize_f32(v: f32); serialize_f64(v: f64); serialize_char(v: char); serialize_str(v: &str); serialize_bytes(v: &[u8]); serialize_none(); serialize_unit(); serialize_unit_struct(name: &'static str); serialize_unit_variant(name: &'static str, index: u32, variant: &'static str); } fn serialize_some(self, value: &T) -> Result { serde_json::to_value(value) } fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result { serde_json::to_value(value) } fn serialize_newtype_variant( self, name: &'static str, index: u32, variant: &'static str, value: &T, ) -> Result { serde_json::value::Serializer.serialize_newtype_variant(name, index, variant, value) } fn serialize_seq(self, len: Option) -> Result { serde_json::value::Serializer.serialize_seq(len) } fn serialize_tuple(self, len: usize) -> Result { serde_json::value::Serializer.serialize_tuple(len) } fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result { serde_json::value::Serializer.serialize_tuple_struct(name, len) } fn serialize_tuple_variant( self, name: &'static str, index: u32, variant: &'static str, len: usize, ) -> Result { serde_json::value::Serializer.serialize_tuple_variant(name, index, variant, len) } fn serialize_struct_variant( self, name: &'static str, index: u32, variant: &'static str, len: usize, ) -> Result { serde_json::value::Serializer.serialize_struct_variant(name, index, variant, len) } fn serialize_map(self, _len: Option) -> Result { Ok(Fields { replacements: self.0, values: Map::new() }) } fn serialize_struct(self, _name: &'static str, _len: usize) -> Result { self.serialize_map(None) } }