diff --git a/Cargo.toml b/Cargo.toml index 56b063d..b9e8ea5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ categories = ["development-tools::ffi", "wasm", "encoding"] keywords = ["serde", "serialization", "javascript", "wasm", "webassembly"] [dependencies] -serde = { version = "^1.0", features = ["derive"] } +serde = { version = "1.0.193", features = ["derive"] } js-sys = "^0.3" wasm-bindgen = "0.2.83" diff --git a/src/de.rs b/src/de.rs index 98b07c2..ed35f73 100644 --- a/src/de.rs +++ b/src/de.rs @@ -65,7 +65,7 @@ impl<'de> de::MapAccess<'de> for MapAccess { struct ObjectAccess { obj: ObjectExt, - fields: std::slice::Iter<'static, &'static str>, + fields: std::iter::Enumerate>, next_value: Option, } @@ -73,23 +73,19 @@ impl ObjectAccess { fn new(obj: ObjectExt, fields: &'static [&'static str]) -> Self { Self { obj, - fields: fields.iter(), + fields: fields.iter().enumerate(), next_value: None, } } } -fn str_deserializer(s: &str) -> de::value::StrDeserializer { - de::IntoDeserializer::into_deserializer(s) -} - impl<'de> de::MapAccess<'de> for ObjectAccess { type Error = Error; fn next_key_seed>(&mut self, seed: K) -> Result> { debug_assert!(self.next_value.is_none()); - for field in &mut self.fields { + for (i, &field) in &mut self.fields { let js_field = static_str_to_js(field); let next_value = self.obj.get_with_ref_key(&js_field); // If this value is `undefined`, it might be actually a missing field; @@ -97,7 +93,12 @@ impl<'de> de::MapAccess<'de> for ObjectAccess { let is_missing_field = next_value.is_undefined() && !js_field.js_in(&self.obj); if !is_missing_field { self.next_value = Some(Deserializer::from(next_value)); - return Ok(Some(seed.deserialize(str_deserializer(field))?)); + // Serde can deserialize struct fields from their indices. + // Using them allows for more efficient deserialization as it + // avoids string comparisons. + return Ok(Some(seed.deserialize( + de::IntoDeserializer::::into_deserializer(i), + )?)); } } @@ -127,8 +128,10 @@ impl<'de> de::SeqAccess<'de> for PreservedValueAccess { match this { Self::OnMagic(value) => { *self = Self::OnValue(value); - seed.deserialize(str_deserializer(PRESERVED_VALUE_MAGIC)) - .map(Some) + seed.deserialize(de::IntoDeserializer::into_deserializer( + PRESERVED_VALUE_MAGIC, + )) + .map(Some) } Self::OnValue(value) => seed .deserialize(Deserializer {