diff --git a/.github/workflows/quality.yaml b/.github/workflows/quality.yaml index 75cf2178..0fa0e0dc 100644 --- a/.github/workflows/quality.yaml +++ b/.github/workflows/quality.yaml @@ -6,7 +6,6 @@ on: branches: - main - jobs: clippy_check: strategy: @@ -19,48 +18,48 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@1.72 # do clippy chekcs with the minimum supported version + - uses: dtolnay/rust-toolchain@1.80 # do clippy chekcs with the minimum supported version with: components: rustfmt, clippy - name: Validate cargo format run: cargo fmt -- --check - - name: Run tests + - name: Run tests env: RUSTFLAGS: "-C target-cpu=native ${{ matrix.rustflags }}" run: cargo clippy - + - name: Run tests (no-default-features) env: RUSTFLAGS: "-C target-cpu=native ${{ matrix.rustflags }}" run: cargo clippy - + - name: Run tests (value-no-dup-keys) env: RUSTFLAGS: "-C target-cpu=native ${{ matrix.rustflags }}" run: cargo clippy --features value-no-dup-keys - + - name: Run tests (known-key) env: RUSTFLAGS: "-C target-cpu=native ${{ matrix.rustflags }}" run: cargo clippy --features known-key - + - name: Run tests (128bit) env: RUSTFLAGS: "-C target-cpu=native ${{ matrix.rustflags }}" run: cargo clippy --features 128bit - + - name: Run tests (beef) env: RUSTFLAGS: "-C target-cpu=native ${{ matrix.rustflags }}" run: cargo clippy --features beef - + - name: Run tests (arraybackend) env: RUSTFLAGS: "-C target-cpu=native ${{ matrix.rustflags }}" run: cargo clippy --features arraybackend - + - name: Run tests (approx-number-parsing) env: RUSTFLAGS: "-C target-cpu=native ${{ matrix.rustflags }}" diff --git a/Cargo.toml b/Cargo.toml index 419b0725..6de0b9fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ description = "High performance JSON parser based on a port of simdjson" repository = "https://github.com/simd-lite/simd-json" readme = "README.md" documentation = "https://docs.rs/simd-json" -rust-version = "1.64" +rust-version = "1.80" [target.'cfg(target_family = "wasm")'.dependencies] getrandom = { version = "0.2", features = ["js"] } @@ -34,6 +34,7 @@ colored = { version = "2.0", optional = true } getopts = { version = "0.2", optional = true } jemallocator = { version = "0.5", optional = true } perfcnt = { version = "0.8", optional = true } +iex = { version = "0.2", optional = false } ref-cast = "1.0" diff --git a/src/impls/avx2/deser.rs b/src/impls/avx2/deser.rs index 1e4cc66b..cbe0f124 100644 --- a/src/impls/avx2/deser.rs +++ b/src/impls/avx2/deser.rs @@ -16,13 +16,14 @@ use crate::{ Deserializer, Result, SillyWrapper, }; -#[target_feature(enable = "avx2")] #[allow( clippy::if_not_else, clippy::cast_possible_wrap, clippy::too_many_lines )] #[cfg_attr(not(feature = "no-inline"), inline)] +#[iex::iex] +#[target_feature(enable = "avx2")] pub(crate) unsafe fn parse_str<'invoke, 'de>( input: SillyWrapper<'de>, data: &'invoke [u8], diff --git a/src/impls/native/deser.rs b/src/impls/native/deser.rs index b947a63b..61e1fcf8 100644 --- a/src/impls/native/deser.rs +++ b/src/impls/native/deser.rs @@ -5,6 +5,7 @@ use crate::{ }; #[allow(clippy::cast_possible_truncation)] +#[iex::iex] pub(crate) unsafe fn parse_str<'invoke, 'de>( input: SillyWrapper<'de>, data: &'invoke [u8], diff --git a/src/impls/neon/deser.rs b/src/impls/neon/deser.rs index 3782cf29..98b4d10e 100644 --- a/src/impls/neon/deser.rs +++ b/src/impls/neon/deser.rs @@ -1,3 +1,5 @@ +use iex::Outcome; + use crate::error::ErrorType; use crate::impls::neon::stage1::bit_mask; use crate::safer_unchecked::GetSaferUnchecked; @@ -42,6 +44,7 @@ fn find_bs_bits_and_quote_bits(v0: uint8x16_t, v1: uint8x16_t) -> (u32, u32) { #[allow(clippy::if_not_else, clippy::too_many_lines)] #[cfg_attr(not(feature = "no-inline"), inline)] +#[iex::iex] pub(crate) fn parse_str<'invoke, 'de>( input: SillyWrapper<'de>, data: &'invoke [u8], @@ -168,14 +171,11 @@ pub(crate) fn parse_str<'invoke, 'de>( // within the unicode codepoint handling code. src_i += bs_dist as usize; dst_i += bs_dist as usize; - let (o, s) = if let Ok(r) = + let (o, s) = handle_unicode_codepoint(unsafe { src.get_kinda_unchecked(src_i..) }, unsafe { buffer.get_kinda_unchecked_mut(dst_i..) - }) { - r - } else { - return Err(Deserializer::error_c(src_i, 'u', InvalidUnicodeCodepoint)); - }; + }) + .map_err(|_| Deserializer::error_c(src_i, 'u', InvalidUnicodeCodepoint))?; if o == 0 { return Err(Deserializer::error_c(src_i, 'u', InvalidUnicodeCodepoint)); }; diff --git a/src/impls/portable/deser.rs b/src/impls/portable/deser.rs index 75b6b52a..be49901a 100644 --- a/src/impls/portable/deser.rs +++ b/src/impls/portable/deser.rs @@ -7,6 +7,7 @@ use crate::{ }; #[cfg_attr(not(feature = "no-inline"), inline)] +#[iex::iex] pub(crate) unsafe fn parse_str<'invoke, 'de>( input: SillyWrapper<'de>, data: &'invoke [u8], diff --git a/src/impls/simd128/deser.rs b/src/impls/simd128/deser.rs index af77e16b..5e9b11f0 100644 --- a/src/impls/simd128/deser.rs +++ b/src/impls/simd128/deser.rs @@ -14,6 +14,7 @@ use crate::{ clippy::too_many_lines )] #[cfg_attr(not(feature = "no-inline"), inline)] +#[iex::iex] pub(crate) fn parse_str<'invoke, 'de>( input: SillyWrapper<'de>, data: &'invoke [u8], diff --git a/src/impls/sse42/deser.rs b/src/impls/sse42/deser.rs index ebf21b57..bf4eab07 100644 --- a/src/impls/sse42/deser.rs +++ b/src/impls/sse42/deser.rs @@ -17,6 +17,7 @@ use arch::{ #[target_feature(enable = "sse4.2")] #[allow(clippy::if_not_else, clippy::cast_possible_wrap)] #[cfg_attr(not(feature = "no-inline"), inline)] +#[iex::iex] pub(crate) unsafe fn parse_str<'invoke, 'de>( input: SillyWrapper<'de>, data: &'invoke [u8], diff --git a/src/lib.rs b/src/lib.rs index 75e7faf9..14621219 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -139,6 +139,7 @@ mod numberparse; mod safer_unchecked; mod stringparse; +use iex::Outcome; use safer_unchecked::GetSaferUnchecked; use stage2::StackState; @@ -225,7 +226,9 @@ pub fn to_tape(s: &mut [u8]) -> Result { /// Will return `Err` if `s` is invalid JSON. #[cfg_attr(not(feature = "no-inline"), inline)] pub fn to_tape_with_buffers<'de>(s: &'de mut [u8], buffers: &mut Buffers) -> Result> { - Deserializer::from_slice_with_buffers(s, buffers).map(Deserializer::into_tape) + Deserializer::from_slice_with_buffers(s, buffers) + .into_result() + .map(Deserializer::into_tape) } /// Fills a already existing tape from the input for later consumption @@ -235,7 +238,7 @@ pub fn to_tape_with_buffers<'de>(s: &'de mut [u8], buffers: &mut Buffers) -> Res #[cfg_attr(not(feature = "no-inline"), inline)] pub fn fill_tape<'de>(s: &'de mut [u8], buffers: &mut Buffers, tape: &mut Tape<'de>) -> Result<()> { tape.0.clear(); - Deserializer::fill_tape(s, buffers, &mut tape.0) + Deserializer::fill_tape(s, buffers, &mut tape.0).into_result() } pub(crate) trait Stage1Parse { @@ -547,6 +550,7 @@ impl<'de> Deserializer<'de> { feature = "runtime-detection", any(target_arch = "x86_64", target_arch = "x86"), ))] + #[iex::iex] pub(crate) unsafe fn parse_str_<'invoke>( input: *mut u8, data: &'invoke [u8], @@ -606,6 +610,7 @@ impl<'de> Deserializer<'de> { target_feature = "simd128", target_arch = "aarch64", )))] + #[iex::iex] pub(crate) unsafe fn parse_str_<'invoke>( input: *mut u8, data: &'invoke [u8], @@ -620,6 +625,7 @@ impl<'de> Deserializer<'de> { } #[cfg_attr(not(feature = "no-inline"), inline)] #[cfg(all(feature = "portable", not(feature = "runtime-detection")))] + #[iex::iex] pub(crate) unsafe fn parse_str_<'invoke>( input: *mut u8, data: &'invoke [u8], @@ -639,6 +645,7 @@ impl<'de> Deserializer<'de> { not(feature = "portable"), not(feature = "runtime-detection"), ))] + #[iex::iex] pub(crate) unsafe fn parse_str_<'invoke>( input: *mut u8, data: &'invoke [u8], @@ -656,6 +663,7 @@ impl<'de> Deserializer<'de> { not(feature = "runtime-detection"), not(feature = "portable"), ))] + #[iex::iex] pub(crate) unsafe fn parse_str_<'invoke>( input: *mut u8, data: &'invoke [u8], @@ -668,6 +676,7 @@ impl<'de> Deserializer<'de> { #[cfg_attr(not(feature = "no-inline"), inline)] #[cfg(all(target_arch = "aarch64", not(feature = "portable")))] + #[iex::iex] pub(crate) unsafe fn parse_str_<'invoke>( input: *mut u8, data: &'invoke [u8], @@ -679,6 +688,7 @@ impl<'de> Deserializer<'de> { } #[cfg_attr(not(feature = "no-inline"), inline)] #[cfg(all(target_feature = "simd128", not(feature = "portable")))] + #[iex::iex] pub(crate) unsafe fn parse_str_<'invoke>( input: *mut u8, data: &'invoke [u8], @@ -842,7 +852,7 @@ impl<'de> Deserializer<'de> { let mut buffer = Buffers::new(len); - Self::from_slice_with_buffers(input, &mut buffer) + Self::from_slice_with_buffers(input, &mut buffer).into_result() } /// Fills the tape without creating a serializer, this function poses @@ -854,6 +864,7 @@ impl<'de> Deserializer<'de> { /// Will return `Err` if `input` is invalid JSON. #[allow(clippy::uninit_vec)] #[cfg_attr(not(feature = "no-inline"), inline)] + #[iex::iex(captures = "'de")] fn fill_tape( input: &'de mut [u8], buffer: &mut Buffers, @@ -905,7 +916,8 @@ impl<'de> Deserializer<'de> { &buffer.structural_indexes, &mut buffer.stage2_stack, tape, - ) + )?; + Ok(()) } /// Creates a serializer from a mutable slice of bytes using a temporary @@ -914,6 +926,7 @@ impl<'de> Deserializer<'de> { /// # Errors /// /// Will return `Err` if `s` is invalid JSON. + #[iex::iex] pub fn from_slice_with_buffers(input: &'de mut [u8], buffer: &mut Buffers) -> Result { let mut tape: Vec> = Vec::with_capacity(buffer.structural_indexes.len()); @@ -1113,16 +1126,14 @@ impl AlignedBuf { /// Creates a new buffer that is aligned with the simd register size #[must_use] pub fn with_capacity(capacity: usize) -> Self { - let layout = match Layout::from_size_align(capacity, SIMDJSON_PADDING) { - Ok(layout) => layout, - Err(_) => Self::capacity_overflow(), + let Ok(layout) = Layout::from_size_align(capacity, SIMDJSON_PADDING) else { + Self::capacity_overflow() }; if mem::size_of::() < 8 && capacity > isize::MAX as usize { Self::capacity_overflow() } - let inner = match unsafe { NonNull::new(alloc(layout)) } { - Some(ptr) => ptr, - None => handle_alloc_error(layout), + let Some(inner) = NonNull::new(unsafe { alloc(layout) }) else { + handle_alloc_error(layout) }; Self { layout, diff --git a/src/macros.rs b/src/macros.rs index 17018489..04066fd6 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1298,19 +1298,6 @@ macro_rules! static_cast_u64 { }; } -/// FROM serde-json -/// We only use our own error type; no need for From conversions provided by the -/// standard library's try! macro. This reduces lines of LLVM IR by 4%. -#[macro_export] -macro_rules! stry { - ($e:expr) => { - match $e { - ::std::result::Result::Ok(val) => val, - ::std::result::Result::Err(err) => return ::std::result::Result::Err(err), - } - }; -} - #[cfg(test)] mod test { use crate::prelude::*; diff --git a/src/numberparse/approx.rs b/src/numberparse/approx.rs index a47804ef..9ea8f1b8 100644 --- a/src/numberparse/approx.rs +++ b/src/numberparse/approx.rs @@ -77,6 +77,7 @@ impl<'de> Deserializer<'de> { clippy::cast_precision_loss, clippy::too_many_lines )] + #[iex::iex] fn parse_float(idx: usize, p: &[u8], negative: bool) -> Result { let mut digitcount = usize::from(negative); let mut i: f64; @@ -222,6 +223,7 @@ impl<'de> Deserializer<'de> { #[cfg(not(feature = "128bit"))] #[inline(never)] #[allow(clippy::cast_possible_wrap)] + #[iex::iex] fn parse_large_integer(idx: usize, buf: &[u8], negative: bool) -> Result { let mut digitcount = usize::from(negative); let mut i: u64; @@ -283,6 +285,7 @@ impl<'de> Deserializer<'de> { #[cfg(feature = "128bit")] #[inline(never)] #[allow(clippy::cast_possible_wrap)] + #[iex::iex] fn parse_large_integer(idx: usize, buf: &[u8], negative: bool) -> Result { let mut digitcount = usize::from(negative); let mut i: u128; @@ -358,6 +361,7 @@ impl<'de> Deserializer<'de> { clippy::cast_possible_wrap, clippy::too_many_lines )] + #[iex::iex] pub(crate) fn parse_number(idx: usize, buf: &[u8], negative: bool) -> Result { let buf = unsafe { buf.get_kinda_unchecked(idx..) }; let mut byte_count = usize::from(negative); diff --git a/src/numberparse/correct.rs b/src/numberparse/correct.rs index b7706256..9e3e338f 100644 --- a/src/numberparse/correct.rs +++ b/src/numberparse/correct.rs @@ -17,6 +17,7 @@ macro_rules! get { unsafe { *$buf.get_kinda_unchecked($idx as usize) } }; } + macro_rules! err { ($idx:ident, $num:expr) => { return Err(Error::new_c($idx, $num as char, ErrorType::InvalidNumber)) @@ -28,7 +29,7 @@ macro_rules! check_overflow { if $overflowed { #[cfg(not(feature = "big-int-as-float"))] { - err!($idx, get!($buf, $idx)) + err!($idx, get!($buf, $idx)); } #[cfg(feature = "big-int-as-float")] { @@ -55,13 +56,14 @@ impl<'de> Deserializer<'de> { clippy::cast_possible_truncation, clippy::too_many_lines )] + #[iex::iex] pub(crate) fn parse_number(idx: usize, buf: &[u8], negative: bool) -> Result { let start_idx = idx; let mut idx = idx; if negative { idx += 1; if !is_integer(get!(buf, idx)) { - err!(idx, get!(buf, idx)) + err!(idx, get!(buf, idx)); } } let mut start = idx; @@ -69,11 +71,11 @@ impl<'de> Deserializer<'de> { if get!(buf, idx) == b'0' { idx += 1; if is_not_structural_or_whitespace_or_exponent_or_decimal(get!(buf, idx)) { - err!(idx, get!(buf, idx)) + err!(idx, get!(buf, idx)); } } else { if !is_integer(get!(buf, idx)) { - err!(idx, get!(buf, idx)) + err!(idx, get!(buf, idx)); } num = u64::from(get!(buf, idx) - b'0'); idx += 1; @@ -96,7 +98,7 @@ impl<'de> Deserializer<'de> { .wrapping_add(u64::from(get!(buf, idx) - b'0')); idx += 1; } else { - err!(idx, get!(buf, idx)) + err!(idx, get!(buf, idx)); } #[cfg(feature = "swar-number-parsing")] @@ -139,7 +141,7 @@ impl<'de> Deserializer<'de> { } } if !is_integer(get!(buf, idx)) { - err!(idx, get!(buf, idx)) + err!(idx, get!(buf, idx)); } let mut exp_number = i64::from(get!(buf, idx) - b'0'); idx += 1; @@ -153,7 +155,7 @@ impl<'de> Deserializer<'de> { } while is_integer(get!(buf, idx)) { if exp_number > 0x0001_0000_0000 { - err!(idx, get!(buf, idx)) + err!(idx, get!(buf, idx)); } exp_number = 10 * exp_number + i64::from(get!(buf, idx) - b'0'); idx += 1; @@ -170,30 +172,30 @@ impl<'de> Deserializer<'de> { } digit_count = digit_count.wrapping_sub(start.wrapping_sub(start_digits)); if digit_count >= 19 { - return f64_from_parts_slow( + let res = f64_from_parts_slow( unsafe { buf.get_kinda_unchecked(start_idx..idx) }, start_idx, - ); + )?; + return Ok(res); } } if is_structural_or_whitespace(get!(buf, idx)) == 0 { - err!(idx, get!(buf, idx)) + err!(idx, get!(buf, idx)); } - f64_from_parts( + Ok(f64_from_parts( !negative, num, exponent as i32, unsafe { buf.get_kinda_unchecked(start_idx..idx) }, start_idx, - ) + )?) } else if unlikely!(digit_count >= 18) { - parse_large_integer(start_idx, buf, negative, idx) + Ok(parse_large_integer(start_idx, buf, negative, idx)?) } else if is_structural_or_whitespace(get!(buf, idx)) == 0 { err!(idx, get!(buf, idx)) } else { Ok(if negative { StaticNode::I64(unsafe { static_cast_i64!(num.wrapping_neg()) }) - // -(num as i64) } else { StaticNode::U64(num) }) @@ -204,6 +206,7 @@ impl<'de> Deserializer<'de> { #[cfg(not(feature = "128bit"))] #[cold] #[allow(clippy::cast_possible_wrap)] +#[iex::iex] fn parse_large_integer( start_idx: usize, buf: &[u8], @@ -246,6 +249,7 @@ fn parse_large_integer( #[cfg(feature = "128bit")] #[cold] #[allow(clippy::cast_possible_wrap)] +#[iex::iex] fn parse_large_integer( start_idx: usize, buf: &[u8], @@ -307,6 +311,7 @@ fn parse_large_integer( clippy::cast_precision_loss, clippy::cast_possible_wrap )] +#[iex::iex] fn f64_from_parts( positive: bool, significand: u64, @@ -342,7 +347,8 @@ fn f64_from_parts( && product_high & 0x1FF == 0x1FF && product_low.wrapping_add(f) < product_low { - return f64_from_parts_slow(slice, offset); + let res = f64_from_parts_slow(slice, offset)?; + return Ok(res); } upper = product_high; lower = product_middle; @@ -352,7 +358,7 @@ fn f64_from_parts( leading_zeroes += 1 ^ upperbit; if lower == 0 && upper.trailing_zeros() >= 9 && mantissa & 3 == 1 { - return f64_from_parts_slow(slice, offset); + return Ok(f64_from_parts_slow(slice, offset)?); } mantissa += mantissa & 1; mantissa >>= 1; @@ -365,30 +371,32 @@ fn f64_from_parts( let real_exponent = (factor_exponent as u64).wrapping_sub(leading_zeroes); // we have to check that real_exponent is in range, otherwise we bail out if !(1..=2046).contains(&real_exponent) { - return f64_from_parts_slow(slice, offset); + return Ok(f64_from_parts_slow(slice, offset)?); } mantissa |= real_exponent.wrapping_shl(52); mantissa |= u64::from(!positive) << 63; let res = f64::from_bits(mantissa); if res.is_infinite() { err!(offset, get!(slice, offset)) + } else { + Ok(StaticNode::F64(res)) } - Ok(StaticNode::F64(res)) } else { - f64_from_parts_slow(slice, offset) + let res = f64_from_parts_slow(slice, offset)?; + Ok(res) } } #[cold] +#[iex::iex] fn f64_from_parts_slow(slice: &[u8], offset: usize) -> Result { // we already validated the content of the slice we only need to translate // the slice to a string and parse it as parse is not defined for a u8 slice match unsafe { std::str::from_utf8_unchecked(slice).parse::() } { Ok(val) => { if val.is_infinite() { - err!(offset, get!(slice, 0)) + err!(offset, get!(slice, 0)); } - Ok(StaticNode::F64(val)) } Err(_) => err!(offset, get!(slice, offset)), diff --git a/src/serde.rs b/src/serde.rs index df08e906..0796a39c 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -11,8 +11,9 @@ mod se; mod value; pub use self::se::*; pub use self::value::*; -use crate::{stry, Buffers, Deserializer, Error, ErrorType, Node, Result}; use crate::{BorrowedValue, OwnedValue}; +use crate::{Buffers, Deserializer, Error, ErrorType, Node, Result}; +use iex::Outcome; use serde::de::DeserializeOwned; use serde_ext::Deserialize; use std::fmt; @@ -57,7 +58,7 @@ pub fn from_slice<'a, T>(s: &'a mut [u8]) -> Result where T: Deserialize<'a>, { - let mut deserializer = stry!(Deserializer::from_slice(s)); + let mut deserializer = Deserializer::from_slice(s)?; T::deserialize(&mut deserializer) } @@ -74,7 +75,7 @@ pub fn from_slice_with_buffers<'a, T>(s: &'a mut [u8], buffers: &mut Buffers) -> where T: Deserialize<'a>, { - let mut deserializer = stry!(Deserializer::from_slice_with_buffers(s, buffers)); + let mut deserializer = Deserializer::from_slice_with_buffers(s, buffers).into_result()?; T::deserialize(&mut deserializer) } @@ -98,7 +99,7 @@ pub unsafe fn from_str<'a, T>(s: &'a mut str) -> Result where T: Deserialize<'a>, { - let mut deserializer = stry!(Deserializer::from_slice(s.as_bytes_mut())); + let mut deserializer = Deserializer::from_slice(s.as_bytes_mut())?; T::deserialize(&mut deserializer) } @@ -125,10 +126,8 @@ pub unsafe fn from_str_with_buffers<'a, T>(s: &'a mut str, buffers: &mut Buffers where T: Deserialize<'a>, { - let mut deserializer = stry!(Deserializer::from_slice_with_buffers( - s.as_bytes_mut(), - buffers - )); + let mut deserializer = + Deserializer::from_slice_with_buffers(s.as_bytes_mut(), buffers).into_result()?; T::deserialize(&mut deserializer) } @@ -149,7 +148,7 @@ where if let Err(e) = rdr.read_to_end(&mut data) { return Err(Error::generic(ErrorType::Io(e))); }; - let mut deserializer = stry!(Deserializer::from_slice(&mut data)); + let mut deserializer = Deserializer::from_slice(&mut data)?; T::deserialize(&mut deserializer) } @@ -171,7 +170,8 @@ where if let Err(e) = rdr.read_to_end(&mut data) { return Err(Error::generic(ErrorType::Io(e))); }; - let mut deserializer = stry!(Deserializer::from_slice_with_buffers(&mut data, buffers)); + let mut deserializer = + Deserializer::from_slice_with_buffers(&mut data, buffers).into_result()?; T::deserialize(&mut deserializer) } diff --git a/src/serde/de.rs b/src/serde/de.rs index 9c94e559..c6ef4bc8 100644 --- a/src/serde/de.rs +++ b/src/serde/de.rs @@ -1,5 +1,5 @@ use crate::serde_ext::de::IntoDeserializer; -use crate::{stry, Deserializer, Error, ErrorType, Node, Result, StaticNode}; +use crate::{Deserializer, Error, ErrorType, Node, Result, StaticNode}; use serde_ext::de::{self, DeserializeSeed, MapAccess, SeqAccess, Visitor}; use serde_ext::forward_to_deserialize_any; use std::str; @@ -18,7 +18,7 @@ where where V: Visitor<'de>, { - match stry!(self.next()) { + match self.next()? { Node::String(s) => visitor.visit_borrowed_str(s), Node::Static(StaticNode::Null) => visitor.visit_unit(), Node::Static(StaticNode::Bool(b)) => visitor.visit_bool(b), @@ -53,7 +53,7 @@ where where V: Visitor<'de>, { - match stry!(self.next()) { + match self.next()? { Node::Static(StaticNode::Bool(b)) => visitor.visit_bool(b), _c => Err(Deserializer::error(ErrorType::ExpectedBoolean)), } @@ -93,7 +93,7 @@ where where V: Visitor<'de>, { - visitor.visit_i8(stry!(self.parse_i8())) + visitor.visit_i8(self.parse_i8()?) } #[cfg_attr(not(feature = "no-inline"), inline)] @@ -102,7 +102,7 @@ where where V: Visitor<'de>, { - visitor.visit_i16(stry!(self.parse_i16())) + visitor.visit_i16(self.parse_i16()?) } #[cfg_attr(not(feature = "no-inline"), inline)] @@ -111,7 +111,7 @@ where where V: Visitor<'de>, { - visitor.visit_i32(stry!(self.parse_i32())) + visitor.visit_i32(self.parse_i32()?) } #[cfg_attr(not(feature = "no-inline"), inline)] @@ -119,7 +119,7 @@ where where V: Visitor<'de>, { - visitor.visit_i64(stry!(self.parse_i64())) + visitor.visit_i64(self.parse_i64()?) } #[cfg_attr(not(feature = "no-inline"), inline)] @@ -127,7 +127,7 @@ where where V: Visitor<'de>, { - visitor.visit_i128(stry!(self.parse_i128())) + visitor.visit_i128(self.parse_i128()?) } #[cfg_attr(not(feature = "no-inline"), inline)] @@ -136,7 +136,7 @@ where where V: Visitor<'de>, { - visitor.visit_u8(stry!(self.parse_u8())) + visitor.visit_u8(self.parse_u8()?) } #[cfg_attr(not(feature = "no-inline"), inline)] @@ -145,7 +145,7 @@ where where V: Visitor<'de>, { - visitor.visit_u16(stry!(self.parse_u16())) + visitor.visit_u16(self.parse_u16()?) } #[cfg_attr(not(feature = "no-inline"), inline)] @@ -154,7 +154,7 @@ where where V: Visitor<'de>, { - visitor.visit_u32(stry!(self.parse_u32())) + visitor.visit_u32(self.parse_u32()?) } #[cfg_attr(not(feature = "no-inline"), inline)] @@ -162,7 +162,7 @@ where where V: Visitor<'de>, { - visitor.visit_u64(stry!(self.parse_u64())) + visitor.visit_u64(self.parse_u64()?) } #[cfg_attr(not(feature = "no-inline"), inline)] @@ -170,7 +170,7 @@ where where V: Visitor<'de>, { - visitor.visit_u128(stry!(self.parse_u128())) + visitor.visit_u128(self.parse_u128()?) } #[cfg_attr(not(feature = "no-inline"), inline)] @@ -179,7 +179,7 @@ where where V: Visitor<'de>, { - let v: f64 = stry!(self.parse_double()); + let v: f64 = self.parse_double()?; visitor.visit_f32(v as f32) } @@ -188,7 +188,7 @@ where where V: Visitor<'de>, { - visitor.visit_f64(stry!(self.parse_double())) + visitor.visit_f64(self.parse_double()?) } // An absent optional is represented as the JSON `null` and a present @@ -205,7 +205,7 @@ where where V: Visitor<'de>, { - if stry!(self.peek()) == Node::Static(StaticNode::Null) { + if self.peek()? == Node::Static(StaticNode::Null) { self.skip(); visitor.visit_unit() } else { @@ -219,7 +219,7 @@ where where V: Visitor<'de>, { - if stry!(self.next()) != Node::Static(StaticNode::Null) { + if self.next()? != Node::Static(StaticNode::Null) { return Err(Deserializer::error(ErrorType::ExpectedNull)); } visitor.visit_unit() @@ -371,7 +371,7 @@ impl<'de, 'a> de::EnumAccess<'de> for VariantAccess<'a, 'de> { where V: de::DeserializeSeed<'de>, { - let val = stry!(seed.deserialize(&mut *self.de)); + let val = seed.deserialize(&mut *self.de)?; Ok((val, self)) } } @@ -487,12 +487,12 @@ macro_rules! deserialize_integer_key { where V: de::Visitor<'de>, { - visitor.$visit(stry!(match unsafe { self.de.next_() } { + visitor.$visit(match unsafe { self.de.next_() } { Node::String(s) => s .parse::<$type>() .map_err(|_| Deserializer::error(ErrorType::InvalidNumber)), _ => Err(Deserializer::error(ErrorType::ExpectedString)), - })) + }?) } }; } @@ -505,7 +505,7 @@ impl<'de, 'a> de::Deserializer<'de> for MapKey<'de, 'a> { where V: de::Visitor<'de>, { - match stry!(self.de.next()) { + match self.de.next()? { Node::String(s) => visitor.visit_borrowed_str(s), _ => Err(Deserializer::error(ErrorType::ExpectedString)), } diff --git a/src/serde/se/pp.rs b/src/serde/se/pp.rs index 8eea294a..13049307 100644 --- a/src/serde/se/pp.rs +++ b/src/serde/se/pp.rs @@ -1,4 +1,4 @@ -use crate::{stry, Error, ErrorType}; +use crate::{Error, ErrorType}; use serde_ext::ser; use std::io::Write; use std::str; @@ -87,7 +87,7 @@ where 9 => self.get_writer().write_all(b" "), _ => { for _ in 0..(self.dent * 2) { - stry!(self.get_writer().write_all(b" ")); + self.get_writer().write_all(b" ")?; } Ok(()) } diff --git a/src/serde/value/borrowed/de.rs b/src/serde/value/borrowed/de.rs index 0e397d66..2669ad33 100644 --- a/src/serde/value/borrowed/de.rs +++ b/src/serde/value/borrowed/de.rs @@ -80,11 +80,8 @@ impl<'de> de::Deserializer<'de> for Value<'de> { let (variant, value) = match self { Value::Object(value) => { let mut iter = value.into_iter(); - let (variant, value) = match iter.next() { - Some(v) => v, - None => { - return Err(crate::Deserializer::error(ErrorType::Eof)); - } + let Some((variant, value)) = iter.next() else { + return Err(crate::Deserializer::error(ErrorType::Eof)); }; // enums are encoded in json as maps with a single key:value pair if iter.next().is_some() { @@ -685,11 +682,8 @@ impl<'de> de::Deserializer<'de> for &'de Value<'de> { let (variant, value) = match self { Value::Object(value) => { let mut iter = value.iter(); - let (variant, value) = match iter.next() { - Some(v) => v, - None => { - return Err(crate::Deserializer::error(ErrorType::Eof)); - } + let Some((variant, value)) = iter.next() else { + return Err(crate::Deserializer::error(ErrorType::Eof)); }; // enums are encoded in json as maps with a single key:value pair if iter.next().is_some() { diff --git a/src/serde/value/borrowed/se.rs b/src/serde/value/borrowed/se.rs index 64848dcf..c12d3d0d 100644 --- a/src/serde/value/borrowed/se.rs +++ b/src/serde/value/borrowed/se.rs @@ -1,7 +1,6 @@ use super::to_value; use crate::{ cow::Cow, - stry, value::borrowed::{Object, Value}, Error, ErrorType, Result, }; @@ -192,7 +191,7 @@ impl<'se> serde::Serializer for Serializer<'se> { T: ?Sized + Serialize, { let mut values = Object::with_capacity_and_hasher(1, ObjectHasher::default()); - let x = stry!(to_value(value)); + let x = to_value(value)?; values.insert_nocheck(variant.into(), x); Ok(Value::from(values)) } @@ -293,7 +292,7 @@ impl<'se> serde::ser::SerializeSeq for SerializeVec<'se> { where T: ?Sized + Serialize, { - self.vec.push(stry!(to_value(value))); + self.vec.push(to_value(value)?); Ok(()) } @@ -342,7 +341,7 @@ impl<'se> serde::ser::SerializeTupleVariant for SerializeTupleVariant<'se> { where T: ?Sized + Serialize, { - self.vec.push(stry!(to_value(value))); + self.vec.push(to_value(value)?); Ok(()) } @@ -362,9 +361,9 @@ impl<'se> serde::ser::SerializeMap for SerializeMap<'se> { where T: ?Sized + Serialize, { - self.next_key = Some(stry!(key.serialize(MapKeySerializer { - marker: PhantomData - }))); + self.next_key = Some(key.serialize(MapKeySerializer { + marker: PhantomData, + })?); Ok(()) } @@ -376,7 +375,7 @@ impl<'se> serde::ser::SerializeMap for SerializeMap<'se> { // Panic because this indicates a bug in the program rather than an // expected failure. let key = key.expect("serialize_value called before serialize_key"); - self.map.insert(key, stry!(to_value(value))); + self.map.insert(key, to_value(value)?); Ok(()) } @@ -570,7 +569,7 @@ impl<'se> serde::ser::SerializeStruct for SerializeMap<'se> { where T: ?Sized + Serialize, { - stry!(serde::ser::SerializeMap::serialize_key(self, key)); + serde::ser::SerializeMap::serialize_key(self, key)?; serde::ser::SerializeMap::serialize_value(self, value) } @@ -587,7 +586,7 @@ impl<'se> serde::ser::SerializeStructVariant for SerializeStructVariant<'se> { where T: ?Sized + Serialize, { - self.map.insert(key.into(), stry!(to_value(value))); + self.map.insert(key.into(), to_value(value)?); Ok(()) } diff --git a/src/serde/value/owned/de.rs b/src/serde/value/owned/de.rs index e4321c37..66948fc4 100644 --- a/src/serde/value/owned/de.rs +++ b/src/serde/value/owned/de.rs @@ -68,11 +68,8 @@ impl<'de> de::Deserializer<'de> for Value { let (variant, value) = match self { Value::Object(value) => { let mut iter = value.into_iter(); - let (variant, value) = match iter.next() { - Some(v) => v, - None => { - return Err(crate::Deserializer::error(ErrorType::Eof)); - } + let Some((variant, value)) = iter.next() else { + return Err(crate::Deserializer::error(ErrorType::Eof)); }; // enums are encoded in json as maps with a single key:value pair if iter.next().is_some() { @@ -673,11 +670,8 @@ impl<'de> de::Deserializer<'de> for &'de Value { let (variant, value) = match self { Value::Object(value) => { let mut iter = value.iter(); - let (variant, value) = match iter.next() { - Some(v) => v, - None => { - return Err(crate::Deserializer::error(ErrorType::Eof)); - } + let Some((variant, value)) = iter.next() else { + return Err(crate::Deserializer::error(ErrorType::Eof)); }; // enums are encoded in json as maps with a single key:value pair if iter.next().is_some() { diff --git a/src/serde/value/owned/se.rs b/src/serde/value/owned/se.rs index 10562b79..9ccb9d1f 100644 --- a/src/serde/value/owned/se.rs +++ b/src/serde/value/owned/se.rs @@ -1,6 +1,5 @@ use super::to_value; use crate::{ - stry, value::owned::{Object, Value}, Error, ErrorType, ObjectHasher, Result, StaticNode, }; @@ -179,7 +178,7 @@ impl serde::Serializer for Serializer { T: ?Sized + Serialize, { let mut values = Object::with_capacity_and_hasher(1, ObjectHasher::default()); - values.insert_nocheck(variant.into(), stry!(to_value(value))); + values.insert_nocheck(variant.into(), to_value(value)?); Ok(Value::from(values)) } @@ -279,7 +278,7 @@ impl serde::ser::SerializeSeq for SerializeVec { where T: ?Sized + Serialize, { - self.vec.push(stry!(to_value(value))); + self.vec.push(to_value(value)?); Ok(()) } @@ -328,7 +327,7 @@ impl serde::ser::SerializeTupleVariant for SerializeTupleVariant { where T: ?Sized + Serialize, { - self.vec.push(stry!(to_value(value))); + self.vec.push(to_value(value)?); Ok(()) } @@ -347,7 +346,7 @@ impl serde::ser::SerializeMap for SerializeMap { where T: ?Sized + Serialize, { - self.next_key = Some(stry!(key.serialize(MapKeySerializer {}))); + self.next_key = Some(key.serialize(MapKeySerializer {})?); Ok(()) } @@ -359,7 +358,7 @@ impl serde::ser::SerializeMap for SerializeMap { // Panic because this indicates a bug in the program rather than an // expected failure. let key = key.expect("serialize_value called before serialize_key"); - self.map.insert(key, stry!(to_value(value))); + self.map.insert(key, to_value(value)?); Ok(()) } @@ -550,7 +549,7 @@ impl serde::ser::SerializeStruct for SerializeMap { where T: ?Sized + Serialize, { - stry!(serde::ser::SerializeMap::serialize_key(self, key)); + serde::ser::SerializeMap::serialize_key(self, key)?; serde::ser::SerializeMap::serialize_value(self, value) } @@ -567,7 +566,7 @@ impl serde::ser::SerializeStructVariant for SerializeStructVariant { where T: ?Sized + Serialize, { - self.map.insert(key.into(), stry!(to_value(value))); + self.map.insert(key.into(), to_value(value)?); Ok(()) } diff --git a/src/stage2.rs b/src/stage2.rs index 39853c0f..6f361d82 100644 --- a/src/stage2.rs +++ b/src/stage2.rs @@ -5,6 +5,8 @@ use crate::value::tape::Node; use crate::{Deserializer, Error, ErrorType, InternalError, Result}; use value_trait::StaticNode; +use iex::Outcome; + #[cfg_attr(not(feature = "no-inline"), inline)] pub fn is_valid_true_atom(loc: &[u8]) -> bool { debug_assert!(loc.len() >= 8, "loc too short for a u64 read"); @@ -92,6 +94,7 @@ pub(crate) enum StackState { impl<'de> Deserializer<'de> { #[cfg_attr(not(feature = "no-inline"), inline)] #[allow(clippy::cognitive_complexity, clippy::too_many_lines, unused_unsafe)] + #[iex::iex(captures = "'de")] pub(crate) fn build_tape( input: &'de mut [u8], input2: &[u8], @@ -102,18 +105,49 @@ impl<'de> Deserializer<'de> { ) -> Result<()> { res.clear(); res.reserve(structural_indexes.len()); + + let res_ptr = res.as_mut_ptr(); + let mut i = 0; + let r_i = (&mut i) as *mut usize; + Self::build_tape_( + input, + input2, + buffer, + structural_indexes, + stack, + res_ptr, + r_i, + ) + .inspect_err(|_| unsafe { + res.set_len(i); + })?; + unsafe { + res.set_len(i); + } + Ok(()) + } + #[cfg_attr(not(feature = "no-inline"), inline)] + #[allow(clippy::cognitive_complexity, clippy::too_many_lines, unused_unsafe)] + #[iex::iex(captures = "'de")] + pub(crate) fn build_tape_( + input: &'de mut [u8], + input2: &[u8], + buffer: &mut [u8], + structural_indexes: &[u32], + stack: &mut Vec, + res_ptr: *mut Node<'de>, + r_i: *mut usize, + ) -> Result<()> { // While a valid json can have at max len/2 (`[[[]]]`)elements that are relevant // a invalid json might exceed this `[[[[[[` and we need to protect against that. stack.clear(); stack.reserve(structural_indexes.len()); - let res_ptr = res.as_mut_ptr(); let stack_ptr = stack.as_mut_ptr(); let mut depth: usize = 0; let mut last_start; let mut cnt: usize; - let mut r_i = 0; // let mut i: usize = 0; // index of the structural character (0,1,2,3...) // location of the structural character in the input (buf) @@ -125,36 +159,16 @@ impl<'de> Deserializer<'de> { let mut i: usize = 0; let mut state; - macro_rules! s2try { - ($e:expr) => { - match $e { - ::std::result::Result::Ok(val) => val, - ::std::result::Result::Err(err) => { - // We need to ensure that rust doesn't - // try to free strings that we never - // allocated - unsafe { - res.set_len(r_i); - }; - return ::std::result::Result::Err(err); - } - } - }; - } - macro_rules! insert_res { ($t:expr) => { unsafe { - res_ptr.add(r_i).write($t); - r_i += 1; + res_ptr.add(*r_i).write($t); + *r_i += 1; } }; } macro_rules! success { () => { - unsafe { - res.set_len(r_i); - } return Ok(()); }; } @@ -177,17 +191,6 @@ impl<'de> Deserializer<'de> { }}; } - macro_rules! insert_str { - () => { - insert_res!(Node::String(s2try!(Self::parse_str_( - input.as_mut_ptr(), - &input2, - buffer, - idx - )))); - }; - } - // The continue cases are the most frequently called onces it's // worth pulling them out into a macro (aka inlining them) // Since we don't have a 'gogo' in rust. @@ -218,7 +221,11 @@ impl<'de> Deserializer<'de> { cnt += 1; update_char!(); if c == b'"' { - insert_str!(); + unsafe { + let n = Self::parse_str_(input.as_mut_ptr(), &input2, buffer, idx) + .into_result()?; + insert_res!(Node::String(n)); + } goto!(ObjectKey); } fail!(ErrorType::ExpectedObjectKey); @@ -249,7 +256,11 @@ impl<'de> Deserializer<'de> { update_char!(); match c { b'"' => { - insert_str!(); + unsafe { + let n = Self::parse_str_(input.as_mut_ptr(), &input2, buffer, idx) + .into_result()?; + insert_res!(Node::String(n)); + } goto!(ObjectKey) } b'}' => { @@ -265,12 +276,6 @@ impl<'de> Deserializer<'de> { macro_rules! fail { () => { - // We need to ensure that rust doesn't - // try to free strings that we never - // allocated - unsafe { - res.set_len(r_i); - }; return Err(Error::new_c( idx, c as char, @@ -278,12 +283,6 @@ impl<'de> Deserializer<'de> { )); }; ($t:expr) => { - // We need to ensure that rust doesn't - // try to free strings that we never - // allocated - unsafe { - res.set_len(r_i); - }; return Err(Error::new_c(idx, c as char, $t)); }; } @@ -294,9 +293,9 @@ impl<'de> Deserializer<'de> { b'{' => { unsafe { stack_ptr.add(depth).write(StackState::Start); + last_start = *r_i; } - last_start = r_i; insert_res!(Node::Object { len: 0, count: 0 }); depth += 1; @@ -305,7 +304,10 @@ impl<'de> Deserializer<'de> { update_char!(); match c { b'"' => { - insert_str!(); + unsafe { + let n = Self::parse_str_(input.as_mut_ptr(), &input2, buffer, idx)?; + insert_res!(Node::String(n)); + } state = State::ObjectKey; } b'}' => { @@ -320,9 +322,8 @@ impl<'de> Deserializer<'de> { b'[' => { unsafe { stack_ptr.add(depth).write(StackState::Start); + last_start = *r_i; } - - last_start = r_i; insert_res!(Node::Array { len: 0, count: 0 }); depth += 1; @@ -373,14 +374,18 @@ impl<'de> Deserializer<'de> { fail!(ErrorType::TrailingData); } b'"' => { - insert_str!(); + unsafe { + let n = Self::parse_str_(input.as_mut_ptr(), &input2, buffer, idx)?; + insert_res!(Node::String(n)); + } if i == structural_indexes.len() { success!(); } fail!(ErrorType::TrailingData); } b'-' => { - insert_res!(Node::Static(s2try!(Self::parse_number(idx, input2, true)))); + let n = Self::parse_number(idx, input2, true)?; + insert_res!(Node::Static(n)); if i == structural_indexes.len() { success!(); @@ -388,7 +393,8 @@ impl<'de> Deserializer<'de> { fail!(ErrorType::TrailingData); } b'0'..=b'9' => { - insert_res!(Node::Static(s2try!(Self::parse_number(idx, input2, false)))); + let n = Self::parse_number(idx, input2, false)?; + insert_res!(Node::Static(n)); if i == structural_indexes.len() { success!(); @@ -412,7 +418,10 @@ impl<'de> Deserializer<'de> { update_char!(); match c { b'"' => { - insert_str!(); + unsafe { + let n = Self::parse_str_(input.as_mut_ptr(), &input2, buffer, idx)?; + insert_res!(Node::String(n)); + } object_continue!(); } b't' => { @@ -437,16 +446,14 @@ impl<'de> Deserializer<'de> { object_continue!(); } b'-' => { - insert_res!(Node::Static(s2try!(Self::parse_number( - idx, input2, true - )))); + let n = Self::parse_number(idx, input2, true)?; + insert_res!(Node::Static(n)); object_continue!(); } b'0'..=b'9' => { - insert_res!(Node::Static(s2try!(Self::parse_number( - idx, input2, false - )))); + let n = Self::parse_number(idx, input2, false)?; + insert_res!(Node::Static(n)); object_continue!(); } @@ -455,8 +462,8 @@ impl<'de> Deserializer<'de> { stack_ptr .add(depth) .write(StackState::Object { last_start, cnt }); + last_start = *r_i; } - last_start = r_i; insert_res!(Node::Object { len: 0, count: 0 }); depth += 1; cnt = 1; @@ -467,8 +474,8 @@ impl<'de> Deserializer<'de> { stack_ptr .add(depth) .write(StackState::Object { last_start, cnt }); + last_start = *r_i; } - last_start = r_i; insert_res!(Node::Array { len: 0, count: 0 }); depth += 1; cnt = 1; @@ -496,7 +503,7 @@ impl<'de> Deserializer<'de> { count: ref mut end, } => { *len = cnt; - *end = r_i - last_start - 1; + *end = *r_i - last_start - 1; } _ => unreachable!(), }; @@ -535,7 +542,10 @@ impl<'de> Deserializer<'de> { // on paths that can accept a close square brace (post-, and at start) match c { b'"' => { - insert_str!(); + unsafe { + let n = Self::parse_str_(input.as_mut_ptr(), &input2, buffer, idx)?; + insert_res!(Node::String(n)); + } array_continue!(); } b't' => { @@ -560,17 +570,13 @@ impl<'de> Deserializer<'de> { array_continue!(); } b'-' => { - insert_res!(Node::Static(s2try!(Self::parse_number( - idx, input2, true - )))); - + let n = Self::parse_number(idx, input2, true)?; + insert_res!(Node::Static(n)); array_continue!(); } b'0'..=b'9' => { - insert_res!(Node::Static(s2try!(Self::parse_number( - idx, input2, false - )))); - + let n = Self::parse_number(idx, input2, false)?; + insert_res!(Node::Static(n)); array_continue!(); } b'{' => { @@ -578,8 +584,8 @@ impl<'de> Deserializer<'de> { stack_ptr .add(depth) .write(StackState::Array { last_start, cnt }); + last_start = *r_i; } - last_start = r_i; insert_res!(Node::Object { len: 0, count: 0 }); depth += 1; cnt = 1; @@ -590,8 +596,8 @@ impl<'de> Deserializer<'de> { stack_ptr .add(depth) .write(StackState::Array { last_start, cnt }); + last_start = *r_i; } - last_start = r_i; insert_res!(Node::Array { len: 0, count: 0 }); depth += 1; cnt = 1; @@ -609,6 +615,8 @@ impl<'de> Deserializer<'de> { #[cfg(test)] mod test { + use iex::Outcome; + use crate::SIMDJSON_PADDING; use super::*; @@ -686,7 +694,8 @@ mod test { let mut buffer = vec![0; 1024]; let s = unsafe { - Deserializer::parse_str_(input.as_mut_ptr(), &input2, buffer.as_mut_slice(), 0)? + Deserializer::parse_str_(input.as_mut_ptr(), &input2, buffer.as_mut_slice(), 0) + .into_result()? }; assert_eq!(r#"{"arg":"test"}"#, s); Ok(()) diff --git a/src/stringparse.rs b/src/stringparse.rs index 6c5fcaac..e9c3a42e 100644 --- a/src/stringparse.rs +++ b/src/stringparse.rs @@ -29,6 +29,7 @@ const LOW_SURROGATES: Range = 0xdc00..0xe000; /// write appropriate values into dest #[cfg_attr(not(feature = "no-inline"), inline)] #[allow(dead_code)] +#[iex::iex] pub(crate) fn handle_unicode_codepoint( src_ptr: &[u8], dst_ptr: &mut [u8], @@ -45,6 +46,7 @@ pub(crate) fn handle_unicode_codepoint( /// return true if the unicode codepoint was valid /// We work in little-endian then swap at write time #[cfg_attr(not(feature = "no-inline"), inline)] +#[iex::iex] pub(crate) fn get_unicode_codepoint(mut src_ptr: &[u8]) -> Result<(u32, usize), ErrorType> { // hex_to_u32_nocheck fills high 16 bits of the return value with 1s if the // conversion isn't valid; we defer the check for this to inside the @@ -71,14 +73,10 @@ pub(crate) fn get_unicode_codepoint(mut src_ptr: &[u8]) -> Result<(u32, usize), if ((code_point | code_point_2) >> 16) != 0 { return Ok((0, src_offset)); } - let c1 = if let Some(c) = code_point.checked_sub(0xd800) { - c - } else { + let Some(c1) = code_point.checked_sub(0xd800) else { return Err(ErrorType::InvalidUtf8); }; - let c2 = if let Some(c) = code_point_2.checked_sub(0xdc00) { - c - } else { + let Some(c2) = code_point_2.checked_sub(0xdc00) else { return Err(ErrorType::InvalidUtf8); }; code_point = ((c1 << 10) | c2) + 0x10000; diff --git a/src/value.rs b/src/value.rs index 003ad621..81741b6f 100644 --- a/src/value.rs +++ b/src/value.rs @@ -70,6 +70,7 @@ pub use self::owned::{ }; use crate::{Buffers, Deserializer, Result}; use halfbrown::HashMap; +use iex::Outcome; use std::hash::Hash; use std::marker::PhantomData; use tape::Node; @@ -119,7 +120,7 @@ where Value: ValueBuilder<'de> + From> + From> + 'de, Key: Hash + Eq + From<&'de str>, { - match Deserializer::from_slice_with_buffers(s, buffers) { + match Deserializer::from_slice_with_buffers(s, buffers).into_result() { Ok(de) => Ok(ValueDeserializer::from_deserializer(de).parse()), Err(e) => Err(e), } diff --git a/src/value/borrowed.rs b/src/value/borrowed.rs index 7f9e5ee4..54930728 100644 --- a/src/value/borrowed.rs +++ b/src/value/borrowed.rs @@ -29,6 +29,7 @@ use crate::{cow::Cow, safer_unchecked::GetSaferUnchecked as _}; use crate::{prelude::*, Buffers}; use crate::{Deserializer, Node, Result}; use halfbrown::HashMap; +use iex::Outcome; use std::fmt; use std::ops::{Index, IndexMut}; @@ -66,7 +67,7 @@ pub fn to_value_with_buffers<'value>( s: &'value mut [u8], buffers: &mut Buffers, ) -> Result> { - match Deserializer::from_slice_with_buffers(s, buffers) { + match Deserializer::from_slice_with_buffers(s, buffers).into_result() { Ok(de) => Ok(BorrowDeserializer::from_deserializer(de).parse()), Err(e) => Err(e), } diff --git a/src/value/borrowed/cmp.rs b/src/value/borrowed/cmp.rs index c8c11a9f..d5749002 100644 --- a/src/value/borrowed/cmp.rs +++ b/src/value/borrowed/cmp.rs @@ -49,7 +49,7 @@ impl<'v> PartialEq for Value<'v> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &bool) -> bool { - self.as_bool().map(|t| t.eq(other)).unwrap_or_default() + self.as_bool().is_some_and(|t| t.eq(other)) } } @@ -57,7 +57,7 @@ impl<'v> PartialEq for Value<'v> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &str) -> bool { - self.as_str().map(|t| t.eq(other)).unwrap_or_default() + self.as_str().is_some_and(|t| t.eq(other)) } } @@ -73,7 +73,7 @@ impl<'v> PartialEq for Value<'v> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &String) -> bool { - self.as_str().map(|t| t.eq(other)).unwrap_or_default() + self.as_str().is_some_and(|t| t.eq(other)) } } @@ -81,7 +81,7 @@ impl<'v> PartialEq for Value<'v> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &i8) -> bool { - self.as_i8().map(|t| t.eq(other)).unwrap_or_default() + self.as_i8().is_some_and(|t| t.eq(other)) } } @@ -89,7 +89,7 @@ impl<'v> PartialEq for Value<'v> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &i16) -> bool { - self.as_i16().map(|t| t.eq(other)).unwrap_or_default() + self.as_i16().is_some_and(|t| t.eq(other)) } } @@ -97,7 +97,7 @@ impl<'v> PartialEq for Value<'v> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &i32) -> bool { - self.as_i32().map(|t| t.eq(other)).unwrap_or_default() + self.as_i32().is_some_and(|t| t.eq(other)) } } @@ -105,7 +105,7 @@ impl<'v> PartialEq for Value<'v> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &i64) -> bool { - self.as_i64().map(|t| t.eq(other)).unwrap_or_default() + self.as_i64().is_some_and(|t| t.eq(other)) } } @@ -113,7 +113,7 @@ impl<'v> PartialEq for Value<'v> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &i128) -> bool { - self.as_i128().map(|t| t.eq(other)).unwrap_or_default() + self.as_i128().is_some_and(|t| t.eq(other)) } } @@ -121,7 +121,7 @@ impl<'v> PartialEq for Value<'v> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &u8) -> bool { - self.as_u8().map(|t| t.eq(other)).unwrap_or_default() + self.as_u8().is_some_and(|t| t.eq(other)) } } @@ -129,7 +129,7 @@ impl<'v> PartialEq for Value<'v> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &u16) -> bool { - self.as_u16().map(|t| t.eq(other)).unwrap_or_default() + self.as_u16().is_some_and(|t| t.eq(other)) } } @@ -137,7 +137,7 @@ impl<'v> PartialEq for Value<'v> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &u32) -> bool { - self.as_u32().map(|t| t.eq(other)).unwrap_or_default() + self.as_u32().is_some_and(|t| t.eq(other)) } } @@ -145,7 +145,7 @@ impl<'v> PartialEq for Value<'v> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &u64) -> bool { - self.as_u64().map(|t| t.eq(other)).unwrap_or_default() + self.as_u64().is_some_and(|t| t.eq(other)) } } @@ -153,7 +153,7 @@ impl<'v> PartialEq for Value<'v> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &usize) -> bool { - self.as_usize().map(|t| t.eq(other)).unwrap_or_default() + self.as_usize().is_some_and(|t| t.eq(other)) } } @@ -161,7 +161,7 @@ impl<'v> PartialEq for Value<'v> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &u128) -> bool { - self.as_u128().map(|t| t.eq(other)).unwrap_or_default() + self.as_u128().is_some_and(|t| t.eq(other)) } } @@ -169,7 +169,7 @@ impl<'v> PartialEq for Value<'v> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &f32) -> bool { - self.as_f32().map(|t| t.eq(other)).unwrap_or_default() + self.as_f32().is_some_and(|t| t.eq(other)) } } @@ -177,7 +177,7 @@ impl<'v> PartialEq for Value<'v> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &f64) -> bool { - self.as_f64().map(|t| t.eq(other)).unwrap_or_default() + self.as_f64().is_some_and(|t| t.eq(other)) } } @@ -188,7 +188,7 @@ where #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &&[T]) -> bool { - self.as_array().map(|t| t.eq(other)).unwrap_or_default() + self.as_array().is_some_and(|t| t.eq(other)) } } diff --git a/src/value/borrowed/serialize.rs b/src/value/borrowed/serialize.rs index bae9c99a..3aec324a 100644 --- a/src/value/borrowed/serialize.rs +++ b/src/value/borrowed/serialize.rs @@ -57,30 +57,28 @@ trait Generator: BaseGenerator { self.write(b"{}") } else { let mut iter = object.iter(); - stry!(self.write(b"{")); + self.write(b"{")?; // We know this exists since it's not empty - let (key, value) = if let Some(v) = iter.next() { - v - } else { + let Some((key, value)) = iter.next() else { // We check against size unreachable!(); }; self.indent(); - stry!(self.new_line()); - stry!(self.write_simple_string(key)); - stry!(self.write_min(b": ", b':')); - stry!(self.write_json(value)); + self.new_line()?; + self.write_simple_string(key)?; + self.write_min(b": ", b':')?; + self.write_json(value)?; for (key, value) in iter { - stry!(self.write(b",")); - stry!(self.new_line()); - stry!(self.write_simple_string(key)); - stry!(self.write_min(b": ", b':')); - stry!(self.write_json(value)); + self.write(b",")?; + self.new_line()?; + self.write_simple_string(key)?; + self.write_min(b": ", b':')?; + self.write_json(value)?; } self.dedent(); - stry!(self.new_line()); + self.new_line()?; self.write(b"}") } } @@ -106,25 +104,23 @@ trait Generator: BaseGenerator { let mut iter = <[Value]>::iter(array); // We know we have one item - let item = if let Some(v) = iter.next() { - v - } else { + let Some(item) = iter.next() else { // We check against size unreachable!(); }; - stry!(self.write(b"[")); + self.write(b"[")?; self.indent(); - stry!(self.new_line()); - stry!(self.write_json(item)); + self.new_line()?; + self.write_json(item)?; for item in iter { - stry!(self.write(b",")); - stry!(self.new_line()); - stry!(self.write_json(item)); + self.write(b",")?; + self.new_line()?; + self.write_json(item)?; } self.dedent(); - stry!(self.new_line()); + self.new_line()?; self.write(b"]") } } @@ -142,24 +138,22 @@ trait FastGenerator: BaseGenerator { self.write(b"{}") } else { let mut iter = object.iter(); - stry!(self.write(b"{\"")); + self.write(b"{\"")?; // We know this exists since it's not empty - let (key, value) = if let Some(v) = iter.next() { - v - } else { + let Some((key, value)) = iter.next() else { // We check against size unreachable!(); }; - stry!(self.write_simple_str_content(key)); - stry!(self.write(b"\":")); - stry!(self.write_json(value)); + self.write_simple_str_content(key)?; + self.write(b"\":")?; + self.write_json(value)?; for (key, value) in iter { - stry!(self.write(b",\"")); - stry!(self.write_simple_str_content(key)); - stry!(self.write(b"\":")); - stry!(self.write_json(value)); + self.write(b",\"")?; + self.write_simple_str_content(key)?; + self.write(b"\":")?; + self.write_json(value)?; } self.write(b"}") } @@ -185,19 +179,17 @@ trait FastGenerator: BaseGenerator { } else { let mut iter = <[Value]>::iter(array); // We know we have one item - let item = if let Some(v) = iter.next() { - v - } else { + let Some(item) = iter.next() else { // We check against size unreachable!(); }; - stry!(self.write(b"[")); - stry!(self.write_json(item)); + self.write(b"[")?; + self.write_json(item)?; for item in iter { - stry!(self.write(b",")); - stry!(self.write_json(item)); + self.write(b",")?; + self.write_json(item)?; } self.write(b"]") } diff --git a/src/value/lazy/cmp.rs b/src/value/lazy/cmp.rs index 4e54998a..f99d3d1c 100644 --- a/src/value/lazy/cmp.rs +++ b/src/value/lazy/cmp.rs @@ -15,7 +15,7 @@ impl<'borrow, 'tape, 'input> PartialEq for Value<'borrow, 'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &bool) -> bool { - self.as_bool().map(|t| t.eq(other)).unwrap_or_default() + self.as_bool().is_some_and(|t| t.eq(other)) } } @@ -23,7 +23,7 @@ impl<'borrow, 'tape, 'input> PartialEq for Value<'borrow, 'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &str) -> bool { - self.as_str().map(|t| t.eq(other)).unwrap_or_default() + self.as_str().is_some_and(|t| t.eq(other)) } } @@ -39,7 +39,7 @@ impl<'borrow, 'tape, 'input> PartialEq for Value<'borrow, 'tape, 'input> #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &String) -> bool { - self.as_str().map(|t| t.eq(other)).unwrap_or_default() + self.as_str().is_some_and(|t| t.eq(other)) } } @@ -47,7 +47,7 @@ impl<'borrow, 'tape, 'input> PartialEq for Value<'borrow, 'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &i8) -> bool { - self.as_i8().map(|t| t.eq(other)).unwrap_or_default() + self.as_i8().is_some_and(|t| t.eq(other)) } } @@ -55,7 +55,7 @@ impl<'borrow, 'tape, 'input> PartialEq for Value<'borrow, 'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &i16) -> bool { - self.as_i16().map(|t| t.eq(other)).unwrap_or_default() + self.as_i16().is_some_and(|t| t.eq(other)) } } @@ -63,7 +63,7 @@ impl<'borrow, 'tape, 'input> PartialEq for Value<'borrow, 'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &i32) -> bool { - self.as_i32().map(|t| t.eq(other)).unwrap_or_default() + self.as_i32().is_some_and(|t| t.eq(other)) } } @@ -71,7 +71,7 @@ impl<'borrow, 'tape, 'input> PartialEq for Value<'borrow, 'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &i64) -> bool { - self.as_i64().map(|t| t.eq(other)).unwrap_or_default() + self.as_i64().is_some_and(|t| t.eq(other)) } } @@ -79,7 +79,7 @@ impl<'borrow, 'tape, 'input> PartialEq for Value<'borrow, 'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &i128) -> bool { - self.as_i128().map(|t| t.eq(other)).unwrap_or_default() + self.as_i128().is_some_and(|t| t.eq(other)) } } @@ -87,7 +87,7 @@ impl<'borrow, 'tape, 'input> PartialEq for Value<'borrow, 'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &u8) -> bool { - self.as_u8().map(|t| t.eq(other)).unwrap_or_default() + self.as_u8().is_some_and(|t| t.eq(other)) } } @@ -95,7 +95,7 @@ impl<'borrow, 'tape, 'input> PartialEq for Value<'borrow, 'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &u16) -> bool { - self.as_u16().map(|t| t.eq(other)).unwrap_or_default() + self.as_u16().is_some_and(|t| t.eq(other)) } } @@ -103,7 +103,7 @@ impl<'borrow, 'tape, 'input> PartialEq for Value<'borrow, 'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &u32) -> bool { - self.as_u32().map(|t| t.eq(other)).unwrap_or_default() + self.as_u32().is_some_and(|t| t.eq(other)) } } @@ -111,7 +111,7 @@ impl<'borrow, 'tape, 'input> PartialEq for Value<'borrow, 'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &u64) -> bool { - self.as_u64().map(|t| t.eq(other)).unwrap_or_default() + self.as_u64().is_some_and(|t| t.eq(other)) } } @@ -119,7 +119,7 @@ impl<'borrow, 'tape, 'input> PartialEq for Value<'borrow, 'tape, 'input> #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &usize) -> bool { - self.as_usize().map(|t| t.eq(other)).unwrap_or_default() + self.as_usize().is_some_and(|t| t.eq(other)) } } @@ -127,7 +127,7 @@ impl<'borrow, 'tape, 'input> PartialEq for Value<'borrow, 'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &u128) -> bool { - self.as_u128().map(|t| t.eq(other)).unwrap_or_default() + self.as_u128().is_some_and(|t| t.eq(other)) } } @@ -135,7 +135,7 @@ impl<'borrow, 'tape, 'input> PartialEq for Value<'borrow, 'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &f32) -> bool { - self.as_f32().map(|t| t.eq(other)).unwrap_or_default() + self.as_f32().is_some_and(|t| t.eq(other)) } } @@ -143,7 +143,7 @@ impl<'borrow, 'tape, 'input> PartialEq for Value<'borrow, 'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &f64) -> bool { - self.as_f64().map(|t| t.eq(other)).unwrap_or_default() + self.as_f64().is_some_and(|t| t.eq(other)) } } diff --git a/src/value/owned.rs b/src/value/owned.rs index c7d6e81f..867a4894 100644 --- a/src/value/owned.rs +++ b/src/value/owned.rs @@ -27,6 +27,7 @@ use super::ObjectHasher; use crate::{prelude::*, Buffers}; use crate::{Deserializer, Node, Result}; use halfbrown::HashMap; +use iex::Outcome; use std::fmt; use std::ops::{Index, IndexMut}; @@ -61,7 +62,7 @@ pub fn to_value(s: &mut [u8]) -> Result { /// /// Will return `Err` if `s` is invalid JSON. pub fn to_value_with_buffers(s: &mut [u8], buffers: &mut Buffers) -> Result { - match Deserializer::from_slice_with_buffers(s, buffers) { + match Deserializer::from_slice_with_buffers(s, buffers).into_result() { Ok(de) => Ok(OwnedDeserializer::from_deserializer(de).parse()), Err(e) => Err(e), } diff --git a/src/value/owned/cmp.rs b/src/value/owned/cmp.rs index 63dfa897..294c3f50 100644 --- a/src/value/owned/cmp.rs +++ b/src/value/owned/cmp.rs @@ -60,7 +60,7 @@ impl PartialEq for Value { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &bool) -> bool { - self.as_bool().map(|t| t.eq(other)).unwrap_or_default() + self.as_bool().is_some_and(|t| t.eq(other)) } } @@ -68,7 +68,7 @@ impl PartialEq for Value { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &str) -> bool { - self.as_str().map(|t| t.eq(other)).unwrap_or_default() + self.as_str().is_some_and(|t| t.eq(other)) } } @@ -84,7 +84,7 @@ impl PartialEq for Value { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &String) -> bool { - self.as_str().map(|t| t.eq(other)).unwrap_or_default() + self.as_str().is_some_and(|t| t.eq(other)) } } @@ -92,7 +92,7 @@ impl PartialEq for Value { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &i8) -> bool { - self.as_i8().map(|t| t.eq(other)).unwrap_or_default() + self.as_i8().is_some_and(|t| t.eq(other)) } } @@ -100,7 +100,7 @@ impl PartialEq for Value { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &i16) -> bool { - self.as_i16().map(|t| t.eq(other)).unwrap_or_default() + self.as_i16().is_some_and(|t| t.eq(other)) } } @@ -108,7 +108,7 @@ impl PartialEq for Value { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &i32) -> bool { - self.as_i32().map(|t| t.eq(other)).unwrap_or_default() + self.as_i32().is_some_and(|t| t.eq(other)) } } @@ -116,7 +116,7 @@ impl PartialEq for Value { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &i64) -> bool { - self.as_i64().map(|t| t.eq(other)).unwrap_or_default() + self.as_i64().is_some_and(|t| t.eq(other)) } } @@ -124,7 +124,7 @@ impl PartialEq for Value { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &i128) -> bool { - self.as_i128().map(|t| t.eq(other)).unwrap_or_default() + self.as_i128().is_some_and(|t| t.eq(other)) } } @@ -132,7 +132,7 @@ impl PartialEq for Value { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &u8) -> bool { - self.as_u8().map(|t| t.eq(other)).unwrap_or_default() + self.as_u8().is_some_and(|t| t.eq(other)) } } @@ -140,7 +140,7 @@ impl PartialEq for Value { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &u16) -> bool { - self.as_u16().map(|t| t.eq(other)).unwrap_or_default() + self.as_u16().is_some_and(|t| t.eq(other)) } } @@ -148,7 +148,7 @@ impl PartialEq for Value { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &u32) -> bool { - self.as_u32().map(|t| t.eq(other)).unwrap_or_default() + self.as_u32().is_some_and(|t| t.eq(other)) } } @@ -156,7 +156,7 @@ impl PartialEq for Value { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &u64) -> bool { - self.as_u64().map(|t| t.eq(other)).unwrap_or_default() + self.as_u64().is_some_and(|t| t.eq(other)) } } @@ -164,7 +164,7 @@ impl PartialEq for Value { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &usize) -> bool { - self.as_usize().map(|t| t.eq(other)).unwrap_or_default() + self.as_usize().is_some_and(|t| t.eq(other)) } } @@ -172,7 +172,7 @@ impl PartialEq for Value { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &u128) -> bool { - self.as_u128().map(|t| t.eq(other)).unwrap_or_default() + self.as_u128().is_some_and(|t| t.eq(other)) } } @@ -180,7 +180,7 @@ impl PartialEq for Value { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &f32) -> bool { - self.as_f32().map(|t| t.eq(other)).unwrap_or_default() + self.as_f32().is_some_and(|t| t.eq(other)) } } @@ -188,7 +188,7 @@ impl PartialEq for Value { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &f64) -> bool { - self.as_f64().map(|t| t.eq(other)).unwrap_or_default() + self.as_f64().is_some_and(|t| t.eq(other)) } } @@ -199,7 +199,7 @@ where #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &&[T]) -> bool { - self.as_array().map(|t| t.eq(other)).unwrap_or_default() + self.as_array().is_some_and(|t| t.eq(other)) } } impl PartialEq> for Value diff --git a/src/value/owned/serialize.rs b/src/value/owned/serialize.rs index 3ef60046..daf416cf 100644 --- a/src/value/owned/serialize.rs +++ b/src/value/owned/serialize.rs @@ -57,30 +57,28 @@ trait Generator: BaseGenerator { self.write(b"{}") } else { let mut iter = object.iter(); - stry!(self.write(b"{")); + self.write(b"{")?; // We know this exists since it's not empty - let (key, value) = if let Some(v) = iter.next() { - v - } else { + let Some((key, value)) = iter.next() else { // We check against size unreachable!(); }; self.indent(); - stry!(self.new_line()); - stry!(self.write_simple_string(key)); - stry!(self.write_min(b": ", b':')); - stry!(self.write_json(value)); + self.new_line()?; + self.write_simple_string(key)?; + self.write_min(b": ", b':')?; + self.write_json(value)?; for (key, value) in iter { - stry!(self.write(b",")); - stry!(self.new_line()); - stry!(self.write_simple_string(key)); - stry!(self.write_min(b": ", b':')); - stry!(self.write_json(value)); + self.write(b",")?; + self.new_line()?; + self.write_simple_string(key)?; + self.write_min(b": ", b':')?; + self.write_json(value)?; } self.dedent(); - stry!(self.new_line()); + self.new_line()?; self.write(b"}") } } @@ -106,27 +104,25 @@ trait Generator: BaseGenerator { let mut iter = <[Value]>::iter(array); // We know we have one item - let item = if let Some(v) = iter.next() { - v - } else { + let Some(item) = iter.next() else { // We check against size unreachable!(); }; - stry!(self.write(b"[")); + self.write(b"[")?; self.indent(); - stry!(self.new_line()); - stry!(self.write_json(item)); + self.new_line()?; + self.write_json(item)?; for item in iter { - stry!(self.write(b",")); - stry!(self.new_line()); - stry!(self.write_json(item)); + self.write(b",")?; + self.new_line()?; + self.write_json(item)?; } self.dedent(); - stry!(self.new_line()); + self.new_line()?; self.write(b"]") } } @@ -144,24 +140,22 @@ trait FastGenerator: BaseGenerator { self.write(b"{}") } else { let mut iter = object.iter(); - stry!(self.write(b"{\"")); + self.write(b"{\"")?; // We know this exists since it's not empty - let (key, value) = if let Some(v) = iter.next() { - v - } else { + let Some((key, value)) = iter.next() else { // We check against size unreachable!(); }; - stry!(self.write_simple_str_content(key)); - stry!(self.write(b"\":")); - stry!(self.write_json(value)); + self.write_simple_str_content(key)?; + self.write(b"\":")?; + self.write_json(value)?; for (key, value) in iter { - stry!(self.write(b",\"")); - stry!(self.write_simple_str_content(key)); - stry!(self.write(b"\":")); - stry!(self.write_json(value)); + self.write(b",\"")?; + self.write_simple_str_content(key)?; + self.write(b"\":")?; + self.write_json(value)?; } self.write(b"}") } @@ -187,19 +181,17 @@ trait FastGenerator: BaseGenerator { } else { let mut iter = <[Value]>::iter(array); // We know we have one item - let item = if let Some(v) = iter.next() { - v - } else { + let Some(item) = iter.next() else { // We check against size unreachable!(); }; - stry!(self.write(b"[")); - stry!(self.write_json(item)); + self.write(b"[")?; + self.write_json(item)?; for item in iter { - stry!(self.write(b",")); - stry!(self.write_json(item)); + self.write(b",")?; + self.write_json(item)?; } self.write(b"]") } diff --git a/src/value/tape/cmp.rs b/src/value/tape/cmp.rs index d79b8e00..d803316f 100644 --- a/src/value/tape/cmp.rs +++ b/src/value/tape/cmp.rs @@ -36,7 +36,7 @@ impl<'tape, 'input> PartialEq for Value<'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &bool) -> bool { - self.as_bool().map(|t| t.eq(other)).unwrap_or_default() + self.as_bool().is_some_and(|t| t.eq(other)) } } @@ -44,7 +44,7 @@ impl<'tape, 'input> PartialEq for Value<'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &str) -> bool { - self.as_str().map(|t| t.eq(other)).unwrap_or_default() + self.as_str().is_some_and(|t| t.eq(other)) } } @@ -60,7 +60,7 @@ impl<'tape, 'input> PartialEq for Value<'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &String) -> bool { - self.as_str().map(|t| t.eq(other)).unwrap_or_default() + self.as_str().is_some_and(|t| t.eq(other)) } } @@ -68,7 +68,7 @@ impl<'tape, 'input> PartialEq for Value<'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &i8) -> bool { - self.as_i8().map(|t| t.eq(other)).unwrap_or_default() + self.as_i8().is_some_and(|t| t.eq(other)) } } @@ -76,7 +76,7 @@ impl<'tape, 'input> PartialEq for Value<'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &i16) -> bool { - self.as_i16().map(|t| t.eq(other)).unwrap_or_default() + self.as_i16().is_some_and(|t| t.eq(other)) } } @@ -84,7 +84,7 @@ impl<'tape, 'input> PartialEq for Value<'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &i32) -> bool { - self.as_i32().map(|t| t.eq(other)).unwrap_or_default() + self.as_i32().is_some_and(|t| t.eq(other)) } } @@ -92,7 +92,7 @@ impl<'tape, 'input> PartialEq for Value<'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &i64) -> bool { - self.as_i64().map(|t| t.eq(other)).unwrap_or_default() + self.as_i64().is_some_and(|t| t.eq(other)) } } @@ -100,7 +100,7 @@ impl<'tape, 'input> PartialEq for Value<'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &i128) -> bool { - self.as_i128().map(|t| t.eq(other)).unwrap_or_default() + self.as_i128().is_some_and(|t| t.eq(other)) } } @@ -108,7 +108,7 @@ impl<'tape, 'input> PartialEq for Value<'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &u8) -> bool { - self.as_u8().map(|t| t.eq(other)).unwrap_or_default() + self.as_u8().is_some_and(|t| t.eq(other)) } } @@ -116,7 +116,7 @@ impl<'tape, 'input> PartialEq for Value<'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &u16) -> bool { - self.as_u16().map(|t| t.eq(other)).unwrap_or_default() + self.as_u16().is_some_and(|t| t.eq(other)) } } @@ -124,7 +124,7 @@ impl<'tape, 'input> PartialEq for Value<'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &u32) -> bool { - self.as_u32().map(|t| t.eq(other)).unwrap_or_default() + self.as_u32().is_some_and(|t| t.eq(other)) } } @@ -132,7 +132,7 @@ impl<'tape, 'input> PartialEq for Value<'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &u64) -> bool { - self.as_u64().map(|t| t.eq(other)).unwrap_or_default() + self.as_u64().is_some_and(|t| t.eq(other)) } } @@ -140,7 +140,7 @@ impl<'tape, 'input> PartialEq for Value<'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &usize) -> bool { - self.as_usize().map(|t| t.eq(other)).unwrap_or_default() + self.as_usize().is_some_and(|t| t.eq(other)) } } @@ -148,7 +148,7 @@ impl<'tape, 'input> PartialEq for Value<'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &u128) -> bool { - self.as_u128().map(|t| t.eq(other)).unwrap_or_default() + self.as_u128().is_some_and(|t| t.eq(other)) } } @@ -156,7 +156,7 @@ impl<'tape, 'input> PartialEq for Value<'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &f32) -> bool { - self.as_f32().map(|t| t.eq(other)).unwrap_or_default() + self.as_f32().is_some_and(|t| t.eq(other)) } } @@ -164,7 +164,7 @@ impl<'tape, 'input> PartialEq for Value<'tape, 'input> { #[cfg_attr(not(feature = "no-inline"), inline)] #[must_use] fn eq(&self, other: &f64) -> bool { - self.as_f64().map(|t| t.eq(other)).unwrap_or_default() + self.as_f64().is_some_and(|t| t.eq(other)) } } diff --git a/src/value/tape/trait_impls.rs b/src/value/tape/trait_impls.rs index 126ae616..fc66df14 100644 --- a/src/value/tape/trait_impls.rs +++ b/src/value/tape/trait_impls.rs @@ -699,30 +699,28 @@ trait Generator: BaseGenerator { self.write(b"{}") } else { let mut iter = object.iter(); - stry!(self.write(b"{")); + self.write(b"{")?; // We know this exists since it's not empty - let (key, value) = if let Some(v) = iter.next() { - v - } else { + let Some((key, value)) = iter.next() else { // We check against size unreachable!(); }; self.indent(); - stry!(self.new_line()); - stry!(self.write_simple_string(key)); - stry!(self.write_min(b": ", b':')); - stry!(self.write_json(&value)); + self.new_line()?; + self.write_simple_string(key)?; + self.write_min(b": ", b':')?; + self.write_json(&value)?; for (key, value) in iter { - stry!(self.write(b",")); - stry!(self.new_line()); - stry!(self.write_simple_string(key)); - stry!(self.write_min(b": ", b':')); - stry!(self.write_json(&value)); + self.write(b",")?; + self.new_line()?; + self.write_simple_string(key)?; + self.write_min(b": ", b':')?; + self.write_json(&value)?; } self.dedent(); - stry!(self.new_line()); + self.new_line()?; self.write(b"}") } } @@ -750,25 +748,23 @@ trait Generator: BaseGenerator { let mut iter = array.iter(); // We know we have one item - let item = if let Some(v) = iter.next() { - v - } else { + let Some(item) = iter.next() else { // We check against size unreachable!(); }; - stry!(self.write(b"[")); + self.write(b"[")?; self.indent(); - stry!(self.new_line()); - stry!(self.write_json(&item)); + self.new_line()?; + self.write_json(&item)?; for item in iter { - stry!(self.write(b",")); - stry!(self.new_line()); - stry!(self.write_json(&item)); + self.write(b",")?; + self.new_line()?; + self.write_json(&item)?; } self.dedent(); - stry!(self.new_line()); + self.new_line()?; self.write(b"]") } } @@ -786,24 +782,22 @@ trait FastGenerator: BaseGenerator { self.write(b"{}") } else { let mut iter = object.iter(); - stry!(self.write(b"{\"")); + self.write(b"{\"")?; // We know this exists since it's not empty - let (key, value) = if let Some(v) = iter.next() { - v - } else { + let Some((key, value)) = iter.next() else { // We check against size unreachable!(); }; - stry!(self.write_simple_str_content(key)); - stry!(self.write(b"\":")); - stry!(self.write_json(&value)); + self.write_simple_str_content(key)?; + self.write(b"\":")?; + self.write_json(&value)?; for (key, value) in iter { - stry!(self.write(b",\"")); - stry!(self.write_simple_str_content(key)); - stry!(self.write(b"\":")); - stry!(self.write_json(&value)); + self.write(b",\"")?; + self.write_simple_str_content(key)?; + self.write(b"\":")?; + self.write_json(&value)?; } self.write(b"}") } @@ -830,19 +824,17 @@ trait FastGenerator: BaseGenerator { let array = Array(&json.0[..=count]); let mut iter = array.iter(); // We know we have one item - let item = if let Some(v) = iter.next() { - v - } else { + let Some(item) = iter.next() else { // We check against size unreachable!(); }; - stry!(self.write(b"[")); - stry!(self.write_json(&item)); + self.write(b"[")?; + self.write_json(&item)?; for item in iter { - stry!(self.write(b",")); - stry!(self.write_json(&item)); + self.write(b",")?; + self.write_json(&item)?; } self.write(b"]") }