napi/js_values/
de.rs

1use serde::de::Visitor;
2use serde::de::{DeserializeSeed, EnumAccess, MapAccess, SeqAccess, Unexpected, VariantAccess};
3
4#[cfg(feature = "napi6")]
5use crate::bindgen_runtime::BigInt;
6use crate::{
7  bindgen_runtime::{ArrayBuffer, BufferSlice, FromNapiValue, JsObjectValue, Object, Unknown},
8  type_of, Error, JsValue, Result, Status, Value, ValueType,
9};
10
11pub struct De<'env>(pub(crate) &'env Value);
12impl<'env> De<'env> {
13  pub fn new(value: &'env Object<'env>) -> Self {
14    Self(&value.0)
15  }
16}
17
18#[doc(hidden)]
19impl<'x> serde::de::Deserializer<'x> for &mut De<'_> {
20  type Error = Error;
21
22  fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
23  where
24    V: Visitor<'x>,
25  {
26    let js_value_type = type_of!(self.0.env, self.0.value)?;
27    match js_value_type {
28      ValueType::Null | ValueType::Undefined => visitor.visit_unit(),
29      ValueType::Boolean => {
30        let val: bool = unsafe { FromNapiValue::from_napi_value(self.0.env, self.0.value)? };
31        visitor.visit_bool(val)
32      }
33      ValueType::Number => {
34        let js_number: f64 = unsafe { FromNapiValue::from_napi_value(self.0.env, self.0.value)? };
35        if (js_number.trunc() - js_number).abs() < f64::EPSILON {
36          visitor.visit_i64(js_number as i64)
37        } else {
38          visitor.visit_f64(js_number)
39        }
40      }
41      ValueType::String => visitor.visit_str(
42        unsafe { <String as FromNapiValue>::from_napi_value(self.0.env, self.0.value) }?.as_str(),
43      ),
44      ValueType::Object => {
45        let js_object = Object::from_raw(self.0.env, self.0.value);
46        if js_object.is_array()? {
47          let mut deserializer =
48            JsArrayAccess::new(&js_object, js_object.get_array_length_unchecked()?);
49          visitor.visit_seq(&mut deserializer)
50        } else if js_object.is_typedarray()? {
51          visitor.visit_bytes(unsafe { FromNapiValue::from_napi_value(self.0.env, self.0.value)? })
52        } else if js_object.is_buffer()? {
53          visitor.visit_bytes(&unsafe { BufferSlice::from_napi_value(self.0.env, self.0.value)? })
54        } else if js_object.is_arraybuffer()? {
55          let array_buf = unsafe { ArrayBuffer::from_napi_value(self.0.env, self.0.value)? };
56          if array_buf.data.is_empty() {
57            return visitor.visit_bytes(&[]);
58          }
59          visitor.visit_bytes(array_buf.data)
60        } else {
61          let mut deserializer = JsObjectAccess::new(&js_object)?;
62          visitor.visit_map(&mut deserializer)
63        }
64      }
65      #[cfg(feature = "napi6")]
66      ValueType::BigInt => {
67        let js_bigint = unsafe { BigInt::from_napi_value(self.0.env, self.0.value)? };
68
69        let BigInt { sign_bit, words } = &js_bigint;
70        let word_sized = words.len() < 2;
71
72        match (sign_bit, word_sized) {
73          (true, true) => visitor.visit_i64(js_bigint.get_i64().0),
74          (true, false) => visitor.visit_i128(js_bigint.get_i128().0),
75          (false, true) => visitor.visit_u64(js_bigint.get_u64().1),
76          (false, false) => visitor.visit_u128(js_bigint.get_u128().1),
77        }
78      }
79      ValueType::External | ValueType::Function | ValueType::Symbol => Err(Error::new(
80        Status::InvalidArg,
81        format!("typeof {js_value_type:?} value could not be deserialized"),
82      )),
83      ValueType::Unknown => unreachable!(),
84    }
85  }
86
87  fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value>
88  where
89    V: Visitor<'x>,
90  {
91    match type_of!(self.0.env, self.0.value)? {
92      ValueType::Object => {
93        let js_object = Object::from_raw(self.0.env, self.0.value);
94        if js_object.is_buffer()? {
95          return visitor
96            .visit_bytes(&unsafe { BufferSlice::from_napi_value(self.0.env, self.0.value)? });
97        } else if js_object.is_arraybuffer()? {
98          let array_buf = unsafe { ArrayBuffer::from_napi_value(self.0.env, self.0.value)? };
99          if array_buf.data.is_empty() {
100            return visitor.visit_bytes(&[]);
101          }
102          return visitor.visit_bytes(array_buf.data);
103        }
104        visitor.visit_bytes(unsafe { FromNapiValue::from_napi_value(self.0.env, self.0.value)? })
105      }
106      _ => unreachable!(),
107    }
108  }
109
110  fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value>
111  where
112    V: Visitor<'x>,
113  {
114    match type_of!(self.0.env, self.0.value)? {
115      ValueType::Object => {
116        let js_object = Object::from_raw(self.0.env, self.0.value);
117        if js_object.is_buffer()? {
118          return visitor.visit_byte_buf(
119            unsafe { BufferSlice::from_napi_value(self.0.env, self.0.value)? }.to_vec(),
120          );
121        } else if js_object.is_typedarray()? {
122          return visitor.visit_byte_buf(unsafe {
123            let u8_slice: &[u8] = FromNapiValue::from_napi_value(self.0.env, self.0.value)?;
124            u8_slice.to_vec()
125          });
126        } else if js_object.is_arraybuffer()? {
127          let array_buf = unsafe { ArrayBuffer::from_napi_value(self.0.env, self.0.value)? };
128          if array_buf.data.is_empty() {
129            return visitor.visit_byte_buf(Vec::new());
130          }
131          return visitor.visit_byte_buf(array_buf.data.to_vec());
132        }
133        visitor.visit_byte_buf(unsafe { FromNapiValue::from_napi_value(self.0.env, self.0.value)? })
134      }
135      _ => unreachable!(),
136    }
137  }
138
139  fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
140  where
141    V: Visitor<'x>,
142  {
143    match type_of!(self.0.env, self.0.value)? {
144      ValueType::Undefined | ValueType::Null => visitor.visit_none(),
145      _ => visitor.visit_some(self),
146    }
147  }
148
149  fn deserialize_enum<V>(
150    self,
151    _name: &'static str,
152    _variants: &'static [&'static str],
153    visitor: V,
154  ) -> Result<V::Value>
155  where
156    V: Visitor<'x>,
157  {
158    let js_value_type = type_of!(self.0.env, self.0.value)?;
159    match js_value_type {
160      ValueType::String => visitor.visit_enum(JsEnumAccess::new(
161        unsafe { FromNapiValue::from_napi_value(self.0.env, self.0.value) }?,
162        None,
163      )),
164      ValueType::Object => {
165        let js_object = Object::from_raw(self.0.env, self.0.value);
166        let properties = js_object.get_property_names()?;
167        let property_len = properties.get_array_length_unchecked()?;
168        if property_len != 1 {
169          Err(Error::new(
170            Status::InvalidArg,
171            format!("object key length: {property_len}, can not deserialize to Enum"),
172          ))
173        } else {
174          let key = properties.get_element::<String>(0)?;
175          let value: Unknown = js_object.get_named_property_unchecked(&key)?;
176          visitor.visit_enum(JsEnumAccess::new(key, Some(&value.0)))
177        }
178      }
179      _ => Err(Error::new(
180        Status::InvalidArg,
181        format!("{js_value_type:?} type could not deserialize to Enum type"),
182      )),
183    }
184  }
185
186  fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
187  where
188    V: Visitor<'x>,
189  {
190    visitor.visit_unit()
191  }
192
193  forward_to_deserialize_any! {
194     <V: Visitor<'x>>
195      bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
196      unit unit_struct seq tuple tuple_struct map struct identifier
197      newtype_struct
198  }
199}
200
201#[doc(hidden)]
202pub(crate) struct JsEnumAccess<'env> {
203  variant: String,
204  value: Option<&'env Value>,
205}
206
207#[doc(hidden)]
208impl<'env> JsEnumAccess<'env> {
209  fn new(variant: String, value: Option<&'env Value>) -> Self {
210    Self { variant, value }
211  }
212}
213
214#[doc(hidden)]
215impl<'de, 'env> EnumAccess<'de> for JsEnumAccess<'env> {
216  type Error = Error;
217  type Variant = JsVariantAccess<'env>;
218
219  fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
220  where
221    V: DeserializeSeed<'de>,
222  {
223    use serde::de::IntoDeserializer;
224    let variant = self.variant.into_deserializer();
225    let variant_access = JsVariantAccess { value: self.value };
226    seed.deserialize(variant).map(|v| (v, variant_access))
227  }
228}
229
230#[doc(hidden)]
231pub(crate) struct JsVariantAccess<'env> {
232  value: Option<&'env Value>,
233}
234
235#[doc(hidden)]
236impl<'de> VariantAccess<'de> for JsVariantAccess<'_> {
237  type Error = Error;
238  fn unit_variant(self) -> Result<()> {
239    match self.value {
240      Some(val) => {
241        let mut deserializer = De(val);
242        serde::de::Deserialize::deserialize(&mut deserializer)
243      }
244      None => Ok(()),
245    }
246  }
247
248  fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
249  where
250    T: DeserializeSeed<'de>,
251  {
252    match self.value {
253      Some(val) => {
254        let mut deserializer = De(val);
255        seed.deserialize(&mut deserializer)
256      }
257      None => Err(serde::de::Error::invalid_type(
258        Unexpected::UnitVariant,
259        &"newtype variant",
260      )),
261    }
262  }
263
264  fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
265  where
266    V: Visitor<'de>,
267  {
268    match self.value {
269      Some(js_value) => {
270        let js_object = Object::from_raw(js_value.env, js_value.value);
271        if js_object.is_array()? {
272          let mut deserializer =
273            JsArrayAccess::new(&js_object, js_object.get_array_length_unchecked()?);
274          visitor.visit_seq(&mut deserializer)
275        } else {
276          Err(serde::de::Error::invalid_type(
277            Unexpected::Other("JsValue"),
278            &"tuple variant",
279          ))
280        }
281      }
282      None => Err(serde::de::Error::invalid_type(
283        Unexpected::UnitVariant,
284        &"tuple variant",
285      )),
286    }
287  }
288
289  fn struct_variant<V>(self, _fields: &'static [&'static str], visitor: V) -> Result<V::Value>
290  where
291    V: Visitor<'de>,
292  {
293    match self.value {
294      Some(js_value) => {
295        if let Ok(val) = unsafe { Object::from_napi_value(js_value.env, js_value.value) } {
296          let mut deserializer = JsObjectAccess::new(&val)?;
297          visitor.visit_map(&mut deserializer)
298        } else {
299          Err(serde::de::Error::invalid_type(
300            Unexpected::Other("JsValue"),
301            &"struct variant",
302          ))
303        }
304      }
305      _ => Err(serde::de::Error::invalid_type(
306        Unexpected::UnitVariant,
307        &"struct variant",
308      )),
309    }
310  }
311}
312
313#[doc(hidden)]
314struct JsArrayAccess<'env> {
315  input: &'env Object<'env>,
316  idx: u32,
317  len: u32,
318}
319
320#[doc(hidden)]
321impl<'env> JsArrayAccess<'env> {
322  fn new(input: &'env Object, len: u32) -> Self {
323    Self { input, idx: 0, len }
324  }
325}
326
327#[doc(hidden)]
328impl<'de> SeqAccess<'de> for JsArrayAccess<'_> {
329  type Error = Error;
330
331  fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
332  where
333    T: DeserializeSeed<'de>,
334  {
335    if self.idx >= self.len {
336      return Ok(None);
337    }
338    let v = self.input.get_element::<Unknown>(self.idx)?;
339    self.idx += 1;
340
341    let mut de = De(&v.0);
342    seed.deserialize(&mut de).map(Some)
343  }
344}
345
346#[doc(hidden)]
347pub(crate) struct JsObjectAccess<'env> {
348  value: &'env Object<'env>,
349  properties: Object<'env>,
350  idx: u32,
351  property_len: u32,
352}
353
354#[doc(hidden)]
355impl<'env> JsObjectAccess<'env> {
356  fn new(value: &'env Object) -> Result<Self> {
357    let properties = value.get_property_names()?;
358    let property_len = properties.get_array_length_unchecked()?;
359    Ok(Self {
360      value,
361      properties,
362      idx: 0,
363      property_len,
364    })
365  }
366}
367
368#[doc(hidden)]
369impl<'de> MapAccess<'de> for JsObjectAccess<'_> {
370  type Error = Error;
371
372  fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
373  where
374    K: DeserializeSeed<'de>,
375  {
376    if self.idx >= self.property_len {
377      return Ok(None);
378    }
379
380    let prop_name = self.properties.get_element::<Unknown>(self.idx)?;
381
382    let mut de = De(&prop_name.0);
383    seed.deserialize(&mut de).map(Some)
384  }
385
386  fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
387  where
388    V: DeserializeSeed<'de>,
389  {
390    if self.idx >= self.property_len {
391      return Err(Error::new(
392        Status::InvalidArg,
393        format!("Index:{} out of range: {}", self.property_len, self.idx),
394      ));
395    }
396    let prop_name = self.properties.get_element::<String>(self.idx)?;
397    let value: Unknown = self.value.get_named_property_unchecked(&prop_name)?;
398
399    self.idx += 1;
400    let mut de = De(&value.0);
401    let res = seed.deserialize(&mut de)?;
402    Ok(res)
403  }
404}