feat(serde): Add hooks for fixed-sized arrays

Closes #244
This commit is contained in:
Erick Tryzelaar 2016-02-23 05:15:44 -08:00
parent d24b2c86f2
commit 76b3dead9b
8 changed files with 335 additions and 59 deletions

View File

@ -529,7 +529,7 @@ macro_rules! array_impls {
fn deserialize<D>(deserializer: &mut D) -> Result<[T; $len], D::Error> fn deserialize<D>(deserializer: &mut D) -> Result<[T; $len], D::Error>
where D: Deserializer, where D: Deserializer,
{ {
deserializer.deserialize_seq($visitor::new()) deserializer.deserialize_fixed_size_array($len, $visitor::new())
} }
} }
)+ )+

View File

@ -329,6 +329,19 @@ pub trait Deserializer {
self.deserialize(visitor) self.deserialize(visitor)
} }
/// This method hints that the `Deserialize` type is expecting a fixed size array. This allows
/// deserializers to parse arrays that aren't tagged as arrays.
///
/// By default, this deserializes arrays from a sequence.
#[inline]
fn deserialize_fixed_size_array<V>(&mut self,
_len: usize,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
/// This method hints that the `Deserialize` type is expecting a map of values. This allows /// This method hints that the `Deserialize` type is expecting a map of values. This allows
/// deserializers to parse sequences that aren't tagged as maps. /// deserializers to parse sequences that aren't tagged as maps.
#[inline] #[inline]

View File

@ -196,6 +196,8 @@ impl<T> Serialize for [T]
} }
} }
///////////////////////////////////////////////////////////////////////////////
macro_rules! array_impls { macro_rules! array_impls {
($len:expr) => { ($len:expr) => {
impl<T> Serialize for [T; $len] where T: Serialize { impl<T> Serialize for [T; $len] where T: Serialize {
@ -203,7 +205,8 @@ macro_rules! array_impls {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer, where S: Serializer,
{ {
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some($len))) let visitor = SeqIteratorVisitor::new(self.iter(), Some($len));
serializer.serialize_fixed_size_array(visitor)
} }
} }
} }

View File

@ -220,6 +220,16 @@ pub trait Serializer {
self.serialize_seq_elt(value) self.serialize_seq_elt(value)
} }
/// Serializes a fixed-size array.
///
/// By default this serializes an array as a sequence.
#[inline]
fn serialize_fixed_size_array<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.serialize_seq(visitor)
}
/// Serializes a tuple struct. /// Serializes a tuple struct.
/// ///
/// By default, tuple structs are serialized as a tuple. /// By default, tuple structs are serialized as a tuple.

View File

@ -186,27 +186,27 @@ declare_tests! {
], ],
TupleStruct(1, 2, 3) => vec![ TupleStruct(1, 2, 3) => vec![
Token::TupleStructStart("TupleStruct", Some(3)), Token::TupleStructStart("TupleStruct", Some(3)),
Token::TupleSeqSep, Token::TupleStructSep,
Token::I32(1), Token::I32(1),
Token::TupleSeqSep, Token::TupleStructSep,
Token::I32(2), Token::I32(2),
Token::TupleSeqSep, Token::TupleStructSep,
Token::I32(3), Token::I32(3),
Token::TupleSeqEnd, Token::TupleStructEnd,
], ],
TupleStruct(1, 2, 3) => vec![ TupleStruct(1, 2, 3) => vec![
Token::TupleStructStart("TupleStruct", None), Token::TupleStructStart("TupleStruct", None),
Token::TupleSeqSep, Token::TupleStructSep,
Token::I32(1), Token::I32(1),
Token::TupleSeqSep, Token::TupleStructSep,
Token::I32(2), Token::I32(2),
Token::TupleSeqSep, Token::TupleStructSep,
Token::I32(3), Token::I32(3),
Token::TupleSeqEnd, Token::TupleStructEnd,
], ],
} }
test_btreeset { test_btreeset {
@ -321,6 +321,10 @@ declare_tests! {
Token::SeqStart(Some(0)), Token::SeqStart(Some(0)),
Token::SeqEnd, Token::SeqEnd,
], ],
[0; 0] => vec![
Token::SeqArrayStart(0),
Token::SeqEnd,
],
([0; 0], [1], [2, 3]) => vec![ ([0; 0], [1], [2, 3]) => vec![
Token::SeqStart(Some(3)), Token::SeqStart(Some(3)),
Token::SeqSep, Token::SeqSep,
@ -343,6 +347,28 @@ declare_tests! {
Token::SeqEnd, Token::SeqEnd,
Token::SeqEnd, Token::SeqEnd,
], ],
([0; 0], [1], [2, 3]) => vec![
Token::SeqArrayStart(3),
Token::SeqSep,
Token::SeqArrayStart(0),
Token::SeqEnd,
Token::SeqSep,
Token::SeqArrayStart(1),
Token::SeqSep,
Token::I32(1),
Token::SeqEnd,
Token::SeqSep,
Token::SeqArrayStart(2),
Token::SeqSep,
Token::I32(2),
Token::SeqSep,
Token::I32(3),
Token::SeqEnd,
Token::SeqEnd,
],
[0; 0] => vec![ [0; 0] => vec![
Token::UnitStruct("Anything"), Token::UnitStruct("Anything"),
], ],
@ -370,6 +396,24 @@ declare_tests! {
Token::I32(3), Token::I32(3),
Token::SeqEnd, Token::SeqEnd,
], ],
(1,) => vec![
Token::TupleStart(1),
Token::TupleSep,
Token::I32(1),
Token::TupleEnd,
],
(1, 2, 3) => vec![
Token::TupleStart(3),
Token::TupleSep,
Token::I32(1),
Token::TupleSep,
Token::I32(2),
Token::TupleSep,
Token::I32(3),
Token::TupleEnd,
],
} }
test_btreemap { test_btreemap {
BTreeMap::<isize, isize>::new() => vec![ BTreeMap::<isize, isize>::new() => vec![

View File

@ -153,16 +153,16 @@ fn test_ser_named_tuple() {
&SerNamedTuple(&a, &mut b, c), &SerNamedTuple(&a, &mut b, c),
&[ &[
Token::TupleStructStart("SerNamedTuple", Some(3)), Token::TupleStructStart("SerNamedTuple", Some(3)),
Token::TupleSeqSep, Token::TupleStructSep,
Token::I32(5), Token::I32(5),
Token::TupleSeqSep, Token::TupleStructSep,
Token::I32(6), Token::I32(6),
Token::TupleSeqSep, Token::TupleStructSep,
Token::I32(7), Token::I32(7),
Token::TupleSeqEnd, Token::TupleStructEnd,
], ],
); );
} }
@ -190,16 +190,16 @@ fn test_de_named_tuple() {
&DeNamedTuple(5, 6, 7), &DeNamedTuple(5, 6, 7),
vec![ vec![
Token::TupleStructStart("DeNamedTuple", Some(3)), Token::TupleStructStart("DeNamedTuple", Some(3)),
Token::TupleSeqSep, Token::TupleStructSep,
Token::I32(5), Token::I32(5),
Token::TupleSeqSep, Token::TupleStructSep,
Token::I32(6), Token::I32(6),
Token::TupleSeqSep, Token::TupleStructSep,
Token::I32(7), Token::I32(7),
Token::TupleSeqEnd, Token::TupleStructEnd,
] ]
); );
} }
@ -525,13 +525,13 @@ fn test_generic_tuple_struct() {
vec![ vec![
Token::TupleStructStart("GenericTupleStruct", Some(2)), Token::TupleStructStart("GenericTupleStruct", Some(2)),
Token::TupleSeqSep, Token::TupleStructSep,
Token::U32(5), Token::U32(5),
Token::TupleSeqSep, Token::TupleStructSep,
Token::U32(6), Token::U32(6),
Token::TupleSeqEnd, Token::TupleStructEnd,
] ]
); );
} }

View File

@ -100,11 +100,11 @@ declare_ser_tests! {
} }
test_array { test_array {
[0; 0] => &[ [0; 0] => &[
Token::SeqStart(Some(0)), Token::SeqArrayStart(0),
Token::SeqEnd, Token::SeqEnd,
], ],
[1, 2, 3] => &[ [1, 2, 3] => &[
Token::SeqStart(Some(3)), Token::SeqArrayStart(3),
Token::SeqSep, Token::SeqSep,
Token::I32(1), Token::I32(1),
@ -146,22 +146,22 @@ declare_ser_tests! {
} }
test_tuple { test_tuple {
(1,) => &[ (1,) => &[
Token::SeqStart(Some(1)), Token::TupleStart(1),
Token::SeqSep, Token::TupleSep,
Token::I32(1), Token::I32(1),
Token::SeqEnd, Token::TupleEnd,
], ],
(1, 2, 3) => &[ (1, 2, 3) => &[
Token::SeqStart(Some(3)), Token::TupleStart(3),
Token::SeqSep, Token::TupleSep,
Token::I32(1), Token::I32(1),
Token::SeqSep, Token::TupleSep,
Token::I32(2), Token::I32(2),
Token::SeqSep, Token::TupleSep,
Token::I32(3), Token::I32(3),
Token::SeqEnd, Token::TupleEnd,
], ],
} }
test_btreemap { test_btreemap {
@ -210,15 +210,15 @@ declare_ser_tests! {
test_tuple_struct { test_tuple_struct {
TupleStruct(1, 2, 3) => &[ TupleStruct(1, 2, 3) => &[
Token::TupleStructStart("TupleStruct", Some(3)), Token::TupleStructStart("TupleStruct", Some(3)),
Token::TupleSeqSep, Token::TupleStructSep,
Token::I32(1), Token::I32(1),
Token::TupleSeqSep, Token::TupleStructSep,
Token::I32(2), Token::I32(2),
Token::TupleSeqSep, Token::TupleStructSep,
Token::I32(3), Token::I32(3),
Token::TupleSeqEnd, Token::TupleStructEnd,
], ],
} }
test_struct { test_struct {

View File

@ -38,12 +38,17 @@ pub enum Token<'a> {
EnumNewType(&'a str, &'a str), EnumNewType(&'a str, &'a str),
SeqStart(Option<usize>), SeqStart(Option<usize>),
SeqArrayStart(usize),
SeqSep, SeqSep,
SeqEnd, SeqEnd,
TupleStart(usize),
TupleSep,
TupleEnd,
TupleStructStart(&'a str, Option<usize>), TupleStructStart(&'a str, Option<usize>),
TupleSeqSep, TupleStructSep,
TupleSeqEnd, TupleStructEnd,
MapStart(Option<usize>), MapStart(Option<usize>),
MapSep, MapSep,
@ -231,6 +236,16 @@ impl<'a, I> ser::Serializer for Serializer<I>
self.visit_sequence(visitor) self.visit_sequence(visitor)
} }
fn serialize_fixed_size_array<V>(&mut self, visitor: V) -> Result<(), Error>
where V: ser::SeqVisitor
{
let len = visitor.len().expect("arrays must have a length");
assert_eq!(self.tokens.next(), Some(&Token::SeqArrayStart(len)));
self.visit_sequence(visitor)
}
fn serialize_seq_elt<T>(&mut self, value: T) -> Result<(), Error> fn serialize_seq_elt<T>(&mut self, value: T) -> Result<(), Error>
where T: ser::Serialize where T: ser::Serialize
{ {
@ -238,6 +253,27 @@ impl<'a, I> ser::Serializer for Serializer<I>
value.serialize(self) value.serialize(self)
} }
fn serialize_tuple<V>(&mut self, mut visitor: V) -> Result<(), Error>
where V: ser::SeqVisitor
{
let len = visitor.len().expect("arrays must have a length");
assert_eq!(self.tokens.next(), Some(&Token::TupleStart(len)));
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::TupleEnd));
Ok(())
}
fn serialize_tuple_elt<T>(&mut self, value: T) -> Result<(), Error>
where T: ser::Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::TupleSep));
value.serialize(self)
}
fn serialize_newtype_struct<T>(&mut self, fn serialize_newtype_struct<T>(&mut self,
name: &'static str, name: &'static str,
value: T) -> Result<(), Error> value: T) -> Result<(), Error>
@ -256,7 +292,7 @@ impl<'a, I> ser::Serializer for Serializer<I>
while let Some(()) = try!(visitor.visit(self)) { } while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::TupleSeqEnd)); assert_eq!(self.tokens.next(), Some(&Token::TupleStructEnd));
Ok(()) Ok(())
} }
@ -264,7 +300,7 @@ impl<'a, I> ser::Serializer for Serializer<I>
fn serialize_tuple_struct_elt<T>(&mut self, value: T) -> Result<(), Error> fn serialize_tuple_struct_elt<T>(&mut self, value: T) -> Result<(), Error>
where T: ser::Serialize, where T: ser::Serialize,
{ {
assert_eq!(self.tokens.next(), Some(&Token::TupleSeqSep)); assert_eq!(self.tokens.next(), Some(&Token::TupleStructSep));
value.serialize(self) value.serialize(self)
} }
@ -449,10 +485,28 @@ impl<I> Deserializer<I>
}) })
} }
fn visit_tuple_seq<V>(&mut self, len: Option<usize>, mut visitor: V) -> Result<V::Value, Error> fn visit_array<V>(&mut self, len: usize, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor, where V: de::Visitor,
{ {
visitor.visit_seq(DeserializerTupleSeqVisitor { visitor.visit_seq(DeserializerArrayVisitor {
de: self,
len: len,
})
}
fn visit_tuple<V>(&mut self, len: usize, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_seq(DeserializerTupleVisitor {
de: self,
len: len,
})
}
fn visit_tuple_struct<V>(&mut self, len: usize, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_seq(DeserializerTupleStructVisitor {
de: self, de: self,
len: len, len: len,
}) })
@ -528,6 +582,9 @@ impl<I> de::Deserializer for Deserializer<I>
Some(Token::SeqStart(len)) | Some(Token::TupleStructStart(_, len)) => { Some(Token::SeqStart(len)) | Some(Token::TupleStructStart(_, len)) => {
self.visit_seq(len, visitor) self.visit_seq(len, visitor)
} }
Some(Token::SeqArrayStart(len)) => {
self.visit_seq(Some(len), visitor)
}
Some(Token::MapStart(len)) | Some(Token::StructStart(_, len)) => { Some(Token::MapStart(len)) | Some(Token::StructStart(_, len)) => {
self.visit_map(len, visitor) self.visit_map(len, visitor)
} }
@ -625,6 +682,56 @@ impl<I> de::Deserializer for Deserializer<I>
} }
} }
fn deserialize_fixed_size_array<V>(&mut self,
len: usize,
visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.tokens.peek() {
Some(&Token::SeqArrayStart(_)) => {
self.tokens.next();
self.visit_array(len, visitor)
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfStreamError),
}
}
fn deserialize_tuple<V>(&mut self,
len: usize,
mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.tokens.peek() {
Some(&Token::Unit) => {
self.tokens.next();
visitor.visit_unit()
}
Some(&Token::UnitStruct(_)) => {
self.tokens.next();
visitor.visit_unit()
}
Some(&Token::SeqStart(_)) => {
self.tokens.next();
self.visit_seq(Some(len), visitor)
}
Some(&Token::SeqArrayStart(_)) => {
self.tokens.next();
self.visit_array(len, visitor)
}
Some(&Token::TupleStart(_)) => {
self.tokens.next();
self.visit_tuple(len, visitor)
}
Some(&Token::TupleStructStart(_, _)) => {
self.tokens.next();
self.visit_tuple_struct(len, visitor)
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfStreamError),
}
}
fn deserialize_tuple_struct<V>(&mut self, fn deserialize_tuple_struct<V>(&mut self,
name: &str, name: &str,
len: usize, len: usize,
@ -632,6 +739,10 @@ impl<I> de::Deserializer for Deserializer<I>
where V: de::Visitor, where V: de::Visitor,
{ {
match self.tokens.peek() { match self.tokens.peek() {
Some(&Token::Unit) => {
self.tokens.next();
visitor.visit_unit()
}
Some(&Token::UnitStruct(n)) => { Some(&Token::UnitStruct(n)) => {
self.tokens.next(); self.tokens.next();
if name == n { if name == n {
@ -640,18 +751,26 @@ impl<I> de::Deserializer for Deserializer<I>
Err(Error::InvalidName(n)) Err(Error::InvalidName(n))
} }
} }
Some(&Token::TupleStructStart(n, _)) => {
self.tokens.next();
if name == n {
self.visit_tuple_seq(Some(len), visitor)
} else {
Err(Error::InvalidName(n))
}
}
Some(&Token::SeqStart(_)) => { Some(&Token::SeqStart(_)) => {
self.tokens.next(); self.tokens.next();
self.visit_seq(Some(len), visitor) self.visit_seq(Some(len), visitor)
} }
Some(&Token::SeqArrayStart(_)) => {
self.tokens.next();
self.visit_array(len, visitor)
}
Some(&Token::TupleStart(_)) => {
self.tokens.next();
self.visit_tuple(len, visitor)
}
Some(&Token::TupleStructStart(n, _)) => {
self.tokens.next();
if name == n {
self.visit_tuple_struct(len, visitor)
} else {
Err(Error::InvalidName(n))
}
}
Some(_) => self.deserialize(visitor), Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfStreamError), None => Err(Error::EndOfStreamError),
} }
@ -729,12 +848,12 @@ impl<'a, I> de::SeqVisitor for DeserializerSeqVisitor<'a, I>
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
struct DeserializerTupleSeqVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> { struct DeserializerArrayVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>, de: &'a mut Deserializer<I>,
len: Option<usize>, len: usize,
} }
impl<'a, I> de::SeqVisitor for DeserializerTupleSeqVisitor<'a, I> impl<'a, I> de::SeqVisitor for DeserializerArrayVisitor<'a, I>
where I: Iterator<Item=Token<'static>>, where I: Iterator<Item=Token<'static>>,
{ {
type Error = Error; type Error = Error;
@ -743,12 +862,12 @@ impl<'a, I> de::SeqVisitor for DeserializerTupleSeqVisitor<'a, I>
where T: de::Deserialize, where T: de::Deserialize,
{ {
match self.de.tokens.peek() { match self.de.tokens.peek() {
Some(&Token::TupleSeqSep) => { Some(&Token::SeqSep) => {
self.de.tokens.next(); self.de.tokens.next();
self.len = self.len.map(|len| len - 1); self.len -= 1;
Ok(Some(try!(de::Deserialize::deserialize(self.de)))) Ok(Some(try!(de::Deserialize::deserialize(self.de))))
} }
Some(&Token::TupleSeqEnd) => Ok(None), Some(&Token::SeqEnd) => Ok(None),
Some(_) => { Some(_) => {
let token = self.de.tokens.next().unwrap(); let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token)) Err(Error::UnexpectedToken(token))
@ -758,17 +877,104 @@ impl<'a, I> de::SeqVisitor for DeserializerTupleSeqVisitor<'a, I>
} }
fn end(&mut self) -> Result<(), Error> { fn end(&mut self) -> Result<(), Error> {
//assert_eq!(self.len.unwrap_or(0), 0); assert_eq!(self.len, 0);
match self.de.tokens.next() { match self.de.tokens.next() {
Some(Token::TupleSeqEnd) => Ok(()), Some(Token::SeqEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)), Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStreamError), None => Err(Error::EndOfStreamError),
} }
} }
fn size_hint(&self) -> (usize, Option<usize>) { fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len.unwrap_or(0); (self.len, Some(self.len))
(len, self.len) }
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerTupleVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: usize,
}
impl<'a, I> de::SeqVisitor for DeserializerTupleVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: de::Deserialize,
{
match self.de.tokens.peek() {
Some(&Token::TupleSep) => {
self.de.tokens.next();
self.len -= 1;
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
Some(&Token::TupleEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfStreamError),
}
}
fn end(&mut self) -> Result<(), Error> {
assert_eq!(self.len, 0);
match self.de.tokens.next() {
Some(Token::TupleEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStreamError),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerTupleStructVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: usize,
}
impl<'a, I> de::SeqVisitor for DeserializerTupleStructVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit<T>(&mut self) -> Result<Option<T>, Error>
where T: de::Deserialize,
{
match self.de.tokens.peek() {
Some(&Token::TupleStructSep) => {
self.de.tokens.next();
self.len -= 1;
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
Some(&Token::TupleStructEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfStreamError),
}
}
fn end(&mut self) -> Result<(), Error> {
assert_eq!(self.len, 0);
match self.de.tokens.next() {
Some(Token::TupleStructEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStreamError),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
} }
} }