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
63pub const DEFAULT_MAX_DEPTH: usize = 1024;
66
67mod stage2;
68pub mod value;
70
71use std::{alloc::dealloc, mem};
72pub use value_trait::StaticNode;
73
74pub use crate::error::{Error, ErrorType};
75#[doc(inline)]
76pub use crate::value::*;
77pub use value_trait::ValueType;
78
79pub type Result<T> = std::result::Result<T, Error>;
81
82#[cfg(feature = "known-key")]
83mod known_key;
84#[cfg(feature = "known-key")]
85pub use known_key::{Error as KnownKeyError, KnownKey};
86
87pub use crate::tape::{Node, Tape};
88use std::alloc::{Layout, alloc, handle_alloc_error};
89use std::ops::{Deref, DerefMut};
90use std::ptr::NonNull;
91
92use simdutf8::basic::imp::ChunkedUtf8Validator;
93
94pub struct Buffers {
96 string_buffer: Vec<u8>,
97 structural_indexes: Vec<u32>,
98 input_buffer: AlignedBuf,
99 stage2_stack: Vec<StackState>,
100 max_depth: usize,
101}
102
103impl Default for Buffers {
104 #[cfg_attr(not(feature = "no-inline"), inline)]
105 fn default() -> Self {
106 Self::new(128)
107 }
108}
109
110impl Buffers {
111 #[cfg_attr(not(feature = "no-inline"), inline)]
121 #[must_use]
122 pub fn structural_indexes(&self) -> &[u32] {
123 &self.structural_indexes
124 }
125
126 #[cfg_attr(not(feature = "no-inline"), inline)]
129 #[must_use]
130 pub fn new(input_len: usize) -> Self {
131 Self::with_max_depth(input_len, DEFAULT_MAX_DEPTH)
132 }
133
134 #[cfg_attr(not(feature = "no-inline"), inline)]
137 #[must_use]
138 pub fn with_max_depth(input_len: usize, max_depth: usize) -> Self {
139 let heuristic_index_cout = input_len / 128;
141 Self {
142 string_buffer: Vec::with_capacity(input_len + SIMDJSON_PADDING),
143 structural_indexes: Vec::with_capacity(heuristic_index_cout),
144 input_buffer: AlignedBuf::with_capacity(input_len + SIMDJSON_PADDING * 2),
145 stage2_stack: Vec::with_capacity(heuristic_index_cout),
146 max_depth,
147 }
148 }
149}
150
151#[cfg_attr(not(feature = "no-inline"), inline)]
156pub fn to_tape(s: &mut [u8]) -> Result<Tape<'_>> {
157 Deserializer::from_slice(s).map(Deserializer::into_tape)
158}
159
160#[cfg_attr(not(feature = "no-inline"), inline)]
165pub fn to_tape_with_buffers<'de>(s: &'de mut [u8], buffers: &mut Buffers) -> Result<Tape<'de>> {
166 Deserializer::from_slice_with_buffers(s, buffers).map(Deserializer::into_tape)
167}
168
169#[cfg_attr(not(feature = "no-inline"), inline)]
174pub fn fill_tape<'de>(s: &'de mut [u8], buffers: &mut Buffers, tape: &mut Tape<'de>) -> Result<()> {
175 tape.0.clear();
176 Deserializer::fill_tape(s, buffers, &mut tape.0)
177}
178
179pub(crate) trait Stage1Parse {
180 type Utf8Validator: ChunkedUtf8Validator;
181 type SimdRepresentation;
182
183 unsafe fn new(ptr: &[u8]) -> Self;
184
185 unsafe fn compute_quote_mask(quote_bits: u64) -> u64;
186
187 unsafe fn cmp_mask_against_input(&self, m: u8) -> u64;
188
189 unsafe fn unsigned_lteq_against_input(&self, maxval: Self::SimdRepresentation) -> u64;
190
191 unsafe fn find_whitespace_and_structurals(&self, whitespace: &mut u64, structurals: &mut u64);
192
193 unsafe fn flatten_bits(base: &mut Vec<u32>, idx: u32, bits: u64);
194
195 #[cfg_attr(not(feature = "no-inline"), inline)]
207 fn find_quote_mask_and_bits(
208 &self,
209 odd_ends: u64,
210 prev_iter_inside_quote: &mut u64,
211 quote_bits: &mut u64,
212 error_mask: &mut u64,
213 ) -> u64 {
214 unsafe {
215 *quote_bits = self.cmp_mask_against_input(b'"');
216 *quote_bits &= !odd_ends;
217 let mut quote_mask: u64 = Self::compute_quote_mask(*quote_bits);
219 quote_mask ^= *prev_iter_inside_quote;
220 let unescaped: u64 = self.unsigned_lteq_against_input(Self::fill_s8(0x1F));
226 *error_mask |= quote_mask & unescaped;
227 *prev_iter_inside_quote = static_cast_u64!(static_cast_i64!(quote_mask) >> 63);
231 quote_mask
232 }
233 }
234
235 #[cfg_attr(not(feature = "no-inline"), inline)]
245 fn find_odd_backslash_sequences(&self, prev_iter_ends_odd_backslash: &mut u64) -> u64 {
246 const EVEN_BITS: u64 = 0x5555_5555_5555_5555;
247 const ODD_BITS: u64 = !EVEN_BITS;
248
249 let bs_bits: u64 = unsafe { self.cmp_mask_against_input(b'\\') };
250 let start_edges: u64 = bs_bits & !(bs_bits << 1);
251 let even_start_mask: u64 = EVEN_BITS ^ *prev_iter_ends_odd_backslash;
254 let even_starts: u64 = start_edges & even_start_mask;
255 let odd_starts: u64 = start_edges & !even_start_mask;
256 let even_carries: u64 = bs_bits.wrapping_add(even_starts);
257
258 let (mut odd_carries, iter_ends_odd_backslash) = bs_bits.overflowing_add(odd_starts);
262
263 odd_carries |= *prev_iter_ends_odd_backslash;
264 *prev_iter_ends_odd_backslash = u64::from(iter_ends_odd_backslash);
268 let even_carry_ends: u64 = even_carries & !bs_bits;
269 let odd_carry_ends: u64 = odd_carries & !bs_bits;
270 let even_start_odd_end: u64 = even_carry_ends & ODD_BITS;
271 let odd_start_even_end: u64 = odd_carry_ends & EVEN_BITS;
272 let odd_ends: u64 = even_start_odd_end | odd_start_even_end;
273 odd_ends
274 }
275
276 #[cfg_attr(not(feature = "no-inline"), inline)]
283 fn finalize_structurals(
284 mut structurals: u64,
285 whitespace: u64,
286 quote_mask: u64,
287 quote_bits: u64,
288 prev_iter_ends_pseudo_pred: &mut u64,
289 ) -> u64 {
290 structurals &= !quote_mask;
292 structurals |= quote_bits;
295 let pseudo_pred: u64 = structurals | whitespace;
306
307 let shifted_pseudo_pred: u64 = (pseudo_pred << 1) | *prev_iter_ends_pseudo_pred;
308 *prev_iter_ends_pseudo_pred = pseudo_pred >> 63;
309 let pseudo_structurals: u64 = shifted_pseudo_pred & (!whitespace) & (!quote_mask);
310 structurals |= pseudo_structurals;
311
312 structurals &= !(quote_bits & !quote_mask);
315 structurals
316 }
317
318 unsafe fn fill_s8(n: i8) -> Self::SimdRepresentation;
319}
320
321#[derive(Debug)]
323pub struct Deserializer<'de> {
324 pub(crate) tape: Vec<Node<'de>>,
327 idx: usize,
328}
329
330#[derive(Debug, Clone, Copy)]
333pub(crate) struct SillyWrapper<'de> {
334 input: *mut u8,
335 _marker: std::marker::PhantomData<&'de ()>,
336}
337
338impl From<*mut u8> for SillyWrapper<'_> {
339 #[cfg_attr(not(feature = "no-inline"), inline)]
340 fn from(input: *mut u8) -> Self {
341 Self {
342 input,
343 _marker: std::marker::PhantomData,
344 }
345 }
346}
347
348#[cfg(all(
349 feature = "runtime-detection",
350 any(target_arch = "x86_64", target_arch = "x86"),
351))] type FnRaw = *mut ();
353#[cfg(all(
354 feature = "runtime-detection",
355 any(target_arch = "x86_64", target_arch = "x86"),
356))]
357type ParseStrFn = for<'invoke, 'de> unsafe fn(
358 SillyWrapper<'de>,
359 &'invoke [u8],
360 &'invoke mut [u8],
361 usize,
362) -> std::result::Result<&'de str, error::Error>;
363#[cfg(all(
364 feature = "runtime-detection",
365 any(target_arch = "x86_64", target_arch = "x86"),
366))]
367type FindStructuralBitsFn = unsafe fn(
368 input: &[u8],
369 structural_indexes: &mut Vec<u32>,
370) -> std::result::Result<(), ErrorType>;
371
372#[derive(Clone, Copy, Debug, PartialEq, Eq)]
373pub enum Implementation {
375 Native,
377 StdSimd,
379 SSE42,
381 AVX2,
383 NEON,
385 SIMD128,
387}
388
389impl std::fmt::Display for Implementation {
390 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
391 match self {
392 Implementation::Native => write!(f, "Rust Native"),
393 Implementation::StdSimd => write!(f, "std::simd"),
394 Implementation::SSE42 => write!(f, "SSE42"),
395 Implementation::AVX2 => write!(f, "AVX2"),
396 Implementation::NEON => write!(f, "NEON"),
397 Implementation::SIMD128 => write!(f, "SIMD128"),
398 }
399 }
400}
401
402impl Deserializer<'_> {
403 #[cfg(all(
405 feature = "runtime-detection",
406 any(target_arch = "x86_64", target_arch = "x86"),
407 ))]
408 #[must_use]
409 pub fn algorithm() -> Implementation {
410 if std::is_x86_feature_detected!("avx2") {
411 Implementation::AVX2
412 } else if std::is_x86_feature_detected!("sse4.2") {
413 Implementation::SSE42
414 } else {
415 #[cfg(feature = "portable")]
416 let r = Implementation::StdSimd;
417 #[cfg(not(feature = "portable"))]
418 let r = Implementation::Native;
419 r
420 }
421 }
422 #[cfg(not(any(
423 all(
424 feature = "runtime-detection",
425 any(target_arch = "x86_64", target_arch = "x86")
426 ),
427 feature = "portable",
428 target_feature = "avx2",
429 target_feature = "sse4.2",
430 target_feature = "simd128",
431 target_arch = "aarch64",
432 )))]
433 #[must_use]
435 pub fn algorithm() -> Implementation {
436 Implementation::Native
437 }
438 #[cfg(all(feature = "portable", not(feature = "runtime-detection")))]
439 #[must_use]
441 pub fn algorithm() -> Implementation {
442 Implementation::StdSimd
443 }
444
445 #[cfg(all(
446 target_feature = "avx2",
447 not(feature = "portable"),
448 not(feature = "runtime-detection"),
449 ))]
450 #[must_use]
452 pub fn algorithm() -> Implementation {
453 Implementation::AVX2
454 }
455
456 #[cfg(all(
457 target_feature = "sse4.2",
458 not(target_feature = "avx2"),
459 not(feature = "runtime-detection"),
460 not(feature = "portable"),
461 ))]
462 #[must_use]
464 pub fn algorithm() -> Implementation {
465 Implementation::SSE42
466 }
467
468 #[cfg(all(target_arch = "aarch64", not(feature = "portable")))]
469 #[must_use]
471 pub fn algorithm() -> Implementation {
472 Implementation::NEON
473 }
474
475 #[cfg(all(target_feature = "simd128", not(feature = "portable")))]
476 #[must_use]
478 pub fn algorithm() -> Implementation {
479 Implementation::SIMD128
480 }
481}
482
483impl<'de> Deserializer<'de> {
484 #[cfg_attr(not(feature = "no-inline"), inline)]
488 #[cfg(all(
489 feature = "runtime-detection",
490 any(target_arch = "x86_64", target_arch = "x86"),
491 ))]
492 pub(crate) fn parse_str_fn() -> ParseStrFn {
493 if std::is_x86_feature_detected!("avx2") {
494 impls::avx2::parse_str
495 } else if std::is_x86_feature_detected!("sse4.2") {
496 impls::sse42::parse_str
497 } else {
498 #[cfg(feature = "portable")]
499 let r = impls::portable::parse_str;
500 #[cfg(not(feature = "portable"))]
501 let r = impls::native::parse_str;
502 r
503 }
504 }
505
506 #[cfg_attr(not(feature = "no-inline"), inline)]
507 #[cfg(all(
508 feature = "runtime-detection",
509 any(target_arch = "x86_64", target_arch = "x86"),
510 ))]
511 #[allow(dead_code)]
514 pub(crate) unsafe fn parse_str_<'invoke>(
515 input: *mut u8,
516 data: &'invoke [u8],
517 buffer: &'invoke mut [u8],
518 idx: usize,
519 ) -> Result<&'de str>
520 where
521 'de: 'invoke,
522 {
523 let input: SillyWrapper<'de> = SillyWrapper::from(input);
524 unsafe { (Self::parse_str_fn())(input, data, buffer, idx) }
525 }
526 #[cfg_attr(not(feature = "no-inline"), inline)]
527 #[cfg(not(any(
528 all(
529 feature = "runtime-detection",
530 any(target_arch = "x86_64", target_arch = "x86")
531 ),
532 feature = "portable",
533 target_feature = "avx2",
534 target_feature = "sse4.2",
535 target_feature = "simd128",
536 target_arch = "aarch64",
537 )))]
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 unsafe { impls::native::parse_str(input, data, buffer, idx) }
549 }
550 #[cfg_attr(not(feature = "no-inline"), inline)]
551 #[cfg(all(feature = "portable", not(feature = "runtime-detection")))]
552 pub(crate) unsafe fn parse_str_<'invoke>(
553 input: *mut u8,
554 data: &'invoke [u8],
555 buffer: &'invoke mut [u8],
556 idx: usize,
557 ) -> Result<&'de str>
558 where
559 'de: 'invoke,
560 {
561 let input: SillyWrapper<'de> = SillyWrapper::from(input);
562 impls::portable::parse_str(input, data, buffer, idx)
563 }
564
565 #[cfg_attr(not(feature = "no-inline"), inline)]
566 #[cfg(all(
567 target_feature = "avx2",
568 not(feature = "portable"),
569 not(feature = "runtime-detection"),
570 ))]
571 pub(crate) unsafe fn parse_str_<'invoke>(
572 input: *mut u8,
573 data: &'invoke [u8],
574 buffer: &'invoke mut [u8],
575 idx: usize,
576 ) -> Result<&'de str> {
577 let input: SillyWrapper<'de> = SillyWrapper::from(input);
578 unsafe { impls::avx2::parse_str(input, data, buffer, idx) }
579 }
580
581 #[cfg_attr(not(feature = "no-inline"), inline)]
582 #[cfg(all(
583 target_feature = "sse4.2",
584 not(target_feature = "avx2"),
585 not(feature = "runtime-detection"),
586 not(feature = "portable"),
587 ))]
588 pub(crate) unsafe fn parse_str_<'invoke>(
589 input: *mut u8,
590 data: &'invoke [u8],
591 buffer: &'invoke mut [u8],
592 idx: usize,
593 ) -> Result<&'de str> {
594 let input: SillyWrapper<'de> = SillyWrapper::from(input);
595 unsafe { impls::sse42::parse_str(input, data, buffer, idx) }
596 }
597
598 #[cfg_attr(not(feature = "no-inline"), inline)]
599 #[cfg(all(target_arch = "aarch64", not(feature = "portable")))]
600 pub(crate) unsafe fn parse_str_<'invoke>(
601 input: *mut u8,
602 data: &'invoke [u8],
603 buffer: &'invoke mut [u8],
604 idx: usize,
605 ) -> Result<&'de str> {
606 let input: SillyWrapper = SillyWrapper::from(input);
607 impls::neon::parse_str(input, data, buffer, idx)
608 }
609 #[cfg_attr(not(feature = "no-inline"), inline)]
610 #[cfg(all(target_feature = "simd128", not(feature = "portable")))]
611 pub(crate) unsafe fn parse_str_<'invoke>(
612 input: *mut u8,
613 data: &'invoke [u8],
614 buffer: &'invoke mut [u8],
615 idx: usize,
616 ) -> Result<&'de str> {
617 let input: SillyWrapper<'de> = SillyWrapper::from(input);
618 impls::simd128::parse_str(input, data, buffer, idx)
619 }
620}
621
622impl Deserializer<'_> {
624 #[cfg_attr(not(feature = "no-inline"), inline)]
625 #[cfg(all(
628 feature = "runtime-detection",
629 any(target_arch = "x86_64", target_arch = "x86"),
630 not(feature = "portable"),
631 ))]
632 pub(crate) unsafe fn find_structural_bits_native(
633 input: &[u8],
634 structural_indexes: &mut Vec<u32>,
635 ) -> std::result::Result<(), ErrorType> {
636 match core::str::from_utf8(input) {
637 Ok(_) => (),
638 Err(_) => return Err(ErrorType::InvalidUtf8),
639 }
640 unsafe {
641 Self::_find_structural_bits::<impls::native::SimdInput>(input, structural_indexes)
642 }
643 }
644
645 #[cfg_attr(not(feature = "no-inline"), inline)]
646 #[cfg(all(
647 feature = "runtime-detection",
648 any(target_arch = "x86_64", target_arch = "x86"),
649 ))]
650 pub(crate) unsafe fn find_structural_bits(
651 input: &[u8],
652 structural_indexes: &mut Vec<u32>,
653 ) -> std::result::Result<(), ErrorType> {
654 unsafe {
655 use std::sync::atomic::{AtomicPtr, Ordering};
656
657 static FN: AtomicPtr<()> = AtomicPtr::new(get_fastest as FnRaw);
658
659 #[target_feature(enable = "avx2", enable = "pclmulqdq")]
663 unsafe fn find_structural_bits_avx2(
664 input: &[u8],
665 structural_indexes: &mut Vec<u32>,
666 ) -> core::result::Result<(), error::ErrorType> {
667 unsafe {
668 Deserializer::_find_structural_bits::<impls::avx2::SimdInput>(
669 input,
670 structural_indexes,
671 )
672 }
673 }
674
675 #[target_feature(enable = "sse4.2")]
676 unsafe fn find_structural_bits_sse42(
677 input: &[u8],
678 structural_indexes: &mut Vec<u32>,
679 ) -> core::result::Result<(), error::ErrorType> {
680 unsafe {
681 Deserializer::_find_structural_bits::<impls::sse42::SimdInput>(
682 input,
683 structural_indexes,
684 )
685 }
686 }
687
688 #[cfg_attr(not(feature = "no-inline"), inline)]
689 fn get_fastest_available_implementation() -> FindStructuralBitsFn {
690 if std::is_x86_feature_detected!("avx2")
691 && std::is_x86_feature_detected!("pclmulqdq")
692 {
693 find_structural_bits_avx2
694 } else if std::is_x86_feature_detected!("sse4.2") {
695 find_structural_bits_sse42
696 } else {
697 #[cfg(feature = "portable")]
698 let r = Deserializer::_find_structural_bits::<impls::portable::SimdInput>;
699 #[cfg(not(feature = "portable"))]
700 let r = Deserializer::find_structural_bits_native;
701 r
702 }
703 }
704
705 #[cfg_attr(not(feature = "no-inline"), inline)]
706 unsafe fn get_fastest(
707 input: &[u8],
708 structural_indexes: &mut Vec<u32>,
709 ) -> core::result::Result<(), error::ErrorType> {
710 unsafe {
711 let fun = get_fastest_available_implementation();
712 FN.store(fun as FnRaw, Ordering::Relaxed);
713 (fun)(input, structural_indexes)
714 }
715 }
716
717 let fun = FN.load(Ordering::Relaxed);
718 mem::transmute::<FnRaw, FindStructuralBitsFn>(fun)(input, structural_indexes)
719 }
720 }
721
722 #[cfg(not(any(
723 all(
724 feature = "runtime-detection",
725 any(target_arch = "x86_64", target_arch = "x86")
726 ),
727 feature = "portable",
728 target_feature = "avx2",
729 target_feature = "sse4.2",
730 target_feature = "simd128",
731 target_arch = "aarch64",
732 )))]
733 #[cfg_attr(not(feature = "no-inline"), inline)]
734 pub(crate) unsafe fn find_structural_bits(
735 input: &[u8],
736 structural_indexes: &mut Vec<u32>,
737 ) -> std::result::Result<(), ErrorType> {
738 match core::str::from_utf8(input) {
741 Ok(_) => (),
742 Err(_) => return Err(ErrorType::InvalidUtf8),
743 }
744 #[cfg(not(feature = "portable"))]
745 unsafe {
746 Self::_find_structural_bits::<impls::native::SimdInput>(input, structural_indexes)
747 }
748 }
749
750 #[cfg(all(feature = "portable", not(feature = "runtime-detection")))]
751 #[cfg_attr(not(feature = "no-inline"), inline)]
752 pub(crate) unsafe fn find_structural_bits(
753 input: &[u8],
754 structural_indexes: &mut Vec<u32>,
755 ) -> std::result::Result<(), ErrorType> {
756 unsafe {
757 Self::_find_structural_bits::<impls::portable::SimdInput>(input, structural_indexes)
758 }
759 }
760
761 #[cfg(all(
762 target_feature = "avx2",
763 not(feature = "portable"),
764 not(feature = "runtime-detection"),
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::avx2::SimdInput>(input, structural_indexes) }
772 }
773
774 #[cfg(all(
775 target_feature = "sse4.2",
776 not(target_feature = "avx2"),
777 not(feature = "runtime-detection"),
778 not(feature = "portable"),
779 ))]
780 #[cfg_attr(not(feature = "no-inline"), inline)]
781 pub(crate) unsafe fn find_structural_bits(
782 input: &[u8],
783 structural_indexes: &mut Vec<u32>,
784 ) -> std::result::Result<(), ErrorType> {
785 unsafe { Self::_find_structural_bits::<impls::sse42::SimdInput>(input, structural_indexes) }
786 }
787
788 #[cfg(all(target_arch = "aarch64", not(feature = "portable")))]
789 #[cfg_attr(not(feature = "no-inline"), inline)]
790 pub(crate) unsafe fn find_structural_bits(
791 input: &[u8],
792 structural_indexes: &mut Vec<u32>,
793 ) -> std::result::Result<(), ErrorType> {
794 unsafe { Self::_find_structural_bits::<impls::neon::SimdInput>(input, structural_indexes) }
795 }
796
797 #[cfg(all(target_feature = "simd128", not(feature = "portable")))]
798 #[cfg_attr(not(feature = "no-inline"), inline)]
799 pub(crate) unsafe fn find_structural_bits(
800 input: &[u8],
801 structural_indexes: &mut Vec<u32>,
802 ) -> std::result::Result<(), ErrorType> {
803 unsafe {
804 Self::_find_structural_bits::<impls::simd128::SimdInput>(input, structural_indexes)
805 }
806 }
807}
808
809impl<'de> Deserializer<'de> {
810 #[must_use]
812 pub fn into_tape(self) -> Tape<'de> {
813 Tape(self.tape)
814 }
815
816 #[must_use]
818 pub fn as_value(&self) -> Value<'_, 'de> {
819 Value(&self.tape)
821 }
822
823 pub fn restart(&mut self) {
825 self.idx = 0;
827 }
828
829 #[cold]
830 #[inline(never)]
831 fn error(error: ErrorType) -> Error {
832 Error::new(0, None, error)
833 }
834
835 #[cold]
836 #[inline(never)]
837 fn error_c(idx: usize, c: char, error: ErrorType) -> Error {
838 Error::new(idx, Some(c), error)
839 }
840
841 pub fn from_slice(input: &'de mut [u8]) -> Result<Self> {
847 let len = input.len();
848
849 let mut buffer = Buffers::new(len);
850
851 Self::from_slice_with_buffers(input, &mut buffer)
852 }
853
854 #[allow(clippy::uninit_vec)]
862 #[cfg_attr(not(feature = "no-inline"), inline)]
863 fn fill_tape(
864 input: &'de mut [u8],
865 buffer: &mut Buffers,
866 tape: &mut Vec<Node<'de>>,
867 ) -> Result<()> {
868 const LOTS_OF_SPACES: [u8; SIMDINPUT_LENGTH] = [b' '; SIMDINPUT_LENGTH];
869 let len = input.len();
870 let simd_safe_len = len + SIMDINPUT_LENGTH;
871
872 if len > u32::MAX as usize {
873 return Err(Self::error(ErrorType::InputTooLarge));
874 }
875
876 buffer.string_buffer.clear();
877 buffer.string_buffer.reserve(len + SIMDJSON_PADDING);
878
879 unsafe {
880 buffer.string_buffer.set_len(len + SIMDJSON_PADDING);
881 };
882
883 let input_buffer = &mut buffer.input_buffer;
884 if input_buffer.capacity() < simd_safe_len {
885 *input_buffer = AlignedBuf::with_capacity(simd_safe_len);
886 }
887
888 unsafe {
889 input_buffer
890 .as_mut_ptr()
891 .copy_from_nonoverlapping(input.as_ptr(), len);
892
893 input_buffer
896 .as_mut_ptr()
897 .add(len)
898 .copy_from_nonoverlapping(LOTS_OF_SPACES.as_ptr(), SIMDINPUT_LENGTH);
899
900 input_buffer.set_len(simd_safe_len);
902
903 Self::find_structural_bits(input, &mut buffer.structural_indexes)
904 .map_err(Error::generic)?;
905 };
906
907 Self::build_tape(
908 input,
909 input_buffer,
910 &mut buffer.string_buffer,
911 &buffer.structural_indexes,
912 &mut buffer.stage2_stack,
913 buffer.max_depth,
914 tape,
915 )
916 }
917
918 pub fn from_slice_with_buffers(input: &'de mut [u8], buffer: &mut Buffers) -> Result<Self> {
925 let mut tape: Vec<Node<'de>> = Vec::with_capacity(buffer.structural_indexes.len());
926
927 Self::fill_tape(input, buffer, &mut tape)?;
928
929 Ok(Self { tape, idx: 0 })
930 }
931
932 #[cfg(feature = "serde_impl")]
933 #[cfg_attr(not(feature = "no-inline"), inline)]
934 fn skip(&mut self) {
935 self.idx += 1;
936 }
937
938 #[cfg_attr(not(feature = "no-inline"), inline)]
946 pub unsafe fn next_(&mut self) -> Node<'de> {
947 let r = *unsafe { self.tape.get_kinda_unchecked(self.idx) };
948 self.idx += 1;
949 r
950 }
951
952 #[cfg_attr(not(feature = "no-inline"), inline)]
953 #[allow(clippy::cast_possible_truncation)]
954 pub(crate) unsafe fn _find_structural_bits<S: Stage1Parse>(
955 input: &[u8],
956 structural_indexes: &mut Vec<u32>,
957 ) -> std::result::Result<(), ErrorType> {
958 let len = input.len();
959 structural_indexes.clear();
962 structural_indexes.reserve(len / 8);
963
964 let mut utf8_validator = unsafe { S::Utf8Validator::new() };
965
966 let mut prev_iter_ends_odd_backslash: u64 = 0;
973 let mut prev_iter_inside_quote: u64 = 0;
975 let mut prev_iter_ends_pseudo_pred: u64 = 1;
982
983 let mut structurals: u64 = 0;
989
990 let lenminus64: usize = len.saturating_sub(64);
991 let mut idx: usize = 0;
992 let mut error_mask: u64 = 0; while idx < lenminus64 {
995 let chunk = unsafe { input.get_kinda_unchecked(idx..idx + 64) };
1001 unsafe { utf8_validator.update_from_chunks(chunk) };
1002
1003 let input = unsafe { S::new(chunk) };
1004 let odd_ends: u64 =
1006 input.find_odd_backslash_sequences(&mut prev_iter_ends_odd_backslash);
1007
1008 let mut quote_bits: u64 = 0;
1011 let quote_mask: u64 = input.find_quote_mask_and_bits(
1012 odd_ends,
1013 &mut prev_iter_inside_quote,
1014 &mut quote_bits,
1015 &mut error_mask,
1016 );
1017
1018 unsafe { S::flatten_bits(structural_indexes, idx as u32, structurals) };
1021
1022 let mut whitespace: u64 = 0;
1023 unsafe { input.find_whitespace_and_structurals(&mut whitespace, &mut structurals) };
1024
1025 structurals = S::finalize_structurals(
1027 structurals,
1028 whitespace,
1029 quote_mask,
1030 quote_bits,
1031 &mut prev_iter_ends_pseudo_pred,
1032 );
1033 idx += SIMDINPUT_LENGTH;
1034 }
1035
1036 if idx < len {
1040 let mut tmpbuf: [u8; SIMDINPUT_LENGTH] = [0x20; SIMDINPUT_LENGTH];
1041 unsafe {
1042 tmpbuf
1043 .as_mut_ptr()
1044 .copy_from(input.as_ptr().add(idx), len - idx);
1045 };
1046 unsafe { utf8_validator.update_from_chunks(&tmpbuf) };
1047
1048 let input = unsafe { S::new(&tmpbuf) };
1049
1050 let odd_ends: u64 =
1052 input.find_odd_backslash_sequences(&mut prev_iter_ends_odd_backslash);
1053
1054 let mut quote_bits: u64 = 0;
1057 let quote_mask: u64 = input.find_quote_mask_and_bits(
1058 odd_ends,
1059 &mut prev_iter_inside_quote,
1060 &mut quote_bits,
1061 &mut error_mask,
1062 );
1063
1064 unsafe { S::flatten_bits(structural_indexes, idx as u32, structurals) };
1067
1068 let mut whitespace: u64 = 0;
1069 unsafe { input.find_whitespace_and_structurals(&mut whitespace, &mut structurals) };
1070
1071 structurals = S::finalize_structurals(
1073 structurals,
1074 whitespace,
1075 quote_mask,
1076 quote_bits,
1077 &mut prev_iter_ends_pseudo_pred,
1078 );
1079 idx += SIMDINPUT_LENGTH;
1080 }
1081 if prev_iter_inside_quote != 0 {
1083 return Err(ErrorType::Syntax);
1084 }
1085 unsafe { S::flatten_bits(structural_indexes, idx as u32, structurals) };
1087
1088 if structural_indexes.is_empty() {
1091 return Err(ErrorType::Eof);
1092 }
1093
1094 if error_mask != 0 {
1095 return Err(ErrorType::Syntax);
1096 }
1097
1098 if unsafe { utf8_validator.finalize(None).is_err() } {
1099 Err(ErrorType::InvalidUtf8)
1100 } else {
1101 Ok(())
1102 }
1103 }
1104}
1105
1106struct AlignedBuf {
1108 layout: Layout,
1109 capacity: usize,
1110 len: usize,
1111 inner: NonNull<u8>,
1112}
1113unsafe impl Send for AlignedBuf {}
1120unsafe impl Sync for AlignedBuf {}
1121impl AlignedBuf {
1122 #[must_use]
1124 pub fn with_capacity(capacity: usize) -> Self {
1125 if capacity == 0 {
1126 let layout = Layout::from_size_align(0, SIMDJSON_PADDING)
1127 .expect("Layout for size 0 should always be valid");
1128 return Self {
1129 layout,
1130 capacity: 0,
1131 len: 0,
1132 inner: NonNull::dangling(),
1133 };
1134 }
1135 let Ok(layout) = Layout::from_size_align(capacity, SIMDJSON_PADDING) else {
1136 Self::capacity_overflow()
1137 };
1138 if mem::size_of::<usize>() < 8 && capacity > isize::MAX as usize {
1139 Self::capacity_overflow()
1140 }
1141 unsafe {
1142 let Some(inner) = NonNull::new(alloc(layout)) else {
1143 handle_alloc_error(layout)
1144 };
1145 Self {
1146 layout,
1147 capacity,
1148 len: 0,
1149 inner,
1150 }
1151 }
1152 }
1153
1154 fn as_mut_ptr(&mut self) -> *mut u8 {
1155 self.inner.as_ptr()
1156 }
1157
1158 fn capacity_overflow() -> ! {
1159 panic!("capacity overflow");
1160 }
1161 fn capacity(&self) -> usize {
1162 self.capacity
1163 }
1164 unsafe fn set_len(&mut self, n: usize) {
1165 assert!(
1166 n <= self.capacity,
1167 "New size ({}) can not be larger then capacity ({}).",
1168 n,
1169 self.capacity
1170 );
1171 self.len = n;
1172 }
1173}
1174impl Drop for AlignedBuf {
1175 fn drop(&mut self) {
1176 if self.capacity > 0 {
1177 unsafe {
1178 dealloc(self.inner.as_ptr(), self.layout);
1179 }
1180 }
1181 }
1182}
1183
1184impl Deref for AlignedBuf {
1185 type Target = [u8];
1186
1187 fn deref(&self) -> &Self::Target {
1188 unsafe { std::slice::from_raw_parts(self.inner.as_ptr(), self.len) }
1189 }
1190}
1191
1192impl DerefMut for AlignedBuf {
1193 fn deref_mut(&mut self) -> &mut Self::Target {
1194 unsafe { std::slice::from_raw_parts_mut(self.inner.as_ptr(), self.len) }
1195 }
1196}