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