diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index d00e483d..0b43eed3 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -565,7 +565,7 @@ array_impls! { macro_rules! tuple_impls { () => {}; - ($($visitor:ident => ($($name:ident),+),)+) => { + ($($len:expr => $visitor:ident => ($($name:ident),+),)+) => { $( pub struct $visitor<$($name,)+> { marker: PhantomData<($($name,)+)>, @@ -610,7 +610,7 @@ macro_rules! tuple_impls { fn deserialize(deserializer: &mut D) -> Result<($($name,)+), D::Error> where D: Deserializer, { - deserializer.visit_tuple($visitor::new()) + deserializer.visit_tuple($len, $visitor::new()) } } )+ @@ -618,18 +618,18 @@ macro_rules! tuple_impls { } tuple_impls! { - TupleVisitor1 => (T0), - TupleVisitor2 => (T0, T1), - TupleVisitor3 => (T0, T1, T2), - TupleVisitor4 => (T0, T1, T2, T3), - TupleVisitor5 => (T0, T1, T2, T3, T4), - TupleVisitor6 => (T0, T1, T2, T3, T4, T5), - TupleVisitor7 => (T0, T1, T2, T3, T4, T5, T6), - TupleVisitor8 => (T0, T1, T2, T3, T4, T5, T6, T7), - TupleVisitor9 => (T0, T1, T2, T3, T4, T5, T6, T7, T8), - TupleVisitor10 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9), - TupleVisitor11 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10), - TupleVisitor12 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11), + 1 => TupleVisitor1 => (T0), + 2 => TupleVisitor2 => (T0, T1), + 3 => TupleVisitor3 => (T0, T1, T2), + 4 => TupleVisitor4 => (T0, T1, T2, T3), + 5 => TupleVisitor5 => (T0, T1, T2, T3, T4), + 6 => TupleVisitor6 => (T0, T1, T2, T3, T4, T5), + 7 => TupleVisitor7 => (T0, T1, T2, T3, T4, T5, T6), + 8 => TupleVisitor8 => (T0, T1, T2, T3, T4, T5, T6, T7), + 9 => TupleVisitor9 => (T0, T1, T2, T3, T4, T5, T6, T7, T8), + 10 => TupleVisitor10 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9), + 11 => TupleVisitor11 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10), + 12 => TupleVisitor12 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11), } /////////////////////////////////////////////////////////////////////////////// @@ -916,17 +916,19 @@ impl Deserialize for Result where T: Deserialize, E: Deserialize { { match try!(visitor.visit_variant()) { Field::Ok => { - let (value,) = try!(visitor.visit_seq(TupleVisitor1::new())); + let (value,) = try!(visitor.visit_seq(1, TupleVisitor1::new())); Ok(Ok(value)) } Field::Err => { - let (value,) = try!(visitor.visit_seq(TupleVisitor1::new())); + let (value,) = try!(visitor.visit_seq(1, TupleVisitor1::new())); Ok(Err(value)) } } } } - deserializer.visit_enum("Result", Visitor(PhantomData)) + const VARIANTS: &'static [&'static str] = &["Ok", "Err"]; + + deserializer.visit_enum("Result", VARIANTS, Visitor(PhantomData)) } } diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index 2f3c6a30..a04e0a74 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -220,10 +220,13 @@ pub trait Deserializer { /// This method hints that the `Deserialize` type is expecting a tuple struct. This allows /// deserializers to parse sequences that aren't tagged as sequences. #[inline] - fn visit_tuple_struct(&mut self, _name: &str, visitor: V) -> Result + fn visit_tuple_struct(&mut self, + _name: &str, + len: usize, + visitor: V) -> Result where V: Visitor, { - self.visit_tuple(visitor) + self.visit_tuple(len, visitor) } /// This method hints that the `Deserialize` type is expecting a struct. This allows @@ -241,7 +244,7 @@ pub trait Deserializer { /// This method hints that the `Deserialize` type is expecting a tuple value. This allows /// deserializers that provide a custom tuple serialization to properly deserialize the type. #[inline] - fn visit_tuple(&mut self, visitor: V) -> Result + fn visit_tuple(&mut self, _len: usize, visitor: V) -> Result where V: Visitor, { self.visit_seq(visitor) @@ -251,7 +254,10 @@ pub trait Deserializer { /// deserializers that provide a custom enumeration serialization to properly deserialize the /// type. #[inline] - fn visit_enum(&mut self, _enum: &str, _visitor: V) -> Result + fn visit_enum(&mut self, + _enum: &str, + _variants: &'static [&'static str], + _visitor: V) -> Result where V: EnumVisitor, { Err(Error::syntax_error()) @@ -577,7 +583,7 @@ pub trait VariantVisitor { } /// `visit_seq` is called when deserializing a tuple-like variant. - fn visit_seq(&mut self, _visitor: V) -> Result + fn visit_seq(&mut self, _len: usize, _visitor: V) -> Result where V: Visitor { Err(Error::syntax_error()) @@ -610,10 +616,10 @@ impl<'a, T> VariantVisitor for &'a mut T where T: VariantVisitor { (**self).visit_simple() } - fn visit_seq(&mut self, visitor: V) -> Result + fn visit_seq(&mut self, len: usize, visitor: V) -> Result where V: Visitor, { - (**self).visit_seq(visitor) + (**self).visit_seq(len, visitor) } fn visit_map(&mut self, diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index e512badc..8ad281b7 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -136,7 +136,10 @@ impl<'a> de::Deserializer for StrDeserializer<'a> { } } - fn visit_enum(&mut self, _name: &str, mut visitor: V) -> Result + fn visit_enum(&mut self, + _name: &str, + _variants: &'static [&'static str], + mut visitor: V) -> Result where V: de::EnumVisitor, { visitor.visit(self) @@ -182,7 +185,10 @@ impl de::Deserializer for StringDeserializer { } } - fn visit_enum(&mut self, _name: &str, mut visitor: V) -> Result + fn visit_enum(&mut self, + _name: &str, + _variants: &'static [&'static str], + mut visitor: V) -> Result where V: de::EnumVisitor, { visitor.visit(self) diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index 8fb69f0e..ab8adced 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -318,7 +318,7 @@ fn deserialize_tuple_struct( } } - deserializer.visit_tuple_struct($type_name, $visitor_expr) + deserializer.visit_tuple_struct($type_name, $fields, $visitor_expr) }) } @@ -489,6 +489,19 @@ fn deserialize_item_enum( .collect() ); + let variants_expr = builder.expr().addr_of().slice() + .with_exprs( + enum_def.variants.iter() + .map(|variant| { + builder.expr().str(variant.node.name) + }) + ) + .build(); + + let variants_stmt = quote_stmt!(cx, + const VARIANTS: &'static [&'static str] = $variants_expr; + ).unwrap(); + // Match arms to extract a variant from a string let variant_arms: Vec<_> = enum_def.variants.iter() .enumerate() @@ -535,7 +548,9 @@ fn deserialize_item_enum( } } - deserializer.visit_enum($type_name, $visitor_expr) + $variants_stmt + + deserializer.visit_enum($type_name, VARIANTS, $visitor_expr) }) } @@ -626,7 +641,7 @@ fn deserialize_tuple_variant( } } - visitor.visit_seq($visitor_expr) + visitor.visit_seq($fields, $visitor_expr) }) } diff --git a/serde_json/src/de.rs b/serde_json/src/de.rs index efdd53df..dc0ce34d 100644 --- a/serde_json/src/de.rs +++ b/serde_json/src/de.rs @@ -454,7 +454,10 @@ impl de::Deserializer for Deserializer } #[inline] - fn visit_enum(&mut self, _name: &str, mut visitor: V) -> Result + fn visit_enum(&mut self, + _name: &str, + _variants: &'static [&'static str], + mut visitor: V) -> Result where V: de::EnumVisitor, { try!(self.parse_whitespace()); @@ -645,7 +648,9 @@ impl de::VariantVisitor for Deserializer de::Deserialize::deserialize(self) } - fn visit_seq(&mut self, visitor: V) -> Result + fn visit_seq(&mut self, + _len: usize, + visitor: V) -> Result where V: de::Visitor, { de::Deserializer::visit(self, visitor) diff --git a/serde_json/src/value.rs b/serde_json/src/value.rs index f01dfe1d..061c80ab 100644 --- a/serde_json/src/value.rs +++ b/serde_json/src/value.rs @@ -692,7 +692,10 @@ impl de::Deserializer for Deserializer { } #[inline] - fn visit_enum(&mut self, _name: &str, mut visitor: V) -> Result + fn visit_enum(&mut self, + _name: &str, + _variants: &'static [&'static str], + mut visitor: V) -> Result where V: de::EnumVisitor, { let value = match self.value.take() { @@ -750,7 +753,9 @@ impl<'a> de::VariantVisitor for VariantDeserializer<'a> { de::Deserialize::deserialize(&mut Deserializer::new(self.val.take().unwrap())) } - fn visit_seq(&mut self, visitor: V) -> Result + fn visit_seq(&mut self, + _len: usize, + visitor: V) -> Result where V: de::Visitor, { if let Value::Array(fields) = self.val.take().unwrap() { @@ -767,7 +772,9 @@ impl<'a> de::VariantVisitor for VariantDeserializer<'a> { } } - fn visit_map(&mut self, _fields: &'static[&'static str], visitor: V) -> Result + fn visit_map(&mut self, + _fields: &'static[&'static str], + visitor: V) -> Result where V: de::Visitor, { if let Value::Object(fields) = self.val.take().unwrap() { diff --git a/serde_tests/benches/bench_enum.rs b/serde_tests/benches/bench_enum.rs index 2b83507b..b97c20cc 100644 --- a/serde_tests/benches/bench_enum.rs +++ b/serde_tests/benches/bench_enum.rs @@ -288,7 +288,10 @@ mod deserializer { } #[inline] - fn visit_enum(&mut self, _name: &str, mut visitor: V) -> Result + fn visit_enum(&mut self, + _name: &str, + _variants: &[&str], + mut visitor: V) -> Result where V: de::EnumVisitor, { match self.stack.pop() { @@ -350,7 +353,9 @@ mod deserializer { de::Deserialize::deserialize(self.de) } - fn visit_seq(&mut self, mut visitor: V) -> Result + fn visit_tuple(&mut self, + _len: usize, + mut visitor: V) -> Result where V: de::Visitor, { visitor.visit_seq(self) diff --git a/serde_tests/tests/test_de.rs b/serde_tests/tests/test_de.rs index 9b789c84..67ad4c74 100644 --- a/serde_tests/tests/test_de.rs +++ b/serde_tests/tests/test_de.rs @@ -143,7 +143,10 @@ impl Deserializer for TokenDeserializer { } } - fn visit_enum(&mut self, name: &str, mut visitor: V) -> Result + fn visit_enum(&mut self, + name: &str, + _variants: &'static [&'static str], + mut visitor: V) -> Result where V: de::EnumVisitor, { match self.tokens.next() { @@ -178,7 +181,10 @@ impl Deserializer for TokenDeserializer { } } - fn visit_tuple_struct(&mut self, name: &str, visitor: V) -> Result + fn visit_tuple_struct(&mut self, + name: &str, + _len: usize, + visitor: V) -> Result where V: de::Visitor, { match self.tokens.peek() { @@ -321,7 +327,9 @@ impl<'a> de::VariantVisitor for TokenDeserializerVariantVisitor<'a> { de::Deserialize::deserialize(self.de) } - fn visit_seq(&mut self, visitor: V) -> Result + fn visit_seq(&mut self, + _len: usize, + visitor: V) -> Result where V: de::Visitor, { de::Deserializer::visit(self.de, visitor)