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
47use macros::static_cast_u64;
48use safer_unchecked::GetSaferUnchecked;
49use stage2::StackState;
50use tape::Value;
51
52mod impls;
53
54pub mod cow;
56
57pub(crate) const SIMDJSON_PADDING: usize = 32; pub(crate) const SIMDINPUT_LENGTH: usize = 64;
61
62mod stage2;
63pub mod value;
65
66use std::{alloc::dealloc, mem};
67pub use value_trait::StaticNode;
68
69pub use crate::error::{Error, ErrorType};
70#[doc(inline)]
71pub use crate::value::*;
72pub use value_trait::ValueType;
73
74pub type Result<T> = std::result::Result<T, Error>;
76
77#[cfg(feature = "known-key")]
78mod known_key;
79#[cfg(feature = "known-key")]
80pub use known_key::{Error as KnownKeyError, KnownKey};
81
82pub use crate::tape::{Node, Tape};
83use std::alloc::{Layout, alloc, handle_alloc_error};
84use std::ops::{Deref, DerefMut};
85use std::ptr::NonNull;
86
87use simdutf8::basic::imp::ChunkedUtf8Validator;
88
89pub struct Buffers {
91 string_buffer: Vec<u8>,
92 structural_indexes: Vec<u32>,
93 input_buffer: AlignedBuf,
94 stage2_stack: Vec<StackState>,
95}
96
97impl Default for Buffers {
98 #[cfg_attr(not(feature = "no-inline"), inline)]
99 fn default() -> Self {
100 Self::new(128)
101 }
102}
103
104impl Buffers {
105 #[cfg_attr(not(feature = "no-inline"), inline)]
108 #[must_use]
109 pub fn new(input_len: usize) -> Self {
110 let heuristic_index_cout = input_len / 128;
112 Self {
113 string_buffer: Vec::with_capacity(input_len + SIMDJSON_PADDING),
114 structural_indexes: Vec::with_capacity(heuristic_index_cout),
115 input_buffer: AlignedBuf::with_capacity(input_len + SIMDJSON_PADDING * 2),
116 stage2_stack: Vec::with_capacity(heuristic_index_cout),
117 }
118 }
119}
120
121#[cfg_attr(not(feature = "no-inline"), inline)]
126pub fn to_tape(s: &mut [u8]) -> Result<Tape> {
127 Deserializer::from_slice(s).map(Deserializer::into_tape)
128}
129
130#[cfg_attr(not(feature = "no-inline"), inline)]
135pub fn to_tape_with_buffers<'de>(s: &'de mut [u8], buffers: &mut Buffers) -> Result<Tape<'de>> {
136 Deserializer::from_slice_with_buffers(s, buffers).map(Deserializer::into_tape)
137}
138
139#[cfg_attr(not(feature = "no-inline"), inline)]
144pub fn fill_tape<'de>(s: &'de mut [u8], buffers: &mut Buffers, tape: &mut Tape<'de>) -> Result<()> {
145 tape.0.clear();
146 Deserializer::fill_tape(s, buffers, &mut tape.0)
147}
148
149pub(crate) trait Stage1Parse {
150 type Utf8Validator: ChunkedUtf8Validator;
151 type SimdRepresentation;
152
153 unsafe fn new(ptr: &[u8]) -> Self;
154
155 unsafe fn compute_quote_mask(quote_bits: u64) -> u64;
156
157 unsafe fn cmp_mask_against_input(&self, m: u8) -> u64;
158
159 unsafe fn unsigned_lteq_against_input(&self, maxval: Self::SimdRepresentation) -> u64;
160
161 unsafe fn find_whitespace_and_structurals(&self, whitespace: &mut u64, structurals: &mut u64);
162
163 unsafe fn flatten_bits(base: &mut Vec<u32>, idx: u32, bits: u64);
164
165 #[cfg_attr(not(feature = "no-inline"), inline)]
177 fn find_quote_mask_and_bits(
178 &self,
179 odd_ends: u64,
180 prev_iter_inside_quote: &mut u64,
181 quote_bits: &mut u64,
182 error_mask: &mut u64,
183 ) -> u64 {
184 unsafe {
185 *quote_bits = self.cmp_mask_against_input(b'"');
186 *quote_bits &= !odd_ends;
187 let mut quote_mask: u64 = Self::compute_quote_mask(*quote_bits);
189 quote_mask ^= *prev_iter_inside_quote;
190 let unescaped: u64 = self.unsigned_lteq_against_input(Self::fill_s8(0x1F));
196 *error_mask |= quote_mask & unescaped;
197 *prev_iter_inside_quote = static_cast_u64!(static_cast_i64!(quote_mask) >> 63);
201 quote_mask
202 }
203 }
204
205 #[cfg_attr(not(feature = "no-inline"), inline)]
215 fn find_odd_backslash_sequences(&self, prev_iter_ends_odd_backslash: &mut u64) -> u64 {
216 const EVEN_BITS: u64 = 0x5555_5555_5555_5555;
217 const ODD_BITS: u64 = !EVEN_BITS;
218
219 let bs_bits: u64 = unsafe { self.cmp_mask_against_input(b'\\') };
220 let start_edges: u64 = bs_bits & !(bs_bits << 1);
221 let even_start_mask: u64 = EVEN_BITS ^ *prev_iter_ends_odd_backslash;
224 let even_starts: u64 = start_edges & even_start_mask;
225 let odd_starts: u64 = start_edges & !even_start_mask;
226 let even_carries: u64 = bs_bits.wrapping_add(even_starts);
227
228 let (mut odd_carries, iter_ends_odd_backslash) = bs_bits.overflowing_add(odd_starts);
232
233 odd_carries |= *prev_iter_ends_odd_backslash;
234 *prev_iter_ends_odd_backslash = u64::from(iter_ends_odd_backslash);
238 let even_carry_ends: u64 = even_carries & !bs_bits;
239 let odd_carry_ends: u64 = odd_carries & !bs_bits;
240 let even_start_odd_end: u64 = even_carry_ends & ODD_BITS;
241 let odd_start_even_end: u64 = odd_carry_ends & EVEN_BITS;
242 let odd_ends: u64 = even_start_odd_end | odd_start_even_end;
243 odd_ends
244 }
245
246 #[cfg_attr(not(feature = "no-inline"), inline)]
253 fn finalize_structurals(
254 mut structurals: u64,
255 whitespace: u64,
256 quote_mask: u64,
257 quote_bits: u64,
258 prev_iter_ends_pseudo_pred: &mut u64,
259 ) -> u64 {
260 structurals &= !quote_mask;
262 structurals |= quote_bits;
265 let pseudo_pred: u64 = structurals | whitespace;
276
277 let shifted_pseudo_pred: u64 = (pseudo_pred << 1) | *prev_iter_ends_pseudo_pred;
278 *prev_iter_ends_pseudo_pred = pseudo_pred >> 63;
279 let pseudo_structurals: u64 = shifted_pseudo_pred & (!whitespace) & (!quote_mask);
280 structurals |= pseudo_structurals;
281
282 structurals &= !(quote_bits & !quote_mask);
285 structurals
286 }
287
288 unsafe fn fill_s8(n: i8) -> Self::SimdRepresentation;
289}
290
291#[derive(Debug)]
293pub struct Deserializer<'de> {
294 pub(crate) tape: Vec<Node<'de>>,
297 idx: usize,
298}
299
300#[derive(Debug, Clone, Copy)]
303pub(crate) struct SillyWrapper<'de> {
304 input: *mut u8,
305 _marker: std::marker::PhantomData<&'de ()>,
306}
307
308impl From<*mut u8> for SillyWrapper<'_> {
309 #[cfg_attr(not(feature = "no-inline"), inline)]
310 fn from(input: *mut u8) -> Self {
311 Self {
312 input,
313 _marker: std::marker::PhantomData,
314 }
315 }
316}
317
318#[cfg(all(
319 feature = "runtime-detection",
320 any(target_arch = "x86_64", target_arch = "x86"),
321))] type FnRaw = *mut ();
323#[cfg(all(
324 feature = "runtime-detection",
325 any(target_arch = "x86_64", target_arch = "x86"),
326))]
327type ParseStrFn = for<'invoke, 'de> unsafe fn(
328 SillyWrapper<'de>,
329 &'invoke [u8],
330 &'invoke mut [u8],
331 usize,
332) -> std::result::Result<&'de str, error::Error>;
333#[cfg(all(
334 feature = "runtime-detection",
335 any(target_arch = "x86_64", target_arch = "x86"),
336))]
337type FindStructuralBitsFn = unsafe fn(
338 input: &[u8],
339 structural_indexes: &mut Vec<u32>,
340) -> std::result::Result<(), ErrorType>;
341
342#[derive(Clone, Copy, Debug, PartialEq, Eq)]
343pub enum Implementation {
345 Native,
347 StdSimd,
349 SSE42,
351 AVX2,
353 NEON,
355 SIMD128,
357}
358
359impl std::fmt::Display for Implementation {
360 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
361 match self {
362 Implementation::Native => write!(f, "Rust Native"),
363 Implementation::StdSimd => write!(f, "std::simd"),
364 Implementation::SSE42 => write!(f, "SSE42"),
365 Implementation::AVX2 => write!(f, "AVX2"),
366 Implementation::NEON => write!(f, "NEON"),
367 Implementation::SIMD128 => write!(f, "SIMD128"),
368 }
369 }
370}
371
372impl Deserializer<'_> {
373 #[cfg(all(
375 feature = "runtime-detection",
376 any(target_arch = "x86_64", target_arch = "x86"),
377 ))]
378 #[must_use]
379 pub fn algorithm() -> Implementation {
380 if std::is_x86_feature_detected!("avx2") {
381 Implementation::AVX2
382 } else if std::is_x86_feature_detected!("sse4.2") {
383 Implementation::SSE42
384 } else {
385 #[cfg(feature = "portable")]
386 let r = Implementation::StdSimd;
387 #[cfg(not(feature = "portable"))]
388 let r = Implementation::Native;
389 r
390 }
391 }
392 #[cfg(not(any(
393 all(
394 feature = "runtime-detection",
395 any(target_arch = "x86_64", target_arch = "x86")
396 ),
397 feature = "portable",
398 target_feature = "avx2",
399 target_feature = "sse4.2",
400 target_feature = "simd128",
401 target_arch = "aarch64",
402 )))]
403 #[must_use]
405 pub fn algorithm() -> Implementation {
406 Implementation::Native
407 }
408 #[cfg(all(feature = "portable", not(feature = "runtime-detection")))]
409 #[must_use]
411 pub fn algorithm() -> Implementation {
412 Implementation::StdSimd
413 }
414
415 #[cfg(all(
416 target_feature = "avx2",
417 not(feature = "portable"),
418 not(feature = "runtime-detection"),
419 ))]
420 #[must_use]
422 pub fn algorithm() -> Implementation {
423 Implementation::AVX2
424 }
425
426 #[cfg(all(
427 target_feature = "sse4.2",
428 not(target_feature = "avx2"),
429 not(feature = "runtime-detection"),
430 not(feature = "portable"),
431 ))]
432 #[must_use]
434 pub fn algorithm() -> Implementation {
435 Implementation::SSE42
436 }
437
438 #[cfg(all(target_arch = "aarch64", not(feature = "portable")))]
439 #[must_use]
441 pub fn algorithm() -> Implementation {
442 Implementation::NEON
443 }
444
445 #[cfg(all(target_feature = "simd128", not(feature = "portable")))]
446 #[must_use]
448 pub fn algorithm() -> Implementation {
449 Implementation::SIMD128
450 }
451}
452
453impl<'de> Deserializer<'de> {
454 #[cfg_attr(not(feature = "no-inline"), inline)]
455 #[cfg(all(
456 feature = "runtime-detection",
457 any(target_arch = "x86_64", target_arch = "x86"),
458 ))]
459 pub(crate) unsafe fn parse_str_<'invoke>(
460 input: *mut u8,
461 data: &'invoke [u8],
462 buffer: &'invoke mut [u8],
463 idx: usize,
464 ) -> Result<&'de str>
465 where
466 'de: 'invoke,
467 {
468 unsafe {
469 use std::sync::atomic::{AtomicPtr, Ordering};
470
471 static FN: AtomicPtr<()> = AtomicPtr::new(get_fastest as FnRaw);
472
473 #[cfg_attr(not(feature = "no-inline"), inline)]
474 fn get_fastest_available_implementation() -> ParseStrFn {
475 if std::is_x86_feature_detected!("avx2") {
476 impls::avx2::parse_str
477 } else if std::is_x86_feature_detected!("sse4.2") {
478 impls::sse42::parse_str
479 } else {
480 #[cfg(feature = "portable")]
481 let r = impls::portable::parse_str;
482 #[cfg(not(feature = "portable"))]
483 let r = impls::native::parse_str;
484 r
485 }
486 }
487
488 #[cfg_attr(not(feature = "no-inline"), inline)]
489 unsafe fn get_fastest<'invoke, 'de>(
490 input: SillyWrapper<'de>,
491 data: &'invoke [u8],
492 buffer: &'invoke mut [u8],
493 idx: usize,
494 ) -> core::result::Result<&'de str, error::Error>
495 where
496 'de: 'invoke,
497 {
498 unsafe {
499 let fun = get_fastest_available_implementation();
500 FN.store(fun as FnRaw, Ordering::Relaxed);
501 (fun)(input, data, buffer, idx)
502 }
503 }
504
505 let input: SillyWrapper<'de> = SillyWrapper::from(input);
506 let fun = FN.load(Ordering::Relaxed);
507 mem::transmute::<FnRaw, ParseStrFn>(fun)(input, data, buffer, idx)
508 }
509 }
510 #[cfg_attr(not(feature = "no-inline"), inline)]
511 #[cfg(not(any(
512 all(
513 feature = "runtime-detection",
514 any(target_arch = "x86_64", target_arch = "x86")
515 ),
516 feature = "portable",
517 target_feature = "avx2",
518 target_feature = "sse4.2",
519 target_feature = "simd128",
520 target_arch = "aarch64",
521 )))]
522 pub(crate) unsafe fn parse_str_<'invoke>(
523 input: *mut u8,
524 data: &'invoke [u8],
525 buffer: &'invoke mut [u8],
526 idx: usize,
527 ) -> Result<&'de str>
528 where
529 'de: 'invoke,
530 {
531 let input: SillyWrapper<'de> = SillyWrapper::from(input);
532 unsafe { impls::native::parse_str(input, data, buffer, idx) }
533 }
534 #[cfg_attr(not(feature = "no-inline"), inline)]
535 #[cfg(all(feature = "portable", not(feature = "runtime-detection")))]
536 pub(crate) unsafe fn parse_str_<'invoke>(
537 input: *mut u8,
538 data: &'invoke [u8],
539 buffer: &'invoke mut [u8],
540 idx: usize,
541 ) -> Result<&'de str>
542 where
543 'de: 'invoke,
544 {
545 let input: SillyWrapper<'de> = SillyWrapper::from(input);
546 impls::portable::parse_str(input, data, buffer, idx)
547 }
548
549 #[cfg_attr(not(feature = "no-inline"), inline)]
550 #[cfg(all(
551 target_feature = "avx2",
552 not(feature = "portable"),
553 not(feature = "runtime-detection"),
554 ))]
555 pub(crate) unsafe fn parse_str_<'invoke>(
556 input: *mut u8,
557 data: &'invoke [u8],
558 buffer: &'invoke mut [u8],
559 idx: usize,
560 ) -> Result<&'de str> {
561 let input: SillyWrapper<'de> = SillyWrapper::from(input);
562 unsafe { impls::avx2::parse_str(input, data, buffer, idx) }
563 }
564
565 #[cfg_attr(not(feature = "no-inline"), inline)]
566 #[cfg(all(
567 target_feature = "sse4.2",
568 not(target_feature = "avx2"),
569 not(feature = "runtime-detection"),
570 not(feature = "portable"),
571 ))]
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 unsafe { impls::sse42::parse_str(input, data, buffer, idx) }
580 }
581
582 #[cfg_attr(not(feature = "no-inline"), inline)]
583 #[cfg(all(target_arch = "aarch64", not(feature = "portable")))]
584 pub(crate) unsafe fn parse_str_<'invoke>(
585 input: *mut u8,
586 data: &'invoke [u8],
587 buffer: &'invoke mut [u8],
588 idx: usize,
589 ) -> Result<&'de str> {
590 let input: SillyWrapper = SillyWrapper::from(input);
591 impls::neon::parse_str(input, data, buffer, idx)
592 }
593 #[cfg_attr(not(feature = "no-inline"), inline)]
594 #[cfg(all(target_feature = "simd128", not(feature = "portable")))]
595 pub(crate) unsafe fn parse_str_<'invoke>(
596 input: *mut u8,
597 data: &'invoke [u8],
598 buffer: &'invoke mut [u8],
599 idx: usize,
600 ) -> Result<&'de str> {
601 let input: SillyWrapper<'de> = SillyWrapper::from(input);
602 impls::simd128::parse_str(input, data, buffer, idx)
603 }
604}
605
606impl Deserializer<'_> {
608 #[cfg_attr(not(feature = "no-inline"), inline)]
609 #[cfg(all(
610 feature = "runtime-detection",
611 any(target_arch = "x86_64", target_arch = "x86"),
612 ))]
613 pub(crate) unsafe fn find_structural_bits(
614 input: &[u8],
615 structural_indexes: &mut Vec<u32>,
616 ) -> std::result::Result<(), ErrorType> {
617 unsafe {
618 use std::sync::atomic::{AtomicPtr, Ordering};
619
620 static FN: AtomicPtr<()> = AtomicPtr::new(get_fastest as FnRaw);
621
622 #[cfg_attr(not(feature = "no-inline"), inline)]
623 fn get_fastest_available_implementation() -> FindStructuralBitsFn {
624 if std::is_x86_feature_detected!("avx2") {
625 Deserializer::_find_structural_bits::<impls::avx2::SimdInput>
626 } else if std::is_x86_feature_detected!("sse4.2") {
627 Deserializer::_find_structural_bits::<impls::sse42::SimdInput>
628 } else {
629 #[cfg(feature = "portable")]
630 let r = Deserializer::_find_structural_bits::<impls::portable::SimdInput>;
631 #[cfg(not(feature = "portable"))]
632 let r = Deserializer::_find_structural_bits::<impls::native::SimdInput>;
633 r
634 }
635 }
636
637 #[cfg_attr(not(feature = "no-inline"), inline)]
638 unsafe fn get_fastest(
639 input: &[u8],
640 structural_indexes: &mut Vec<u32>,
641 ) -> core::result::Result<(), error::ErrorType> {
642 unsafe {
643 let fun = get_fastest_available_implementation();
644 FN.store(fun as FnRaw, Ordering::Relaxed);
645 (fun)(input, structural_indexes)
646 }
647 }
648
649 let fun = FN.load(Ordering::Relaxed);
650 mem::transmute::<FnRaw, FindStructuralBitsFn>(fun)(input, structural_indexes)
651 }
652 }
653
654 #[cfg(not(any(
655 all(
656 feature = "runtime-detection",
657 any(target_arch = "x86_64", target_arch = "x86")
658 ),
659 feature = "portable",
660 target_feature = "avx2",
661 target_feature = "sse4.2",
662 target_feature = "simd128",
663 target_arch = "aarch64",
664 )))]
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 match core::str::from_utf8(input) {
673 Ok(_) => (),
674 Err(_) => return Err(ErrorType::InvalidUtf8),
675 };
676 #[cfg(not(feature = "portable"))]
677 unsafe {
678 Self::_find_structural_bits::<impls::native::SimdInput>(input, structural_indexes)
679 }
680 }
681
682 #[cfg(all(feature = "portable", not(feature = "runtime-detection")))]
683 #[cfg_attr(not(feature = "no-inline"), inline)]
684 pub(crate) unsafe fn find_structural_bits(
685 input: &[u8],
686 structural_indexes: &mut Vec<u32>,
687 ) -> std::result::Result<(), ErrorType> {
688 unsafe {
689 Self::_find_structural_bits::<impls::portable::SimdInput>(input, structural_indexes)
690 }
691 }
692
693 #[cfg(all(
694 target_feature = "avx2",
695 not(feature = "portable"),
696 not(feature = "runtime-detection"),
697 ))]
698 #[cfg_attr(not(feature = "no-inline"), inline)]
699 pub(crate) unsafe fn find_structural_bits(
700 input: &[u8],
701 structural_indexes: &mut Vec<u32>,
702 ) -> std::result::Result<(), ErrorType> {
703 unsafe { Self::_find_structural_bits::<impls::avx2::SimdInput>(input, structural_indexes) }
704 }
705
706 #[cfg(all(
707 target_feature = "sse4.2",
708 not(target_feature = "avx2"),
709 not(feature = "runtime-detection"),
710 not(feature = "portable"),
711 ))]
712 #[cfg_attr(not(feature = "no-inline"), inline)]
713 pub(crate) unsafe fn find_structural_bits(
714 input: &[u8],
715 structural_indexes: &mut Vec<u32>,
716 ) -> std::result::Result<(), ErrorType> {
717 unsafe { Self::_find_structural_bits::<impls::sse42::SimdInput>(input, structural_indexes) }
718 }
719
720 #[cfg(all(target_arch = "aarch64", not(feature = "portable")))]
721 #[cfg_attr(not(feature = "no-inline"), inline)]
722 pub(crate) unsafe fn find_structural_bits(
723 input: &[u8],
724 structural_indexes: &mut Vec<u32>,
725 ) -> std::result::Result<(), ErrorType> {
726 unsafe { Self::_find_structural_bits::<impls::neon::SimdInput>(input, structural_indexes) }
727 }
728
729 #[cfg(all(target_feature = "simd128", not(feature = "portable")))]
730 #[cfg_attr(not(feature = "no-inline"), inline)]
731 pub(crate) unsafe fn find_structural_bits(
732 input: &[u8],
733 structural_indexes: &mut Vec<u32>,
734 ) -> std::result::Result<(), ErrorType> {
735 unsafe {
736 Self::_find_structural_bits::<impls::simd128::SimdInput>(input, structural_indexes)
737 }
738 }
739}
740
741impl<'de> Deserializer<'de> {
742 #[must_use]
744 pub fn into_tape(self) -> Tape<'de> {
745 Tape(self.tape)
746 }
747
748 #[must_use]
750 pub fn as_value(&self) -> Value<'_, 'de> {
751 Value(&self.tape)
753 }
754
755 pub fn restart(&mut self) {
757 self.idx = 0;
759 }
760
761 #[cfg_attr(not(feature = "no-inline"), inline)]
762 fn error(error: ErrorType) -> Error {
763 Error::new(0, None, error)
764 }
765
766 #[cfg_attr(not(feature = "no-inline"), inline)]
767 fn error_c(idx: usize, c: char, error: ErrorType) -> Error {
768 Error::new(idx, Some(c), error)
769 }
770
771 pub fn from_slice(input: &'de mut [u8]) -> Result<Self> {
777 let len = input.len();
778
779 let mut buffer = Buffers::new(len);
780
781 Self::from_slice_with_buffers(input, &mut buffer)
782 }
783
784 #[allow(clippy::uninit_vec)]
792 #[cfg_attr(not(feature = "no-inline"), inline)]
793 fn fill_tape(
794 input: &'de mut [u8],
795 buffer: &mut Buffers,
796 tape: &mut Vec<Node<'de>>,
797 ) -> Result<()> {
798 const LOTS_OF_ZOERS: [u8; SIMDINPUT_LENGTH] = [0; SIMDINPUT_LENGTH];
799 let len = input.len();
800 let simd_safe_len = len + SIMDINPUT_LENGTH;
801
802 if len > u32::MAX as usize {
803 return Err(Self::error(ErrorType::InputTooLarge));
804 }
805
806 buffer.string_buffer.clear();
807 buffer.string_buffer.reserve(len + SIMDJSON_PADDING);
808
809 unsafe {
810 buffer.string_buffer.set_len(len + SIMDJSON_PADDING);
811 };
812
813 let input_buffer = &mut buffer.input_buffer;
814 if input_buffer.capacity() < simd_safe_len {
815 *input_buffer = AlignedBuf::with_capacity(simd_safe_len);
816 }
817
818 unsafe {
819 input_buffer
820 .as_mut_ptr()
821 .copy_from_nonoverlapping(input.as_ptr(), len);
822
823 input_buffer
826 .as_mut_ptr()
827 .add(len)
828 .copy_from_nonoverlapping(LOTS_OF_ZOERS.as_ptr(), SIMDINPUT_LENGTH);
829
830 input_buffer.set_len(simd_safe_len);
832
833 Self::find_structural_bits(input, &mut buffer.structural_indexes)
834 .map_err(Error::generic)?;
835 };
836
837 Self::build_tape(
838 input,
839 input_buffer,
840 &mut buffer.string_buffer,
841 &buffer.structural_indexes,
842 &mut buffer.stage2_stack,
843 tape,
844 )
845 }
846
847 pub fn from_slice_with_buffers(input: &'de mut [u8], buffer: &mut Buffers) -> Result<Self> {
854 let mut tape: Vec<Node<'de>> = Vec::with_capacity(buffer.structural_indexes.len());
855
856 Self::fill_tape(input, buffer, &mut tape)?;
857
858 Ok(Self { tape, idx: 0 })
859 }
860
861 #[cfg(feature = "serde_impl")]
862 #[cfg_attr(not(feature = "no-inline"), inline)]
863 fn skip(&mut self) {
864 self.idx += 1;
865 }
866
867 #[cfg_attr(not(feature = "no-inline"), inline)]
875 pub unsafe fn next_(&mut self) -> Node<'de> {
876 let r = *unsafe { self.tape.get_kinda_unchecked(self.idx) };
877 self.idx += 1;
878 r
879 }
880
881 #[cfg_attr(not(feature = "no-inline"), inline)]
882 #[allow(clippy::cast_possible_truncation)]
883 pub(crate) unsafe fn _find_structural_bits<S: Stage1Parse>(
884 input: &[u8],
885 structural_indexes: &mut Vec<u32>,
886 ) -> std::result::Result<(), ErrorType> {
887 let len = input.len();
888 structural_indexes.clear();
891 structural_indexes.reserve(len / 8);
892
893 let mut utf8_validator = unsafe { S::Utf8Validator::new() };
894
895 let mut prev_iter_ends_odd_backslash: u64 = 0;
902 let mut prev_iter_inside_quote: u64 = 0;
904 let mut prev_iter_ends_pseudo_pred: u64 = 1;
911
912 let mut structurals: u64 = 0;
918
919 let lenminus64: usize = if len < 64 { 0 } else { len - 64 };
920 let mut idx: usize = 0;
921 let mut error_mask: u64 = 0; while idx < lenminus64 {
924 let chunk = unsafe { input.get_kinda_unchecked(idx..idx + 64) };
930 unsafe { utf8_validator.update_from_chunks(chunk) };
931
932 let input = unsafe { S::new(chunk) };
933 let odd_ends: u64 =
935 input.find_odd_backslash_sequences(&mut prev_iter_ends_odd_backslash);
936
937 let mut quote_bits: u64 = 0;
940 let quote_mask: u64 = input.find_quote_mask_and_bits(
941 odd_ends,
942 &mut prev_iter_inside_quote,
943 &mut quote_bits,
944 &mut error_mask,
945 );
946
947 unsafe { S::flatten_bits(structural_indexes, idx as u32, structurals) };
950
951 let mut whitespace: u64 = 0;
952 unsafe { input.find_whitespace_and_structurals(&mut whitespace, &mut structurals) };
953
954 structurals = S::finalize_structurals(
956 structurals,
957 whitespace,
958 quote_mask,
959 quote_bits,
960 &mut prev_iter_ends_pseudo_pred,
961 );
962 idx += SIMDINPUT_LENGTH;
963 }
964
965 if idx < len {
969 let mut tmpbuf: [u8; SIMDINPUT_LENGTH] = [0x20; SIMDINPUT_LENGTH];
970 unsafe {
971 tmpbuf
972 .as_mut_ptr()
973 .copy_from(input.as_ptr().add(idx), len - idx);
974 };
975 unsafe { utf8_validator.update_from_chunks(&tmpbuf) };
976
977 let input = unsafe { S::new(&tmpbuf) };
978
979 let odd_ends: u64 =
981 input.find_odd_backslash_sequences(&mut prev_iter_ends_odd_backslash);
982
983 let mut quote_bits: u64 = 0;
986 let quote_mask: u64 = input.find_quote_mask_and_bits(
987 odd_ends,
988 &mut prev_iter_inside_quote,
989 &mut quote_bits,
990 &mut error_mask,
991 );
992
993 unsafe { S::flatten_bits(structural_indexes, idx as u32, structurals) };
996
997 let mut whitespace: u64 = 0;
998 unsafe { input.find_whitespace_and_structurals(&mut whitespace, &mut structurals) };
999
1000 structurals = S::finalize_structurals(
1002 structurals,
1003 whitespace,
1004 quote_mask,
1005 quote_bits,
1006 &mut prev_iter_ends_pseudo_pred,
1007 );
1008 idx += SIMDINPUT_LENGTH;
1009 }
1010 if prev_iter_inside_quote != 0 {
1012 return Err(ErrorType::Syntax);
1013 }
1014 unsafe { S::flatten_bits(structural_indexes, idx as u32, structurals) };
1016
1017 if structural_indexes.is_empty() {
1020 return Err(ErrorType::Eof);
1021 }
1022
1023 if error_mask != 0 {
1024 return Err(ErrorType::Syntax);
1025 }
1026
1027 if unsafe { utf8_validator.finalize(None).is_err() } {
1028 Err(ErrorType::InvalidUtf8)
1029 } else {
1030 Ok(())
1031 }
1032 }
1033}
1034
1035struct AlignedBuf {
1037 layout: Layout,
1038 capacity: usize,
1039 len: usize,
1040 inner: NonNull<u8>,
1041}
1042unsafe impl Send for AlignedBuf {}
1049unsafe impl Sync for AlignedBuf {}
1050impl AlignedBuf {
1051 #[must_use]
1053 pub fn with_capacity(capacity: usize) -> Self {
1054 let Ok(layout) = Layout::from_size_align(capacity, SIMDJSON_PADDING) else {
1055 Self::capacity_overflow()
1056 };
1057 if mem::size_of::<usize>() < 8 && capacity > isize::MAX as usize {
1058 Self::capacity_overflow()
1059 }
1060 unsafe {
1061 let Some(inner) = NonNull::new(alloc(layout)) else {
1062 handle_alloc_error(layout)
1063 };
1064 Self {
1065 layout,
1066 capacity,
1067 len: 0,
1068 inner,
1069 }
1070 }
1071 }
1072
1073 fn as_mut_ptr(&mut self) -> *mut u8 {
1074 self.inner.as_ptr()
1075 }
1076
1077 fn capacity_overflow() -> ! {
1078 panic!("capacity overflow");
1079 }
1080 fn capacity(&self) -> usize {
1081 self.capacity
1082 }
1083 unsafe fn set_len(&mut self, n: usize) {
1084 assert!(
1085 n <= self.capacity,
1086 "New size ({}) can not be larger then capacity ({}).",
1087 n,
1088 self.capacity
1089 );
1090 self.len = n;
1091 }
1092}
1093impl Drop for AlignedBuf {
1094 fn drop(&mut self) {
1095 unsafe {
1096 dealloc(self.inner.as_ptr(), self.layout);
1097 }
1098 }
1099}
1100
1101impl Deref for AlignedBuf {
1102 type Target = [u8];
1103
1104 fn deref(&self) -> &Self::Target {
1105 unsafe { std::slice::from_raw_parts(self.inner.as_ptr(), self.len) }
1106 }
1107}
1108
1109impl DerefMut for AlignedBuf {
1110 fn deref_mut(&mut self) -> &mut Self::Target {
1111 unsafe { std::slice::from_raw_parts_mut(self.inner.as_ptr(), self.len) }
1112 }
1113}