/ duper-js-node / src / de.rs
de.rs
  1  use napi::{
  2      Env, JsString, JsValue, Unknown, ValueType,
  3      bindgen_prelude::{BigInt, FromNapiValue, JsObjectValue, Object, Uint8Array},
  4  };
  5  use serde_core::{
  6      de::{DeserializeSeed, Error, IntoDeserializer, MapAccess, SeqAccess},
  7      forward_to_deserialize_any,
  8  };
  9  
 10  pub(crate) struct DuperMetaDeserializer<'env> {
 11      pub(crate) env: &'env Env,
 12      pub(crate) object: Object<'env>,
 13  }
 14  
 15  impl<'de, 'env> serde_core::Deserializer<'de> for DuperMetaDeserializer<'env> {
 16      type Error = serde_core::de::value::Error;
 17  
 18      fn is_human_readable(&self) -> bool {
 19          true
 20      }
 21  
 22      fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
 23      where
 24          V: serde_core::de::Visitor<'de>,
 25      {
 26          self.deserialize_map(visitor)
 27      }
 28  
 29      fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
 30      where
 31          V: serde_core::de::Visitor<'de>,
 32      {
 33          let keys = self.object.get_property_names().map_err(|err| {
 34              serde_core::de::value::Error::custom(format!("failed to get property names: {err}"))
 35          })?;
 36          let array_length = keys.get_array_length().expect("checked array creation");
 37          visitor.visit_map(DuperMetaMapAccess {
 38              env: self.env,
 39              object: self.object,
 40              keys,
 41              array_length,
 42              curr_value: None,
 43              i: 0,
 44          })
 45      }
 46  
 47      forward_to_deserialize_any! {
 48          bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char
 49          str string bytes byte_buf identifier ignored_any struct
 50          option unit unit_struct newtype_struct seq tuple tuple_struct enum
 51      }
 52  }
 53  
 54  struct DuperMetaMapAccess<'env> {
 55      env: &'env Env,
 56      object: Object<'env>,
 57      keys: Object<'env>,
 58      curr_value: Option<Unknown<'env>>,
 59      array_length: u32,
 60      i: u32,
 61  }
 62  
 63  impl<'de, 'env> MapAccess<'de> for DuperMetaMapAccess<'env> {
 64      type Error = serde_core::de::value::Error;
 65  
 66      fn size_hint(&self) -> Option<usize> {
 67          Some((self.array_length - self.i) as usize)
 68      }
 69  
 70      fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
 71      where
 72          K: DeserializeSeed<'de>,
 73      {
 74          if self.i < self.array_length {
 75              let key: String = self.keys.get_element(self.i).map_err(|err| {
 76                  serde_core::de::value::Error::custom(format!(
 77                      "error accessing index {} of object keys: {err:?}",
 78                      self.i
 79                  ))
 80              })?;
 81              self.curr_value = Some(
 82                  self.object
 83                      .get_property::<JsString, Unknown>(
 84                          self.env
 85                              .create_string(key.as_str())
 86                              .expect("checked string"),
 87                      )
 88                      .map_err(|err| {
 89                          serde_core::de::value::Error::custom(format!(
 90                              "error accessing property {} of object: {err:?}",
 91                              &key
 92                          ))
 93                      })?,
 94              );
 95              self.i += 1;
 96              seed.deserialize(key.into_deserializer()).map(Some)
 97          } else {
 98              Ok(None)
 99          }
100      }
101  
102      fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
103      where
104          V: DeserializeSeed<'de>,
105      {
106          if let Some(value) = self.curr_value.take() {
107              match value.get_type() {
108                  Ok(ValueType::Undefined) | Ok(ValueType::Null) => {
109                      seed.deserialize(DuperMetaInnerNull)
110                  }
111                  Ok(ValueType::Boolean) => seed.deserialize(
112                      value
113                          .coerce_to_bool()
114                          .expect("checked bool")
115                          .into_deserializer(),
116                  ),
117                  Ok(ValueType::Number) => seed.deserialize(
118                      value
119                          .coerce_to_number()
120                          .expect("checked number")
121                          .get_double()
122                          .expect("infallible conversion to f64")
123                          .into_deserializer(),
124                  ),
125                  Ok(ValueType::String) => seed.deserialize(
126                      value
127                          .coerce_to_string()
128                          .expect("checked string")
129                          .into_utf8()
130                          .expect("valid UTF-8")
131                          .as_str()
132                          .expect("valid conversion to &str")
133                          .into_deserializer(),
134                  ),
135                  Ok(ValueType::BigInt) => seed.deserialize(
136                      BigInt::from_unknown(value)
137                          .expect("checked bigint")
138                          .get_i64()
139                          .0
140                          .into_deserializer(),
141                  ),
142                  Ok(ValueType::Object) => {
143                      if value.is_array().expect("array type check") {
144                          seed.deserialize(DuperMetaInnerArrayDeserializer {
145                              env: self.env,
146                              array: value.coerce_to_object().expect("checked object"),
147                          })
148                      } else if let Ok(bytes) = Uint8Array::from_unknown(value) {
149                          seed.deserialize(bytes.as_ref().into_deserializer())
150                      } else {
151                          seed.deserialize(DuperMetaInnerObjectDeserializer {
152                              env: self.env,
153                              object: value.coerce_to_object().expect("checked object"),
154                          })
155                      }
156                  }
157                  Ok(_) | Err(_) => Err(serde_core::de::value::Error::custom("unknown value type")),
158              }
159          } else {
160              Err(serde_core::de::value::Error::custom("missing value"))
161          }
162      }
163  }
164  
165  pub(crate) struct DuperMetaInnerObjectDeserializer<'env> {
166      pub(crate) env: &'env Env,
167      pub(crate) object: Object<'env>,
168  }
169  
170  impl<'de, 'env> serde_core::Deserializer<'de> for DuperMetaInnerObjectDeserializer<'env> {
171      type Error = serde_core::de::value::Error;
172  
173      fn is_human_readable(&self) -> bool {
174          true
175      }
176  
177      fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
178      where
179          V: serde_core::de::Visitor<'de>,
180      {
181          self.deserialize_map(visitor)
182      }
183  
184      fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
185      where
186          V: serde_core::de::Visitor<'de>,
187      {
188          let keys = self.object.get_property_names().map_err(|err| {
189              serde_core::de::value::Error::custom(format!("failed to get property names: {err}"))
190          })?;
191          let array_length = keys.get_array_length().expect("checked array creation");
192          visitor.visit_map(DuperMetaInnerObjectMapAccess {
193              env: self.env,
194              object: self.object,
195              keys,
196              array_length,
197              curr_value: None,
198              i: 0,
199          })
200      }
201  
202      forward_to_deserialize_any! {
203          bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char
204          str string bytes byte_buf identifier ignored_any struct
205          option unit unit_struct newtype_struct seq tuple tuple_struct enum
206      }
207  }
208  
209  struct DuperMetaInnerObjectMapAccess<'env> {
210      env: &'env Env,
211      object: Object<'env>,
212      keys: Object<'env>,
213      curr_value: Option<Unknown<'env>>,
214      array_length: u32,
215      i: u32,
216  }
217  
218  impl<'de, 'env> MapAccess<'de> for DuperMetaInnerObjectMapAccess<'env> {
219      type Error = serde_core::de::value::Error;
220  
221      fn size_hint(&self) -> Option<usize> {
222          Some((self.array_length - self.i) as usize)
223      }
224  
225      fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
226      where
227          K: DeserializeSeed<'de>,
228      {
229          if self.i < self.array_length {
230              let key: String = self.keys.get_element(self.i).map_err(|err| {
231                  serde_core::de::value::Error::custom(format!(
232                      "error accessing index {} of object keys: {err:?}",
233                      self.i
234                  ))
235              })?;
236              self.curr_value = Some(
237                  self.object
238                      .get_property::<JsString, Unknown>(
239                          self.env.create_string(key.as_str()).map_err(|err| {
240                              serde_core::de::value::Error::custom(format!(
241                                  "error converting property {} to string: {err:?}",
242                                  &key
243                              ))
244                          })?,
245                      )
246                      .map_err(|err| {
247                          serde_core::de::value::Error::custom(format!(
248                              "error accessing property {} of object: {err:?}",
249                              &key
250                          ))
251                      })?,
252              );
253              self.i += 1;
254              seed.deserialize(key.into_deserializer()).map(Some)
255          } else {
256              Ok(None)
257          }
258      }
259  
260      fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
261      where
262          V: DeserializeSeed<'de>,
263      {
264          if let Some(value) = self.curr_value.take() {
265              seed.deserialize(DuperMetaDeserializer {
266                  env: self.env,
267                  object: value.coerce_to_object().map_err(|err| {
268                      serde_core::de::value::Error::custom(format!(
269                          "error converting map value to object: {err:?}",
270                      ))
271                  })?,
272              })
273          } else {
274              Err(serde_core::de::value::Error::custom("missing value"))
275          }
276      }
277  }
278  
279  pub(crate) struct DuperMetaInnerArrayDeserializer<'env> {
280      pub(crate) env: &'env Env,
281      pub(crate) array: Object<'env>,
282  }
283  
284  impl<'de, 'env> serde_core::Deserializer<'de> for DuperMetaInnerArrayDeserializer<'env> {
285      type Error = serde_core::de::value::Error;
286  
287      fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
288      where
289          V: serde_core::de::Visitor<'de>,
290      {
291          self.deserialize_seq(visitor)
292      }
293  
294      fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
295      where
296          V: serde_core::de::Visitor<'de>,
297      {
298          let array_length = self.array.get_array_length().expect("checked array");
299          visitor.visit_seq(DuperMetaInnerArraySeqAccess {
300              env: self.env,
301              array: self.array,
302              array_length,
303              i: 0,
304          })
305      }
306  
307      forward_to_deserialize_any! {
308          bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char
309          str string bytes byte_buf identifier ignored_any map struct
310          option unit unit_struct newtype_struct tuple tuple_struct enum
311      }
312  }
313  
314  struct DuperMetaInnerArraySeqAccess<'env> {
315      env: &'env Env,
316      array: Object<'env>,
317      array_length: u32,
318      i: u32,
319  }
320  
321  impl<'de, 'env> SeqAccess<'de> for DuperMetaInnerArraySeqAccess<'env> {
322      type Error = serde_core::de::value::Error;
323  
324      fn size_hint(&self) -> Option<usize> {
325          Some((self.array_length - self.i) as usize)
326      }
327  
328      fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
329      where
330          T: DeserializeSeed<'de>,
331      {
332          if self.i < self.array_length {
333              let object = self.array.get_element::<Object>(self.i).map_err(|err| {
334                  serde_core::de::value::Error::custom(format!(
335                      "failed to get object from array: {err}"
336                  ))
337              })?;
338              self.i += 1;
339              Ok(Some(seed.deserialize(DuperMetaDeserializer {
340                  env: self.env,
341                  object,
342              })?))
343          } else {
344              Ok(None)
345          }
346      }
347  }
348  
349  struct DuperMetaInnerNull;
350  
351  impl<'de> serde_core::Deserializer<'de> for DuperMetaInnerNull {
352      type Error = serde_core::de::value::Error;
353  
354      fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
355      where
356          V: serde_core::de::Visitor<'de>,
357      {
358          visitor.visit_none()
359      }
360  
361      forward_to_deserialize_any! {
362          bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char
363          str string bytes byte_buf identifier ignored_any map struct
364          option unit unit_struct newtype_struct seq tuple tuple_struct enum
365      }
366  }