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(
13 clippy::module_name_repetitions,
14 unused_unsafe, )]
16#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
17
18#[cfg(feature = "serde_impl")]
19extern crate serde as serde_ext;
20
21#[cfg(feature = "serde_impl")]
22pub mod serde;
24
25#[cfg(test)]
26pub mod tests;
28
29use crate::error::InternalError;
30#[cfg(feature = "serde_impl")]
31pub use crate::serde::{
32 from_reader, from_slice, from_str, to_string, to_string_pretty, to_vec, to_vec_pretty,
33 to_writer, to_writer_pretty,
34};
35
36pub mod prelude;
38
39mod charutils;
40#[macro_use]
41mod macros;
42mod error;
43mod numberparse;
44mod safer_unchecked;
45mod stringparse;
46
47#[allow(unused_imports)]
48use macros::static_cast_u64;
49use safer_unchecked::GetSaferUnchecked;
50use stage2::StackState;
51use tape::Value;
52
53mod impls;
54
55pub mod cow;
57
58pub(crate) const SIMDJSON_PADDING: usize = 32; pub(crate) const SIMDINPUT_LENGTH: usize = 64;
62
63mod stage2;
64pub mod value;
66
67use std::{alloc::dealloc, mem};
68pub use value_trait::StaticNode;
69
70pub use crate::error::{Error, ErrorType};
71#[doc(inline)]
72pub use crate::value::*;
73pub use value_trait::ValueType;
74
75pub type Result<T> = std::result::Result<T, Error>;
77
78#[cfg(feature = "known-key")]
79mod known_key;
80#[cfg(feature = "known-key")]
81pub use known_key::{Error as KnownKeyError, KnownKey};
82
83pub use crate::tape::{Node, Tape};
84use std::alloc::{Layout, alloc, handle_alloc_error};
85use std::ops::{Deref, DerefMut};
86use std::ptr::NonNull;
87
88use simdutf8::basic::imp::ChunkedUtf8Validator;
89
90pub struct Buffers {
92 string_buffer: Vec<u8>,
93 structural_indexes: Vec<u32>,
94 input_buffer: AlignedBuf,
95 stage2_stack: Vec<StackState>,
96}
97
98impl Default for Buffers {
99 #[cfg_attr(not(feature = "no-inline"), inline)]
100 fn default() -> Self {
101 Self::new(128)
102 }
103}
104
105impl Buffers {
106 #[cfg_attr(not(feature = "no-inline"), inline)]
116 #[must_use]
117 pub fn structural_indexes(&self) -> &[u32] {
118 &self.structural_indexes
119 }
120
121 #[cfg_attr(not(feature = "no-inline"), inline)]
124 #[must_use]
125 pub fn new(input_len: usize) -> Self {
126 let heuristic_index_cout = input_len / 128;
128 Self {
129 string_buffer: Vec::with_capacity(input_len + SIMDJSON_PADDING),
130 structural_indexes: Vec::with_capacity(heuristic_index_cout),
131 input_buffer: AlignedBuf::with_capacity(input_len + SIMDJSON_PADDING * 2),
132 stage2_stack: Vec::with_capacity(heuristic_index_cout),
133 }
134 }
135}
136
137#[cfg_attr(not(feature = "no-inline"), inline)]
142pub fn to_tape(s: &mut [u8]) -> Result<Tape<'_>> {
143 Deserializer::from_slice(s).map(Deserializer::into_tape)
144}
145
146#[cfg_attr(not(feature = "no-inline"), inline)]
151pub fn to_tape_with_buffers<'de>(s: &'de mut [u8], buffers: &mut Buffers) -> Result<Tape<'de>> {
152 Deserializer::from_slice_with_buffers(s, buffers).map(Deserializer::into_tape)
153}
154
155#[cfg_attr(not(feature = "no-inline"), inline)]
160pub fn fill_tape<'de>(s: &'de mut [u8], buffers: &mut Buffers, tape: &mut Tape<'de>) -> Result<()> {
161 tape.0.clear();
162 Deserializer::fill_tape(s, buffers, &mut tape.0)
163}
164
165pub(crate) trait Stage1Parse {
166 type Utf8Validator: ChunkedUtf8Validator;
167 type SimdRepresentation;
168
169 unsafe fn new(ptr: &[u8]) -> Self;
170
171 unsafe fn compute_quote_mask(quote_bits: u64) -> u64;
172
173 unsafe fn cmp_mask_against_input(&self, m: u8) -> u64;
174
175 unsafe fn unsigned_lteq_against_input(&self, maxval: Self::SimdRepresentation) -> u64;
176
177 unsafe fn find_whitespace_and_structurals(&self, whitespace: &mut u64, structurals: &mut u64);
178
179 unsafe fn flatten_bits(base: &mut Vec<u32>, idx: u32, bits: u64);
180
181 #[cfg_attr(not(feature = "no-inline"), inline)]
193 fn find_quote_mask_and_bits(
194 &self,
195 odd_ends: u64,
196 prev_iter_inside_quote: &mut u64,
197 quote_bits: &mut u64,
198 error_mask: &mut u64,
199 ) -> u64 {
200 unsafe {
201 *quote_bits = self.cmp_mask_against_input(b'"');
202 *quote_bits &= !odd_ends;
203 let mut quote_mask: u64 = Self::compute_quote_mask(*quote_bits);
205 quote_mask ^= *prev_iter_inside_quote;
206 let unescaped: u64 = self.unsigned_lteq_against_input(Self::fill_s8(0x1F));
212 *error_mask |= quote_mask & unescaped;
213 *prev_iter_inside_quote = static_cast_u64!(static_cast_i64!(quote_mask) >> 63);
217 quote_mask
218 }
219 }
220
221 #[cfg_attr(not(feature = "no-inline"), inline)]
231 fn find_odd_backslash_sequences(&self, prev_iter_ends_odd_backslash: &mut u64) -> u64 {
232 const EVEN_BITS: u64 = 0x5555_5555_5555_5555;
233 const ODD_BITS: u64 = !EVEN_BITS;
234
235 let bs_bits: u64 = unsafe { self.cmp_mask_against_input(b'\\') };
236 let start_edges: u64 = bs_bits & !(bs_bits << 1);
237 let even_start_mask: u64 = EVEN_BITS ^ *prev_iter_ends_odd_backslash;
240 let even_starts: u64 = start_edges & even_start_mask;
241 let odd_starts: u64 = start_edges & !even_start_mask;
242 let even_carries: u64 = bs_bits.wrapping_add(even_starts);
243
244 let (mut odd_carries, iter_ends_odd_backslash) = bs_bits.overflowing_add(odd_starts);
248
249 odd_carries |= *prev_iter_ends_odd_backslash;
250 *prev_iter_ends_odd_backslash = u64::from(iter_ends_odd_backslash);
254 let even_carry_ends: u64 = even_carries & !bs_bits;
255 let odd_carry_ends: u64 = odd_carries & !bs_bits;
256 let even_start_odd_end: u64 = even_carry_ends & ODD_BITS;
257 let odd_start_even_end: u64 = odd_carry_ends & EVEN_BITS;
258 let odd_ends: u64 = even_start_odd_end | odd_start_even_end;
259 odd_ends
260 }
261
262 #[cfg_attr(not(feature = "no-inline"), inline)]
269 fn finalize_structurals(
270 mut structurals: u64,
271 whitespace: u64,
272 quote_mask: u64,
273 quote_bits: u64,
274 prev_iter_ends_pseudo_pred: &mut u64,
275 ) -> u64 {
276 structurals &= !quote_mask;
278 structurals |= quote_bits;
281 let pseudo_pred: u64 = structurals | whitespace;
292
293 let shifted_pseudo_pred: u64 = (pseudo_pred << 1) | *prev_iter_ends_pseudo_pred;
294 *prev_iter_ends_pseudo_pred = pseudo_pred >> 63;
295 let pseudo_structurals: u64 = shifted_pseudo_pred & (!whitespace) & (!quote_mask);
296 structurals |= pseudo_structurals;
297
298 structurals &= !(quote_bits & !quote_mask);
301 structurals
302 }
303
304 unsafe fn fill_s8(n: i8) -> Self::SimdRepresentation;
305}
306
307#[derive(Debug)]
309pub struct Deserializer<'de> {
310 pub(crate) tape: Vec<Node<'de>>,
313 idx: usize,
314}
315
316#[derive(Debug, Clone, Copy)]
319pub(crate) struct SillyWrapper<'de> {
320 input: *mut u8,
321 _marker: std::marker::PhantomData<&'de ()>,
322}
323
324impl From<*mut u8> for SillyWrapper<'_> {
325 #[cfg_attr(not(feature = "no-inline"), inline)]
326 fn from(input: *mut u8) -> Self {
327 Self {
328 input,
329 _marker: std::marker::PhantomData,
330 }
331 }
332}
333
334#[cfg(all(
335 feature = "runtime-detection",
336 any(target_arch = "x86_64", target_arch = "x86"),
337))] type FnRaw = *mut ();
339#[cfg(all(
340 feature = "runtime-detection",
341 any(target_arch = "x86_64", target_arch = "x86"),
342))]
343type ParseStrFn = for<'invoke, 'de> unsafe fn(
344 SillyWrapper<'de>,
345 &'invoke [u8],
346 &'invoke mut [u8],
347 usize,
348) -> std::result::Result<&'de str, error::Error>;
349#[cfg(all(
350 feature = "runtime-detection",
351 any(target_arch = "x86_64", target_arch = "x86"),
352))]
353type FindStructuralBitsFn = unsafe fn(
354 input: &[u8],
355 structural_indexes: &mut Vec<u32>,
356) -> std::result::Result<(), ErrorType>;
357
358#[derive(Clone, Copy, Debug, PartialEq, Eq)]
359pub enum Implementation {
361 Native,
363 StdSimd,
365 SSE42,
367 AVX2,
369 NEON,
371 SIMD128,
373}
374
375impl std::fmt::Display for Implementation {
376 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
377 match self {
378 Implementation::Native => write!(f, "Rust Native"),
379 Implementation::StdSimd => write!(f, "std::simd"),
380 Implementation::SSE42 => write!(f, "SSE42"),
381 Implementation::AVX2 => write!(f, "AVX2"),
382 Implementation::NEON => write!(f, "NEON"),
383 Implementation::SIMD128 => write!(f, "SIMD128"),
384 }
385 }
386}
387
388impl Deserializer<'_> {
389 #[cfg(all(
391 feature = "runtime-detection",
392 any(target_arch = "x86_64", target_arch = "x86"),
393 ))]
394 #[must_use]
395 pub fn algorithm() -> Implementation {
396 if std::is_x86_feature_detected!("avx2") {
397 Implementation::AVX2
398 } else if std::is_x86_feature_detected!("sse4.2") {
399 Implementation::SSE42
400 } else {
401 #[cfg(feature = "portable")]
402 let r = Implementation::StdSimd;
403 #[cfg(not(feature = "portable"))]
404 let r = Implementation::Native;
405 r
406 }
407 }
408 #[cfg(not(any(
409 all(
410 feature = "runtime-detection",
411 any(target_arch = "x86_64", target_arch = "x86")
412 ),
413 feature = "portable",
414 target_feature = "avx2",
415 target_feature = "sse4.2",
416 target_feature = "simd128",
417 target_arch = "aarch64",
418 )))]
419 #[must_use]
421 pub fn algorithm() -> Implementation {
422 Implementation::Native
423 }
424 #[cfg(all(feature = "portable", not(feature = "runtime-detection")))]
425 #[must_use]
427 pub fn algorithm() -> Implementation {
428 Implementation::StdSimd
429 }
430
431 #[cfg(all(
432 target_feature = "avx2",
433 not(feature = "portable"),
434 not(feature = "runtime-detection"),
435 ))]
436 #[must_use]
438 pub fn algorithm() -> Implementation {
439 Implementation::AVX2
440 }
441
442 #[cfg(all(
443 target_feature = "sse4.2",
444 not(target_feature = "avx2"),
445 not(feature = "runtime-detection"),
446 not(feature = "portable"),
447 ))]
448 #[must_use]
450 pub fn algorithm() -> Implementation {
451 Implementation::SSE42
452 }
453
454 #[cfg(all(target_arch = "aarch64", not(feature = "portable")))]
455 #[must_use]
457 pub fn algorithm() -> Implementation {
458 Implementation::NEON
459 }
460
461 #[cfg(all(target_feature = "simd128", not(feature = "portable")))]
462 #[must_use]
464 pub fn algorithm() -> Implementation {
465 Implementation::SIMD128
466 }
467}
468
469impl<'de> Deserializer<'de> {
470 #[cfg_attr(not(feature = "no-inline"), inline)]
474 #[cfg(all(
475 feature = "runtime-detection",
476 any(target_arch = "x86_64", target_arch = "x86"),
477 ))]
478 pub(crate) fn parse_str_fn() -> ParseStrFn {
479 if std::is_x86_feature_detected!("avx2") {
480 impls::avx2::parse_str
481 } else if std::is_x86_feature_detected!("sse4.2") {
482 impls::sse42::parse_str
483 } else {
484 #[cfg(feature = "portable")]
485 let r = impls::portable::parse_str;
486 #[cfg(not(feature = "portable"))]
487 let r = impls::native::parse_str;
488 r
489 }
490 }
491
492 #[cfg_attr(not(feature = "no-inline"), inline)]
493 #[cfg(all(
494 feature = "runtime-detection",
495 any(target_arch = "x86_64", target_arch = "x86"),
496 ))]
497 #[allow(dead_code)]
500 pub(crate) unsafe fn parse_str_<'invoke>(
501 input: *mut u8,
502 data: &'invoke [u8],
503 buffer: &'invoke mut [u8],
504 idx: usize,
505 ) -> Result<&'de str>
506 where
507 'de: 'invoke,
508 {
509 let input: SillyWrapper<'de> = SillyWrapper::from(input);
510 unsafe { (Self::parse_str_fn())(input, data, buffer, idx) }
511 }
512 #[cfg_attr(not(feature = "no-inline"), inline)]
513 #[cfg(not(any(
514 all(
515 feature = "runtime-detection",
516 any(target_arch = "x86_64", target_arch = "x86")
517 ),
518 feature = "portable",
519 target_feature = "avx2",
520 target_feature = "sse4.2",
521 target_feature = "simd128",
522 target_arch = "aarch64",
523 )))]
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 unsafe { impls::native::parse_str(input, data, buffer, idx) }
535 }
536 #[cfg_attr(not(feature = "no-inline"), inline)]
537 #[cfg(all(feature = "portable", not(feature = "runtime-detection")))]
538 pub(crate) unsafe fn parse_str_<'invoke>(
539 input: *mut u8,
540 data: &'invoke [u8],
541 buffer: &'invoke mut [u8],
542 idx: usize,
543 ) -> Result<&'de str>
544 where
545 'de: 'invoke,
546 {
547 let input: SillyWrapper<'de> = SillyWrapper::from(input);
548 impls::portable::parse_str(input, data, buffer, idx)
549 }
550
551 #[cfg_attr(not(feature = "no-inline"), inline)]
552 #[cfg(all(
553 target_feature = "avx2",
554 not(feature = "portable"),
555 not(feature = "runtime-detection"),
556 ))]
557 pub(crate) unsafe fn parse_str_<'invoke>(
558 input: *mut u8,
559 data: &'invoke [u8],
560 buffer: &'invoke mut [u8],
561 idx: usize,
562 ) -> Result<&'de str> {
563 let input: SillyWrapper<'de> = SillyWrapper::from(input);
564 unsafe { impls::avx2::parse_str(input, data, buffer, idx) }
565 }
566
567 #[cfg_attr(not(feature = "no-inline"), inline)]
568 #[cfg(all(
569 target_feature = "sse4.2",
570 not(target_feature = "avx2"),
571 not(feature = "runtime-detection"),
572 not(feature = "portable"),
573 ))]
574 pub(crate) unsafe fn parse_str_<'invoke>(
575 input: *mut u8,
576 data: &'invoke [u8],
577 buffer: &'invoke mut [u8],
578 idx: usize,
579 ) -> Result<&'de str> {
580 let input: SillyWrapper<'de> = SillyWrapper::from(input);
581 unsafe { impls::sse42::parse_str(input, data, buffer, idx) }
582 }
583
584 #[cfg_attr(not(feature = "no-inline"), inline)]
585 #[cfg(all(target_arch = "aarch64", not(feature = "portable")))]
586 pub(crate) unsafe fn parse_str_<'invoke>(
587 input: *mut u8,
588 data: &'invoke [u8],
589 buffer: &'invoke mut [u8],
590 idx: usize,
591 ) -> Result<&'de str> {
592 let input: SillyWrapper = SillyWrapper::from(input);
593 impls::neon::parse_str(input, data, buffer, idx)
594 }
595 #[cfg_attr(not(feature = "no-inline"), inline)]
596 #[cfg(all(target_feature = "simd128", not(feature = "portable")))]
597 pub(crate) unsafe fn parse_str_<'invoke>(
598 input: *mut u8,
599 data: &'invoke [u8],
600 buffer: &'invoke mut [u8],
601 idx: usize,
602 ) -> Result<&'de str> {
603 let input: SillyWrapper<'de> = SillyWrapper::from(input);
604 impls::simd128::parse_str(input, data, buffer, idx)
605 }
606}
607
608impl Deserializer<'_> {
610 #[cfg_attr(not(feature = "no-inline"), inline)]
611 #[cfg(all(
614 feature = "runtime-detection",
615 any(target_arch = "x86_64", target_arch = "x86"),
616 not(feature = "portable"),
617 ))]
618 pub(crate) unsafe fn find_structural_bits_native(
619 input: &[u8],
620 structural_indexes: &mut Vec<u32>,
621 ) -> std::result::Result<(), ErrorType> {
622 match core::str::from_utf8(input) {
623 Ok(_) => (),
624 Err(_) => return Err(ErrorType::InvalidUtf8),
625 }
626 unsafe {
627 Self::_find_structural_bits::<impls::native::SimdInput>(input, structural_indexes)
628 }
629 }
630
631 #[cfg_attr(not(feature = "no-inline"), inline)]
632 #[cfg(all(
633 feature = "runtime-detection",
634 any(target_arch = "x86_64", target_arch = "x86"),
635 ))]
636 pub(crate) unsafe fn find_structural_bits(
637 input: &[u8],
638 structural_indexes: &mut Vec<u32>,
639 ) -> std::result::Result<(), ErrorType> {
640 unsafe {
641 use std::sync::atomic::{AtomicPtr, Ordering};
642
643 static FN: AtomicPtr<()> = AtomicPtr::new(get_fastest as FnRaw);
644
645 #[target_feature(enable = "avx2", enable = "pclmulqdq")]
649 unsafe fn find_structural_bits_avx2(
650 input: &[u8],
651 structural_indexes: &mut Vec<u32>,
652 ) -> core::result::Result<(), error::ErrorType> {
653 unsafe {
654 Deserializer::_find_structural_bits::<impls::avx2::SimdInput>(
655 input,
656 structural_indexes,
657 )
658 }
659 }
660
661 #[target_feature(enable = "sse4.2")]
662 unsafe fn find_structural_bits_sse42(
663 input: &[u8],
664 structural_indexes: &mut Vec<u32>,
665 ) -> core::result::Result<(), error::ErrorType> {
666 unsafe {
667 Deserializer::_find_structural_bits::<impls::sse42::SimdInput>(
668 input,
669 structural_indexes,
670 )
671 }
672 }
673
674 #[cfg_attr(not(feature = "no-inline"), inline)]
675 fn get_fastest_available_implementation() -> FindStructuralBitsFn {
676 if std::is_x86_feature_detected!("avx2")
677 && std::is_x86_feature_detected!("pclmulqdq")
678 {
679 find_structural_bits_avx2
680 } else if std::is_x86_feature_detected!("sse4.2") {
681 find_structural_bits_sse42
682 } else {
683 #[cfg(feature = "portable")]
684 let r = Deserializer::_find_structural_bits::<impls::portable::SimdInput>;
685 #[cfg(not(feature = "portable"))]
686 let r = Deserializer::find_structural_bits_native;
687 r
688 }
689 }
690
691 #[cfg_attr(not(feature = "no-inline"), inline)]
692 unsafe fn get_fastest(
693 input: &[u8],
694 structural_indexes: &mut Vec<u32>,
695 ) -> core::result::Result<(), error::ErrorType> {
696 unsafe {
697 let fun = get_fastest_available_implementation();
698 FN.store(fun as FnRaw, Ordering::Relaxed);
699 (fun)(input, structural_indexes)
700 }
701 }
702
703 let fun = FN.load(Ordering::Relaxed);
704 mem::transmute::<FnRaw, FindStructuralBitsFn>(fun)(input, structural_indexes)
705 }
706 }
707
708 #[cfg(not(any(
709 all(
710 feature = "runtime-detection",
711 any(target_arch = "x86_64", target_arch = "x86")
712 ),
713 feature = "portable",
714 target_feature = "avx2",
715 target_feature = "sse4.2",
716 target_feature = "simd128",
717 target_arch = "aarch64",
718 )))]
719 #[cfg_attr(not(feature = "no-inline"), inline)]
720 pub(crate) unsafe fn find_structural_bits(
721 input: &[u8],
722 structural_indexes: &mut Vec<u32>,
723 ) -> std::result::Result<(), ErrorType> {
724 match core::str::from_utf8(input) {
727 Ok(_) => (),
728 Err(_) => return Err(ErrorType::InvalidUtf8),
729 }
730 #[cfg(not(feature = "portable"))]
731 unsafe {
732 Self::_find_structural_bits::<impls::native::SimdInput>(input, structural_indexes)
733 }
734 }
735
736 #[cfg(all(feature = "portable", not(feature = "runtime-detection")))]
737 #[cfg_attr(not(feature = "no-inline"), inline)]
738 pub(crate) unsafe fn find_structural_bits(
739 input: &[u8],
740 structural_indexes: &mut Vec<u32>,
741 ) -> std::result::Result<(), ErrorType> {
742 unsafe {
743 Self::_find_structural_bits::<impls::portable::SimdInput>(input, structural_indexes)
744 }
745 }
746
747 #[cfg(all(
748 target_feature = "avx2",
749 not(feature = "portable"),
750 not(feature = "runtime-detection"),
751 ))]
752 #[cfg_attr(not(feature = "no-inline"), inline)]
753 pub(crate) unsafe fn find_structural_bits(
754 input: &[u8],
755 structural_indexes: &mut Vec<u32>,
756 ) -> std::result::Result<(), ErrorType> {
757 unsafe { Self::_find_structural_bits::<impls::avx2::SimdInput>(input, structural_indexes) }
758 }
759
760 #[cfg(all(
761 target_feature = "sse4.2",
762 not(target_feature = "avx2"),
763 not(feature = "runtime-detection"),
764 not(feature = "portable"),
765 ))]
766 #[cfg_attr(not(feature = "no-inline"), inline)]
767 pub(crate) unsafe fn find_structural_bits(
768 input: &[u8],
769 structural_indexes: &mut Vec<u32>,
770 ) -> std::result::Result<(), ErrorType> {
771 unsafe { Self::_find_structural_bits::<impls::sse42::SimdInput>(input, structural_indexes) }
772 }
773
774 #[cfg(all(target_arch = "aarch64", not(feature = "portable")))]
775 #[cfg_attr(not(feature = "no-inline"), inline)]
776 pub(crate) unsafe fn find_structural_bits(
777 input: &[u8],
778 structural_indexes: &mut Vec<u32>,
779 ) -> std::result::Result<(), ErrorType> {
780 unsafe { Self::_find_structural_bits::<impls::neon::SimdInput>(input, structural_indexes) }
781 }
782
783 #[cfg(all(target_feature = "simd128", not(feature = "portable")))]
784 #[cfg_attr(not(feature = "no-inline"), inline)]
785 pub(crate) unsafe fn find_structural_bits(
786 input: &[u8],
787 structural_indexes: &mut Vec<u32>,
788 ) -> std::result::Result<(), ErrorType> {
789 unsafe {
790 Self::_find_structural_bits::<impls::simd128::SimdInput>(input, structural_indexes)
791 }
792 }
793}
794
795impl<'de> Deserializer<'de> {
796 #[must_use]
798 pub fn into_tape(self) -> Tape<'de> {
799 Tape(self.tape)
800 }
801
802 #[must_use]
804 pub fn as_value(&self) -> Value<'_, 'de> {
805 Value(&self.tape)
807 }
808
809 pub fn restart(&mut self) {
811 self.idx = 0;
813 }
814
815 #[cfg_attr(not(feature = "no-inline"), inline)]
816 fn error(error: ErrorType) -> Error {
817 Error::new(0, None, error)
818 }
819
820 #[cfg_attr(not(feature = "no-inline"), inline)]
821 fn error_c(idx: usize, c: char, error: ErrorType) -> Error {
822 Error::new(idx, Some(c), error)
823 }
824
825 pub fn from_slice(input: &'de mut [u8]) -> Result<Self> {
831 let len = input.len();
832
833 let mut buffer = Buffers::new(len);
834
835 Self::from_slice_with_buffers(input, &mut buffer)
836 }
837
838 #[allow(clippy::uninit_vec)]
846 #[cfg_attr(not(feature = "no-inline"), inline)]
847 fn fill_tape(
848 input: &'de mut [u8],
849 buffer: &mut Buffers,
850 tape: &mut Vec<Node<'de>>,
851 ) -> Result<()> {
852 const LOTS_OF_ZOERS: [u8; SIMDINPUT_LENGTH] = [0; SIMDINPUT_LENGTH];
853 let len = input.len();
854 let simd_safe_len = len + SIMDINPUT_LENGTH;
855
856 if len > u32::MAX as usize {
857 return Err(Self::error(ErrorType::InputTooLarge));
858 }
859
860 buffer.string_buffer.clear();
861 buffer.string_buffer.reserve(len + SIMDJSON_PADDING);
862
863 unsafe {
864 buffer.string_buffer.set_len(len + SIMDJSON_PADDING);
865 };
866
867 let input_buffer = &mut buffer.input_buffer;
868 if input_buffer.capacity() < simd_safe_len {
869 *input_buffer = AlignedBuf::with_capacity(simd_safe_len);
870 }
871
872 unsafe {
873 input_buffer
874 .as_mut_ptr()
875 .copy_from_nonoverlapping(input.as_ptr(), len);
876
877 input_buffer
880 .as_mut_ptr()
881 .add(len)
882 .copy_from_nonoverlapping(LOTS_OF_ZOERS.as_ptr(), SIMDINPUT_LENGTH);
883
884 input_buffer.set_len(simd_safe_len);
886
887 Self::find_structural_bits(input, &mut buffer.structural_indexes)
888 .map_err(Error::generic)?;
889 };
890
891 Self::build_tape(
892 input,
893 input_buffer,
894 &mut buffer.string_buffer,
895 &buffer.structural_indexes,
896 &mut buffer.stage2_stack,
897 tape,
898 )
899 }
900
901 pub fn from_slice_with_buffers(input: &'de mut [u8], buffer: &mut Buffers) -> Result<Self> {
908 let mut tape: Vec<Node<'de>> = Vec::with_capacity(buffer.structural_indexes.len());
909
910 Self::fill_tape(input, buffer, &mut tape)?;
911
912 Ok(Self { tape, idx: 0 })
913 }
914
915 #[cfg(feature = "serde_impl")]
916 #[cfg_attr(not(feature = "no-inline"), inline)]
917 fn skip(&mut self) {
918 self.idx += 1;
919 }
920
921 #[cfg_attr(not(feature = "no-inline"), inline)]
929 pub unsafe fn next_(&mut self) -> Node<'de> {
930 let r = *unsafe { self.tape.get_kinda_unchecked(self.idx) };
931 self.idx += 1;
932 r
933 }
934
935 #[cfg_attr(not(feature = "no-inline"), inline)]
936 #[allow(clippy::cast_possible_truncation)]
937 pub(crate) unsafe fn _find_structural_bits<S: Stage1Parse>(
938 input: &[u8],
939 structural_indexes: &mut Vec<u32>,
940 ) -> std::result::Result<(), ErrorType> {
941 let len = input.len();
942 structural_indexes.clear();
945 structural_indexes.reserve(len / 8);
946
947 let mut utf8_validator = unsafe { S::Utf8Validator::new() };
948
949 let mut prev_iter_ends_odd_backslash: u64 = 0;
956 let mut prev_iter_inside_quote: u64 = 0;
958 let mut prev_iter_ends_pseudo_pred: u64 = 1;
965
966 let mut structurals: u64 = 0;
972
973 let lenminus64: usize = len.saturating_sub(64);
974 let mut idx: usize = 0;
975 let mut error_mask: u64 = 0; while idx < lenminus64 {
978 let chunk = unsafe { input.get_kinda_unchecked(idx..idx + 64) };
984 unsafe { utf8_validator.update_from_chunks(chunk) };
985
986 let input = unsafe { S::new(chunk) };
987 let odd_ends: u64 =
989 input.find_odd_backslash_sequences(&mut prev_iter_ends_odd_backslash);
990
991 let mut quote_bits: u64 = 0;
994 let quote_mask: u64 = input.find_quote_mask_and_bits(
995 odd_ends,
996 &mut prev_iter_inside_quote,
997 &mut quote_bits,
998 &mut error_mask,
999 );
1000
1001 unsafe { S::flatten_bits(structural_indexes, idx as u32, structurals) };
1004
1005 let mut whitespace: u64 = 0;
1006 unsafe { input.find_whitespace_and_structurals(&mut whitespace, &mut structurals) };
1007
1008 structurals = S::finalize_structurals(
1010 structurals,
1011 whitespace,
1012 quote_mask,
1013 quote_bits,
1014 &mut prev_iter_ends_pseudo_pred,
1015 );
1016 idx += SIMDINPUT_LENGTH;
1017 }
1018
1019 if idx < len {
1023 let mut tmpbuf: [u8; SIMDINPUT_LENGTH] = [0x20; SIMDINPUT_LENGTH];
1024 unsafe {
1025 tmpbuf
1026 .as_mut_ptr()
1027 .copy_from(input.as_ptr().add(idx), len - idx);
1028 };
1029 unsafe { utf8_validator.update_from_chunks(&tmpbuf) };
1030
1031 let input = unsafe { S::new(&tmpbuf) };
1032
1033 let odd_ends: u64 =
1035 input.find_odd_backslash_sequences(&mut prev_iter_ends_odd_backslash);
1036
1037 let mut quote_bits: u64 = 0;
1040 let quote_mask: u64 = input.find_quote_mask_and_bits(
1041 odd_ends,
1042 &mut prev_iter_inside_quote,
1043 &mut quote_bits,
1044 &mut error_mask,
1045 );
1046
1047 unsafe { S::flatten_bits(structural_indexes, idx as u32, structurals) };
1050
1051 let mut whitespace: u64 = 0;
1052 unsafe { input.find_whitespace_and_structurals(&mut whitespace, &mut structurals) };
1053
1054 structurals = S::finalize_structurals(
1056 structurals,
1057 whitespace,
1058 quote_mask,
1059 quote_bits,
1060 &mut prev_iter_ends_pseudo_pred,
1061 );
1062 idx += SIMDINPUT_LENGTH;
1063 }
1064 if prev_iter_inside_quote != 0 {
1066 return Err(ErrorType::Syntax);
1067 }
1068 unsafe { S::flatten_bits(structural_indexes, idx as u32, structurals) };
1070
1071 if structural_indexes.is_empty() {
1074 return Err(ErrorType::Eof);
1075 }
1076
1077 if error_mask != 0 {
1078 return Err(ErrorType::Syntax);
1079 }
1080
1081 if unsafe { utf8_validator.finalize(None).is_err() } {
1082 Err(ErrorType::InvalidUtf8)
1083 } else {
1084 Ok(())
1085 }
1086 }
1087}
1088
1089struct AlignedBuf {
1091 layout: Layout,
1092 capacity: usize,
1093 len: usize,
1094 inner: NonNull<u8>,
1095}
1096unsafe impl Send for AlignedBuf {}
1103unsafe impl Sync for AlignedBuf {}
1104impl AlignedBuf {
1105 #[must_use]
1107 pub fn with_capacity(capacity: usize) -> Self {
1108 if capacity == 0 {
1109 let layout = Layout::from_size_align(0, SIMDJSON_PADDING)
1110 .expect("Layout for size 0 should always be valid");
1111 return Self {
1112 layout,
1113 capacity: 0,
1114 len: 0,
1115 inner: NonNull::dangling(),
1116 };
1117 }
1118 let Ok(layout) = Layout::from_size_align(capacity, SIMDJSON_PADDING) else {
1119 Self::capacity_overflow()
1120 };
1121 if mem::size_of::<usize>() < 8 && capacity > isize::MAX as usize {
1122 Self::capacity_overflow()
1123 }
1124 unsafe {
1125 let Some(inner) = NonNull::new(alloc(layout)) else {
1126 handle_alloc_error(layout)
1127 };
1128 Self {
1129 layout,
1130 capacity,
1131 len: 0,
1132 inner,
1133 }
1134 }
1135 }
1136
1137 fn as_mut_ptr(&mut self) -> *mut u8 {
1138 self.inner.as_ptr()
1139 }
1140
1141 fn capacity_overflow() -> ! {
1142 panic!("capacity overflow");
1143 }
1144 fn capacity(&self) -> usize {
1145 self.capacity
1146 }
1147 unsafe fn set_len(&mut self, n: usize) {
1148 assert!(
1149 n <= self.capacity,
1150 "New size ({}) can not be larger then capacity ({}).",
1151 n,
1152 self.capacity
1153 );
1154 self.len = n;
1155 }
1156}
1157impl Drop for AlignedBuf {
1158 fn drop(&mut self) {
1159 if self.capacity > 0 {
1160 unsafe {
1161 dealloc(self.inner.as_ptr(), self.layout);
1162 }
1163 }
1164 }
1165}
1166
1167impl Deref for AlignedBuf {
1168 type Target = [u8];
1169
1170 fn deref(&self) -> &Self::Target {
1171 unsafe { std::slice::from_raw_parts(self.inner.as_ptr(), self.len) }
1172 }
1173}
1174
1175impl DerefMut for AlignedBuf {
1176 fn deref_mut(&mut self) -> &mut Self::Target {
1177 unsafe { std::slice::from_raw_parts_mut(self.inner.as_ptr(), self.len) }
1178 }
1179}