From 67037eef9ba28e74a4d4046bc27f2189efc095e2 Mon Sep 17 00:00:00 2001 From: Clouds Date: Fri, 17 Jan 2020 18:15:32 +0800 Subject: [PATCH 1/2] split deserialize_seq try fix #8, we expect `seq` other than `map` even when it doesn't `contains_key(1)`, and vice versa --- src/de.rs | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/de.rs b/src/de.rs index 6dd70bc..dfc7233 100644 --- a/src/de.rs +++ b/src/de.rs @@ -23,17 +23,7 @@ impl<'lua, 'de> serde::Deserializer<'de> for Deserializer<'lua> { Value::Integer(v) => visitor.visit_i64(v), Value::Number(v) => visitor.visit_f64(v), Value::String(v) => visitor.visit_str(v.to_str()?), - Value::Table(v) => if v.contains_key(1)? { - let len = v.len()? as usize; - let mut deserializer = SeqDeserializer(v.sequence_values()); - let seq = visitor.visit_seq(&mut deserializer)?; - let remaining = deserializer.0.count(); - if remaining == 0 { - Ok(seq) - } else { - Err(serde::de::Error::invalid_length(len, &"fewer elements in array")) - } - } else { + Value::Table(v) => { let len = v.len()? as usize; let mut deserializer = MapDeserializer(v.pairs(), None); let map = visitor.visit_map(&mut deserializer)?; @@ -90,9 +80,29 @@ impl<'lua, 'de> serde::Deserializer<'de> for Deserializer<'lua> { visitor.visit_enum(EnumDeserializer { variant, value }) } + #[inline] + fn deserialize_seq(self, visitor: V) -> Result + where V: serde::de::Visitor<'de> + { + match self.value { + Value::Table(v) => { + let len = v.len()? as usize; + let mut deserializer = SeqDeserializer(v.sequence_values()); + let seq = visitor.visit_seq(&mut deserializer)?; + let remaining = deserializer.0.count(); + if remaining == 0 { + Ok(seq) + } else { + Err(serde::de::Error::invalid_length(len, &"fewer elements in array")) + } + } + _ => Err(serde::de::Error::custom("invalid value type")), + } + } + forward_to_deserialize_any! { bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes - byte_buf unit unit_struct newtype_struct seq tuple + byte_buf unit unit_struct newtype_struct tuple tuple_struct map struct identifier ignored_any } } @@ -253,16 +263,26 @@ mod tests { struct Test { int: u32, seq: Vec, + map: std::collections::HashMap, + empty: Vec<()>, } - let expected = Test { int: 1, seq: vec!["a".to_owned(), "b".to_owned()] }; + let expected = Test { + int: 1, + seq: vec!["a".to_owned(), "b".to_owned()], + map: vec![(1, 2), (4, 1)].into_iter().collect(), + empty: vec![] + }; + println!("{:?}", expected); let lua = Lua::new(); lua.context(|lua| { let value = lua.load(r#" a = {} a.int = 1 a.seq = {"a", "b"} + a.map = {2, [4]=1} + a.empty = {} return a "#).eval().unwrap(); let got = from_value(value).unwrap(); From 2b0dce2a9583959fd2318674e44c5054742a7e38 Mon Sep 17 00:00:00 2001 From: Clouds Date: Fri, 17 Jan 2020 18:30:07 +0800 Subject: [PATCH 2/2] fix broken for tuple and tuple_struct --- src/de.rs | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/src/de.rs b/src/de.rs index dfc7233..0387c17 100644 --- a/src/de.rs +++ b/src/de.rs @@ -100,10 +100,24 @@ impl<'lua, 'de> serde::Deserializer<'de> for Deserializer<'lua> { } } + #[inline] + fn deserialize_tuple(self, _len: usize, visitor: V) -> Result + where V: serde::de::Visitor<'de> + { + self.deserialize_seq(visitor) + } + + #[inline] + fn deserialize_tuple_struct(self, _name: &'static str, _len: usize, visitor: V) -> Result + where V: serde::de::Visitor<'de> + { + self.deserialize_seq(visitor) + } + forward_to_deserialize_any! { bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes - byte_buf unit unit_struct newtype_struct tuple - tuple_struct map struct identifier ignored_any + byte_buf unit unit_struct newtype_struct + map struct identifier ignored_any } } @@ -290,6 +304,32 @@ mod tests { }); } + #[test] + fn test_tuple() { + #[derive(Deserialize, PartialEq, Debug)] + struct Rgb(u8, u8, u8); + + let lua = Lua::new(); + lua.context(|lua| { + let expected = Rgb(1, 2, 3); + let value = lua.load( + r#" + a = {1, 2, 3} + return a + "#).eval().unwrap(); + let got = from_value(value).unwrap(); + assert_eq!(expected, got); + + let expected = (1, 2, 3); + let value = lua.load( + r#" + a = {1, 2, 3} + return a + "#).eval().unwrap(); + let got = from_value(value).unwrap(); + assert_eq!(expected, got); + }); + } #[test] fn test_enum() {