From b40d8f7bace42b6766b28603df036759e2c0fd56 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Mon, 16 Mar 2015 22:30:02 -0700 Subject: [PATCH] Remove the `first` argument from visit_{seq,map}_elt --- serde_macros/src/ser.rs | 6 +- src/json/ser.rs | 20 +++- src/json/value.rs | 4 +- src/ser.rs | 30 +----- tests/test_json.rs | 210 ++++++++++++++++++++++++++++++++++++++++ tests/test_ser.rs | 80 +++++++-------- 6 files changed, 271 insertions(+), 79 deletions(-) diff --git a/serde_macros/src/ser.rs b/serde_macros/src/ser.rs index 1197500a..fb6bb9bf 100644 --- a/serde_macros/src/ser.rs +++ b/serde_macros/src/ser.rs @@ -449,7 +449,6 @@ fn serialize_tuple_struct_visitor( ) -> (P, P) { let arms: Vec = (0 .. fields) .map(|i| { - let first = builder.expr().bool(i == 0); let expr = builder.expr() .tup_field(i) .field("value").self_(); @@ -457,7 +456,7 @@ fn serialize_tuple_struct_visitor( quote_arm!(cx, $i => { self.state += 1; - let v = try!(serializer.visit_seq_elt($first, &$expr)); + let v = try!(serializer.visit_seq_elt(&$expr)); Ok(Some(v)) } ) @@ -524,8 +523,6 @@ fn serialize_struct_visitor( .zip(value_exprs) .enumerate() .map(|(i, (key_expr, value_expr))| { - let first = i == 0; - quote_arm!(cx, $i => { self.state += 1; @@ -533,7 +530,6 @@ fn serialize_struct_visitor( Some( try!( serializer.visit_map_elt( - $first, $key_expr, $value_expr, ) diff --git a/src/json/ser.rs b/src/json/ser.rs index 5544fd51..85133a6c 100644 --- a/src/json/ser.rs +++ b/src/json/ser.rs @@ -9,6 +9,10 @@ use ser; pub struct Serializer { writer: W, formatter: F, + + /// `first` is used to signify if we should print a comma when we are walking through a + /// sequence. + first: bool, } impl Serializer @@ -33,6 +37,7 @@ impl Serializer Serializer { writer: writer, formatter: formatter, + first: false, } } @@ -166,6 +171,8 @@ impl ser::Serializer for Serializer _ => { try!(self.formatter.open(&mut self.writer, b'[')); + self.first = true; + while let Some(()) = try!(visitor.visit(self)) { } self.formatter.close(&mut self.writer, b']') @@ -187,10 +194,11 @@ impl ser::Serializer for Serializer } #[inline] - fn visit_seq_elt(&mut self, first: bool, value: T) -> io::Result<()> + fn visit_seq_elt(&mut self, value: T) -> io::Result<()> where T: ser::Serialize, { - try!(self.formatter.comma(&mut self.writer, first)); + try!(self.formatter.comma(&mut self.writer, self.first)); + self.first = false; value.serialize(self) } @@ -206,6 +214,8 @@ impl ser::Serializer for Serializer _ => { try!(self.formatter.open(&mut self.writer, b'{')); + self.first = true; + while let Some(()) = try!(visitor.visit(self)) { } self.formatter.close(&mut self.writer, b'}') @@ -227,11 +237,13 @@ impl ser::Serializer for Serializer } #[inline] - fn visit_map_elt(&mut self, first: bool, key: K, value: V) -> io::Result<()> + fn visit_map_elt(&mut self, key: K, value: V) -> io::Result<()> where K: ser::Serialize, V: ser::Serialize, { - try!(self.formatter.comma(&mut self.writer, first)); + try!(self.formatter.comma(&mut self.writer, self.first)); + self.first = false; + try!(key.serialize(self)); try!(self.formatter.colon(&mut self.writer)); value.serialize(self) diff --git a/src/json/value.rs b/src/json/value.rs index b7685c52..55caca98 100644 --- a/src/json/value.rs +++ b/src/json/value.rs @@ -271,7 +271,7 @@ impl ser::Serializer for Serializer { } #[inline] - fn visit_seq_elt(&mut self, _first: bool, value: T) -> Result<(), ()> + fn visit_seq_elt(&mut self, value: T) -> Result<(), ()> where T: ser::Serialize, { try!(value.serialize(self)); @@ -330,7 +330,7 @@ impl ser::Serializer for Serializer { } #[inline] - fn visit_map_elt(&mut self, _first: bool, key: K, value: V) -> Result<(), ()> + fn visit_map_elt(&mut self, key: K, value: V) -> Result<(), ()> where K: ser::Serialize, V: ser::Serialize, { diff --git a/src/ser.rs b/src/ser.rs index c6574649..80887812 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -124,9 +124,7 @@ pub trait Serializer { self.visit_seq(visitor) } - fn visit_seq_elt(&mut self, - first: bool, - value: T) -> Result<(), Self::Error> + fn visit_seq_elt(&mut self, value: T) -> Result<(), Self::Error> where T: Serialize; fn visit_map(&mut self, visitor: V) -> Result<(), Self::Error> @@ -151,10 +149,7 @@ pub trait Serializer { self.visit_map(visitor) } - fn visit_map_elt(&mut self, - first: bool, - key: K, - value: V) -> Result<(), Self::Error> + fn visit_map_elt(&mut self, key: K, value: V) -> Result<(), Self::Error> where K: Serialize, V: Serialize; } @@ -250,7 +245,6 @@ impl Serialize for Option where T: Serialize { pub struct SeqIteratorVisitor { iter: Iter, len: Option, - first: bool, } impl SeqIteratorVisitor @@ -261,7 +255,6 @@ impl SeqIteratorVisitor SeqIteratorVisitor { iter: iter, len: len, - first: true, } } } @@ -274,12 +267,9 @@ impl SeqVisitor for SeqIteratorVisitor fn visit(&mut self, serializer: &mut S) -> Result, S::Error> where S: Serializer, { - let first = self.first; - self.first = false; - match self.iter.next() { Some(value) => { - let value = try!(serializer.visit_seq_elt(first, value)); + let value = try!(serializer.visit_seq_elt(value)); Ok(Some(value)) } None => Ok(None), @@ -365,7 +355,6 @@ macro_rules! tuple_impls { pub struct $TupleVisitor<'a, $($T: 'a),+> { tuple: &'a ($($T,)+), state: u8, - first: bool, } impl<'a, $($T: 'a),+> $TupleVisitor<'a, $($T),+> { @@ -373,7 +362,6 @@ macro_rules! tuple_impls { $TupleVisitor { tuple: tuple, state: 0, - first: true, } } } @@ -384,14 +372,11 @@ macro_rules! tuple_impls { fn visit(&mut self, serializer: &mut S) -> Result, S::Error> where S: Serializer, { - let first = self.first; - self.first = false; - match self.state { $( $state => { self.state += 1; - Ok(Some(try!(serializer.visit_seq_elt(first, &e!(self.tuple.$idx))))) + Ok(Some(try!(serializer.visit_seq_elt(&e!(self.tuple.$idx))))) } )+ _ => { @@ -527,7 +512,6 @@ tuple_impls! { pub struct MapIteratorVisitor { iter: Iter, len: Option, - first: bool, } impl MapIteratorVisitor @@ -538,7 +522,6 @@ impl MapIteratorVisitor MapIteratorVisitor { iter: iter, len: len, - first: true, } } } @@ -552,12 +535,9 @@ impl MapVisitor for MapIteratorVisitor fn visit(&mut self, serializer: &mut S) -> Result, S::Error> where S: Serializer, { - let first = self.first; - self.first = false; - match self.iter.next() { Some((key, value)) => { - let value = try!(serializer.visit_map_elt(first, key, value)); + let value = try!(serializer.visit_map_elt(key, value)); Ok(Some(value)) } None => Ok(None) diff --git a/tests/test_json.rs b/tests/test_json.rs index 014a5656..6fdc1a4c 100644 --- a/tests/test_json.rs +++ b/tests/test_json.rs @@ -144,6 +144,68 @@ fn test_write_list() { (vec![true, false], "[true,false]"), ]); + test_encode_ok(&[ + (vec![vec![], vec![], vec![]], "[[],[],[]]"), + (vec![vec![1, 2, 3], vec![], vec![]], "[[1,2,3],[],[]]"), + (vec![vec![], vec![1, 2, 3], vec![]], "[[],[1,2,3],[]]"), + (vec![vec![], vec![], vec![1, 2, 3]], "[[],[],[1,2,3]]"), + ]); + + test_pretty_encode_ok(&[ + ( + vec![vec![], vec![], vec![]], + concat!( + "[\n", + " [],\n", + " [],\n", + " []\n", + "]" + ), + ), + ( + vec![vec![1, 2, 3], vec![], vec![]], + concat!( + "[\n", + " [\n", + " 1,\n", + " 2,\n", + " 3\n", + " ],\n", + " [],\n", + " []\n", + "]" + ), + ), + ( + vec![vec![], vec![1, 2, 3], vec![]], + concat!( + "[\n", + " [],\n", + " [\n", + " 1,\n", + " 2,\n", + " 3\n", + " ],\n", + " []\n", + "]" + ), + ), + ( + vec![vec![], vec![], vec![1, 2, 3]], + concat!( + "[\n", + " [],\n", + " [],\n", + " [\n", + " 1,\n", + " 2,\n", + " 3\n", + " ]\n", + "]" + ), + ), + ]); + test_pretty_encode_ok(&[ (vec![], "[]"), ( @@ -207,6 +269,154 @@ fn test_write_object() { "{\"a\":true,\"b\":false}"), ]); + test_encode_ok(&[ + ( + treemap![ + "a".to_string() => treemap![], + "b".to_string() => treemap![], + "c".to_string() => treemap![] + ], + "{\"a\":{},\"b\":{},\"c\":{}}", + ), + ( + treemap![ + "a".to_string() => treemap![ + "a".to_string() => treemap!["a" => vec![1,2,3]], + "b".to_string() => treemap![], + "c".to_string() => treemap![] + ], + "b".to_string() => treemap![], + "c".to_string() => treemap![] + ], + "{\"a\":{\"a\":{\"a\":[1,2,3]},\"b\":{},\"c\":{}},\"b\":{},\"c\":{}}", + ), + ( + treemap![ + "a".to_string() => treemap![], + "b".to_string() => treemap![ + "a".to_string() => treemap!["a" => vec![1,2,3]], + "b".to_string() => treemap![], + "c".to_string() => treemap![] + ], + "c".to_string() => treemap![] + ], + "{\"a\":{},\"b\":{\"a\":{\"a\":[1,2,3]},\"b\":{},\"c\":{}},\"c\":{}}", + ), + ( + treemap![ + "a".to_string() => treemap![], + "b".to_string() => treemap![], + "c".to_string() => treemap![ + "a".to_string() => treemap!["a" => vec![1,2,3]], + "b".to_string() => treemap![], + "c".to_string() => treemap![] + ] + ], + "{\"a\":{},\"b\":{},\"c\":{\"a\":{\"a\":[1,2,3]},\"b\":{},\"c\":{}}}", + ), + ]); + + test_pretty_encode_ok(&[ + ( + treemap![ + "a".to_string() => treemap![], + "b".to_string() => treemap![], + "c".to_string() => treemap![] + ], + concat!( + "{\n", + " \"a\": {},\n", + " \"b\": {},\n", + " \"c\": {}\n", + "}", + ), + ), + ( + treemap![ + "a".to_string() => treemap![ + "a".to_string() => treemap!["a" => vec![1,2,3]], + "b".to_string() => treemap![], + "c".to_string() => treemap![] + ], + "b".to_string() => treemap![], + "c".to_string() => treemap![] + ], + concat!( + "{\n", + " \"a\": {\n", + " \"a\": {\n", + " \"a\": [\n", + " 1,\n", + " 2,\n", + " 3\n", + " ]\n", + " },\n", + " \"b\": {},\n", + " \"c\": {}\n", + " },\n", + " \"b\": {},\n", + " \"c\": {}\n", + "}" + ), + ), + ( + treemap![ + "a".to_string() => treemap![], + "b".to_string() => treemap![ + "a".to_string() => treemap!["a" => vec![1,2,3]], + "b".to_string() => treemap![], + "c".to_string() => treemap![] + ], + "c".to_string() => treemap![] + ], + concat!( + "{\n", + " \"a\": {},\n", + " \"b\": {\n", + " \"a\": {\n", + " \"a\": [\n", + " 1,\n", + " 2,\n", + " 3\n", + " ]\n", + " },\n", + " \"b\": {},\n", + " \"c\": {}\n", + " },\n", + " \"c\": {}\n", + "}" + ), + ), + ( + treemap![ + "a".to_string() => treemap![], + "b".to_string() => treemap![], + "c".to_string() => treemap![ + "a".to_string() => treemap!["a" => vec![1,2,3]], + "b".to_string() => treemap![], + "c".to_string() => treemap![] + ] + ], + concat!( + "{\n", + " \"a\": {},\n", + " \"b\": {},\n", + " \"c\": {\n", + " \"a\": {\n", + " \"a\": [\n", + " 1,\n", + " 2,\n", + " 3\n", + " ]\n", + " },\n", + " \"b\": {},\n", + " \"c\": {}\n", + " }\n", + "}" + ), + ), + ]); + test_pretty_encode_ok(&[ (treemap!(), "{}"), ( diff --git a/tests/test_ser.rs b/tests/test_ser.rs index 9e5ea9ba..b8979820 100644 --- a/tests/test_ser.rs +++ b/tests/test_ser.rs @@ -36,13 +36,13 @@ pub enum Token<'a> { SeqStart(Option), NamedSeqStart(&'a str, Option), EnumSeqStart(&'a str, &'a str, Option), - SeqSep(bool), + SeqSep, SeqEnd, MapStart(Option), NamedMapStart(&'a str, Option), EnumMapStart(&'a str, &'a str, Option), - MapSep(bool), + MapSep, MapEnd, } @@ -217,10 +217,10 @@ impl<'a> Serializer for AssertSerializer<'a> { self.visit_sequence(visitor) } - fn visit_seq_elt(&mut self, first: bool, value: T) -> Result<(), ()> + fn visit_seq_elt(&mut self, value: T) -> Result<(), ()> where T: Serialize { - assert_eq!(self.iter.next(), Some(Token::SeqSep(first))); + assert_eq!(self.iter.next(), Some(Token::SeqSep)); value.serialize(self) } @@ -244,10 +244,7 @@ impl<'a> Serializer for AssertSerializer<'a> { self.visit_mapping(visitor) } - fn visit_enum_map(&mut self, - name: &str, - variant: &str, - visitor: V) -> Result<(), ()> + fn visit_enum_map(&mut self, name: &str, variant: &str, visitor: V) -> Result<(), ()> where V: MapVisitor { let len = visitor.len(); @@ -257,14 +254,11 @@ impl<'a> Serializer for AssertSerializer<'a> { self.visit_mapping(visitor) } - fn visit_map_elt(&mut self, - first: bool, - key: K, - value: V) -> Result<(), ()> + fn visit_map_elt(&mut self, key: K, value: V) -> Result<(), ()> where K: Serialize, V: Serialize, { - assert_eq!(self.iter.next(), Some(Token::MapSep(first))); + assert_eq!(self.iter.next(), Some(Token::MapSep)); try!(key.serialize(self)); value.serialize(self) @@ -375,13 +369,13 @@ declare_tests! { ], &[1, 2, 3][..] => vec![ Token::SeqStart(Some(3)), - Token::SeqSep(true), + Token::SeqSep, Token::I32(1), - Token::SeqSep(false), + Token::SeqSep, Token::I32(2), - Token::SeqSep(false), + Token::SeqSep, Token::I32(3), Token::SeqEnd, ], @@ -393,22 +387,22 @@ declare_tests! { ], vec![vec![], vec![1], vec![2, 3]] => vec![ Token::SeqStart(Some(3)), - Token::SeqSep(true), + Token::SeqSep, Token::SeqStart(Some(0)), Token::SeqEnd, - Token::SeqSep(false), + Token::SeqSep, Token::SeqStart(Some(1)), - Token::SeqSep(true), + Token::SeqSep, Token::I32(1), Token::SeqEnd, - Token::SeqSep(false), + Token::SeqSep, Token::SeqStart(Some(2)), - Token::SeqSep(true), + Token::SeqSep, Token::I32(2), - Token::SeqSep(false), + Token::SeqSep, Token::I32(3), Token::SeqEnd, Token::SeqEnd, @@ -417,19 +411,19 @@ declare_tests! { test_tuple { (1,) => vec![ Token::SeqStart(Some(1)), - Token::SeqSep(true), + Token::SeqSep, Token::I32(1), Token::SeqEnd, ], (1, 2, 3) => vec![ Token::SeqStart(Some(3)), - Token::SeqSep(true), + Token::SeqSep, Token::I32(1), - Token::SeqSep(false), + Token::SeqSep, Token::I32(2), - Token::SeqSep(false), + Token::SeqSep, Token::I32(3), Token::SeqEnd, ], @@ -437,37 +431,37 @@ declare_tests! { test_btreemap { btreemap![1 => 2] => vec![ Token::MapStart(Some(1)), - Token::MapSep(true), + Token::MapSep, Token::I32(1), Token::I32(2), Token::MapEnd, ], btreemap![1 => 2, 3 => 4] => vec![ Token::MapStart(Some(2)), - Token::MapSep(true), + Token::MapSep, Token::I32(1), Token::I32(2), - Token::MapSep(false), + Token::MapSep, Token::I32(3), Token::I32(4), Token::MapEnd, ], btreemap![1 => btreemap![], 2 => btreemap![3 => 4, 5 => 6]] => vec![ Token::MapStart(Some(2)), - Token::MapSep(true), + Token::MapSep, Token::I32(1), Token::MapStart(Some(0)), Token::MapEnd, - Token::MapSep(false), + Token::MapSep, Token::I32(2), Token::MapStart(Some(2)), - Token::MapSep(true), + Token::MapSep, Token::I32(3), Token::I32(4), - Token::MapSep(false), + Token::MapSep, Token::I32(5), Token::I32(6), Token::MapEnd, @@ -480,13 +474,13 @@ declare_tests! { test_named_seq { NamedSeq(1, 2, 3) => vec![ Token::NamedSeqStart("NamedSeq", Some(3)), - Token::SeqSep(true), + Token::SeqSep, Token::I32(1), - Token::SeqSep(false), + Token::SeqSep, Token::I32(2), - Token::SeqSep(false), + Token::SeqSep, Token::I32(3), Token::SeqEnd, ], @@ -494,15 +488,15 @@ declare_tests! { test_named_map { NamedMap { a: 1, b: 2, c: 3 } => vec![ Token::NamedMapStart("NamedMap", Some(3)), - Token::MapSep(true), + Token::MapSep, Token::Str("a"), Token::I32(1), - Token::MapSep(false), + Token::MapSep, Token::Str("b"), Token::I32(2), - Token::MapSep(false), + Token::MapSep, Token::Str("c"), Token::I32(3), Token::MapEnd, @@ -512,20 +506,20 @@ declare_tests! { Enum::Unit => vec![Token::EnumUnit("Enum", "Unit")], Enum::Seq(1, 2) => vec![ Token::EnumSeqStart("Enum", "Seq", Some(2)), - Token::SeqSep(true), + Token::SeqSep, Token::I32(1), - Token::SeqSep(false), + Token::SeqSep, Token::I32(2), Token::SeqEnd, ], Enum::Map { a: 1, b: 2 } => vec![ Token::EnumMapStart("Enum", "Map", Some(2)), - Token::MapSep(true), + Token::MapSep, Token::Str("a"), Token::I32(1), - Token::MapSep(false), + Token::MapSep, Token::Str("b"), Token::I32(2), Token::MapEnd,