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}