1#![deny(warnings)]
2#![cfg_attr(feature = "hints", feature(core_intrinsics))]
3#![cfg_attr(feature = "portable", feature(portable_simd))]
4#![warn(unused_extern_crates)]
5#![deny(
6 clippy::all,
7 clippy::unwrap_used,
8 clippy::unnecessary_unwrap,
9 clippy::pedantic,
10 missing_docs
11)]
12#![allow(clippy::module_name_repetitions, renamed_and_removed_lints)]
13#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
14
15#[cfg(feature = "serde_impl")]
16extern crate serde as serde_ext;
17
18#[cfg(feature = "serde_impl")]
19pub mod serde;
21
22use crate::error::InternalError;
23#[cfg(feature = "serde_impl")]
24pub use crate::serde::{
25 from_reader, from_slice, from_str, to_string, to_string_pretty, to_vec, to_vec_pretty,
26 to_writer, to_writer_pretty,
27};
28
29pub mod prelude;
31
32mod charutils;
33#[macro_use]
34mod macros;
35mod error;
36mod numberparse;
37mod safer_unchecked;
38mod stringparse;
39
40use safer_unchecked::GetSaferUnchecked;
41use stage2::StackState;
42use tape::Value;
43
44mod impls;
45
46pub mod cow;
48
49pub const SIMDJSON_PADDING: usize = 32; pub const SIMDINPUT_LENGTH: usize = 64;
53
54mod stage2;
55pub mod value;
57
58use std::{alloc::dealloc, mem};
59pub use value_trait::StaticNode;
60
61pub use crate::error::{Error, ErrorType};
62#[doc(inline)]
63pub use crate::value::*;
64pub use value_trait::ValueType;
65
66pub type Result<T> = std::result::Result<T, Error>;
68
69#[cfg(feature = "known-key")]
70mod known_key;
71#[cfg(feature = "known-key")]
72pub use known_key::{Error as KnownKeyError, KnownKey};
73
74pub use crate::tape::{Node, Tape};
75use std::alloc::{alloc, handle_alloc_error, Layout};
76use std::ops::{Deref, DerefMut};
77use std::ptr::NonNull;
78
79use simdutf8::basic::imp::ChunkedUtf8Validator;
80
81pub struct Buffers {
83 string_buffer: Vec<u8>,
84 structural_indexes: Vec<u32>,
85 input_buffer: AlignedBuf,
86 stage2_stack: Vec<StackState>,
87}
88
89impl Default for Buffers {
90 #[cfg_attr(not(feature = "no-inline"), inline)]
91 fn default() -> Self {
92 Self::new(128)
93 }
94}
95
96impl Buffers {
97 #[cfg_attr(not(feature = "no-inline"), inline)]
100 #[must_use]
101 pub fn new(input_len: usize) -> Self {
102 let heuristic_index_cout = input_len / 128;
104 Self {
105 string_buffer: Vec::with_capacity(input_len + SIMDJSON_PADDING),
106 structural_indexes: Vec::with_capacity(heuristic_index_cout),
107 input_buffer: AlignedBuf::with_capacity(input_len + SIMDJSON_PADDING * 2),
108 stage2_stack: Vec::with_capacity(heuristic_index_cout),
109 }
110 }
111}
112
113#[cfg_attr(not(feature = "no-inline"), inline)]
118pub fn to_tape(s: &mut [u8]) -> Result<Tape> {
119 Deserializer::from_slice(s).map(Deserializer::into_tape)
120}
121
122#[cfg_attr(not(feature = "no-inline"), inline)]
127pub fn to_tape_with_buffers<'de>(s: &'de mut [u8], buffers: &mut Buffers) -> Result<Tape<'de>> {
128 Deserializer::from_slice_with_buffers(s, buffers).map(Deserializer::into_tape)
129}
130
131#[cfg_attr(not(feature = "no-inline"), inline)]
136pub fn fill_tape<'de>(s: &'de mut [u8], buffers: &mut Buffers, tape: &mut Tape<'de>) -> Result<()> {
137 tape.0.clear();
138 Deserializer::fill_tape(s, buffers, &mut tape.0)
139}
140
141pub(crate) trait Stage1Parse {
142 type Utf8Validator: ChunkedUtf8Validator;
143 type SimdRepresentation;
144
145 unsafe fn new(ptr: &[u8]) -> Self;
146
147 unsafe fn compute_quote_mask(quote_bits: u64) -> u64;
148
149 unsafe fn cmp_mask_against_input(&self, m: u8) -> u64;
150
151 unsafe fn unsigned_lteq_against_input(&self, maxval: Self::SimdRepresentation) -> u64;
152
153 unsafe fn find_whitespace_and_structurals(&self, whitespace: &mut u64, structurals: &mut u64);
154
155 unsafe fn flatten_bits(base: &mut Vec<u32>, idx: u32, bits: u64);
156
157 #[cfg_attr(not(feature = "no-inline"), inline)]
169 fn find_quote_mask_and_bits(
170 &self,
171 odd_ends: u64,
172 prev_iter_inside_quote: &mut u64,
173 quote_bits: &mut u64,
174 error_mask: &mut u64,
175 ) -> u64 {
176 unsafe {
177 *quote_bits = self.cmp_mask_against_input(b'"');
178 *quote_bits &= !odd_ends;
179 let mut quote_mask: u64 = Self::compute_quote_mask(*quote_bits);
181 quote_mask ^= *prev_iter_inside_quote;
182 let unescaped: u64 = self.unsigned_lteq_against_input(Self::fill_s8(0x1F));
188 *error_mask |= quote_mask & unescaped;
189 *prev_iter_inside_quote = static_cast_u64!(static_cast_i64!(quote_mask) >> 63);
193 quote_mask
194 }
195 }
196
197 #[cfg_attr(not(feature = "no-inline"), inline)]
207 fn find_odd_backslash_sequences(&self, prev_iter_ends_odd_backslash: &mut u64) -> u64 {
208 const EVEN_BITS: u64 = 0x5555_5555_5555_5555;
209 const ODD_BITS: u64 = !EVEN_BITS;
210
211 let bs_bits: u64 = unsafe { self.cmp_mask_against_input(b'\\') };
212 let start_edges: u64 = bs_bits & !(bs_bits << 1);
213 let even_start_mask: u64 = EVEN_BITS ^ *prev_iter_ends_odd_backslash;
216 let even_starts: u64 = start_edges & even_start_mask;
217 let odd_starts: u64 = start_edges & !even_start_mask;
218 let even_carries: u64 = bs_bits.wrapping_add(even_starts);
219
220 let (mut odd_carries, iter_ends_odd_backslash) = bs_bits.overflowing_add(odd_starts);
224
225 odd_carries |= *prev_iter_ends_odd_backslash;
226 *prev_iter_ends_odd_backslash = u64::from(iter_ends_odd_backslash);
230 let even_carry_ends: u64 = even_carries & !bs_bits;
231 let odd_carry_ends: u64 = odd_carries & !bs_bits;
232 let even_start_odd_end: u64 = even_carry_ends & ODD_BITS;
233 let odd_start_even_end: u64 = odd_carry_ends & EVEN_BITS;
234 let odd_ends: u64 = even_start_odd_end | odd_start_even_end;
235 odd_ends
236 }
237
238 #[cfg_attr(not(feature = "no-inline"), inline)]
245 fn finalize_structurals(
246 mut structurals: u64,
247 whitespace: u64,
248 quote_mask: u64,
249 quote_bits: u64,
250 prev_iter_ends_pseudo_pred: &mut u64,
251 ) -> u64 {
252 structurals &= !quote_mask;
254 structurals |= quote_bits;
257 let pseudo_pred: u64 = structurals | whitespace;
268
269 let shifted_pseudo_pred: u64 = (pseudo_pred << 1) | *prev_iter_ends_pseudo_pred;
270 *prev_iter_ends_pseudo_pred = pseudo_pred >> 63;
271 let pseudo_structurals: u64 = shifted_pseudo_pred & (!whitespace) & (!quote_mask);
272 structurals |= pseudo_structurals;
273
274 structurals &= !(quote_bits & !quote_mask);
277 structurals
278 }
279
280 unsafe fn fill_s8(n: i8) -> Self::SimdRepresentation;
281}
282
283#[derive(Debug)]
285pub struct Deserializer<'de> {
286 pub(crate) tape: Vec<Node<'de>>,
289 idx: usize,
290}
291
292#[derive(Debug, Clone, Copy)]
295pub(crate) struct SillyWrapper<'de> {
296 input: *mut u8,
297 _marker: std::marker::PhantomData<&'de ()>,
298}
299
300impl<'de> From<*mut u8> for SillyWrapper<'de> {
301 #[cfg_attr(not(feature = "no-inline"), inline)]
302 fn from(input: *mut u8) -> Self {
303 Self {
304 input,
305 _marker: std::marker::PhantomData,
306 }
307 }
308}
309
310#[cfg(all(
311 feature = "runtime-detection",
312 any(target_arch = "x86_64", target_arch = "x86"),
313))] type FnRaw = *mut ();
315#[cfg(all(
316 feature = "runtime-detection",
317 any(target_arch = "x86_64", target_arch = "x86"),
318))]
319type ParseStrFn = for<'invoke, 'de> unsafe fn(
320 SillyWrapper<'de>,
321 &'invoke [u8],
322 &'invoke mut [u8],
323 usize,
324) -> std::result::Result<&'de str, error::Error>;
325#[cfg(all(
326 feature = "runtime-detection",
327 any(target_arch = "x86_64", target_arch = "x86"),
328))]
329type FindStructuralBitsFn = unsafe fn(
330 input: &[u8],
331 structural_indexes: &mut Vec<u32>,
332) -> std::result::Result<(), ErrorType>;
333
334#[derive(Clone, Copy, Debug, PartialEq, Eq)]
335pub enum Implementation {
337 Native,
339 StdSimd,
341 SSE42,
343 AVX2,
345 NEON,
347 SIMD128,
349}
350
351impl std::fmt::Display for Implementation {
352 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
353 match self {
354 Implementation::Native => write!(f, "Rust Native"),
355 Implementation::StdSimd => write!(f, "std::simd"),
356 Implementation::SSE42 => write!(f, "SSE42"),
357 Implementation::AVX2 => write!(f, "AVX2"),
358 Implementation::NEON => write!(f, "NEON"),
359 Implementation::SIMD128 => write!(f, "SIMD128"),
360 }
361 }
362}
363
364impl<'de> Deserializer<'de> {
365 #[cfg(all(
367 feature = "runtime-detection",
368 any(target_arch = "x86_64", target_arch = "x86"),
369 ))]
370 #[must_use]
371 pub fn algorithm() -> Implementation {
372 if std::is_x86_feature_detected!("avx2") {
373 Implementation::AVX2
374 } else if std::is_x86_feature_detected!("sse4.2") {
375 Implementation::SSE42
376 } else {
377 #[cfg(feature = "portable")]
378 let r = Implementation::StdSimd;
379 #[cfg(not(feature = "portable"))]
380 let r = Implementation::Native;
381 r
382 }
383 }
384 #[cfg(not(any(
385 all(
386 feature = "runtime-detection",
387 any(target_arch = "x86_64", target_arch = "x86")
388 ),
389 feature = "portable",
390 target_feature = "avx2",
391 target_feature = "sse4.2",
392 target_feature = "simd128",
393 target_arch = "aarch64",
394 )))]
395 #[must_use]
397 pub fn algorithm() -> Implementation {
398 Implementation::Native
399 }
400 #[cfg(all(feature = "portable", not(feature = "runtime-detection")))]
401 #[must_use]
403 pub fn algorithm() -> Implementation {
404 Implementation::StdSimd
405 }
406
407 #[cfg(all(
408 target_feature = "avx2",
409 not(feature = "portable"),
410 not(feature = "runtime-detection"),
411 ))]
412 #[must_use]
414 pub fn algorithm() -> Implementation {
415 Implementation::AVX2
416 }
417
418 #[cfg(all(
419 target_feature = "sse4.2",
420 not(target_feature = "avx2"),
421 not(feature = "runtime-detection"),
422 not(feature = "portable"),
423 ))]
424 #[must_use]
426 pub fn algorithm() -> Implementation {
427 Implementation::SSE42
428 }
429
430 #[cfg(all(target_arch = "aarch64", not(feature = "portable")))]
431 #[must_use]
433 pub fn algorithm() -> Implementation {
434 Implementation::NEON
435 }
436
437 #[cfg(all(target_feature = "simd128", not(feature = "portable")))]
438 #[must_use]
440 pub fn algorithm() -> Implementation {
441 Implementation::SIMD128
442 }
443}
444
445impl<'de> Deserializer<'de> {
446 #[cfg_attr(not(feature = "no-inline"), inline)]
447 #[cfg(all(
448 feature = "runtime-detection",
449 any(target_arch = "x86_64", target_arch = "x86"),
450 ))]
451 pub(crate) unsafe fn parse_str_<'invoke>(
452 input: *mut u8,
453 data: &'invoke [u8],
454 buffer: &'invoke mut [u8],
455 idx: usize,
456 ) -> Result<&'de str>
457 where
458 'de: 'invoke,
459 {
460 use std::sync::atomic::{AtomicPtr, Ordering};
461
462 static FN: AtomicPtr<()> = AtomicPtr::new(get_fastest as FnRaw);
463
464 #[cfg_attr(not(feature = "no-inline"), inline)]
465 fn get_fastest_available_implementation() -> ParseStrFn {
466 if std::is_x86_feature_detected!("avx2") {
467 impls::avx2::parse_str
468 } else if std::is_x86_feature_detected!("sse4.2") {
469 impls::sse42::parse_str
470 } else {
471 #[cfg(feature = "portable")]
472 let r = impls::portable::parse_str;
473 #[cfg(not(feature = "portable"))]
474 let r = impls::native::parse_str;
475 r
476 }
477 }
478
479 #[cfg_attr(not(feature = "no-inline"), inline)]
480 unsafe fn get_fastest<'invoke, 'de>(
481 input: SillyWrapper<'de>,
482 data: &'invoke [u8],
483 buffer: &'invoke mut [u8],
484 idx: usize,
485 ) -> core::result::Result<&'de str, error::Error>
486 where
487 'de: 'invoke,
488 {
489 let fun = get_fastest_available_implementation();
490 FN.store(fun as FnRaw, Ordering::Relaxed);
491 (fun)(input, data, buffer, idx)
492 }
493
494 let input: SillyWrapper<'de> = SillyWrapper::from(input);
495 let fun = FN.load(Ordering::Relaxed);
496 mem::transmute::<FnRaw, ParseStrFn>(fun)(input, data, buffer, idx)
497 }
498 #[cfg_attr(not(feature = "no-inline"), inline)]
499 #[cfg(not(any(
500 all(
501 feature = "runtime-detection",
502 any(target_arch = "x86_64", target_arch = "x86")
503 ),
504 feature = "portable",
505 target_feature = "avx2",
506 target_feature = "sse4.2",
507 target_feature = "simd128",
508 target_arch = "aarch64",
509 )))]
510 pub(crate) unsafe fn parse_str_<'invoke>(
511 input: *mut u8,
512 data: &'invoke [u8],
513 buffer: &'invoke mut [u8],
514 idx: usize,
515 ) -> Result<&'de str>
516 where
517 'de: 'invoke,
518 {
519 let input: SillyWrapper<'de> = SillyWrapper::from(input);
520 impls::native::parse_str(input, data, buffer, idx)
521 }
522 #[cfg_attr(not(feature = "no-inline"), inline)]
523 #[cfg(all(feature = "portable", not(feature = "runtime-detection")))]
524 pub(crate) unsafe fn parse_str_<'invoke>(
525 input: *mut u8,
526 data: &'invoke [u8],
527 buffer: &'invoke mut [u8],
528 idx: usize,
529 ) -> Result<&'de str>
530 where
531 'de: 'invoke,
532 {
533 let input: SillyWrapper<'de> = SillyWrapper::from(input);
534 impls::portable::parse_str(input, data, buffer, idx)
535 }
536
537 #[cfg_attr(not(feature = "no-inline"), inline)]
538 #[cfg(all(
539 target_feature = "avx2",
540 not(feature = "portable"),
541 not(feature = "runtime-detection"),
542 ))]
543 pub(crate) unsafe fn parse_str_<'invoke>(
544 input: *mut u8,
545 data: &'invoke [u8],
546 buffer: &'invoke mut [u8],
547 idx: usize,
548 ) -> Result<&'de str> {
549 let input: SillyWrapper<'de> = SillyWrapper::from(input);
550 impls::avx2::parse_str(input, data, buffer, idx)
551 }
552
553 #[cfg_attr(not(feature = "no-inline"), inline)]
554 #[cfg(all(
555 target_feature = "sse4.2",
556 not(target_feature = "avx2"),
557 not(feature = "runtime-detection"),
558 not(feature = "portable"),
559 ))]
560 pub(crate) unsafe fn parse_str_<'invoke>(
561 input: *mut u8,
562 data: &'invoke [u8],
563 buffer: &'invoke mut [u8],
564 idx: usize,
565 ) -> Result<&'de str> {
566 let input: SillyWrapper<'de> = SillyWrapper::from(input);
567 impls::sse42::parse_str(input, data, buffer, idx)
568 }
569
570 #[cfg_attr(not(feature = "no-inline"), inline)]
571 #[cfg(all(target_arch = "aarch64", not(feature = "portable")))]
572 pub(crate) unsafe fn parse_str_<'invoke>(
573 input: *mut u8,
574 data: &'invoke [u8],
575 buffer: &'invoke mut [u8],
576 idx: usize,
577 ) -> Result<&'de str> {
578 let input: SillyWrapper<'de> = SillyWrapper::from(input);
579 impls::neon::parse_str(input, data, buffer, idx)
580 }
581 #[cfg_attr(not(feature = "no-inline"), inline)]
582 #[cfg(all(target_feature = "simd128", not(feature = "portable")))]
583 pub(crate) unsafe fn parse_str_<'invoke>(
584 input: *mut u8,
585 data: &'invoke [u8],
586 buffer: &'invoke mut [u8],
587 idx: usize,
588 ) -> Result<&'de str> {
589 let input: SillyWrapper<'de> = SillyWrapper::from(input);
590 impls::simd128::parse_str(input, data, buffer, idx)
591 }
592}
593
594impl<'de> Deserializer<'de> {
596 #[cfg_attr(not(feature = "no-inline"), inline)]
597 #[cfg(all(
598 feature = "runtime-detection",
599 any(target_arch = "x86_64", target_arch = "x86"),
600 ))]
601 pub(crate) unsafe fn find_structural_bits(
602 input: &[u8],
603 structural_indexes: &mut Vec<u32>,
604 ) -> std::result::Result<(), ErrorType> {
605 use std::sync::atomic::{AtomicPtr, Ordering};
606
607 static FN: AtomicPtr<()> = AtomicPtr::new(get_fastest as FnRaw);
608
609 #[cfg_attr(not(feature = "no-inline"), inline)]
610 fn get_fastest_available_implementation() -> FindStructuralBitsFn {
611 if std::is_x86_feature_detected!("avx2") {
612 Deserializer::_find_structural_bits::<impls::avx2::SimdInput>
613 } else if std::is_x86_feature_detected!("sse4.2") {
614 Deserializer::_find_structural_bits::<impls::sse42::SimdInput>
615 } else {
616 #[cfg(feature = "portable")]
617 let r = Deserializer::_find_structural_bits::<impls::portable::SimdInput>;
618 #[cfg(not(feature = "portable"))]
619 let r = Deserializer::_find_structural_bits::<impls::native::SimdInput>;
620 r
621 }
622 }
623
624 #[cfg_attr(not(feature = "no-inline"), inline)]
625 unsafe fn get_fastest(
626 input: &[u8],
627 structural_indexes: &mut Vec<u32>,
628 ) -> core::result::Result<(), error::ErrorType> {
629 let fun = get_fastest_available_implementation();
630 FN.store(fun as FnRaw, Ordering::Relaxed);
631 (fun)(input, structural_indexes)
632 }
633
634 let fun = FN.load(Ordering::Relaxed);
635 mem::transmute::<FnRaw, FindStructuralBitsFn>(fun)(input, structural_indexes)
636 }
637
638 #[cfg(not(any(
639 all(
640 feature = "runtime-detection",
641 any(target_arch = "x86_64", target_arch = "x86")
642 ),
643 feature = "portable",
644 target_feature = "avx2",
645 target_feature = "sse4.2",
646 target_feature = "simd128",
647 target_arch = "aarch64",
648 )))]
649 #[cfg_attr(not(feature = "no-inline"), inline)]
650 pub(crate) unsafe fn find_structural_bits(
651 input: &[u8],
652 structural_indexes: &mut Vec<u32>,
653 ) -> std::result::Result<(), ErrorType> {
654 match core::str::from_utf8(input) {
657 Ok(_) => (),
658 Err(_) => return Err(ErrorType::InvalidUtf8),
659 };
660 #[cfg(not(feature = "portable"))]
661 Self::_find_structural_bits::<impls::native::SimdInput>(input, structural_indexes)
662 }
663
664 #[cfg(all(feature = "portable", not(feature = "runtime-detection")))]
665 #[cfg_attr(not(feature = "no-inline"), inline)]
666 pub(crate) unsafe fn find_structural_bits(
667 input: &[u8],
668 structural_indexes: &mut Vec<u32>,
669 ) -> std::result::Result<(), ErrorType> {
670 Self::_find_structural_bits::<impls::portable::SimdInput>(input, structural_indexes)
671 }
672
673 #[cfg(all(
674 target_feature = "avx2",
675 not(feature = "portable"),
676 not(feature = "runtime-detection"),
677 ))]
678 #[cfg_attr(not(feature = "no-inline"), inline)]
679 pub(crate) unsafe fn find_structural_bits(
680 input: &[u8],
681 structural_indexes: &mut Vec<u32>,
682 ) -> std::result::Result<(), ErrorType> {
683 Self::_find_structural_bits::<impls::avx2::SimdInput>(input, structural_indexes)
684 }
685
686 #[cfg(all(
687 target_feature = "sse4.2",
688 not(target_feature = "avx2"),
689 not(feature = "runtime-detection"),
690 not(feature = "portable"),
691 ))]
692 #[cfg_attr(not(feature = "no-inline"), inline)]
693 pub(crate) unsafe fn find_structural_bits(
694 input: &[u8],
695 structural_indexes: &mut Vec<u32>,
696 ) -> std::result::Result<(), ErrorType> {
697 Self::_find_structural_bits::<impls::sse42::SimdInput>(input, structural_indexes)
698 }
699
700 #[cfg(all(target_arch = "aarch64", not(feature = "portable")))]
701 #[cfg_attr(not(feature = "no-inline"), inline)]
702 pub(crate) unsafe fn find_structural_bits(
703 input: &[u8],
704 structural_indexes: &mut Vec<u32>,
705 ) -> std::result::Result<(), ErrorType> {
706 unsafe { Self::_find_structural_bits::<impls::neon::SimdInput>(input, structural_indexes) }
707 }
708
709 #[cfg(all(target_feature = "simd128", not(feature = "portable")))]
710 #[cfg_attr(not(feature = "no-inline"), inline)]
711 pub(crate) unsafe fn find_structural_bits(
712 input: &[u8],
713 structural_indexes: &mut Vec<u32>,
714 ) -> std::result::Result<(), ErrorType> {
715 Self::_find_structural_bits::<impls::simd128::SimdInput>(input, structural_indexes)
716 }
717}
718
719impl<'de> Deserializer<'de> {
720 #[must_use]
722 pub fn into_tape(self) -> Tape<'de> {
723 Tape(self.tape)
724 }
725
726 #[must_use]
728 pub fn as_value(&self) -> Value<'_, 'de> {
729 Value(&self.tape)
731 }
732
733 pub fn restart(&mut self) {
735 self.idx = 0;
737 }
738
739 #[cfg_attr(not(feature = "no-inline"), inline)]
740 fn error(error: ErrorType) -> Error {
741 Error::new(0, None, error)
742 }
743
744 #[cfg_attr(not(feature = "no-inline"), inline)]
745 fn error_c(idx: usize, c: char, error: ErrorType) -> Error {
746 Error::new(idx, Some(c), error)
747 }
748
749 pub fn from_slice(input: &'de mut [u8]) -> Result<Self> {
755 let len = input.len();
756
757 let mut buffer = Buffers::new(len);
758
759 Self::from_slice_with_buffers(input, &mut buffer)
760 }
761
762 #[allow(clippy::uninit_vec)]
770 #[cfg_attr(not(feature = "no-inline"), inline)]
771 fn fill_tape(
772 input: &'de mut [u8],
773 buffer: &mut Buffers,
774 tape: &mut Vec<Node<'de>>,
775 ) -> Result<()> {
776 const LOTS_OF_ZOERS: [u8; SIMDINPUT_LENGTH] = [0; SIMDINPUT_LENGTH];
777 let len = input.len();
778 let simd_safe_len = len + SIMDINPUT_LENGTH;
779
780 if len > u32::MAX as usize {
781 return Err(Self::error(ErrorType::InputTooLarge));
782 }
783
784 buffer.string_buffer.clear();
785 buffer.string_buffer.reserve(len + SIMDJSON_PADDING);
786
787 unsafe {
788 buffer.string_buffer.set_len(len + SIMDJSON_PADDING);
789 };
790
791 let input_buffer = &mut buffer.input_buffer;
792 if input_buffer.capacity() < simd_safe_len {
793 *input_buffer = AlignedBuf::with_capacity(simd_safe_len);
794 }
795
796 unsafe {
797 input_buffer
798 .as_mut_ptr()
799 .copy_from_nonoverlapping(input.as_ptr(), len);
800
801 input_buffer
804 .as_mut_ptr()
805 .add(len)
806 .copy_from_nonoverlapping(LOTS_OF_ZOERS.as_ptr(), SIMDINPUT_LENGTH);
807
808 input_buffer.set_len(simd_safe_len);
810
811 Self::find_structural_bits(input, &mut buffer.structural_indexes)
812 .map_err(Error::generic)?;
813 };
814
815 Self::build_tape(
816 input,
817 input_buffer,
818 &mut buffer.string_buffer,
819 &buffer.structural_indexes,
820 &mut buffer.stage2_stack,
821 tape,
822 )
823 }
824
825 pub fn from_slice_with_buffers(input: &'de mut [u8], buffer: &mut Buffers) -> Result<Self> {
832 let mut tape: Vec<Node<'de>> = Vec::with_capacity(buffer.structural_indexes.len());
833
834 Self::fill_tape(input, buffer, &mut tape)?;
835
836 Ok(Self { tape, idx: 0 })
837 }
838
839 #[cfg(feature = "serde_impl")]
840 #[cfg_attr(not(feature = "no-inline"), inline)]
841 fn skip(&mut self) {
842 self.idx += 1;
843 }
844
845 #[cfg_attr(not(feature = "no-inline"), inline)]
853 pub unsafe fn next_(&mut self) -> Node<'de> {
854 let r = *unsafe { self.tape.get_kinda_unchecked(self.idx) };
855 self.idx += 1;
856 r
857 }
858
859 #[cfg_attr(not(feature = "no-inline"), inline)]
860 #[allow(clippy::cast_possible_truncation)]
861 pub(crate) unsafe fn _find_structural_bits<S: Stage1Parse>(
862 input: &[u8],
863 structural_indexes: &mut Vec<u32>,
864 ) -> std::result::Result<(), ErrorType> {
865 let len = input.len();
866 structural_indexes.clear();
869 structural_indexes.reserve(len / 8);
870
871 let mut utf8_validator = unsafe { S::Utf8Validator::new() };
872
873 let mut prev_iter_ends_odd_backslash: u64 = 0;
880 let mut prev_iter_inside_quote: u64 = 0;
882 let mut prev_iter_ends_pseudo_pred: u64 = 1;
889
890 let mut structurals: u64 = 0;
896
897 let lenminus64: usize = if len < 64 { 0 } else { len - 64 };
898 let mut idx: usize = 0;
899 let mut error_mask: u64 = 0; while idx < lenminus64 {
902 let chunk = unsafe { input.get_kinda_unchecked(idx..idx + 64) };
908 unsafe { utf8_validator.update_from_chunks(chunk) };
909
910 let input = unsafe { S::new(chunk) };
911 let odd_ends: u64 =
913 input.find_odd_backslash_sequences(&mut prev_iter_ends_odd_backslash);
914
915 let mut quote_bits: u64 = 0;
918 let quote_mask: u64 = input.find_quote_mask_and_bits(
919 odd_ends,
920 &mut prev_iter_inside_quote,
921 &mut quote_bits,
922 &mut error_mask,
923 );
924
925 unsafe { S::flatten_bits(structural_indexes, idx as u32, structurals) };
928
929 let mut whitespace: u64 = 0;
930 unsafe { input.find_whitespace_and_structurals(&mut whitespace, &mut structurals) };
931
932 structurals = S::finalize_structurals(
934 structurals,
935 whitespace,
936 quote_mask,
937 quote_bits,
938 &mut prev_iter_ends_pseudo_pred,
939 );
940 idx += SIMDINPUT_LENGTH;
941 }
942
943 if idx < len {
947 let mut tmpbuf: [u8; SIMDINPUT_LENGTH] = [0x20; SIMDINPUT_LENGTH];
948 unsafe {
949 tmpbuf
950 .as_mut_ptr()
951 .copy_from(input.as_ptr().add(idx), len - idx);
952 };
953 unsafe { utf8_validator.update_from_chunks(&tmpbuf) };
954
955 let input = unsafe { S::new(&tmpbuf) };
956
957 let odd_ends: u64 =
959 input.find_odd_backslash_sequences(&mut prev_iter_ends_odd_backslash);
960
961 let mut quote_bits: u64 = 0;
964 let quote_mask: u64 = input.find_quote_mask_and_bits(
965 odd_ends,
966 &mut prev_iter_inside_quote,
967 &mut quote_bits,
968 &mut error_mask,
969 );
970
971 unsafe { S::flatten_bits(structural_indexes, idx as u32, structurals) };
974
975 let mut whitespace: u64 = 0;
976 unsafe { input.find_whitespace_and_structurals(&mut whitespace, &mut structurals) };
977
978 structurals = S::finalize_structurals(
980 structurals,
981 whitespace,
982 quote_mask,
983 quote_bits,
984 &mut prev_iter_ends_pseudo_pred,
985 );
986 idx += SIMDINPUT_LENGTH;
987 }
988 if prev_iter_inside_quote != 0 {
990 return Err(ErrorType::Syntax);
991 }
992 unsafe { S::flatten_bits(structural_indexes, idx as u32, structurals) };
994
995 if structural_indexes.is_empty() {
998 return Err(ErrorType::Eof);
999 }
1000
1001 if error_mask != 0 {
1002 return Err(ErrorType::Syntax);
1003 }
1004
1005 if unsafe { utf8_validator.finalize(None).is_err() } {
1006 Err(ErrorType::InvalidUtf8)
1007 } else {
1008 Ok(())
1009 }
1010 }
1011}
1012
1013struct AlignedBuf {
1015 layout: Layout,
1016 capacity: usize,
1017 len: usize,
1018 inner: NonNull<u8>,
1019}
1020unsafe impl Send for AlignedBuf {}
1027unsafe impl Sync for AlignedBuf {}
1028impl AlignedBuf {
1029 #[must_use]
1031 pub fn with_capacity(capacity: usize) -> Self {
1032 let layout = match Layout::from_size_align(capacity, SIMDJSON_PADDING) {
1033 Ok(layout) => layout,
1034 Err(_) => Self::capacity_overflow(),
1035 };
1036 if mem::size_of::<usize>() < 8 && capacity > isize::MAX as usize {
1037 Self::capacity_overflow()
1038 }
1039 let inner = match unsafe { NonNull::new(alloc(layout)) } {
1040 Some(ptr) => ptr,
1041 None => handle_alloc_error(layout),
1042 };
1043 Self {
1044 layout,
1045 capacity,
1046 len: 0,
1047 inner,
1048 }
1049 }
1050
1051 fn as_mut_ptr(&mut self) -> *mut u8 {
1052 self.inner.as_ptr()
1053 }
1054
1055 fn capacity_overflow() -> ! {
1056 panic!("capacity overflow");
1057 }
1058 fn capacity(&self) -> usize {
1059 self.capacity
1060 }
1061 unsafe fn set_len(&mut self, n: usize) {
1062 assert!(
1063 n <= self.capacity,
1064 "New size ({}) can not be larger then capacity ({}).",
1065 n,
1066 self.capacity
1067 );
1068 self.len = n;
1069 }
1070}
1071impl Drop for AlignedBuf {
1072 fn drop(&mut self) {
1073 unsafe {
1074 dealloc(self.inner.as_ptr(), self.layout);
1075 }
1076 }
1077}
1078
1079impl Deref for AlignedBuf {
1080 type Target = [u8];
1081
1082 fn deref(&self) -> &Self::Target {
1083 unsafe { std::slice::from_raw_parts(self.inner.as_ptr(), self.len) }
1084 }
1085}
1086
1087impl DerefMut for AlignedBuf {
1088 fn deref_mut(&mut self) -> &mut Self::Target {
1089 unsafe { std::slice::from_raw_parts_mut(self.inner.as_ptr(), self.len) }
1090 }
1091}
1092
1093#[cfg(feature = "serde_impl")] #[cfg(test)]
1095mod tests {
1096 use crate::Deserializer;
1097 use serde_ext::Deserialize;
1098
1099 static JSON: &str = r#"{
1100 "code": 200,
1101 "success": true,
1102 "payload": {
1103 "features": [
1104 "serde",
1105 "json"
1106 ]
1107 }
1108 }"#;
1109
1110 #[derive(Deserialize, PartialEq, Debug)]
1111 struct TestPayload {
1112 features: Vec<String>,
1113 }
1114
1115 #[derive(Deserialize, PartialEq, Debug)]
1116 struct TestEnvelope {
1117 code: usize,
1118 success: bool,
1119 payload: TestPayload,
1120 }
1121
1122 #[test]
1123 fn test_deser_to_value() {
1124 let mut json = JSON.as_bytes().to_vec();
1125 let d = Deserializer::from_slice(&mut json).expect("Invalid JSON");
1126
1127 let original_index = d.idx;
1128 let original_nodes = d.tape.len();
1129
1130 let v = d.as_value();
1131
1132 assert!(v.contains_key("payload"), "Failed to find payload key");
1133 let v = v.get("payload").expect("Can't get payload");
1134 assert!(v.is_object(), "payload not recognized as object: {v:?}");
1135 assert!(v.contains_key("features"), "Failed to find features key");
1136 let v = v.get("features").expect("can't get features");
1137 assert!(v.is_array(), "features not recognized as array: {v:?}");
1138
1139 assert_eq!(
1142 original_index, d.idx,
1143 "Deserializer has been internally modified"
1144 );
1145 assert_eq!(
1146 original_nodes,
1147 d.tape.len(),
1148 "Deserializer has been internally modified"
1149 );
1150 }
1151
1152 #[test]
1153 fn test_deser_restart() {
1154 let mut json = JSON.as_bytes().to_vec();
1155 let mut d = Deserializer::from_slice(&mut json).expect("Invalid JSON");
1156
1157 let original_index = d.idx;
1158 let original_nodes = d.tape.len();
1159
1160 let test1 = TestEnvelope::deserialize(&mut d).expect("Deserialization failed");
1161
1162 assert!(
1163 original_index != d.idx,
1164 "Deserializer has NOT been internally modified"
1165 );
1166 assert_eq!(
1167 original_nodes,
1168 d.tape.len(),
1169 "Deserializer nodes are NOT intact"
1170 );
1171
1172 d.restart();
1173
1174 let test2 = TestEnvelope::deserialize(&mut d).expect("Deserialization failed");
1175
1176 assert_eq!(test2, test1, "Deserializer is not idempotent");
1177 }
1178}