diff options
Diffstat (limited to 'serde_v8/de.rs')
-rw-r--r-- | serde_v8/de.rs | 184 |
1 files changed, 113 insertions, 71 deletions
diff --git a/serde_v8/de.rs b/serde_v8/de.rs index 08b28c0f5..c09796d4b 100644 --- a/serde_v8/de.rs +++ b/serde_v8/de.rs @@ -58,19 +58,6 @@ where Ok(t) } -macro_rules! wip { - ($method:ident) => { - fn $method<V>(self, _v: V) -> Result<V::Value> - where - V: Visitor<'de>, - { - unimplemented!() - } - }; -} - -// TODO: maybe check for BigInt truncation ? -// (i.e: values larger than i64/u64 can hold) macro_rules! deserialize_signed { ($dmethod:ident, $vmethod:ident, $t:tt) => { fn $dmethod<V>(self, visitor: V) -> Result<V::Value> @@ -196,7 +183,12 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de> ) } - wip!(deserialize_char); + fn deserialize_char<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_str(visitor) + } fn deserialize_str<V>(self, visitor: V) -> Result<V::Value> where @@ -218,9 +210,6 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de> } } - wip!(deserialize_bytes); - wip!(deserialize_byte_buf); - fn deserialize_option<V>(self, visitor: V) -> Result<V::Value> where V: Visitor<'de>, @@ -286,8 +275,14 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de> where V: Visitor<'de>, { - // TODO: error on length mismatch let obj = v8::Local::<v8::Object>::try_from(self.input).unwrap(); + if obj.is_array() { + // If the obj is an array fail if it's length differs from the tuple length + let array = v8::Local::<v8::Array>::try_from(self.input).unwrap(); + if array.length() as usize != len { + return Err(Error::LengthMismatch); + } + } let seq = SeqAccess { pos: 0, len: len as u32, @@ -317,26 +312,33 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de> // Assume object, then get_own_property_names let obj = v8::Local::<v8::Object>::try_from(self.input) .map_err(|_| Error::ExpectedObject)?; - let prop_names = obj.get_own_property_names(self.scope); - let mut keys: Vec<magic::Value> = match prop_names { - Some(names) => from_v8(self.scope, names.into()).unwrap(), - None => vec![], - }; - let keys: Vec<v8::Local<v8::Value>> = keys - .drain(..) - .map(|x| x.into()) - // Filter keys to drop keys whose value is undefined - // TODO: optimize, since this doubles our get calls - .filter(|key| !obj.get(self.scope, *key).unwrap().is_undefined()) - .collect(); - - let map = MapAccess { - obj, - keys, - pos: 0, - scope: self.scope, - }; - visitor.visit_map(map) + + if v8::Local::<v8::Map>::try_from(self.input).is_ok() { + let pairs_array = v8::Local::<v8::Map>::try_from(self.input) + .unwrap() + .as_array(self.scope); + let map = MapPairsAccess { + pos: 0, + len: pairs_array.length(), + obj: pairs_array, + scope: self.scope, + }; + visitor.visit_map(map) + } else { + let prop_names = obj.get_own_property_names(self.scope); + let keys: Vec<magic::Value> = match prop_names { + Some(names) => from_v8(self.scope, names.into()).unwrap(), + None => vec![], + }; + + let map = MapObjectAccess { + obj, + keys: keys.into_iter(), + next_value: None, + scope: self.scope, + }; + visitor.visit_map(map) + } } fn deserialize_struct<V>( @@ -445,64 +447,104 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de> { visitor.visit_none() } + + fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + magic::buffer::ZeroCopyBuf::from_v8(self.scope, self.input) + .and_then(|zb| visitor.visit_bytes(&*zb)) + } + + fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + magic::buffer::ZeroCopyBuf::from_v8(self.scope, self.input) + .and_then(|zb| visitor.visit_byte_buf(Vec::from(&*zb))) + } } -struct MapAccess<'a, 'b, 's> { +struct MapObjectAccess<'a, 's> { obj: v8::Local<'a, v8::Object>, - scope: &'b mut v8::HandleScope<'s>, - keys: Vec<v8::Local<'a, v8::Value>>, - pos: usize, + scope: &'a mut v8::HandleScope<'s>, + keys: std::vec::IntoIter<magic::Value<'a>>, + next_value: Option<v8::Local<'a, v8::Value>>, } -impl<'de> de::MapAccess<'de> for MapAccess<'_, '_, '_> { +impl<'de> de::MapAccess<'de> for MapObjectAccess<'_, '_> { type Error = Error; fn next_key_seed<K: de::DeserializeSeed<'de>>( &mut self, seed: K, ) -> Result<Option<K::Value>> { - Ok(match self.keys.get(self.pos) { - Some(key) => { - let mut deserializer = Deserializer::new(self.scope, *key, None); - Some(seed.deserialize(&mut deserializer)?) + for key in self.keys.by_ref() { + let v8_val = self.obj.get(self.scope, key.v8_value).unwrap(); + if v8_val.is_undefined() { + // Historically keys/value pairs with undefined values are not added to the output + continue; } - None => None, - }) + self.next_value = Some(v8_val); + let mut deserializer = Deserializer::new(self.scope, key.v8_value, None); + let k = seed.deserialize(&mut deserializer)?; + return Ok(Some(k)); + } + Ok(None) } fn next_value_seed<V: de::DeserializeSeed<'de>>( &mut self, seed: V, ) -> Result<V::Value> { - if self.pos >= self.keys.len() { - return Err(Error::LengthMismatch); - } - let key = self.keys[self.pos]; - self.pos += 1; - let v8_val = self.obj.get(self.scope, key).unwrap(); + let v8_val = self.next_value.take().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>, - >( + fn size_hint(&self) -> Option<usize> { + Some(self.keys.len()) + } +} + +struct MapPairsAccess<'a, 's> { + obj: v8::Local<'a, v8::Array>, + pos: u32, + len: u32, + scope: &'a mut v8::HandleScope<'s>, +} + +impl<'de> de::MapAccess<'de> for MapPairsAccess<'_, '_> { + type Error = Error; + + fn next_key_seed<K: de::DeserializeSeed<'de>>( &mut self, - kseed: K, - vseed: V, - ) -> Result<Option<(K::Value, V::Value)>> { - if self.pos >= self.keys.len() { - return Ok(None); + seed: K, + ) -> Result<Option<K::Value>> { + if self.pos < self.len { + let v8_key = self.obj.get_index(self.scope, self.pos).unwrap(); + self.pos += 1; + let mut deserializer = Deserializer::new(self.scope, v8_key, None); + let k = seed.deserialize(&mut deserializer)?; + Ok(Some(k)) + } else { + Ok(None) } - let v8_key = self.keys[self.pos]; + } + + fn next_value_seed<V: de::DeserializeSeed<'de>>( + &mut self, + seed: V, + ) -> Result<V::Value> { + debug_assert!(self.pos < self.len); + let v8_val = self.obj.get_index(self.scope, self.pos).unwrap(); self.pos += 1; - let mut kdeserializer = Deserializer::new(self.scope, v8_key, None); - Ok(Some((kseed.deserialize(&mut kdeserializer)?, { - let v8_val = self.obj.get(self.scope, v8_key).unwrap(); - let mut deserializer = Deserializer::new(self.scope, v8_val, None); - vseed.deserialize(&mut deserializer)? - }))) + let mut deserializer = Deserializer::new(self.scope, v8_val, None); + seed.deserialize(&mut deserializer) + } + + fn size_hint(&self) -> Option<usize> { + Some((self.len - self.pos) as usize / 2) } } |