napi_calm_down/js_values/
de.rs1use 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}