Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 16 additions & 11 deletions src/charutils.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::mem::MaybeUninit;

use crate::safer_unchecked::GetSaferUnchecked;

const STRUCTURAL_OR_WHITESPACE_NEGATED: [u32; 256] = [
Expand Down Expand Up @@ -83,30 +85,33 @@ pub fn hex_to_u32_nocheck(src: &[u8]) -> u32 {
//
#[cfg_attr(not(feature = "no-inline"), inline)]
#[allow(clippy::cast_possible_truncation)]
pub fn codepoint_to_utf8(cp: u32, c: &mut [u8]) -> usize {
pub fn codepoint_to_utf8(cp: u32, c: &mut [MaybeUninit<u8>]) -> usize {
unsafe {
if cp <= 0x7F {
*c.get_kinda_unchecked_mut(0) = cp as u8;
c.get_kinda_unchecked_mut(0).write(cp as u8);
1 // ascii
} else if cp <= 0x7FF {
*c.get_kinda_unchecked_mut(0) = ((cp >> 6) + 192) as u8;
*c.get_kinda_unchecked_mut(1) = ((cp & 63) + 128) as u8;
c.get_kinda_unchecked_mut(0).write(((cp >> 6) + 192) as u8);
c.get_kinda_unchecked_mut(1).write(((cp & 63) + 128) as u8);
2
// universal plane
// Surrogates are treated elsewhere...
//} //else if (0xd800 <= cp && cp <= 0xdfff) {
// return 0; // surrogates // could put assert here
} else if cp <= 0xFFFF {
*c.get_kinda_unchecked_mut(0) = ((cp >> 12) + 224) as u8;
*c.get_kinda_unchecked_mut(1) = (((cp >> 6) & 63) + 128) as u8;
*c.get_kinda_unchecked_mut(2) = ((cp & 63) + 128) as u8;
c.get_kinda_unchecked_mut(0).write(((cp >> 12) + 224) as u8);
c.get_kinda_unchecked_mut(1)
.write((((cp >> 6) & 63) + 128) as u8);
c.get_kinda_unchecked_mut(2).write(((cp & 63) + 128) as u8);
3
} else if cp <= 0x0010_FFFF {
// if you know you have a valid code point, this is not needed
*c.get_kinda_unchecked_mut(0) = ((cp >> 18) + 240) as u8;
*c.get_kinda_unchecked_mut(1) = (((cp >> 12) & 63) + 128) as u8;
*c.get_kinda_unchecked_mut(2) = (((cp >> 6) & 63) + 128) as u8;
*c.get_kinda_unchecked_mut(3) = ((cp & 63) + 128) as u8;
c.get_kinda_unchecked_mut(0).write(((cp >> 18) + 240) as u8);
c.get_kinda_unchecked_mut(1)
.write((((cp >> 12) & 63) + 128) as u8);
c.get_kinda_unchecked_mut(2)
.write((((cp >> 6) & 63) + 128) as u8);
c.get_kinda_unchecked_mut(3).write(((cp & 63) + 128) as u8);
4
} else {
// will return 0 when the code point was too large.
Expand Down
10 changes: 7 additions & 3 deletions src/impls/avx2/deser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use std::arch::x86 as arch;
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64 as arch;

use std::mem::MaybeUninit;

use arch::{
__m256i, _mm256_cmpeq_epi8, _mm256_loadu_si256, _mm256_movemask_epi8, _mm256_set1_epi8,
_mm256_storeu_si256,
Expand All @@ -27,7 +29,7 @@ use crate::{
pub(crate) unsafe fn parse_str<'invoke, 'de>(
input: SillyWrapper<'de>,
data: &'invoke [u8],
buffer: &'invoke mut [u8],
buffer: &'invoke mut [MaybeUninit<u8>],
mut idx: usize,
) -> Result<&'de str> {
unsafe {
Expand Down Expand Up @@ -129,7 +131,7 @@ pub(crate) unsafe fn parse_str<'invoke, 'de>(
dst_i += quote_dist as usize;
input
.add(idx + len)
.copy_from_nonoverlapping(buffer.as_ptr(), dst_i);
.copy_from_nonoverlapping(buffer.as_ptr().cast::<u8>(), dst_i);
let v = std::str::from_utf8_unchecked(std::slice::from_raw_parts(
input.add(idx),
len + dst_i,
Expand Down Expand Up @@ -174,7 +176,9 @@ pub(crate) unsafe fn parse_str<'invoke, 'de>(
InvalidEscape,
));
}
*buffer.get_kinda_unchecked_mut(dst_i + bs_dist as usize) = escape_result;
buffer
.get_kinda_unchecked_mut(dst_i + bs_dist as usize)
.write(escape_result);
src_i += bs_dist as usize + 2;
dst_i += bs_dist as usize + 1;
}
Expand Down
13 changes: 10 additions & 3 deletions src/impls/native/deser.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::mem::MaybeUninit;

use crate::{
Deserializer, ErrorType, Result, SillyWrapper,
safer_unchecked::GetSaferUnchecked,
Expand All @@ -8,7 +10,7 @@ use crate::{
pub(crate) unsafe fn parse_str<'invoke, 'de>(
input: SillyWrapper<'de>,
data: &'invoke [u8],
_buffer: &'invoke mut [u8],
_buffer: &'invoke mut [MaybeUninit<u8>],
idx: usize,
) -> Result<&'de str> {
use ErrorType::{InvalidEscape, InvalidUnicodeCodepoint};
Expand Down Expand Up @@ -118,10 +120,15 @@ mod test {
let mut input = input.to_vec();
let mut input2 = input.clone();
input2.append(vec![0; SIMDJSON_PADDING * 2].as_mut());
let mut buffer = vec![0; 1024];
let mut buffer = Vec::with_capacity(1024);

let r = unsafe {
super::parse_str(input.as_mut_ptr().into(), &input2, buffer.as_mut_slice(), 0)?
super::parse_str(
input.as_mut_ptr().into(),
&input2,
buffer.spare_capacity_mut(),
0,
)?
};
Ok(String::from(r))
}
Expand Down
14 changes: 10 additions & 4 deletions src/impls/neon/deser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use std::arch::aarch64::{
uint8x16_t, vandq_u8, vceqq_u8, vgetq_lane_u32, vld1q_u8, vmovq_n_u8, vpaddq_u8,
vreinterpretq_u32_u8,
};
use std::mem::MaybeUninit;

#[cfg_attr(not(feature = "no-inline"), inline)]
fn find_bs_bits_and_quote_bits(v0: uint8x16_t, v1: uint8x16_t) -> (u32, u32) {
Expand Down Expand Up @@ -45,7 +46,7 @@ fn find_bs_bits_and_quote_bits(v0: uint8x16_t, v1: uint8x16_t) -> (u32, u32) {
pub(crate) fn parse_str<'invoke, 'de>(
input: SillyWrapper<'de>,
data: &'invoke [u8],
buffer: &'invoke mut [u8],
buffer: &'invoke mut [MaybeUninit<u8>],
mut idx: usize,
) -> Result<&'de str> {
use ErrorType::{InvalidEscape, InvalidUnicodeCodepoint};
Expand Down Expand Up @@ -121,9 +122,12 @@ pub(crate) fn parse_str<'invoke, 'de>(
};

unsafe {
// TODO: this should use `write_copy_of_slice` on Rust 1.93+
buffer
.get_kinda_unchecked_mut(dst_i..dst_i + 32)
.copy_from_slice(src.get_kinda_unchecked(src_i..src_i + 32));
.as_mut_ptr()
.cast::<u8>()
.copy_from_nonoverlapping(src.get_kinda_unchecked(src_i..src_i + 32).as_ptr(), 32);
}

// store to dest unconditionally - we can overwrite the bits we don't like
Expand All @@ -147,7 +151,7 @@ pub(crate) fn parse_str<'invoke, 'de>(
unsafe {
input
.add(idx + len)
.copy_from_nonoverlapping(buffer.as_ptr(), dst_i);
.copy_from_nonoverlapping(buffer.as_ptr().cast::<u8>(), dst_i);
let v = std::str::from_utf8_unchecked(std::slice::from_raw_parts(
input.add(idx),
len + dst_i,
Expand Down Expand Up @@ -196,7 +200,9 @@ pub(crate) fn parse_str<'invoke, 'de>(
));
}
unsafe {
*buffer.get_kinda_unchecked_mut(dst_i + bs_dist as usize) = escape_result;
buffer
.get_kinda_unchecked_mut(dst_i + bs_dist as usize)
.write(escape_result);
}
src_i += bs_dist as usize + 2;
dst_i += bs_dist as usize + 1;
Expand Down
9 changes: 6 additions & 3 deletions src/impls/portable/deser.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::mem::MaybeUninit;
use std::simd::{SimdPartialEq, ToBitMask, u8x32};

use crate::{
Expand All @@ -10,7 +11,7 @@ use crate::{
pub(crate) unsafe fn parse_str<'invoke, 'de>(
input: SillyWrapper<'de>,
data: &'invoke [u8],
buffer: &'invoke mut [u8],
buffer: &'invoke mut [MaybeUninit<u8>],
mut idx: usize,
) -> Result<&'de str> {
let input = input.input;
Expand Down Expand Up @@ -102,7 +103,7 @@ pub(crate) unsafe fn parse_str<'invoke, 'de>(
dst_i += quote_dist as usize;
input
.add(idx + len)
.copy_from_nonoverlapping(buffer.as_ptr(), dst_i);
.copy_from_nonoverlapping(buffer.as_ptr().cast::<u8>(), dst_i);
let v = std::str::from_utf8_unchecked(std::slice::from_raw_parts(
input.add(idx),
len + dst_i,
Expand Down Expand Up @@ -152,7 +153,9 @@ pub(crate) unsafe fn parse_str<'invoke, 'de>(
InvalidEscape,
));
}
*buffer.get_kinda_unchecked_mut(dst_i + bs_dist as usize) = escape_result;
buffer
.get_kinda_unchecked_mut(dst_i + bs_dist as usize)
.write(escape_result);
src_i += bs_dist as usize + 2;
dst_i += bs_dist as usize + 1;
}
Expand Down
9 changes: 6 additions & 3 deletions src/impls/simd128/deser.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::arch::wasm32::{u8x16_bitmask, u8x16_eq, u8x16_splat, v128, v128_load, v128_store};
use std::mem::MaybeUninit;

use crate::{
Deserializer, Result, SillyWrapper,
Expand All @@ -17,7 +18,7 @@ use crate::{
pub(crate) fn parse_str<'invoke, 'de>(
input: SillyWrapper<'de>,
data: &'invoke [u8],
buffer: &'invoke mut [u8],
buffer: &'invoke mut [MaybeUninit<u8>],
mut idx: usize,
) -> Result<&'de str> {
use ErrorType::{InvalidEscape, InvalidUnicodeCodepoint};
Expand Down Expand Up @@ -115,7 +116,7 @@ pub(crate) fn parse_str<'invoke, 'de>(
unsafe {
input
.add(idx + len)
.copy_from_nonoverlapping(buffer.as_ptr(), dst_i);
.copy_from_nonoverlapping(buffer.as_ptr().cast::<u8>(), dst_i);
let v = std::str::from_utf8_unchecked(std::slice::from_raw_parts(
input.add(idx),
len + dst_i,
Expand Down Expand Up @@ -164,7 +165,9 @@ pub(crate) fn parse_str<'invoke, 'de>(
));
}
unsafe {
*buffer.get_kinda_unchecked_mut(dst_i + bs_dist as usize) = escape_result;
buffer
.get_kinda_unchecked_mut(dst_i + bs_dist as usize)
.write(escape_result);
}
src_i += bs_dist as usize + 2;
dst_i += bs_dist as usize + 1;
Expand Down
10 changes: 7 additions & 3 deletions src/impls/sse42/deser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use std::arch::x86 as arch;
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64 as arch;

use std::mem::MaybeUninit;

use crate::{
Deserializer, Result, SillyWrapper,
error::ErrorType,
Expand All @@ -20,7 +22,7 @@ use arch::{
pub(crate) unsafe fn parse_str<'invoke, 'de>(
input: SillyWrapper<'de>,
data: &'invoke [u8],
buffer: &'invoke mut [u8],
buffer: &'invoke mut [MaybeUninit<u8>],
mut idx: usize,
) -> Result<&'de str> {
unsafe {
Expand Down Expand Up @@ -120,7 +122,7 @@ pub(crate) unsafe fn parse_str<'invoke, 'de>(
dst_i += quote_dist as usize;
input
.add(idx + len)
.copy_from_nonoverlapping(buffer.as_ptr(), dst_i);
.copy_from_nonoverlapping(buffer.as_ptr().cast::<u8>(), dst_i);
let v = std::str::from_utf8_unchecked(std::slice::from_raw_parts(
input.add(idx),
len + dst_i,
Expand Down Expand Up @@ -165,7 +167,9 @@ pub(crate) unsafe fn parse_str<'invoke, 'de>(
InvalidEscape,
));
}
*buffer.get_kinda_unchecked_mut(dst_i + bs_dist as usize) = escape_result;
buffer
.get_kinda_unchecked_mut(dst_i + bs_dist as usize)
.write(escape_result);
src_i += bs_dist as usize + 2;
dst_i += bs_dist as usize + 1;
}
Expand Down
23 changes: 10 additions & 13 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ mod stage2;
/// simd-json JSON-DOM value
pub mod value;

use std::mem::MaybeUninit;
use std::{alloc::dealloc, mem};
pub use value_trait::StaticNode;

Expand Down Expand Up @@ -357,7 +358,7 @@ type FnRaw = *mut ();
type ParseStrFn = for<'invoke, 'de> unsafe fn(
SillyWrapper<'de>,
&'invoke [u8],
&'invoke mut [u8],
&'invoke mut [MaybeUninit<u8>],
usize,
) -> std::result::Result<&'de str, error::Error>;
#[cfg(all(
Expand Down Expand Up @@ -514,7 +515,7 @@ impl<'de> Deserializer<'de> {
pub(crate) unsafe fn parse_str_<'invoke>(
input: *mut u8,
data: &'invoke [u8],
buffer: &'invoke mut [u8],
buffer: &'invoke mut [MaybeUninit<u8>],
idx: usize,
) -> Result<&'de str>
where
Expand All @@ -538,7 +539,7 @@ impl<'de> Deserializer<'de> {
pub(crate) unsafe fn parse_str_<'invoke>(
input: *mut u8,
data: &'invoke [u8],
buffer: &'invoke mut [u8],
buffer: &'invoke mut [MaybeUninit<u8>],
idx: usize,
) -> Result<&'de str>
where
Expand All @@ -552,7 +553,7 @@ impl<'de> Deserializer<'de> {
pub(crate) unsafe fn parse_str_<'invoke>(
input: *mut u8,
data: &'invoke [u8],
buffer: &'invoke mut [u8],
buffer: &'invoke mut [MaybeUninit<u8>],
idx: usize,
) -> Result<&'de str>
where
Expand All @@ -571,7 +572,7 @@ impl<'de> Deserializer<'de> {
pub(crate) unsafe fn parse_str_<'invoke>(
input: *mut u8,
data: &'invoke [u8],
buffer: &'invoke mut [u8],
buffer: &'invoke mut [MaybeUninit<u8>],
idx: usize,
) -> Result<&'de str> {
let input: SillyWrapper<'de> = SillyWrapper::from(input);
Expand All @@ -588,7 +589,7 @@ impl<'de> Deserializer<'de> {
pub(crate) unsafe fn parse_str_<'invoke>(
input: *mut u8,
data: &'invoke [u8],
buffer: &'invoke mut [u8],
buffer: &'invoke mut [MaybeUninit<u8>],
idx: usize,
) -> Result<&'de str> {
let input: SillyWrapper<'de> = SillyWrapper::from(input);
Expand All @@ -600,7 +601,7 @@ impl<'de> Deserializer<'de> {
pub(crate) unsafe fn parse_str_<'invoke>(
input: *mut u8,
data: &'invoke [u8],
buffer: &'invoke mut [u8],
buffer: &'invoke mut [MaybeUninit<u8>],
idx: usize,
) -> Result<&'de str> {
let input: SillyWrapper = SillyWrapper::from(input);
Expand All @@ -611,7 +612,7 @@ impl<'de> Deserializer<'de> {
pub(crate) unsafe fn parse_str_<'invoke>(
input: *mut u8,
data: &'invoke [u8],
buffer: &'invoke mut [u8],
buffer: &'invoke mut [MaybeUninit<u8>],
idx: usize,
) -> Result<&'de str> {
let input: SillyWrapper<'de> = SillyWrapper::from(input);
Expand Down Expand Up @@ -876,10 +877,6 @@ impl<'de> Deserializer<'de> {
buffer.string_buffer.clear();
buffer.string_buffer.reserve(len + SIMDJSON_PADDING);

unsafe {
buffer.string_buffer.set_len(len + SIMDJSON_PADDING);
};

let input_buffer = &mut buffer.input_buffer;
if input_buffer.capacity() < simd_safe_len {
*input_buffer = AlignedBuf::with_capacity(simd_safe_len);
Expand Down Expand Up @@ -907,7 +904,7 @@ impl<'de> Deserializer<'de> {
Self::build_tape(
input,
input_buffer,
&mut buffer.string_buffer,
buffer.string_buffer.spare_capacity_mut(),
&buffer.structural_indexes,
&mut buffer.stage2_stack,
buffer.max_depth,
Expand Down
Loading