Skip to content

Commit 2cab1c1

Browse files
committed
Add rmpv::ext::to_value_named to keep struct keys
The current `rmpv::ext::to_value` implementation turns Structs into `Value::Array<Value::String>` which is not deserializable by other languages. Technically I would call this a bug and opt to change the existing `to_value` implementation, but to stay cautious of not breaking existing users' code I think it makes sense to introduce a new `to_value_named` fn which instead turns Structs into `Value::Map` and maintains their keys.
1 parent 69f90c6 commit 2cab1c1

File tree

2 files changed

+48
-9
lines changed

2 files changed

+48
-9
lines changed

rmpv/src/ext/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::{IntPriv, Integer, Value, ValueRef};
77

88
pub use self::de::{deserialize_from, from_value, EnumRefDeserializer};
99
pub use self::se::to_value;
10+
pub use self::se::to_value_named;
1011

1112
mod de;
1213
mod se;

rmpv/src/ext/se.rs

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ impl ser::Error for Error {
6262
}
6363
}
6464

65-
struct Serializer;
65+
struct Serializer {
66+
named_structs: bool
67+
}
6668

6769
/// Convert a `T` into `rmpv::Value` which is an enum that can represent any valid MessagePack data.
6870
///
@@ -77,7 +79,27 @@ struct Serializer;
7779
/// ```
7880
#[inline]
7981
pub fn to_value<T: Serialize>(value: T) -> Result<Value, Error> {
80-
value.serialize(Serializer)
82+
value.serialize(Serializer {
83+
named_structs: false
84+
})
85+
}
86+
87+
/// The same as `rmpv::ext::to_value` with the variation that Structs are encoded as Value::Map
88+
///
89+
/// ```rust
90+
/// # use rmpv::Value;
91+
///
92+
/// struct Book { name: String }
93+
///
94+
/// let val = rmpv::ext::to_value_named(Book { name: "James".into() }).unwrap();
95+
///
96+
/// assert_eq!(Value::Map(vec![(Value::String("name"), Value::String("John Smith".into()))]), val);
97+
/// ```
98+
#[inline]
99+
pub fn to_value_named<T: Serialize>(value: T) -> Result<Value, Error> {
100+
value.serialize(Serializer {
101+
named_structs: true
102+
})
81103
}
82104

83105
impl ser::Serializer for Serializer {
@@ -89,7 +111,7 @@ impl ser::Serializer for Serializer {
89111
type SerializeTupleStruct = SerializeVec;
90112
type SerializeTupleVariant = SerializeTupleVariant;
91113
type SerializeMap = DefaultSerializeMap;
92-
type SerializeStruct = SerializeVec;
114+
type SerializeStruct = DefaultSerializeStruct;
93115
type SerializeStructVariant = SerializeStructVariant;
94116

95117
#[inline]
@@ -251,8 +273,12 @@ impl ser::Serializer for Serializer {
251273
}
252274

253275
#[inline]
254-
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeStruct, Error> {
255-
self.serialize_tuple_struct(name, len)
276+
fn serialize_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeStruct, Error> {
277+
let se = DefaultSerializeStruct {
278+
named: self.named_structs,
279+
map: Vec::with_capacity(len),
280+
};
281+
return Ok(se)
256282
}
257283

258284
#[inline]
@@ -682,6 +708,12 @@ pub struct DefaultSerializeMap {
682708
next_key: Option<Value>,
683709
}
684710

711+
#[doc(hidden)]
712+
pub struct DefaultSerializeStruct {
713+
named: bool,
714+
map: Vec<(Value, Value)>,
715+
}
716+
685717
#[doc(hidden)]
686718
pub struct SerializeStructVariant {
687719
idx: u32,
@@ -787,20 +819,26 @@ impl ser::SerializeMap for DefaultSerializeMap {
787819
}
788820
}
789821

790-
impl SerializeStruct for SerializeVec {
822+
impl SerializeStruct for DefaultSerializeStruct {
791823
type Ok = Value;
792824
type Error = Error;
793825

794826
#[inline]
795-
fn serialize_field<T: ?Sized>(&mut self, _key: &'static str, value: &T) -> Result<(), Error>
827+
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
796828
where T: Serialize
797829
{
798-
ser::SerializeSeq::serialize_element(self, value)
830+
self.map.push((to_value(key)?, to_value(value)?));
831+
Ok(())
799832
}
800833

801834
#[inline]
802835
fn end(self) -> Result<Value, Error> {
803-
ser::SerializeSeq::end(self)
836+
if self.named {
837+
return Ok(Value::Map(self.map))
838+
}
839+
840+
let stripped_keys: Vec<Value> = self.map.into_iter().map(|(_, val)| val).collect();
841+
Ok(Value::Array(stripped_keys))
804842
}
805843
}
806844

0 commit comments

Comments
 (0)