diff --git a/src/lib.rs b/src/lib.rs index a7b2a1b0362190154c5d3d3cdf6dbbaa13eb662d..2c99498d90d1ffb86af3bc66fc27ba927232b6ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,6 +67,7 @@ pub mod sync; pub mod tarantool; pub mod tier; pub mod tlog; +pub mod to_rmpv_named; pub mod traft; pub mod util; pub mod vshard; diff --git a/src/to_rmpv_named.rs b/src/to_rmpv_named.rs new file mode 100644 index 0000000000000000000000000000000000000000..a2397a2c996693b8638869f9f8dadf55e9e4326e --- /dev/null +++ b/src/to_rmpv_named.rs @@ -0,0 +1,1075 @@ +//! This module is copy pasted from rmpv::ext with the sole purpose to +//! implement serializing into [`rmpv::Value`] converting structs to maps +//! (instead of arrays, how [`rmpv::ext::to_value`] does it). + +use rmpv::ext::Error; +use rmpv::Value; +use serde::ser; + +struct RmpvNamedSerializer; + +/// Convert a `T` into `rmpv::Value` which is an enum that can represent any valid MessagePack data. +/// +/// Structs are converted to msgpack maps (not arrays). +/// +/// This conversion can fail if `T`'s implementation of `Serialize` decides to fail. +/// +/// ```rust +/// use picodata::to_rmpv_named::to_rmpv_named; +/// +/// let val = to_rmpv_named("John Smith").unwrap(); +/// +/// assert_eq!(rmpv::Value::String("John Smith".into()), val); +/// ``` +#[inline(always)] +pub fn to_rmpv_named<T: ser::Serialize>(value: T) -> Result<Value, Error> { + value.serialize(RmpvNamedSerializer) +} + +impl ser::Serializer for RmpvNamedSerializer { + type Ok = Value; + type Error = Error; + + type SerializeSeq = SerializeVec; + type SerializeTuple = SerializeVec; + type SerializeTupleStruct = SerializeVec; + type SerializeTupleVariant = SerializeTupleVariant; + type SerializeMap = DefaultSerializeMap; + type SerializeStruct = DefaultSerializeMap; + type SerializeStructVariant = SerializeStructVariant; + + #[inline] + fn serialize_bool(self, val: bool) -> Result<Self::Ok, Self::Error> { + Ok(Value::Boolean(val)) + } + + #[inline] + fn serialize_i8(self, val: i8) -> Result<Self::Ok, Self::Error> { + self.serialize_i64(val as i64) + } + + #[inline] + fn serialize_i16(self, val: i16) -> Result<Self::Ok, Self::Error> { + self.serialize_i64(val as i64) + } + + #[inline] + fn serialize_i32(self, val: i32) -> Result<Self::Ok, Self::Error> { + self.serialize_i64(val as i64) + } + + #[inline] + fn serialize_i64(self, val: i64) -> Result<Self::Ok, Self::Error> { + Ok(Value::from(val)) + } + + #[inline] + fn serialize_u8(self, val: u8) -> Result<Self::Ok, Self::Error> { + self.serialize_u64(val as u64) + } + + #[inline] + fn serialize_u16(self, val: u16) -> Result<Self::Ok, Self::Error> { + self.serialize_u64(val as u64) + } + + #[inline] + fn serialize_u32(self, val: u32) -> Result<Self::Ok, Self::Error> { + self.serialize_u64(val as u64) + } + + #[inline] + fn serialize_u64(self, val: u64) -> Result<Self::Ok, Self::Error> { + Ok(Value::from(val)) + } + + #[inline] + fn serialize_f32(self, val: f32) -> Result<Self::Ok, Self::Error> { + Ok(Value::F32(val)) + } + + #[inline] + fn serialize_f64(self, val: f64) -> Result<Self::Ok, Self::Error> { + Ok(Value::F64(val)) + } + + #[inline] + fn serialize_char(self, val: char) -> Result<Self::Ok, Self::Error> { + let mut buf = String::new(); + buf.push(val); + self.serialize_str(&buf) + } + + #[inline] + fn serialize_str(self, val: &str) -> Result<Self::Ok, Self::Error> { + Ok(Value::String(val.into())) + } + + #[inline] + fn serialize_bytes(self, val: &[u8]) -> Result<Self::Ok, Self::Error> { + Ok(Value::Binary(val.into())) + } + + #[inline(always)] + fn serialize_unit(self) -> Result<Self::Ok, Self::Error> { + Ok(Value::Nil) + } + + #[inline(always)] + fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> { + Ok(Value::Nil) + } + + #[inline(always)] + fn serialize_unit_variant( + self, + _name: &'static str, + _idx: u32, + variant: &'static str, + ) -> Result<Self::Ok, Self::Error> { + Ok(Value::from(variant)) + } + + #[inline] + fn serialize_newtype_struct<T: ?Sized>( + self, + name: &'static str, + value: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: ser::Serialize, + { + if name == rmpv::MSGPACK_EXT_STRUCT_NAME { + let mut ext_se = ExtSerializer::new(); + value.serialize(&mut ext_se)?; + + return ext_se.value(); + } + + to_rmpv_named(value) + } + + #[inline] + fn serialize_newtype_variant<T: ?Sized>( + self, + _name: &'static str, + _idx: u32, + variant: &'static str, + value: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: ser::Serialize, + { + Ok(Value::Map(vec![( + Value::from(variant), + to_rmpv_named(value)?, + )])) + } + + #[inline(always)] + fn serialize_none(self) -> Result<Self::Ok, Self::Error> { + self.serialize_unit() + } + + #[inline(always)] + fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error> + where + T: ser::Serialize, + { + value.serialize(self) + } + + fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> { + let se = SerializeVec { + vec: Vec::with_capacity(len.unwrap_or(0)), + }; + Ok(se) + } + + fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleStruct, Error> { + self.serialize_tuple(len) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _idx: u32, + variant: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleVariant, Error> { + let se = SerializeTupleVariant { + variant, + vec: Vec::with_capacity(len), + }; + Ok(se) + } + + fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Error> { + let se = DefaultSerializeMap { + map: Vec::with_capacity(len.unwrap_or(0)), + next_key: None, + }; + Ok(se) + } + + #[inline(always)] + fn serialize_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<Self::SerializeStruct, Error> { + let se = DefaultSerializeMap { + map: Vec::with_capacity(len), + next_key: None, + }; + Ok(se) + } + + #[inline] + fn serialize_struct_variant( + self, + _name: &'static str, + _idx: u32, + variant: &'static str, + len: usize, + ) -> Result<Self::SerializeStructVariant, Error> { + let se = SerializeStructVariant { + variant, + map: Vec::with_capacity(len), + }; + Ok(se) + } +} + +pub struct ExtSerializer { + fields_se: Option<ExtFieldSerializer>, +} + +impl ser::Serializer for &mut ExtSerializer { + type Ok = (); + type Error = Error; + + type SerializeSeq = ser::Impossible<(), Error>; + type SerializeTuple = Self; + type SerializeTupleStruct = ser::Impossible<(), Error>; + type SerializeTupleVariant = ser::Impossible<(), Error>; + type SerializeMap = ser::Impossible<(), Error>; + type SerializeStruct = ser::Impossible<(), Error>; + type SerializeStructVariant = ser::Impossible<(), Error>; + + #[cold] + fn serialize_bytes(self, _val: &[u8]) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received bytes", + )) + } + + #[cold] + fn serialize_bool(self, _val: bool) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received bool", + )) + } + + #[cold] + fn serialize_i8(self, _value: i8) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom("expected tuple, received i8")) + } + + #[cold] + fn serialize_i16(self, _val: i16) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received i16", + )) + } + + #[cold] + fn serialize_i32(self, _val: i32) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received i32", + )) + } + + #[cold] + fn serialize_i64(self, _val: i64) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received i64", + )) + } + + #[cold] + fn serialize_u8(self, _val: u8) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom("expected tuple, received u8")) + } + + #[cold] + fn serialize_u16(self, _val: u16) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received u16", + )) + } + + #[cold] + fn serialize_u32(self, _val: u32) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received u32", + )) + } + + #[cold] + fn serialize_u64(self, _val: u64) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received u64", + )) + } + + #[cold] + fn serialize_f32(self, _val: f32) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received f32", + )) + } + + #[cold] + fn serialize_f64(self, _val: f64) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received f64", + )) + } + + #[cold] + fn serialize_char(self, _val: char) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received char", + )) + } + + #[cold] + fn serialize_str(self, _val: &str) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received str", + )) + } + + #[cold] + fn serialize_unit(self) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received unit", + )) + } + + #[cold] + fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received unit_struct", + )) + } + + #[cold] + fn serialize_unit_variant( + self, + _name: &'static str, + _idx: u32, + _variant: &'static str, + ) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received unit_variant", + )) + } + + #[cold] + fn serialize_newtype_struct<T: ?Sized>( + self, + _name: &'static str, + _value: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: ser::Serialize, + { + Err(<Error as ser::Error>::custom( + "expected tuple, received newtype_struct", + )) + } + + #[cold] + fn serialize_newtype_variant<T: ?Sized>( + self, + _name: &'static str, + _idx: u32, + _variant: &'static str, + _value: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: ser::Serialize, + { + Err(<Error as ser::Error>::custom( + "expected tuple, received newtype_variant", + )) + } + + #[cold] + fn serialize_none(self) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received none", + )) + } + + #[cold] + fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok, Self::Error> + where + T: ser::Serialize, + { + Err(<Error as ser::Error>::custom( + "expected tuple, received some", + )) + } + + #[cold] + fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received seq", + )) + } + + #[inline] + fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Error> { + // FIXME check len + self.fields_se = Some(ExtFieldSerializer::new()); + + Ok(self) + } + + #[cold] + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result<Self::SerializeTupleStruct, Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received tuple_struct", + )) + } + + #[cold] + fn serialize_tuple_variant( + self, + _name: &'static str, + _idx: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeTupleVariant, Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received tuple_variant", + )) + } + + #[cold] + fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received map", + )) + } + + #[cold] + fn serialize_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result<Self::SerializeStruct, Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received struct", + )) + } + + #[cold] + fn serialize_struct_variant( + self, + _name: &'static str, + _idx: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeStructVariant, Error> { + Err(<Error as ser::Error>::custom( + "expected tuple, received struct_variant", + )) + } +} + +impl ser::SerializeTuple for &mut ExtSerializer { + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: ser::Serialize, + { + match self.fields_se { + Some(ref mut se) => value.serialize(&mut *se), + None => unreachable!(), + } + } + + #[inline(always)] + fn end(self) -> Result<(), Error> { + Ok(()) + } +} + +pub struct ExtFieldSerializer { + tag: Option<i8>, + binary: Option<Vec<u8>>, +} + +impl ser::Serializer for &mut ExtFieldSerializer { + type Ok = (); + type Error = Error; + + type SerializeSeq = ser::Impossible<(), Error>; + type SerializeTuple = ser::Impossible<(), Error>; + type SerializeTupleStruct = ser::Impossible<(), Error>; + type SerializeTupleVariant = ser::Impossible<(), Error>; + type SerializeMap = ser::Impossible<(), Error>; + type SerializeStruct = ser::Impossible<(), Error>; + type SerializeStructVariant = ser::Impossible<(), Error>; + + #[inline] + fn serialize_i8(self, value: i8) -> Result<Self::Ok, Self::Error> { + if self.tag.is_none() { + self.tag.replace(value); + Ok(()) + } else { + Err(<Error as ser::Error>::custom( + "exptected i8 and bytes, received second i8", + )) + } + } + + #[inline] + fn serialize_bytes(self, val: &[u8]) -> Result<Self::Ok, Self::Error> { + if self.binary.is_none() { + self.binary.replace(val.to_vec()); + + Ok(()) + } else { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received second bytes", + )) + } + } + + #[cold] + fn serialize_bool(self, _val: bool) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received bool", + )) + } + + #[cold] + fn serialize_i16(self, _val: i16) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received i16", + )) + } + + #[cold] + fn serialize_i32(self, _val: i32) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received i32", + )) + } + + #[cold] + fn serialize_i64(self, _val: i64) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received i64", + )) + } + + #[cold] + fn serialize_u8(self, _val: u8) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received u8", + )) + } + + #[cold] + fn serialize_u16(self, _val: u16) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received u16", + )) + } + + #[cold] + fn serialize_u32(self, _val: u32) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received u32", + )) + } + + #[cold] + fn serialize_u64(self, _val: u64) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received u64", + )) + } + + #[cold] + fn serialize_f32(self, _val: f32) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received f32", + )) + } + + #[cold] + fn serialize_f64(self, _val: f64) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received f64", + )) + } + + #[cold] + fn serialize_char(self, _val: char) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received char", + )) + } + + #[cold] + fn serialize_str(self, _val: &str) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received str", + )) + } + + #[cold] + fn serialize_unit(self) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received unit", + )) + } + + #[cold] + fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received unit_struct", + )) + } + + #[cold] + fn serialize_unit_variant( + self, + _name: &'static str, + _idx: u32, + _variant: &'static str, + ) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received unit_variant", + )) + } + + #[cold] + fn serialize_newtype_struct<T: ?Sized>( + self, + _name: &'static str, + _value: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: ser::Serialize, + { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received newtype_struct", + )) + } + + fn serialize_newtype_variant<T: ?Sized>( + self, + _name: &'static str, + _idx: u32, + _variant: &'static str, + _value: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: ser::Serialize, + { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received newtype_variant", + )) + } + + #[cold] + fn serialize_none(self) -> Result<Self::Ok, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received none", + )) + } + + #[cold] + fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok, Self::Error> + where + T: ser::Serialize, + { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received some", + )) + } + + #[cold] + fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received seq", + )) + } + + #[cold] + fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received tuple", + )) + } + + #[cold] + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result<Self::SerializeTupleStruct, Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received tuple_struct", + )) + } + + #[cold] + fn serialize_tuple_variant( + self, + _name: &'static str, + _idx: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeTupleVariant, Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received tuple_variant", + )) + } + + #[cold] + fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received map", + )) + } + + #[cold] + fn serialize_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result<Self::SerializeStruct, Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received struct", + )) + } + + #[cold] + fn serialize_struct_variant( + self, + _name: &'static str, + _idx: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeStructVariant, Error> { + Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received struct_variant", + )) + } +} + +impl ExtSerializer { + #[inline] + fn new() -> Self { + Self { fields_se: None } + } + + fn value(self) -> Result<Value, Error> { + match self.fields_se { + Some(fields_se) => fields_se.value(), + None => Err(<Error as ser::Error>::custom( + "expected tuple, received nothing", + )), + } + } +} + +impl ExtFieldSerializer { + #[inline] + fn new() -> Self { + Self { + tag: None, + binary: None, + } + } + + fn value(self) -> Result<Value, Error> { + match (self.tag, self.binary) { + (Some(tag), Some(binary)) => Ok(Value::Ext(tag, binary)), + (Some(_), None) => Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received i8 only", + )), + (None, Some(_)) => Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received bytes only", + )), + (None, None) => Err(<Error as ser::Error>::custom( + "expected i8 and bytes, received nothing", + )), + } + } +} + +#[doc(hidden)] +pub struct SerializeVec { + vec: Vec<Value>, +} + +/// Default implementation for tuple variant serialization. It packs given enums as a tuple of an +/// index with a tuple of arguments. +#[doc(hidden)] +pub struct SerializeTupleVariant { + variant: &'static str, + vec: Vec<Value>, +} + +#[doc(hidden)] +pub struct DefaultSerializeMap { + map: Vec<(Value, Value)>, + next_key: Option<Value>, +} + +#[doc(hidden)] +pub struct SerializeStructVariant { + variant: &'static str, + map: Vec<(Value, Value)>, +} + +impl ser::SerializeSeq for SerializeVec { + type Ok = Value; + type Error = Error; + + #[inline] + fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: ser::Serialize, + { + self.vec.push(to_rmpv_named(value)?); + Ok(()) + } + + #[inline] + fn end(self) -> Result<Value, Error> { + Ok(Value::Array(self.vec)) + } +} + +impl ser::SerializeTuple for SerializeVec { + type Ok = Value; + type Error = Error; + + #[inline] + fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: ser::Serialize, + { + ser::SerializeSeq::serialize_element(self, value) + } + + #[inline] + fn end(self) -> Result<Value, Error> { + ser::SerializeSeq::end(self) + } +} + +impl ser::SerializeTupleStruct for SerializeVec { + type Ok = Value; + type Error = Error; + + #[inline] + fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: ser::Serialize, + { + ser::SerializeSeq::serialize_element(self, value) + } + + #[inline] + fn end(self) -> Result<Value, Error> { + ser::SerializeSeq::end(self) + } +} + +impl ser::SerializeTupleVariant for SerializeTupleVariant { + type Ok = Value; + type Error = Error; + + #[inline] + fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: ser::Serialize, + { + self.vec.push(to_rmpv_named(value)?); + Ok(()) + } + + #[inline] + fn end(self) -> Result<Value, Error> { + Ok(Value::Map(vec![( + Value::from(self.variant), + Value::Array(self.vec), + )])) + } +} + +impl ser::SerializeMap for DefaultSerializeMap { + type Ok = Value; + type Error = Error; + + #[inline(always)] + fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Error> + where + T: ser::Serialize, + { + self.next_key = Some(to_rmpv_named(key)?); + Ok(()) + } + + fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: ser::Serialize, + { + // Panic because this indicates a bug in the program rather than an + // expected failure. + let key = self + .next_key + .take() + .expect("`serialize_value` called before `serialize_key`"); + self.map.push((key, to_rmpv_named(value)?)); + Ok(()) + } + + #[inline(always)] + fn end(self) -> Result<Value, Error> { + Ok(Value::Map(self.map)) + } +} + +impl ser::SerializeStruct for DefaultSerializeMap { + type Ok = Value; + type Error = Error; + + #[inline] + fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error> + where + T: ser::Serialize, + { + self.map.push((to_rmpv_named(key)?, to_rmpv_named(value)?)); + Ok(()) + } + + #[inline(always)] + fn end(self) -> Result<Value, Error> { + Ok(Value::Map(self.map)) + } +} + +impl ser::SerializeStructVariant for SerializeStructVariant { + type Ok = Value; + type Error = Error; + + #[inline] + fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error> + where + T: ser::Serialize, + { + self.map.push((to_rmpv_named(key)?, to_rmpv_named(value)?)); + Ok(()) + } + + #[inline(always)] + fn end(self) -> Result<Value, Error> { + Ok(Value::Map(vec![( + Value::from(self.variant), + Value::Map(self.map), + )])) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn check_to_rmpv_named() { + #[derive(serde::Serialize)] + struct Struct { + field: i32, + } + #[derive(serde::Serialize)] + struct Tuple(i32, i32); + #[derive(serde::Serialize)] + struct NewType(i32); + #[derive(serde::Serialize)] + struct Unit; + + #[derive(serde::Serialize)] + enum E { + Struct { field: i32 }, + Tuple(i32, i32), + NewType(i32), + Unit, + } + + // We do the same thing as what serde_json::to_value does + + assert_eq!( + to_rmpv_named(&Struct { field: 1 }).unwrap(), + Value::Map(vec![(Value::from("field"), Value::from(1))]), + ); + + assert_eq!( + to_rmpv_named(&E::Struct { field: 2 }).unwrap(), + Value::Map(vec![( + Value::from("Struct"), + Value::Map(vec![(Value::from("field"), Value::from(2))]) + )]) + ); + + assert_eq!( + to_rmpv_named(&Tuple(3, 4)).unwrap(), + Value::Array(vec![Value::from(3), Value::from(4)]) + ); + + assert_eq!( + to_rmpv_named(&E::Tuple(5, 6)).unwrap(), + Value::Map(vec![( + Value::from("Tuple"), + Value::Array(vec![Value::from(5), Value::from(6)]) + )]) + ); + + assert_eq!(to_rmpv_named(&NewType(7)).unwrap(), Value::from(7)); + + assert_eq!( + to_rmpv_named(&E::NewType(8)).unwrap(), + Value::Map(vec![(Value::from("NewType"), Value::from(8))]) + ); + + assert_eq!(to_rmpv_named(&Unit).unwrap(), Value::Nil); + assert_eq!(to_rmpv_named(&E::Unit).unwrap(), Value::from("Unit")); + } +}