napi_calm_down/js_values/
de.rs

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