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>
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)
}
/// 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
/// deserializers to parse sequences that aren't tagged as maps.
#[inline]

View File

@ -196,6 +196,8 @@ impl<T> Serialize for [T]
}
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! array_impls {
($len:expr) => {
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>
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)
}
/// 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.
///
/// By default, tuple structs are serialized as a tuple.

View File

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

View File

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

View File

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

View File

@ -38,12 +38,17 @@ pub enum Token<'a> {
EnumNewType(&'a str, &'a str),
SeqStart(Option<usize>),
SeqArrayStart(usize),
SeqSep,
SeqEnd,
TupleStart(usize),
TupleSep,
TupleEnd,
TupleStructStart(&'a str, Option<usize>),
TupleSeqSep,
TupleSeqEnd,
TupleStructSep,
TupleStructEnd,
MapStart(Option<usize>),
MapSep,
@ -231,6 +236,16 @@ impl<'a, I> ser::Serializer for Serializer<I>
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>
where T: ser::Serialize
{
@ -238,6 +253,27 @@ impl<'a, I> ser::Serializer for Serializer<I>
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,
name: &'static str,
value: T) -> Result<(), Error>
@ -256,7 +292,7 @@ impl<'a, I> ser::Serializer for Serializer<I>
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::TupleSeqEnd));
assert_eq!(self.tokens.next(), Some(&Token::TupleStructEnd));
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>
where T: ser::Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::TupleSeqSep));
assert_eq!(self.tokens.next(), Some(&Token::TupleStructSep));
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,
{
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,
len: len,
})
@ -528,6 +582,9 @@ impl<I> de::Deserializer for Deserializer<I>
Some(Token::SeqStart(len)) | Some(Token::TupleStructStart(_, len)) => {
self.visit_seq(len, visitor)
}
Some(Token::SeqArrayStart(len)) => {
self.visit_seq(Some(len), visitor)
}
Some(Token::MapStart(len)) | Some(Token::StructStart(_, len)) => {
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,
name: &str,
len: usize,
@ -632,6 +739,10 @@ impl<I> de::Deserializer for Deserializer<I>
where V: de::Visitor,
{
match self.tokens.peek() {
Some(&Token::Unit) => {
self.tokens.next();
visitor.visit_unit()
}
Some(&Token::UnitStruct(n)) => {
self.tokens.next();
if name == n {
@ -640,18 +751,26 @@ impl<I> de::Deserializer for Deserializer<I>
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(_)) => {
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(n, _)) => {
self.tokens.next();
if name == n {
self.visit_tuple_struct(len, visitor)
} else {
Err(Error::InvalidName(n))
}
}
Some(_) => self.deserialize(visitor),
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>,
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>>,
{
type Error = Error;
@ -743,12 +862,12 @@ impl<'a, I> de::SeqVisitor for DeserializerTupleSeqVisitor<'a, I>
where T: de::Deserialize,
{
match self.de.tokens.peek() {
Some(&Token::TupleSeqSep) => {
Some(&Token::SeqSep) => {
self.de.tokens.next();
self.len = self.len.map(|len| len - 1);
self.len -= 1;
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
}
Some(&Token::TupleSeqEnd) => Ok(None),
Some(&Token::SeqEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
@ -758,17 +877,104 @@ impl<'a, I> de::SeqVisitor for DeserializerTupleSeqVisitor<'a, I>
}
fn end(&mut self) -> Result<(), Error> {
//assert_eq!(self.len.unwrap_or(0), 0);
assert_eq!(self.len, 0);
match self.de.tokens.next() {
Some(Token::TupleSeqEnd) => Ok(()),
Some(Token::SeqEnd) => Ok(()),
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfStreamError),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len.unwrap_or(0);
(len, self.len)
(self.len, Some(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))
}
}