Skip to main content

simdjson_rust/
serde.rs

1//! `serde::Deserializer` implementation backed by the simdjson tape.
2//!
3//! This allows you to deserialize any `serde::Deserialize` type directly from
4//! simdjson's DOM tape without first converting to an intermediate AST.
5//!
6//! # Example
7//!
8//! ```rust
9//! use serde::Deserialize;
10//! use simdjson_rust::serde::from_str;
11//!
12//! #[derive(Debug, Deserialize, PartialEq)]
13//! struct Point {
14//!     x: f64,
15//!     y: f64,
16//! }
17//!
18//! let p: Point = from_str(r#"{"x": 1.0, "y": 2.0}"#).unwrap();
19//! assert_eq!(p, Point { x: 1.0, y: 2.0 });
20//! ```
21
22use serde::{
23    Deserialize,
24    de::{self, DeserializeSeed, EnumAccess, MapAccess, SeqAccess, VariantAccess, Visitor},
25};
26use snafu::prelude::*;
27
28use crate::{
29    dom::Parser,
30    tape::{self, TapeRef, TapeType},
31};
32
33/// The error type returned by the Serde deserializer.
34#[derive(Debug, Snafu)]
35#[snafu(visibility(pub(crate)))]
36pub enum Error {
37    #[snafu(display("serde error: {message}"))]
38    Custom { message: String },
39
40    /// A malformed or unsupported tape state was encountered while
41    /// deserializing. Carries the structured [`tape::Error`] so callers can
42    /// match on the concrete failure.
43    #[snafu(transparent)]
44    Tape {
45        #[snafu(backtrace)]
46        source: tape::Error,
47    },
48
49    #[snafu(display("dom error: {source}"))]
50    Dom {
51        #[snafu(backtrace)]
52        source: crate::dom::Error,
53    },
54}
55
56pub type Result<T, E = Error> = std::result::Result<T, E>;
57
58impl From<crate::dom::Error> for Error {
59    fn from(source: crate::dom::Error) -> Self {
60        Error::Dom { source }
61    }
62}
63
64impl de::Error for Error {
65    fn custom<T: std::fmt::Display>(msg: T) -> Self {
66        Error::Custom {
67            message: msg.to_string(),
68        }
69    }
70}
71
72/// Deserialize `T` from a JSON string using the simdjson DOM tape.
73pub fn from_str<T: for<'de> Deserialize<'de>>(json: &str) -> Result<T> {
74    let mut parser = Parser::default();
75    let tape = parser.parse_str(json)?;
76    let mut de = TapeDeserializer { tape };
77    T::deserialize(&mut de)
78}
79
80/// Deserialize `T` from a JSON byte slice using the simdjson DOM tape.
81pub fn from_bytes<T: for<'de> Deserialize<'de>>(json: &[u8]) -> Result<T> {
82    let mut parser = Parser::default();
83    let tape = parser.parse_bytes(json)?;
84    let mut de = TapeDeserializer { tape };
85    T::deserialize(&mut de)
86}
87
88/// Deserialize `T` directly from a parsed `TapeRef` cursor.
89///
90/// This allows you to reuse the `Parser` instance across multiple documents,
91/// which is highly recommended for performance.
92pub fn from_tape<'de, T: Deserialize<'de>>(tape: TapeRef<'de>) -> Result<T> {
93    let mut de = TapeDeserializer { tape };
94    T::deserialize(&mut de)
95}
96
97/// A `serde::Deserializer` that reads directly from the simdjson tape.
98///
99/// The lifetime `'de` is tied to the parser that owns the tape, enabling
100/// zero-copy `&str` deserialization.
101pub struct TapeDeserializer<'de> {
102    tape: TapeRef<'de>,
103}
104
105/// Internal helper: deserialize a single JSON value from a mutable tape cursor.
106///
107/// This is the workhorse used by all `SeqAccess`/`MapAccess`/`VariantAccess`
108/// impls so they can share the same tape cursor.
109///
110/// Dispatches on the raw tag byte of the current tape word rather than going
111/// through `Option<TapeType>`, avoiding an enum round-trip and a second match
112/// on every node.
113#[inline]
114fn deserialize_value<'de, V: Visitor<'de>>(
115    tape: &mut TapeRef<'de>,
116    visitor: V,
117) -> Result<V::Value> {
118    if tape.pos >= tape.tape.len() {
119        return Err(tape::OutOfBoundsSnafu {
120            pos: tape.pos,
121            len: tape.tape.len(),
122        }
123        .build()
124        .into());
125    }
126    let word = tape.current_word_public();
127    let tag = (word >> 56) as u8;
128    match tag {
129        b'r' => {
130            tape.skip(1);
131            deserialize_value(tape, visitor)
132        }
133        b'n' => {
134            tape.skip(1);
135            visitor.visit_unit()
136        }
137        b't' => {
138            tape.skip(1);
139            visitor.visit_bool(true)
140        }
141        b'f' => {
142            tape.skip(1);
143            visitor.visit_bool(false)
144        }
145        b'l' => {
146            let v = tape.get_int64()?;
147            tape.skip(2);
148            visitor.visit_i64(v)
149        }
150        b'u' => {
151            let v = tape.get_uint64()?;
152            tape.skip(2);
153            visitor.visit_u64(v)
154        }
155        b'd' => {
156            let v = tape.get_double()?;
157            tape.skip(2);
158            visitor.visit_f64(v)
159        }
160        b'"' => {
161            let s: &'de str = tape.get_string()?;
162            tape.skip(1);
163            visitor.visit_borrowed_str(s)
164        }
165        b'[' => {
166            let end_idx = tape.scope_close_idx();
167            let count = tape.scope_count();
168            tape.skip(1); // past `[`
169            let result = visitor.visit_seq(TapeSeqAccess {
170                tape,
171                end_idx,
172                count,
173            })?;
174            tape.skip(1); // past `]`
175            Ok(result)
176        }
177        b'{' => {
178            let end_idx = tape.scope_close_idx();
179            tape.skip(1); // past `{`
180            let result = visitor.visit_map(TapeMapAccess { tape, end_idx })?;
181            tape.skip(1); // past `}`
182            Ok(result)
183        }
184        _ => match TapeType::from_tape_word(word) {
185            // Recognised tag that isn't a valid value position (e.g. a stray
186            // `}` / `]`). `tag` is known, so this is unexpected, not unknown.
187            Some(_) => Err(tape::UnexpectedTapeTypeSnafu {
188                found: tag,
189                pos: tape.pos(),
190            }
191            .build()
192            .into()),
193            None => Err(tape::UnknownTapeTypeSnafu {
194                tag,
195                pos: tape.pos(),
196            }
197            .build()
198            .into()),
199        },
200    }
201}
202
203/// Skip a complete JSON value on the tape without deserializing it.
204fn skip_value(tape: &mut TapeRef<'_>) -> Result<()> {
205    match tape.tape_type() {
206        Some(TapeType::Null) | Some(TapeType::True) | Some(TapeType::False) => {
207            tape.skip(1);
208        }
209        Some(TapeType::Int64) | Some(TapeType::Uint64) | Some(TapeType::Double) => {
210            tape.skip(2);
211        }
212        Some(TapeType::String) => {
213            tape.skip(1);
214        }
215        Some(TapeType::StartArray) | Some(TapeType::StartObject) => {
216            // scope_close_idx = position of the closing `]` / `}` entry
217            let end_idx = tape.scope_close_idx();
218            tape.seek_public(end_idx);
219            tape.skip(1); // past the closing bracket
220        }
221        Some(t) => {
222            return Err(tape::UnexpectedTapeTypeSnafu {
223                found: t as u8,
224                pos: tape.pos(),
225            }
226            .build()
227            .into());
228        }
229        None => {
230            return Err(tape::UnknownTapeTypeSnafu {
231                tag: (tape.current_word_public() >> 56) as u8,
232                pos: tape.pos(),
233            }
234            .build()
235            .into());
236        }
237    }
238    Ok(())
239}
240
241// ---------------------------------------------------------------------------
242// SeqAccess for arrays
243// ---------------------------------------------------------------------------
244
245struct TapeSeqAccess<'a, 'de: 'a> {
246    tape: &'a mut TapeRef<'de>,
247    end_idx: usize,
248    /// Element count read from the `[` tape word, used as a `size_hint` so
249    /// serde can pre-allocate the destination `Vec` and avoid a grow storm.
250    count: usize,
251}
252
253impl<'a, 'de> SeqAccess<'de> for TapeSeqAccess<'a, 'de> {
254    type Error = Error;
255
256    fn next_element_seed<T: DeserializeSeed<'de>>(&mut self, seed: T) -> Result<Option<T::Value>> {
257        if self.tape.pos() >= self.end_idx {
258            return Ok(None);
259        }
260        seed.deserialize(&mut TapeRefDeserializer { tape: self.tape })
261            .map(Some)
262    }
263
264    fn size_hint(&self) -> Option<usize> {
265        Some(self.count)
266    }
267}
268
269// ---------------------------------------------------------------------------
270// MapAccess for objects
271// ---------------------------------------------------------------------------
272
273struct TapeMapAccess<'a, 'de: 'a> {
274    tape: &'a mut TapeRef<'de>,
275    end_idx: usize,
276}
277
278impl<'a, 'de> MapAccess<'de> for TapeMapAccess<'a, 'de> {
279    type Error = Error;
280
281    fn next_key_seed<K: DeserializeSeed<'de>>(&mut self, seed: K) -> Result<Option<K::Value>> {
282        if self.tape.pos() >= self.end_idx {
283            return Ok(None);
284        }
285        // Keys in object tape are always String nodes.
286        let word = self.tape.current_word_public();
287        let tag = (word >> 56) as u8;
288        if tag != b'"' {
289            return Err(tape::UnexpectedTapeTypeSnafu {
290                found: tag,
291                pos: self.tape.pos(),
292            }
293            .build()
294            .into());
295        }
296        let key: &'de str = self.tape.get_string()?;
297        self.tape.skip(1);
298        let key_deserializer = de::value::BorrowedStrDeserializer::<Error>::new(key);
299        seed.deserialize(key_deserializer).map(Some)
300    }
301
302    fn next_value_seed<V: DeserializeSeed<'de>>(&mut self, seed: V) -> Result<V::Value> {
303        seed.deserialize(&mut TapeRefDeserializer { tape: self.tape })
304    }
305}
306
307// ---------------------------------------------------------------------------
308// EnumAccess / VariantAccess
309// ---------------------------------------------------------------------------
310
311struct TapeEnumAccess<'a, 'de: 'a> {
312    tape: &'a mut TapeRef<'de>,
313    end_idx: usize,
314}
315
316impl<'a, 'de> EnumAccess<'de> for TapeEnumAccess<'a, 'de> {
317    type Error = Error;
318    type Variant = TapeVariantAccess<'a, 'de>;
319
320    fn variant_seed<V: DeserializeSeed<'de>>(self, seed: V) -> Result<(V::Value, Self::Variant)> {
321        let word = self.tape.current_word_public();
322        let tag = (word >> 56) as u8;
323        if tag != b'"' {
324            return Err(tape::UnexpectedTapeTypeSnafu {
325                found: tag,
326                pos: self.tape.pos(),
327            }
328            .build()
329            .into());
330        }
331        let name: &'de str = self.tape.get_string()?;
332        self.tape.skip(1);
333        let name_deserializer = de::value::BorrowedStrDeserializer::<Error>::new(name);
334        let val = seed.deserialize(name_deserializer)?;
335        Ok((
336            val,
337            TapeVariantAccess {
338                tape: self.tape,
339                end_idx: self.end_idx,
340            },
341        ))
342    }
343}
344
345struct TapeVariantAccess<'a, 'de: 'a> {
346    tape: &'a mut TapeRef<'de>,
347    #[allow(dead_code)]
348    end_idx: usize,
349}
350
351impl<'a, 'de> VariantAccess<'de> for TapeVariantAccess<'a, 'de> {
352    type Error = Error;
353
354    fn unit_variant(self) -> Result<()> {
355        Ok(())
356    }
357
358    fn newtype_variant_seed<T: DeserializeSeed<'de>>(self, seed: T) -> Result<T::Value> {
359        seed.deserialize(&mut TapeRefDeserializer { tape: self.tape })
360    }
361
362    fn tuple_variant<V: Visitor<'de>>(self, _len: usize, visitor: V) -> Result<V::Value> {
363        deserialize_value(self.tape, visitor)
364    }
365
366    fn struct_variant<V: Visitor<'de>>(
367        self,
368        _fields: &'static [&'static str],
369        visitor: V,
370    ) -> Result<V::Value> {
371        deserialize_value(self.tape, visitor)
372    }
373}
374
375// ---------------------------------------------------------------------------
376// TapeRefDeserializer - thin wrapper that delegates to `deserialize_value`
377// ---------------------------------------------------------------------------
378
379/// A thin `serde::Deserializer` that mutates a shared `TapeRef` cursor.
380///
381/// This is used by `SeqAccess`, `MapAccess`, and `VariantAccess` to
382/// delegate element deserialization.
383struct TapeRefDeserializer<'a, 'de: 'a> {
384    tape: &'a mut TapeRef<'de>,
385}
386
387macro_rules! forward_to_deserialize_value {
388    ($($fn:ident)*) => {
389        $(
390            fn $fn<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
391                deserialize_value(self.tape, visitor)
392            }
393        )*
394    };
395}
396
397impl<'a, 'de> de::Deserializer<'de> for &mut TapeRefDeserializer<'a, 'de> {
398    type Error = Error;
399
400    // All other methods can forward to `deserialize_any`.
401    forward_to_deserialize_value! {
402        deserialize_bool
403        deserialize_i8 deserialize_i16 deserialize_i32 deserialize_i64
404        deserialize_u8 deserialize_u16 deserialize_u32 deserialize_u64
405        deserialize_f32 deserialize_f64
406        deserialize_char deserialize_str deserialize_string
407        deserialize_bytes deserialize_byte_buf
408        deserialize_unit
409        deserialize_seq deserialize_map
410        deserialize_identifier
411    }
412
413    fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
414        deserialize_value(self.tape, visitor)
415    }
416
417    fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
418        if self.tape.tape_type() == Some(TapeType::Null) {
419            self.tape.skip(1);
420            visitor.visit_none()
421        } else {
422            visitor.visit_some(self)
423        }
424    }
425
426    fn deserialize_newtype_struct<V: Visitor<'de>>(
427        self,
428        _name: &'static str,
429        visitor: V,
430    ) -> Result<V::Value> {
431        visitor.visit_newtype_struct(self)
432    }
433
434    fn deserialize_enum<V: Visitor<'de>>(
435        self,
436        _name: &'static str,
437        _variants: &'static [&'static str],
438        visitor: V,
439    ) -> Result<V::Value> {
440        match self.tape.tape_type() {
441            Some(TapeType::String) => {
442                let s: &'de str = self.tape.get_string()?;
443                self.tape.skip(1);
444                let enum_deserializer = de::value::StrDeserializer::<Error>::new(s);
445                visitor.visit_enum(enum_deserializer)
446            }
447            Some(TapeType::StartObject) => {
448                let end_idx = self.tape.scope_close_idx();
449                self.tape.skip(1); // past `{`
450                let result = visitor.visit_enum(TapeEnumAccess {
451                    tape: self.tape,
452                    end_idx,
453                })?;
454                self.tape.skip(1); // past `}`
455                Ok(result)
456            }
457            _ => deserialize_value(self.tape, visitor),
458        }
459    }
460
461    fn deserialize_ignored_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
462        skip_value(self.tape)?;
463        visitor.visit_unit()
464    }
465
466    fn deserialize_unit_struct<V: Visitor<'de>>(
467        self,
468        _name: &'static str,
469        visitor: V,
470    ) -> Result<V::Value> {
471        deserialize_value(self.tape, visitor)
472    }
473
474    fn deserialize_tuple<V: Visitor<'de>>(self, _len: usize, visitor: V) -> Result<V::Value> {
475        deserialize_value(self.tape, visitor)
476    }
477
478    fn deserialize_tuple_struct<V: Visitor<'de>>(
479        self,
480        _name: &'static str,
481        _len: usize,
482        visitor: V,
483    ) -> Result<V::Value> {
484        deserialize_value(self.tape, visitor)
485    }
486
487    fn deserialize_struct<V: Visitor<'de>>(
488        self,
489        _name: &'static str,
490        _fields: &'static [&'static str],
491        visitor: V,
492    ) -> Result<V::Value> {
493        deserialize_value(self.tape, visitor)
494    }
495}
496
497// ---------------------------------------------------------------------------
498// TapeDeserializer (top-level entry point)
499// ---------------------------------------------------------------------------
500
501impl<'de> de::Deserializer<'de> for &mut TapeDeserializer<'de> {
502    type Error = Error;
503
504    fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
505        // Skip root if present.
506        if self.tape.tape_type() == Some(TapeType::Root) {
507            self.tape.skip(1);
508        }
509        deserialize_value(&mut self.tape, visitor)
510    }
511
512    fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
513        if self.tape.tape_type() == Some(TapeType::Root) {
514            self.tape.skip(1);
515        }
516        if self.tape.tape_type() == Some(TapeType::Null) {
517            self.tape.skip(1);
518            visitor.visit_none()
519        } else {
520            visitor.visit_some(self)
521        }
522    }
523
524    fn deserialize_newtype_struct<V: Visitor<'de>>(
525        self,
526        _name: &'static str,
527        visitor: V,
528    ) -> Result<V::Value> {
529        visitor.visit_newtype_struct(self)
530    }
531
532    fn deserialize_enum<V: Visitor<'de>>(
533        self,
534        _name: &'static str,
535        _variants: &'static [&'static str],
536        visitor: V,
537    ) -> Result<V::Value> {
538        if self.tape.tape_type() == Some(TapeType::Root) {
539            self.tape.skip(1);
540        }
541        match self.tape.tape_type() {
542            Some(TapeType::String) => {
543                let s: &'de str = self.tape.get_string()?;
544                self.tape.skip(1);
545                let enum_deserializer = de::value::StrDeserializer::<Error>::new(s);
546                visitor.visit_enum(enum_deserializer)
547            }
548            Some(TapeType::StartObject) => {
549                let end_idx = self.tape.scope_close_idx();
550                self.tape.skip(1);
551                let result = visitor.visit_enum(TapeEnumAccess {
552                    tape: &mut self.tape,
553                    end_idx,
554                })?;
555                self.tape.skip(1); // past `}`
556                Ok(result)
557            }
558            _ => {
559                let t = &mut self.tape;
560                deserialize_value(t, visitor)
561            }
562        }
563    }
564
565    fn deserialize_ignored_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
566        if self.tape.tape_type() == Some(TapeType::Root) {
567            self.tape.skip(1);
568        }
569        skip_value(&mut self.tape)?;
570        visitor.visit_unit()
571    }
572
573    fn deserialize_bool<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
574        self.deserialize_any(visitor)
575    }
576
577    fn deserialize_i8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
578        self.deserialize_any(visitor)
579    }
580
581    fn deserialize_i16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
582        self.deserialize_any(visitor)
583    }
584
585    fn deserialize_i32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
586        self.deserialize_any(visitor)
587    }
588
589    fn deserialize_i64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
590        self.deserialize_any(visitor)
591    }
592
593    fn deserialize_u8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
594        self.deserialize_any(visitor)
595    }
596
597    fn deserialize_u16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
598        self.deserialize_any(visitor)
599    }
600
601    fn deserialize_u32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
602        self.deserialize_any(visitor)
603    }
604
605    fn deserialize_u64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
606        self.deserialize_any(visitor)
607    }
608
609    fn deserialize_f32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
610        self.deserialize_any(visitor)
611    }
612
613    fn deserialize_f64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
614        self.deserialize_any(visitor)
615    }
616
617    fn deserialize_char<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
618        self.deserialize_any(visitor)
619    }
620
621    fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
622        self.deserialize_any(visitor)
623    }
624
625    fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
626        self.deserialize_any(visitor)
627    }
628
629    fn deserialize_bytes<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
630        self.deserialize_any(visitor)
631    }
632
633    fn deserialize_byte_buf<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
634        self.deserialize_any(visitor)
635    }
636
637    fn deserialize_unit<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
638        self.deserialize_any(visitor)
639    }
640
641    fn deserialize_unit_struct<V: Visitor<'de>>(
642        self,
643        _name: &'static str,
644        visitor: V,
645    ) -> Result<V::Value> {
646        self.deserialize_any(visitor)
647    }
648
649    fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
650        self.deserialize_any(visitor)
651    }
652
653    fn deserialize_tuple<V: Visitor<'de>>(self, _len: usize, visitor: V) -> Result<V::Value> {
654        self.deserialize_any(visitor)
655    }
656
657    fn deserialize_tuple_struct<V: Visitor<'de>>(
658        self,
659        _name: &'static str,
660        _len: usize,
661        visitor: V,
662    ) -> Result<V::Value> {
663        self.deserialize_any(visitor)
664    }
665
666    fn deserialize_map<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
667        self.deserialize_any(visitor)
668    }
669
670    fn deserialize_struct<V: Visitor<'de>>(
671        self,
672        _name: &'static str,
673        _fields: &'static [&'static str],
674        visitor: V,
675    ) -> Result<V::Value> {
676        self.deserialize_any(visitor)
677    }
678
679    fn deserialize_identifier<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
680        self.deserialize_any(visitor)
681    }
682}
683
684// ---------------------------------------------------------------------------
685// Tests
686// ---------------------------------------------------------------------------
687
688#[cfg(test)]
689mod tests {
690    use serde::Deserialize;
691
692    use super::*;
693
694    #[derive(Debug, Deserialize, PartialEq)]
695    struct Point {
696        x: f64,
697        y: f64,
698    }
699
700    #[derive(Debug, Deserialize, PartialEq)]
701    struct Nested {
702        name: String,
703        value: i64,
704        tags: Vec<String>,
705    }
706
707    #[derive(Debug, Deserialize, PartialEq)]
708    #[serde(rename_all = "snake_case")]
709    enum Color {
710        Red,
711        Green,
712        Blue,
713        Custom { r: u8, g: u8, b: u8 },
714    }
715
716    #[test]
717    fn deserialize_struct() {
718        let p: Point = from_str(r#"{"x": 1.5, "y": -2.0}"#).unwrap();
719        assert_eq!(p, Point { x: 1.5, y: -2.0 });
720    }
721
722    #[test]
723    fn deserialize_nested() {
724        let n: Nested = from_str(r#"{"name":"hello","value":42,"tags":["a","b","c"]}"#).unwrap();
725        assert_eq!(n.name, "hello");
726        assert_eq!(n.value, 42);
727        assert_eq!(n.tags, vec!["a", "b", "c"]);
728    }
729
730    #[test]
731    fn deserialize_vec_of_ints() {
732        let v: Vec<i64> = from_str("[1, 2, 3, -4]").unwrap();
733        assert_eq!(v, vec![1, 2, 3, -4]);
734    }
735
736    #[test]
737    fn deserialize_option_some() {
738        let v: Option<i64> = from_str("42").unwrap();
739        assert_eq!(v, Some(42));
740    }
741
742    #[test]
743    fn deserialize_option_none() {
744        let v: Option<i64> = from_str("null").unwrap();
745        assert_eq!(v, None);
746    }
747
748    #[test]
749    fn deserialize_bool_true() {
750        assert!(from_str::<bool>("true").unwrap());
751    }
752
753    #[test]
754    fn deserialize_bool_false() {
755        assert!(!from_str::<bool>("false").unwrap());
756    }
757
758    #[test]
759    fn deserialize_unit_enum() {
760        let c: Color = from_str(r#""red""#).unwrap();
761        assert_eq!(c, Color::Red);
762    }
763
764    #[test]
765    fn deserialize_struct_enum() {
766        let c: Color = from_str(r#"{"custom": {"r": 10, "g": 20, "b": 30}}"#).unwrap();
767        assert_eq!(
768            c,
769            Color::Custom {
770                r: 10,
771                g: 20,
772                b: 30
773            }
774        );
775    }
776
777    #[test]
778    fn deserialize_f64() {
779        let v: f64 = from_str("1.5").unwrap();
780        assert_eq!(v, 1.5_f64);
781    }
782
783    #[test]
784    fn deserialize_string() {
785        let s: String = from_str(r#""hello world""#).unwrap();
786        assert_eq!(s, "hello world");
787    }
788
789    #[test]
790    fn deserialize_nested_arrays() {
791        let v: Vec<Vec<i64>> = from_str("[[1,2],[3,4],[5]]").unwrap();
792        assert_eq!(v, vec![vec![1, 2], vec![3, 4], vec![5]]);
793    }
794
795    #[derive(Debug, Deserialize, PartialEq)]
796    struct LargeObject {
797        id: u64,
798        name: String,
799        active: bool,
800        score: f64,
801        tags: Vec<String>,
802        meta: Option<String>,
803    }
804
805    #[test]
806    fn deserialize_large_object() {
807        let json = r#"{
808            "id": 12345,
809            "name": "simdjson",
810            "active": true,
811            "score": 9.99,
812            "tags": ["fast", "safe", "rust"],
813            "meta": null
814        }"#;
815        let v: LargeObject = from_str(json).unwrap();
816        assert_eq!(v.id, 12345);
817        assert_eq!(v.name, "simdjson");
818        assert!(v.active);
819        assert!((v.score - 9.99).abs() < 1e-6);
820        assert_eq!(v.tags[0], "fast");
821        assert!(v.meta.is_none());
822    }
823}