Skip to main content

serde_v8/
de.rs

1// Copyright 2018-2026 the Deno authors. MIT license.
2
3use serde::Deserialize;
4use serde::de::SeqAccess as _;
5use serde::de::Visitor;
6use serde::de::{self};
7
8use crate::AnyValue;
9use crate::BigInt;
10use crate::ByteString;
11use crate::DetachedBuffer;
12use crate::JsBuffer;
13use crate::StringOrBuffer;
14use crate::U16String;
15use crate::error::Error;
16use crate::error::Result;
17use crate::keys::KeyCache;
18use crate::keys::v8_struct_key;
19use crate::magic;
20use crate::magic::transl8::FromV8;
21use crate::magic::transl8::MagicType;
22use crate::magic::transl8::visit_magic;
23use crate::payload::ValueType;
24
25pub struct Deserializer<'b, 's, 'i> {
26  input: v8::Local<'s, v8::Value>,
27  scope: &'b mut v8::PinScope<'s, 'i>,
28  _key_cache: Option<&'b mut KeyCache>,
29}
30
31impl<'b, 's, 'i> Deserializer<'b, 's, 'i> {
32  pub fn new(
33    scope: &'b mut v8::PinScope<'s, 'i>,
34    input: v8::Local<'s, v8::Value>,
35    key_cache: Option<&'b mut KeyCache>,
36  ) -> Self {
37    Deserializer {
38      input,
39      scope,
40      _key_cache: key_cache,
41    }
42  }
43}
44
45// from_v8 deserializes a v8::Value into a Deserializable / rust struct
46pub fn from_v8<'de, 'b, 's, 'i, T>(
47  scope: &'b mut v8::PinScope<'s, 'i>,
48  input: v8::Local<'s, v8::Value>,
49) -> Result<T>
50where
51  T: Deserialize<'de>,
52{
53  let mut deserializer = Deserializer::new(scope, input, None);
54  let t = T::deserialize(&mut deserializer)?;
55  Ok(t)
56}
57
58// like from_v8 except accepts a KeyCache to optimize struct key decoding
59pub fn from_v8_cached<'de, 'b, 's, 'i, T>(
60  scope: &'b mut v8::PinScope<'s, 'i>,
61  input: v8::Local<'s, v8::Value>,
62  key_cache: &mut KeyCache,
63) -> Result<T>
64where
65  T: Deserialize<'de>,
66{
67  let mut deserializer = Deserializer::new(scope, input, Some(key_cache));
68  let t = T::deserialize(&mut deserializer)?;
69  Ok(t)
70}
71
72macro_rules! deserialize_signed {
73  ($dmethod:ident, $vmethod:ident, $t:tt) => {
74    fn $dmethod<V>(self, visitor: V) -> Result<V::Value>
75    where
76      V: Visitor<'de>,
77    {
78      visitor.$vmethod(
79        if let Ok(x) = v8::Local::<v8::Number>::try_from(self.input) {
80          x.value() as $t
81        } else if let Ok(x) = v8::Local::<v8::BigInt>::try_from(self.input) {
82          x.i64_value().0 as $t
83        } else {
84          return Err(Error::ExpectedInteger(self.input.type_repr()));
85        },
86      )
87    }
88  };
89}
90
91macro_rules! deserialize_unsigned {
92  ($dmethod:ident, $vmethod:ident, $t:tt) => {
93    fn $dmethod<V>(self, visitor: V) -> Result<V::Value>
94    where
95      V: Visitor<'de>,
96    {
97      visitor.$vmethod(
98        if let Ok(x) = v8::Local::<v8::Number>::try_from(self.input) {
99          x.value() as $t
100        } else if let Ok(x) = v8::Local::<v8::BigInt>::try_from(self.input) {
101          x.u64_value().0 as $t
102        } else {
103          return Err(Error::ExpectedInteger(self.input.type_repr()));
104        },
105      )
106    }
107  };
108}
109
110impl<'de> de::Deserializer<'de> for &'_ mut Deserializer<'_, '_, '_> {
111  type Error = Error;
112
113  fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
114  where
115    V: Visitor<'de>,
116  {
117    match ValueType::from_v8(self.input) {
118      ValueType::Null => self.deserialize_unit(visitor),
119      ValueType::Bool => self.deserialize_bool(visitor),
120      // Handle floats & ints separately to work with loosely-typed serde_json
121      ValueType::Number => {
122        if self.input.is_uint32() {
123          self.deserialize_u32(visitor)
124        } else if self.input.is_int32() {
125          self.deserialize_i32(visitor)
126        } else {
127          self.deserialize_f64(visitor)
128        }
129      }
130      ValueType::BigInt => Err(Error::UnsupportedType),
131      ValueType::String => self.deserialize_string(visitor),
132      ValueType::Array => self.deserialize_seq(visitor),
133      ValueType::Object => self.deserialize_map(visitor),
134      // Map to Vec<u8> when deserialized via deserialize_any
135      // e.g: for untagged enums or StringOrBuffer
136      ValueType::ArrayBufferView | ValueType::ArrayBuffer => {
137        magic::v8slice::V8Slice::from_v8(&mut *self.scope, self.input)
138          .and_then(|zb| visitor.visit_byte_buf(Vec::from(&*zb)))
139      }
140    }
141  }
142
143  fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
144  where
145    V: Visitor<'de>,
146  {
147    // Relaxed typechecking, will map all non-true vals to false
148    visitor.visit_bool(self.input.is_true())
149  }
150
151  // signed
152  deserialize_signed!(deserialize_i8, visit_i8, i8);
153  deserialize_signed!(deserialize_i16, visit_i16, i16);
154  deserialize_signed!(deserialize_i32, visit_i32, i32);
155  deserialize_signed!(deserialize_i64, visit_i64, i64);
156  // unsigned
157  deserialize_unsigned!(deserialize_u8, visit_u8, u8);
158  deserialize_unsigned!(deserialize_u16, visit_u16, u16);
159  deserialize_unsigned!(deserialize_u32, visit_u32, u32);
160  deserialize_unsigned!(deserialize_u64, visit_u64, u64);
161
162  fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
163  where
164    V: Visitor<'de>,
165  {
166    self.deserialize_f64(visitor)
167  }
168  fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value>
169  where
170    V: Visitor<'de>,
171  {
172    visitor.visit_f64(
173      if let Ok(x) = v8::Local::<v8::Number>::try_from(self.input) {
174        x.value()
175      } else if let Ok(x) = v8::Local::<v8::BigInt>::try_from(self.input) {
176        bigint_to_f64(x)
177      } else {
178        return Err(Error::ExpectedNumber(self.input.type_repr()));
179      },
180    )
181  }
182
183  fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
184  where
185    V: Visitor<'de>,
186  {
187    self.deserialize_str(visitor)
188  }
189
190  fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
191  where
192    V: Visitor<'de>,
193  {
194    self.deserialize_string(visitor)
195  }
196
197  fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
198  where
199    V: Visitor<'de>,
200  {
201    if self.input.is_string() || self.input.is_string_object() {
202      // fixme: this unwrap is not safe because stringifier could have thrown
203      let v8_string = self.input.to_string(self.scope).unwrap();
204      let string = to_utf8(v8_string, self.scope);
205      visitor.visit_string(string)
206    } else {
207      Err(Error::ExpectedString(self.input.type_repr()))
208    }
209  }
210
211  fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
212  where
213    V: Visitor<'de>,
214  {
215    if self.input.is_null_or_undefined() {
216      visitor.visit_none()
217    } else {
218      visitor.visit_some(self)
219    }
220  }
221
222  fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
223  where
224    V: Visitor<'de>,
225  {
226    visitor.visit_unit()
227  }
228
229  fn deserialize_unit_struct<V>(
230    self,
231    _name: &'static str,
232    visitor: V,
233  ) -> Result<V::Value>
234  where
235    V: Visitor<'de>,
236  {
237    self.deserialize_unit(visitor)
238  }
239
240  // As is done here, serializers are encouraged to treat newtype structs as
241  // insignificant wrappers around the data they contain. That means not
242  // parsing anything other than the contained value.
243  fn deserialize_newtype_struct<V>(
244    self,
245    _name: &'static str,
246    visitor: V,
247  ) -> Result<V::Value>
248  where
249    V: Visitor<'de>,
250  {
251    visitor.visit_newtype_struct(self)
252  }
253
254  fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
255  where
256    V: Visitor<'de>,
257  {
258    let arr = v8::Local::<v8::Array>::try_from(self.input)
259      .map_err(|_| Error::ExpectedArray(self.input.type_repr()))?;
260    visitor.visit_seq(SeqAccess::new(arr.into(), self.scope, 0..arr.length()))
261  }
262
263  // Like deserialize_seq except it prefers tuple's length over input array's length
264  fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value>
265  where
266    V: Visitor<'de>,
267  {
268    let obj = v8::Local::<v8::Object>::try_from(self.input)
269      .map_err(|_| Error::ExpectedObject(self.input.type_repr()))?;
270    if let Ok(array) = v8::Local::<v8::Array>::try_from(obj) {
271      // If the obj is an array fail if it's length differs from the tuple length
272      let array_len = array.length() as usize;
273      if array_len != len {
274        return Err(Error::LengthMismatch(array_len, len));
275      }
276    }
277    visitor.visit_seq(SeqAccess::new(obj, self.scope, 0..len as u32))
278  }
279
280  // Tuple structs look just like sequences in JSON.
281  fn deserialize_tuple_struct<V>(
282    self,
283    _name: &'static str,
284    len: usize,
285    visitor: V,
286  ) -> Result<V::Value>
287  where
288    V: Visitor<'de>,
289  {
290    self.deserialize_tuple(len, visitor)
291  }
292
293  fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
294  where
295    V: de::Visitor<'de>,
296  {
297    // Assume object, then get_own_property_names
298    let obj = v8::Local::<v8::Object>::try_from(self.input)
299      .map_err(|_| Error::ExpectedObject(self.input.type_repr()))?;
300
301    if let Ok(map) = v8::Local::<v8::Map>::try_from(self.input) {
302      let pairs_array = map.as_array(self.scope);
303      let map = MapPairsAccess {
304        pos: 0,
305        len: pairs_array.length(),
306        obj: pairs_array,
307        scope: self.scope,
308      };
309      visitor.visit_map(map)
310    } else {
311      visitor.visit_map(MapObjectAccess::new(obj, self.scope))
312    }
313  }
314
315  fn deserialize_struct<V>(
316    self,
317    name: &'static str,
318    fields: &'static [&'static str],
319    visitor: V,
320  ) -> Result<V::Value>
321  where
322    V: Visitor<'de>,
323  {
324    match name {
325      JsBuffer::MAGIC_NAME => {
326        visit_magic(visitor, JsBuffer::from_v8(self.scope, self.input)?)
327      }
328      DetachedBuffer::MAGIC_NAME => {
329        visit_magic(visitor, DetachedBuffer::from_v8(self.scope, self.input)?)
330      }
331      ByteString::MAGIC_NAME => {
332        visit_magic(visitor, ByteString::from_v8(self.scope, self.input)?)
333      }
334      U16String::MAGIC_NAME => {
335        visit_magic(visitor, U16String::from_v8(self.scope, self.input)?)
336      }
337      StringOrBuffer::MAGIC_NAME => {
338        visit_magic(visitor, StringOrBuffer::from_v8(self.scope, self.input)?)
339      }
340      BigInt::MAGIC_NAME => {
341        visit_magic(visitor, BigInt::from_v8(self.scope, self.input)?)
342      }
343      magic::GlobalValue::MAGIC_NAME => visit_magic(
344        visitor,
345        magic::GlobalValue::from_v8(self.scope, self.input)?,
346      ),
347      magic::Value::MAGIC_NAME => {
348        visit_magic(visitor, magic::Value::from_v8(self.scope, self.input)?)
349      }
350      AnyValue::MAGIC_NAME => {
351        visit_magic(visitor, AnyValue::from_v8(self.scope, self.input)?)
352      }
353      _ => {
354        // Regular struct
355        let obj = v8::Local::<v8::Object>::try_from(self.input)
356          .map_err(|_| Error::ExpectedObject(self.input.type_repr()))?;
357
358        // Fields names are a hint and must be inferred when not provided
359        if fields.is_empty() {
360          visitor.visit_map(MapObjectAccess::new(obj, self.scope))
361        } else {
362          visitor.visit_map(StructAccess {
363            obj,
364            scope: self.scope,
365            keys: fields.iter(),
366            next_value: None,
367          })
368        }
369      }
370    }
371  }
372
373  /// To be compatible with `serde-json`, we expect enums to be:
374  /// - `"Variant"`: strings for unit variants, i.e: Enum::Variant
375  /// - `{ Variant: payload }`: single K/V pairs, converted to `Enum::Variant { payload }`
376  fn deserialize_enum<V>(
377    self,
378    _name: &str,
379    _variants: &'static [&'static str],
380    visitor: V,
381  ) -> Result<V::Value>
382  where
383    V: Visitor<'de>,
384  {
385    // Unit variant
386    if self.input.is_string() || self.input.is_string_object() {
387      let payload = v8::undefined(self.scope).into();
388      visitor.visit_enum(EnumAccess {
389        scope: self.scope,
390        tag: self.input,
391        payload,
392      })
393    }
394    // Struct or tuple variant
395    else if let Ok(obj) = v8::Local::<v8::Object>::try_from(self.input) {
396      // Unpack single-key
397      let tag = {
398        let prop_names =
399          obj.get_own_property_names(self.scope, Default::default());
400        let prop_names = prop_names
401          .ok_or_else(|| Error::ExpectedEnum(self.input.type_repr()))?;
402        let prop_names_len = prop_names.length();
403        if prop_names_len != 1 {
404          return Err(Error::LengthMismatch(prop_names_len as usize, 1));
405        }
406        // fixme: this unwrap  is not safe because of proxies
407        prop_names.get_index(self.scope, 0).unwrap()
408      };
409
410      // fixme: this unwrap  is not safe because of proxies
411      let payload = obj.get(self.scope, tag).unwrap();
412      visitor.visit_enum(EnumAccess {
413        scope: self.scope,
414        tag,
415        payload,
416      })
417    } else {
418      Err(Error::ExpectedEnum(self.input.type_repr()))
419    }
420  }
421
422  // An identifier in Serde is the type that identifies a field of a struct or
423  // the variant of an enum. In JSON, struct fields and enum variants are
424  // represented as strings. In other formats they may be represented as
425  // numeric indices.
426  fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
427  where
428    V: Visitor<'de>,
429  {
430    self.deserialize_str(visitor)
431  }
432
433  fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
434  where
435    V: Visitor<'de>,
436  {
437    visitor.visit_none()
438  }
439
440  fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value>
441  where
442    V: Visitor<'de>,
443  {
444    magic::buffer::JsBuffer::from_v8(self.scope, self.input)
445      .and_then(|zb| visitor.visit_bytes(&zb))
446  }
447
448  fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value>
449  where
450    V: Visitor<'de>,
451  {
452    magic::buffer::JsBuffer::from_v8(self.scope, self.input)
453      .and_then(|zb| visitor.visit_byte_buf(Vec::from(&*zb)))
454  }
455}
456
457struct MapObjectAccess<'a, 's, 'i> {
458  obj: v8::Local<'a, v8::Object>,
459  keys: SeqAccess<'a, 's, 'i>,
460  next_value: Option<v8::Local<'s, v8::Value>>,
461}
462
463impl<'a, 's, 'i> MapObjectAccess<'a, 's, 'i> {
464  pub fn new(
465    obj: v8::Local<'a, v8::Object>,
466    scope: &'a mut v8::PinScope<'s, 'i>,
467  ) -> Self {
468    let keys = match obj.get_own_property_names(
469      scope,
470      v8::GetPropertyNamesArgsBuilder::new()
471        .key_conversion(v8::KeyConversionMode::ConvertToString)
472        .build(),
473    ) {
474      Some(keys) => SeqAccess::new(keys.into(), scope, 0..keys.length()),
475      None => SeqAccess::new(obj, scope, 0..0),
476    };
477
478    Self {
479      obj,
480      keys,
481      next_value: None,
482    }
483  }
484}
485
486impl<'de> de::MapAccess<'de> for MapObjectAccess<'_, '_, '_> {
487  type Error = Error;
488
489  fn next_key_seed<K: de::DeserializeSeed<'de>>(
490    &mut self,
491    seed: K,
492  ) -> Result<Option<K::Value>> {
493    while let Some(key) = self.keys.next_element::<magic::Value>()? {
494      let v8_val = self.obj.get(self.keys.scope, key.v8_value).unwrap();
495      if v8_val.is_undefined() {
496        // Historically keys/value pairs with undefined values are not added to the output
497        continue;
498      }
499      self.next_value = Some(v8_val);
500      let mut deserializer =
501        Deserializer::new(self.keys.scope, key.v8_value, None);
502      return seed.deserialize(&mut deserializer).map(Some);
503    }
504    Ok(None)
505  }
506
507  fn next_value_seed<V: de::DeserializeSeed<'de>>(
508    &mut self,
509    seed: V,
510  ) -> Result<V::Value> {
511    let v8_val = self
512      .next_value
513      .take()
514      .expect("Call next_key_seed before next_value_seed");
515    let mut deserializer = Deserializer::new(self.keys.scope, v8_val, None);
516    seed.deserialize(&mut deserializer)
517  }
518
519  fn size_hint(&self) -> Option<usize> {
520    self.keys.size_hint()
521  }
522}
523
524struct MapPairsAccess<'a, 's, 'i> {
525  obj: v8::Local<'a, v8::Array>,
526  pos: u32,
527  len: u32,
528  scope: &'a mut v8::PinScope<'s, 'i>,
529}
530
531impl<'de> de::MapAccess<'de> for MapPairsAccess<'_, '_, '_> {
532  type Error = Error;
533
534  fn next_key_seed<K: de::DeserializeSeed<'de>>(
535    &mut self,
536    seed: K,
537  ) -> Result<Option<K::Value>> {
538    if self.pos < self.len {
539      let v8_key = self.obj.get_index(self.scope, self.pos).unwrap();
540      self.pos += 1;
541      let mut deserializer = Deserializer::new(self.scope, v8_key, None);
542      let k = seed.deserialize(&mut deserializer)?;
543      Ok(Some(k))
544    } else {
545      Ok(None)
546    }
547  }
548
549  fn next_value_seed<V: de::DeserializeSeed<'de>>(
550    &mut self,
551    seed: V,
552  ) -> Result<V::Value> {
553    debug_assert!(self.pos < self.len);
554    let v8_val = self.obj.get_index(self.scope, self.pos).unwrap();
555    self.pos += 1;
556    let mut deserializer = Deserializer::new(self.scope, v8_val, None);
557    seed.deserialize(&mut deserializer)
558  }
559
560  fn size_hint(&self) -> Option<usize> {
561    Some((self.len - self.pos) as usize / 2)
562  }
563}
564
565struct StructAccess<'a, 's, 'i> {
566  obj: v8::Local<'a, v8::Object>,
567  scope: &'a mut v8::PinScope<'s, 'i>,
568  keys: std::slice::Iter<'static, &'static str>,
569  next_value: Option<v8::Local<'s, v8::Value>>,
570}
571
572impl<'de> de::MapAccess<'de> for StructAccess<'_, '_, '_> {
573  type Error = Error;
574
575  fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
576  where
577    K: de::DeserializeSeed<'de>,
578  {
579    for field in self.keys.by_ref() {
580      let key = v8_struct_key(self.scope, field).into();
581      let val = self.obj.get(self.scope, key).unwrap();
582      if val.is_undefined() {
583        // Historically keys/value pairs with undefined values are not added to the output
584        continue;
585      }
586      self.next_value = Some(val);
587      let mut deserializer = Deserializer::new(self.scope, key, None);
588      return seed.deserialize(&mut deserializer).map(Some);
589    }
590    Ok(None)
591  }
592
593  fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
594  where
595    V: de::DeserializeSeed<'de>,
596  {
597    let val = self
598      .next_value
599      .take()
600      .expect("Call next_key_seed before next_value_seed");
601    let mut deserializer = Deserializer::new(self.scope, val, None);
602    seed.deserialize(&mut deserializer)
603  }
604}
605
606struct SeqAccess<'a, 's, 'i> {
607  obj: v8::Local<'a, v8::Object>,
608  scope: &'a mut v8::PinScope<'s, 'i>,
609  range: std::ops::Range<u32>,
610}
611
612impl<'a, 's, 'i> SeqAccess<'a, 's, 'i> {
613  pub fn new(
614    obj: v8::Local<'a, v8::Object>,
615    scope: &'a mut v8::PinScope<'s, 'i>,
616    range: std::ops::Range<u32>,
617  ) -> Self {
618    Self { obj, scope, range }
619  }
620}
621
622impl<'de> de::SeqAccess<'de> for SeqAccess<'_, '_, '_> {
623  type Error = Error;
624
625  fn next_element_seed<T: de::DeserializeSeed<'de>>(
626    &mut self,
627    seed: T,
628  ) -> Result<Option<T::Value>> {
629    if let Some(pos) = self.range.next() {
630      // fixme: this unwrap  is not safe because of proxies
631      let val = self.obj.get_index(self.scope, pos).unwrap();
632      let mut deserializer = Deserializer::new(self.scope, val, None);
633      seed.deserialize(&mut deserializer).map(Some)
634    } else {
635      Ok(None)
636    }
637  }
638
639  fn size_hint(&self) -> Option<usize> {
640    self.range.size_hint().1
641  }
642}
643
644struct EnumAccess<'b, 's, 'i> {
645  tag: v8::Local<'s, v8::Value>,
646  payload: v8::Local<'s, v8::Value>,
647  scope: &'b mut v8::PinScope<'s, 'i>,
648  // p1: std::marker::PhantomData<&'x ()>,
649}
650
651impl<'de, 'b, 's, 'i> de::EnumAccess<'de> for EnumAccess<'b, 's, 'i> {
652  type Error = Error;
653  type Variant = VariantDeserializer<'b, 's, 'i>;
654
655  fn variant_seed<V: de::DeserializeSeed<'de>>(
656    self,
657    seed: V,
658  ) -> Result<(V::Value, Self::Variant)> {
659    let seed = {
660      let mut dtag = Deserializer::new(self.scope, self.tag, None);
661      seed.deserialize(&mut dtag)
662    };
663    let dpayload = VariantDeserializer::<'b, 's, 'i> {
664      scope: self.scope,
665      value: self.payload,
666    };
667
668    Ok((seed?, dpayload))
669  }
670}
671
672struct VariantDeserializer<'b, 's, 'i> {
673  value: v8::Local<'s, v8::Value>,
674  scope: &'b mut v8::PinScope<'s, 'i>,
675}
676
677impl<'de> de::VariantAccess<'de> for VariantDeserializer<'_, '_, '_> {
678  type Error = Error;
679
680  fn unit_variant(self) -> Result<()> {
681    let mut d = Deserializer::new(self.scope, self.value, None);
682    de::Deserialize::deserialize(&mut d)
683  }
684
685  fn newtype_variant_seed<T: de::DeserializeSeed<'de>>(
686    self,
687    seed: T,
688  ) -> Result<T::Value> {
689    let mut d = Deserializer::new(self.scope, self.value, None);
690    seed.deserialize(&mut d)
691  }
692
693  fn tuple_variant<V: de::Visitor<'de>>(
694    self,
695    len: usize,
696    visitor: V,
697  ) -> Result<V::Value> {
698    let mut d = Deserializer::new(self.scope, self.value, None);
699    de::Deserializer::deserialize_tuple(&mut d, len, visitor)
700  }
701
702  fn struct_variant<V: de::Visitor<'de>>(
703    self,
704    fields: &'static [&'static str],
705    visitor: V,
706  ) -> Result<V::Value> {
707    let mut d = Deserializer::new(self.scope, self.value, None);
708    de::Deserializer::deserialize_struct(&mut d, "", fields, visitor)
709  }
710}
711
712fn bigint_to_f64(b: v8::Local<v8::BigInt>) -> f64 {
713  // log2(f64::MAX) == log2(1.7976931348623157e+308) == 1024
714  let mut words: [u64; 16] = [0; 16]; // 1024/64 => 16 64bit words
715  let (neg, words) = b.to_words_array(&mut words);
716  if b.word_count() > 16 {
717    return match neg {
718      true => f64::NEG_INFINITY,
719      false => f64::INFINITY,
720    };
721  }
722  let sign = if neg { -1.0 } else { 1.0 };
723  let x: f64 = words
724    .iter()
725    .enumerate()
726    .map(|(i, w)| (*w as f64) * 2.0f64.powi(64 * i as i32))
727    .sum();
728  sign * x
729}
730
731pub fn to_utf8(s: v8::Local<v8::String>, scope: &mut v8::PinScope) -> String {
732  to_utf8_fast(s, scope).unwrap_or_else(|| to_utf8_slow(s, scope))
733}
734
735fn to_utf8_fast(
736  s: v8::Local<v8::String>,
737  scope: &mut v8::PinScope,
738) -> Option<String> {
739  // Over-allocate by 20% to avoid checking string twice
740  let str_chars = s.length();
741  let capacity = (str_chars as f64 * 1.2) as usize;
742  let mut buf = Vec::with_capacity(capacity);
743
744  let mut nchars = 0;
745  let bytes_len = s.write_utf8_uninit_v2(
746    scope,
747    buf.spare_capacity_mut(),
748    v8::WriteFlags::kReplaceInvalidUtf8,
749    Some(&mut nchars),
750  );
751
752  if nchars < str_chars {
753    return None;
754  }
755
756  // SAFETY: write_utf8_uninit guarantees `bytes_len` bytes are initialized & valid utf8
757  unsafe {
758    buf.set_len(bytes_len);
759    Some(String::from_utf8_unchecked(buf))
760  }
761}
762
763fn to_utf8_slow(s: v8::Local<v8::String>, scope: &mut v8::PinScope) -> String {
764  let capacity = s.utf8_length(scope);
765  let mut buf = Vec::with_capacity(capacity);
766
767  s.write_utf8_uninit_v2(
768    scope,
769    buf.spare_capacity_mut(),
770    v8::WriteFlags::kReplaceInvalidUtf8,
771    None,
772  );
773
774  // SAFETY: write_utf8_uninit guarantees `bytes_len` bytes are initialized & valid utf8
775  unsafe {
776    buf.set_len(capacity);
777    String::from_utf8_unchecked(buf)
778  }
779}