summaryrefslogtreecommitdiff
path: root/serde_v8/de.rs
diff options
context:
space:
mode:
Diffstat (limited to 'serde_v8/de.rs')
-rw-r--r--serde_v8/de.rs184
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)
}
}