Skip to content
Draft
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
14 changes: 11 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,26 @@ rust-version = "1.88"
[dependencies]
simdutf8 = { version = "0.1.4", features = ["public_imp", "aarch64_neon"] }

# no_std necessary crates
core_detect = "1.0.0"
hashbrown = "0.17.1"

value-trait = { version = "0.12" }
beef = { version = "0.5", optional = true }
halfbrown = "0.4"
# ahash known key
ahash = { version = "0.8", optional = true }

# serde compatibilty
serde = { version = "1", features = ["derive"], optional = true }
serde_json = { version = "1", optional = true }
serde_core = { version = "1.0.229", optional = true }
serde_json = { version = "1.0.151", optional = true }

# perf testing
alloc_counter = { version = "0.0.4", optional = true }
colored = { version = "3.0", optional = true }
getopts = { version = "0.2", optional = true }
jemallocator = { version = "0.5", optional = true }
serde = { version = "1.0.229", features = ["derive"] }

[target.'cfg(target_arch = "x86_64")'.dependencies]
perfcnt = { version = "0.8", optional = true }
Expand Down Expand Up @@ -59,6 +64,9 @@ harness = false
[features]
default = ["swar-number-parsing", "serde_impl", "runtime-detection"]


io = []

arraybackend = ["halfbrown/arraybackend"]

# Forces the `owned::Value` and `borrowed::Value` to deduplicate duplicated keys by letting consecutive keys overwrite previous ones. This comes at a
Expand All @@ -82,7 +90,7 @@ swar-number-parsing = []
approx-number-parsing = []

# serde compatibility
serde_impl = ["serde", "serde_json", "halfbrown/serde"]
serde_impl = ["serde_core", "serde_json", "halfbrown/serde"]

# for testing allocations
alloc = ["alloc_counter"]
Expand Down
2 changes: 1 addition & 1 deletion src/cow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//!
//! [beef]: https://docs.rs/beef/latest/beef/lean/type.Cow.html
#[cfg(not(feature = "beef"))]
pub use std::borrow::Cow;
pub use alloc::borrow::Cow;

#[cfg(feature = "beef")]
pub use beef::lean::Cow;
24 changes: 13 additions & 11 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::fmt;
use alloc::string::String;
use core::fmt;

use value_trait::ValueType;

Expand Down Expand Up @@ -91,16 +92,16 @@ pub enum ErrorType {
/// No SIMD support detected during runtime
SimdUnsupported,
/// IO error
Io(std::io::Error),
Io(core::fmt::Error),
}

#[derive(Clone, Debug, PartialEq)]
pub enum InternalError {
TapeError,
}

impl From<std::io::Error> for Error {
fn from(e: std::io::Error) -> Self {
impl From<core::fmt::Error> for Error {
fn from(e: core::fmt::Error) -> Self {
Self::generic(ErrorType::Io(e))
}
}
Expand Down Expand Up @@ -273,7 +274,7 @@ impl Error {
)
}
}
impl std::error::Error for Error {}
impl core::error::Error for Error {}

#[cfg(not(tarpaulin_include))]
impl fmt::Display for Error {
Expand All @@ -286,9 +287,10 @@ impl fmt::Display for Error {
}
}

#[cfg(not(tarpaulin_include))]
impl From<Error> for std::io::Error {
fn from(e: Error) -> Self {
std::io::Error::new(std::io::ErrorKind::InvalidData, e)
}
}
// TODO
// #[cfg(not(tarpaulin_include))]
// impl From<Error> for std::io::Error {
// fn from(e: Error) -> Self {
// std::io::Error::new(std::io::ErrorKind::InvalidData, e)
// }
// }
16 changes: 5 additions & 11 deletions src/impls/avx2/deser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,14 @@
use std::arch::x86 as arch;

#[cfg(target_arch = "x86_64")]
use std::arch::x86_64 as arch;
use core::arch::x86_64 as arch;

use arch::{
__m256i, _mm256_cmpeq_epi8, _mm256_loadu_si256, _mm256_movemask_epi8, _mm256_set1_epi8,
_mm256_storeu_si256,
};

use crate::{
Deserializer, Result, SillyWrapper,
error::ErrorType,
macros::static_cast_u32,
safer_unchecked::GetSaferUnchecked,
stringparse::{ESCAPE_MAP, handle_unicode_codepoint},
};
use crate::{error::ErrorType, macros::static_cast_u32, safer_unchecked::GetSaferUnchecked, stringparse::{ESCAPE_MAP, handle_unicode_codepoint}, Deserializer, SillyWrapper, SJsonResult};

#[target_feature(enable = "avx2")]
#[allow(
Expand All @@ -29,7 +23,7 @@ pub(crate) unsafe fn parse_str<'invoke, 'de>(
data: &'invoke [u8],
buffer: &'invoke mut [u8],
mut idx: usize,
) -> Result<&'de str> {
) -> SJsonResult<&'de str> {
unsafe {
use ErrorType::{InvalidEscape, InvalidUnicodeCodepoint};

Expand Down Expand Up @@ -73,7 +67,7 @@ pub(crate) unsafe fn parse_str<'invoke, 'de>(

len += quote_dist as usize;
let v =
std::str::from_utf8_unchecked(std::slice::from_raw_parts(input.add(idx), len));
core::str::from_utf8_unchecked(core::slice::from_raw_parts(input.add(idx), len));
return Ok(v);

// we compare the pointers since we care if they are 'at the same spot'
Expand Down Expand Up @@ -130,7 +124,7 @@ pub(crate) unsafe fn parse_str<'invoke, 'de>(
input
.add(idx + len)
.copy_from_nonoverlapping(buffer.as_ptr(), dst_i);
let v = std::str::from_utf8_unchecked(std::slice::from_raw_parts(
let v = core::str::from_utf8_unchecked(core::slice::from_raw_parts(
input.add(idx),
len + dst_i,
));
Expand Down
8 changes: 5 additions & 3 deletions src/impls/avx2/stage1.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
#![allow(dead_code)]

use alloc::vec::Vec;
use crate::{
Stage1Parse,
macros::{static_cast_i32, static_cast_i64, static_cast_u32},
};
#[cfg(target_arch = "x86")]
use std::arch::x86 as arch;
use core::arch::x86 as arch;

#[cfg(target_arch = "x86_64")]
use std::arch::x86_64 as arch;
use core::arch::x86_64 as arch;

use arch::{
__m256i, _mm_clmulepi64_si128, _mm_set_epi64x, _mm_set1_epi8, _mm256_add_epi32,
Expand Down Expand Up @@ -62,7 +64,7 @@ impl Stage1Parse for SimdInput {
#[cfg(target_arch = "x86_64")]
unsafe fn compute_quote_mask(quote_bits: u64) -> u64 {
unsafe {
std::arch::x86_64::_mm_cvtsi128_si64(_mm_clmulepi64_si128(
core::arch::x86_64::_mm_cvtsi128_si64(_mm_clmulepi64_si128(
_mm_set_epi64x(0, static_cast_i64!(quote_bits)),
_mm_set1_epi8(-1_i8 /* 0xFF */),
0,
Expand Down
18 changes: 10 additions & 8 deletions src/impls/native/deser.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
Deserializer, ErrorType, Result, SillyWrapper,
Deserializer, ErrorType, SJsonResult, SillyWrapper,
safer_unchecked::GetSaferUnchecked,
stringparse::{ESCAPE_MAP, get_unicode_codepoint},
};
Expand All @@ -10,7 +10,7 @@ pub(crate) unsafe fn parse_str<'invoke, 'de>(
data: &'invoke [u8],
_buffer: &'invoke mut [u8],
idx: usize,
) -> Result<&'de str> {
) -> SJsonResult<&'de str> {
use ErrorType::{InvalidEscape, InvalidUnicodeCodepoint};

let input = input.input;
Expand All @@ -27,7 +27,7 @@ pub(crate) unsafe fn parse_str<'invoke, 'de>(
b = unsafe { *src.get_kinda_unchecked(src_i) };
}
if b == b'"' {
let v = unsafe { std::str::from_utf8_unchecked(std::slice::from_raw_parts(input, src_i)) };
let v = unsafe { core::str::from_utf8_unchecked(core::slice::from_raw_parts(input, src_i)) };
return Ok(v);
}

Expand Down Expand Up @@ -104,17 +104,19 @@ pub(crate) unsafe fn parse_str<'invoke, 'de>(
b = unsafe { *src.get_kinda_unchecked(src_i) };
}
unsafe {
Ok(std::str::from_utf8_unchecked(std::slice::from_raw_parts(
Ok(core::str::from_utf8_unchecked(core::slice::from_raw_parts(
input, dst_i,
)))
}
}

#[cfg(test)]
mod test {
use alloc::string::String;
use alloc::vec;
use crate::SIMDJSON_PADDING;

fn deser_str(input: &[u8]) -> Result<String> {
fn deser_str(input: &[u8]) -> SJsonResult<String> {
let mut input = input.to_vec();
let mut input2 = input.clone();
input2.append(vec![0; SIMDJSON_PADDING * 2].as_mut());
Expand All @@ -127,21 +129,21 @@ mod test {
}
use super::*;
#[test]
fn easy_string() -> Result<()> {
fn easy_string() -> SJsonResult<()> {
let s = deser_str(&br#""snot""#[..])?;
assert_eq!("snot", s);
Ok(())
}

#[test]
fn string_with_quote() -> Result<()> {
fn string_with_quote() -> SJsonResult<()> {
let s = deser_str(&br#""snot says:\n \"badger\"""#[..])?;
assert_eq!("snot says:\n \"badger\"", s);
Ok(())
}

#[test]
fn string_with_utf8() -> Result<()> {
fn string_with_utf8() -> SJsonResult<()> {
let s = deser_str(&br#""\u000e""#[..])?;
assert_eq!("\u{e}", s);
Ok(())
Expand Down
3 changes: 2 additions & 1 deletion src/impls/native/stage1.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![allow(clippy::cast_lossless, clippy::cast_sign_loss)]

use alloc::vec::Vec;
use crate::{Stage1Parse, macros::static_cast_i32};

type V128 = [u8; 16];
Expand Down Expand Up @@ -461,7 +462,7 @@ impl Stage1Parse for SimdInput {
idx_64_v[2] + v2,
idx_64_v[3] + v3,
];
unsafe { std::ptr::write_unaligned(base.as_mut_ptr().add(l).cast::<[i32; 4]>(), v) };
unsafe { core::ptr::write_unaligned(base.as_mut_ptr().add(l).cast::<[i32; 4]>(), v) };
l += 4;
}
// We have written all the data
Expand Down
12 changes: 6 additions & 6 deletions src/impls/sse42/deser.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#[cfg(target_arch = "x86")]
use std::arch::x86 as arch;
use core::arch::x86 as arch;

#[cfg(target_arch = "x86_64")]
use std::arch::x86_64 as arch;
use core::arch::x86_64 as arch;

use crate::{
Deserializer, Result, SillyWrapper,
Deserializer, SJsonResult, SillyWrapper,
error::ErrorType,
safer_unchecked::GetSaferUnchecked,
stringparse::{ESCAPE_MAP, handle_unicode_codepoint},
Expand All @@ -22,7 +22,7 @@ pub(crate) unsafe fn parse_str<'invoke, 'de>(
data: &'invoke [u8],
buffer: &'invoke mut [u8],
mut idx: usize,
) -> Result<&'de str> {
) -> SJsonResult<&'de str> {
unsafe {
use ErrorType::{InvalidEscape, InvalidUnicodeCodepoint};
let input = input.input;
Expand Down Expand Up @@ -64,7 +64,7 @@ pub(crate) unsafe fn parse_str<'invoke, 'de>(

len += quote_dist as usize;
let v =
std::str::from_utf8_unchecked(std::slice::from_raw_parts(input.add(idx), len));
core::str::from_utf8_unchecked(core::slice::from_raw_parts(input.add(idx), len));
return Ok(v);

// we compare the pointers since we care if they are 'at the same spot'
Expand Down Expand Up @@ -121,7 +121,7 @@ pub(crate) unsafe fn parse_str<'invoke, 'de>(
input
.add(idx + len)
.copy_from_nonoverlapping(buffer.as_ptr(), dst_i);
let v = std::str::from_utf8_unchecked(std::slice::from_raw_parts(
let v = core::str::from_utf8_unchecked(core::slice::from_raw_parts(
input.add(idx),
len + dst_i,
));
Expand Down
4 changes: 3 additions & 1 deletion src/impls/sse42/stage1.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use alloc::vec::Vec;

use crate::{
Stage1Parse,
macros::{static_cast_i32, static_cast_i64, static_cast_u32},
Expand All @@ -6,7 +8,7 @@ use crate::{
use std::arch::x86 as arch;

#[cfg(target_arch = "x86_64")]
use std::arch::x86_64 as arch;
use core::arch::x86_64 as arch;

#[cfg(target_arch = "x86")]
use arch::{
Expand Down
Loading