Skip to content

Commit 60d872e

Browse files
committed
Merge pull request #39 from 3Hren/pr/encoding-policy
Struct encoding policy
2 parents 0e69c67 + 46b3d5d commit 60d872e

3 files changed

Lines changed: 122 additions & 5 deletions

File tree

rmp-serde/src/encode.rs

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use serde;
33
use std::fmt;
44
use std::io::Write;
55

6+
use rmp::Marker;
67
use rmp::encode::{
78
write_nil,
89
write_bool,
@@ -58,6 +59,30 @@ impl From<ValueWriteError> for Error {
5859
}
5960
}
6061

62+
pub trait VariantWriter {
63+
fn write_struct_len<W>(&self, wr: &mut W, len: u32) -> Result<Marker, ValueWriteError> where W: Write;
64+
fn write_field_name<W>(&self, wr: &mut W, _key: &str) -> Result<(), ValueWriteError> where W: Write;
65+
}
66+
67+
/// Writes struct as MessagePack array with no field names
68+
pub struct StructArrayWriter;
69+
70+
impl VariantWriter for StructArrayWriter {
71+
fn write_struct_len<W>(&self, wr: &mut W, len: u32) -> Result<Marker, ValueWriteError>
72+
where W: Write
73+
{
74+
write_array_len(wr, len)
75+
}
76+
77+
/// This implementation does not write field names
78+
#[allow(unused_variables)]
79+
fn write_field_name<W>(&self, wr: &mut W, _key: &str) -> Result<(), ValueWriteError>
80+
where W: Write
81+
{
82+
Ok(())
83+
}
84+
}
85+
6186
/// Represents MessagePack serialization implementation.
6287
///
6388
/// # Note
@@ -70,20 +95,32 @@ impl From<ValueWriteError> for Error {
7095
/// All instances of `ErrorKind::Interrupted` are handled by this function and the underlying
7196
/// operation is retried.
7297
// TODO: Docs. Examples.
73-
pub struct Serializer<'a> {
98+
pub struct Serializer<'a, W: VariantWriter> {
7499
wr: &'a mut Write,
100+
vw: W,
75101
}
76102

77-
impl<'a> Serializer<'a> {
103+
impl<'a> Serializer<'a, StructArrayWriter> {
78104
/// Creates a new MessagePack encoder whose output will be written to the writer specified.
79-
pub fn new(wr: &'a mut Write) -> Serializer<'a> {
105+
pub fn new(wr: &'a mut Write) -> Serializer<'a, StructArrayWriter> {
80106
Serializer {
81107
wr: wr,
108+
vw: StructArrayWriter,
82109
}
83110
}
84111
}
85112

86-
impl<'a> serde::Serializer for Serializer<'a> {
113+
impl<'a, W: VariantWriter> Serializer<'a, W> {
114+
/// Creates a new MessagePack encoder whose output will be written to the writer specified.
115+
pub fn with(wr: &'a mut Write, vw: W) -> Serializer<'a, W> {
116+
Serializer {
117+
wr: wr,
118+
vw: vw,
119+
}
120+
}
121+
}
122+
123+
impl<'a, W: VariantWriter> serde::Serializer for Serializer<'a, W> {
87124
type Error = Error;
88125

89126
fn visit_unit(&mut self) -> Result<(), Error> {
@@ -276,7 +313,7 @@ impl<'a> serde::Serializer for Serializer<'a> {
276313
None => panic!("do not know how to serialize a sequence with no length"),
277314
};
278315

279-
try!(write_array_len(&mut self.wr, len as u32));
316+
try!(self.vw.write_struct_len(&mut self.wr, len as u32));
280317

281318
while let Some(()) = try!(visitor.visit(self)) { }
282319

@@ -286,6 +323,7 @@ impl<'a> serde::Serializer for Serializer<'a> {
286323
fn visit_struct_elt<V>(&mut self, _key: &str, value: V) -> Result<(), Error>
287324
where V: serde::Serialize,
288325
{
326+
try!(self.vw.write_field_name(&mut self.wr, _key));
289327
value.serialize(self)
290328
}
291329

rmp-serde/tests/deserializer.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,36 @@ fn pass_map() {
340340
assert_eq!(expected, actual);
341341
}
342342

343+
#[cfg(feature = "serde_macros")]
344+
#[test]
345+
fn pass_struct_map() {
346+
#[derive(Debug, PartialEq, Deserialize)]
347+
struct Custom {
348+
et: String,
349+
le: u8,
350+
shit: u8,
351+
}
352+
353+
let buf = [
354+
0x83, // 3 (size)
355+
0xa2, 0x65, 0x74, // "et"
356+
0xa5, 0x76, 0x6f, 0x69, 0x6c, 0x61, // "voila"
357+
0xa2, 0x6c, 0x65, // "le"
358+
0x00, // 0
359+
0xa4, 0x73, 0x68, 0x69, 0x74, // "shit"
360+
0x01, // 1
361+
];
362+
let cur = Cursor::new(&buf[..]);
363+
364+
// it appears no special behavior is needed for deserializing structs encoded as maps
365+
let mut deserializer = Deserializer::new(cur);
366+
let actual: Custom = Deserialize::deserialize(&mut deserializer).unwrap();
367+
let voila = "voila".to_string(); // so the next line looks more funny
368+
let expected = Custom { et: voila, le: 0, shit: 1 };
369+
370+
assert_eq!(expected, actual);
371+
}
372+
343373
#[cfg(feature = "serde_macros")]
344374
#[test]
345375
fn pass_enum() {

rmp-serde/tests/serializer.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#![cfg_attr(feature = "serde_macros", plugin(serde_macros))]
33

44
extern crate serde;
5+
extern crate rmp;
56
extern crate rmp_serde;
67

78
use std::io::Cursor;
@@ -267,6 +268,54 @@ fn pass_map() {
267268
assert_eq!(out, buf);
268269
}
269270

271+
#[cfg(feature = "serde_macros")]
272+
#[test]
273+
fn pass_struct_map() {
274+
use std::io::Write;
275+
use rmp::Marker;
276+
use rmp::encode::{ValueWriteError, write_map_len, write_str};
277+
use rmp_serde::encode::VariantWriter;
278+
279+
struct StructMapWriter;
280+
281+
impl VariantWriter for StructMapWriter {
282+
fn write_struct_len<W>(&self, wr: &mut W, len: u32) -> Result<Marker, ValueWriteError>
283+
where W: Write
284+
{
285+
write_map_len(wr, len)
286+
}
287+
288+
fn write_field_name<W>(&self, wr: &mut W, _key: &str) -> Result<(), ValueWriteError>
289+
where W: Write
290+
{
291+
write_str(wr, _key)
292+
}
293+
}
294+
295+
#[derive(Debug, PartialEq, Serialize)]
296+
struct Custom<'a> {
297+
et: &'a str,
298+
le: u8,
299+
shit: u8,
300+
}
301+
302+
let mut buf = [0x00; 20];
303+
304+
let val = Custom { et: "voila", le: 0, shit: 1 };
305+
val.serialize(&mut Serializer::with(&mut &mut buf[..], StructMapWriter)).ok().unwrap();
306+
307+
let out = [
308+
0x83, // 3 (size)
309+
0xa2, 0x65, 0x74, // "et"
310+
0xa5, 0x76, 0x6f, 0x69, 0x6c, 0x61, // "voila"
311+
0xa2, 0x6c, 0x65, // "le"
312+
0x00, // 0
313+
0xa4, 0x73, 0x68, 0x69, 0x74, // "shit"
314+
0x01, // 1
315+
];
316+
assert_eq!(out, buf);
317+
}
318+
270319
#[cfg(feature = "serde_macros")]
271320
#[test]
272321
fn pass_enum() {

0 commit comments

Comments
 (0)