diff options
author | Aaron O'Mullan <aaron.omullan@gmail.com> | 2022-01-07 13:07:58 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-07 13:07:58 +0100 |
commit | 12423e16b7df39b2bf995efd1376ba4b6ef41e02 (patch) | |
tree | 02b3eb8ba80d21a8ee5ef13bb5c94cf7d59f8049 /serde_v8/src | |
parent | 59f0eafd19452cb379564e2c55dfcf174998bc04 (diff) |
fix(serde_v8): support #[serde(default)] (#13300)
Diffstat (limited to 'serde_v8/src')
-rw-r--r-- | serde_v8/src/de.rs | 66 |
1 files changed, 20 insertions, 46 deletions
diff --git a/serde_v8/src/de.rs b/serde_v8/src/de.rs index 44f94b2d6..24023b05d 100644 --- a/serde_v8/src/de.rs +++ b/serde_v8/src/de.rs @@ -375,7 +375,7 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de> // Regular struct let obj = v8::Local::<v8::Object>::try_from(self.input) .map_err(|_| Error::ExpectedObject)?; - let map = ObjectAccess { + let struct_access = StructAccess { fields, obj, pos: 0, @@ -383,7 +383,7 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de> _cache: None, }; - visitor.visit_map(map) + visitor.visit_seq(struct_access) } /// To be compatible with `serde-json`, we expect enums to be: @@ -511,7 +511,7 @@ impl<'de> de::MapAccess<'de> for MapAccess<'_, '_, '_> { } } -struct ObjectAccess<'a, 'b, 's> { +struct StructAccess<'a, 'b, 's> { obj: v8::Local<'a, v8::Object>, scope: &'b mut v8::HandleScope<'s>, fields: &'static [&'static str], @@ -519,57 +519,31 @@ struct ObjectAccess<'a, 'b, 's> { _cache: Option<&'b mut KeyCache>, } -fn str_deserializer(s: &str) -> de::value::StrDeserializer<Error> { - de::IntoDeserializer::into_deserializer(s) -} - -impl<'de, 'a, 'b, 's> de::MapAccess<'de> for ObjectAccess<'a, 'b, 's> { +impl<'de> de::SeqAccess<'de> for StructAccess<'_, '_, '_> { type Error = Error; - fn next_key_seed<K: de::DeserializeSeed<'de>>( - &mut self, - seed: K, - ) -> Result<Option<K::Value>> { - Ok(match self.fields.get(self.pos) { - Some(&field) => Some(seed.deserialize(str_deserializer(field))?), - None => None, - }) - } - - fn next_value_seed<V: de::DeserializeSeed<'de>>( + fn next_element_seed<T: de::DeserializeSeed<'de>>( &mut self, - seed: V, - ) -> Result<V::Value> { + seed: T, + ) -> Result<Option<T::Value>> { if self.pos >= self.fields.len() { - return Err(Error::LengthMismatch); + return Ok(None); } - let field = self.fields[self.pos]; + + let pos = self.pos; self.pos += 1; - let key = v8_struct_key(self.scope, field).into(); - let v8_val = self.obj.get(self.scope, key).unwrap(); - let mut deserializer = Deserializer::new(self.scope, v8_val, None); - seed.deserialize(&mut deserializer) - } - fn next_entry_seed< - K: de::DeserializeSeed<'de>, - V: de::DeserializeSeed<'de>, - >( - &mut self, - kseed: K, - vseed: V, - ) -> Result<Option<(K::Value, V::Value)>> { - if self.pos >= self.fields.len() { - return Ok(None); + let field = self.fields[pos]; + let key = v8_struct_key(self.scope, field).into(); + let val = self.obj.get(self.scope, key).unwrap(); + let mut deserializer = Deserializer::new(self.scope, val, None); + match seed.deserialize(&mut deserializer) { + Ok(val) => Ok(Some(val)), + // Fallback to Ok(None) for #[serde(Default)] at cost of error quality ... + // TODO(@AaronO): double check that there's no better solution + Err(_) if val.is_undefined() => Ok(None), + Err(e) => Err(e), } - let field = self.fields[self.pos]; - self.pos += 1; - Ok(Some((kseed.deserialize(str_deserializer(field))?, { - let key = v8_struct_key(self.scope, field).into(); - let v8_val = self.obj.get(self.scope, key).unwrap(); - let mut deserializer = Deserializer::new(self.scope, v8_val, None); - vseed.deserialize(&mut deserializer)? - }))) } } |