diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index dbf0042b..7bb02491 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -529,7 +529,7 @@ macro_rules! array_impls { fn deserialize(deserializer: &mut D) -> Result<[T; $len], D::Error> where D: Deserializer, { - deserializer.deserialize_seq($visitor::new()) + deserializer.deserialize_fixed_size_array($len, $visitor::new()) } } )+ diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index a69f2701..d45930e4 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -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(&mut self, + _len: usize, + visitor: V) -> Result + 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] diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index e7a2e601..a2441e42 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -196,6 +196,8 @@ impl Serialize for [T] } } +/////////////////////////////////////////////////////////////////////////////// + macro_rules! array_impls { ($len:expr) => { impl Serialize for [T; $len] where T: Serialize { @@ -203,7 +205,8 @@ macro_rules! array_impls { fn serialize(&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) } } } diff --git a/serde/src/ser/mod.rs b/serde/src/ser/mod.rs index 16edd953..e700b44f 100644 --- a/serde/src/ser/mod.rs +++ b/serde/src/ser/mod.rs @@ -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(&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. diff --git a/serde_tests/tests/test_de.rs b/serde_tests/tests/test_de.rs index 082d627d..ab5a79ca 100644 --- a/serde_tests/tests/test_de.rs +++ b/serde_tests/tests/test_de.rs @@ -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::::new() => vec![ diff --git a/serde_tests/tests/test_macros.rs b/serde_tests/tests/test_macros.rs index 842fa670..5feb7252 100644 --- a/serde_tests/tests/test_macros.rs +++ b/serde_tests/tests/test_macros.rs @@ -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, ] ); } diff --git a/serde_tests/tests/test_ser.rs b/serde_tests/tests/test_ser.rs index 2edd7c17..a67a6921 100644 --- a/serde_tests/tests/test_ser.rs +++ b/serde_tests/tests/test_ser.rs @@ -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 { diff --git a/serde_tests/tests/token.rs b/serde_tests/tests/token.rs index 30d623be..11c0dc8e 100644 --- a/serde_tests/tests/token.rs +++ b/serde_tests/tests/token.rs @@ -38,12 +38,17 @@ pub enum Token<'a> { EnumNewType(&'a str, &'a str), SeqStart(Option), + SeqArrayStart(usize), SeqSep, SeqEnd, + TupleStart(usize), + TupleSep, + TupleEnd, + TupleStructStart(&'a str, Option), - TupleSeqSep, - TupleSeqEnd, + TupleStructSep, + TupleStructEnd, MapStart(Option), MapSep, @@ -231,6 +236,16 @@ impl<'a, I> ser::Serializer for Serializer self.visit_sequence(visitor) } + fn serialize_fixed_size_array(&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(&mut self, value: T) -> Result<(), Error> where T: ser::Serialize { @@ -238,6 +253,27 @@ impl<'a, I> ser::Serializer for Serializer value.serialize(self) } + fn serialize_tuple(&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(&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(&mut self, name: &'static str, value: T) -> Result<(), Error> @@ -256,7 +292,7 @@ impl<'a, I> ser::Serializer for Serializer 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 fn serialize_tuple_struct_elt(&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 Deserializer }) } - fn visit_tuple_seq(&mut self, len: Option, mut visitor: V) -> Result + fn visit_array(&mut self, len: usize, mut visitor: V) -> Result where V: de::Visitor, { - visitor.visit_seq(DeserializerTupleSeqVisitor { + visitor.visit_seq(DeserializerArrayVisitor { + de: self, + len: len, + }) + } + + fn visit_tuple(&mut self, len: usize, mut visitor: V) -> Result + where V: de::Visitor, + { + visitor.visit_seq(DeserializerTupleVisitor { + de: self, + len: len, + }) + } + + fn visit_tuple_struct(&mut self, len: usize, mut visitor: V) -> Result + where V: de::Visitor, + { + visitor.visit_seq(DeserializerTupleStructVisitor { de: self, len: len, }) @@ -528,6 +582,9 @@ impl de::Deserializer for Deserializer 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 de::Deserializer for Deserializer } } + fn deserialize_fixed_size_array(&mut self, + len: usize, + visitor: V) -> Result + 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(&mut self, + len: usize, + mut visitor: V) -> Result + 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(&mut self, name: &str, len: usize, @@ -632,6 +739,10 @@ impl de::Deserializer for Deserializer 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 de::Deserializer for Deserializer 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> { +struct DeserializerArrayVisitor<'a, I: 'a> where I: Iterator> { de: &'a mut Deserializer, - len: Option, + len: usize, } -impl<'a, I> de::SeqVisitor for DeserializerTupleSeqVisitor<'a, I> +impl<'a, I> de::SeqVisitor for DeserializerArrayVisitor<'a, I> where I: Iterator>, { 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) { - let len = self.len.unwrap_or(0); - (len, self.len) + (self.len, Some(self.len)) + } +} + +////////////////////////////////////////////////////////////////////////// + +struct DeserializerTupleVisitor<'a, I: 'a> where I: Iterator> { + de: &'a mut Deserializer, + len: usize, +} + +impl<'a, I> de::SeqVisitor for DeserializerTupleVisitor<'a, I> + where I: Iterator>, +{ + type Error = Error; + + fn visit(&mut self) -> Result, 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) { + (self.len, Some(self.len)) + } +} + +////////////////////////////////////////////////////////////////////////// + +struct DeserializerTupleStructVisitor<'a, I: 'a> where I: Iterator> { + de: &'a mut Deserializer, + len: usize, +} + +impl<'a, I> de::SeqVisitor for DeserializerTupleStructVisitor<'a, I> + where I: Iterator>, +{ + type Error = Error; + + fn visit(&mut self) -> Result, 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) { + (self.len, Some(self.len)) } }