1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-21 15:04:11 -05:00

fix(serde_v8): support #[serde(default)] (#13300)

This commit is contained in:
Aaron O'Mullan 2022-01-07 13:07:58 +01:00 committed by GitHub
parent 59f0eafd19
commit 12423e16b7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 47 deletions

View file

@ -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>>(
fn next_element_seed<T: 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>>(
&mut self,
seed: V,
) -> Result<V::Value> {
if self.pos >= self.fields.len() {
return Err(Error::LengthMismatch);
}
let field = self.fields[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)>> {
seed: T,
) -> Result<Option<T::Value>> {
if self.pos >= self.fields.len() {
return Ok(None);
}
let field = self.fields[self.pos];
let pos = 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)?
})))
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),
}
}
}

View file

@ -271,3 +271,19 @@ detest!(de_bigint_i64, i64, "BigInt(-(2**59))", -(1 << 59));
defail!(defail_struct, MathOp, "123", |e| e
== Err(Error::ExpectedObject));
#[derive(PartialEq, Debug, Deserialize)]
pub struct SomeThing {
pub a: String,
#[serde(default)]
pub b: String,
}
detest!(
de_struct_defaults,
SomeThing,
"({ a: 'hello' })",
SomeThing {
a: "hello".into(),
b: "".into()
}
);