From 0fd7a0c1b0b67473612a8e82c7fcd14c97206149 Mon Sep 17 00:00:00 2001 From: "Heinz N. Gies" Date: Fri, 23 Aug 2024 22:16:44 +0200 Subject: [PATCH 01/10] bye bye stry Signed-off-by: Heinz N. Gies --- src/macros.rs | 13 --- src/serde.rs | 17 ++-- src/serde/de.rs | 42 +++++----- src/serde/se/pp.rs | 4 +- src/serde/value/borrowed/se.rs | 19 ++--- src/serde/value/owned/se.rs | 15 ++-- src/stage2.rs | 140 +++++++++++--------------------- src/value/borrowed/serialize.rs | 60 +++++++------- src/value/owned/serialize.rs | 60 +++++++------- src/value/tape/trait_impls.rs | 60 +++++++------- 10 files changed, 182 insertions(+), 248 deletions(-) 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/serde.rs b/src/serde.rs index df08e906..da19b568 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -11,8 +11,8 @@ 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 serde::de::DeserializeOwned; use serde_ext::Deserialize; use std::fmt; @@ -57,7 +57,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 +74,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)?; T::deserialize(&mut deserializer) } @@ -98,7 +98,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 +125,7 @@ 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)?; T::deserialize(&mut deserializer) } @@ -149,7 +146,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 +168,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_with_buffers(&mut data, buffers)); + let mut deserializer = Deserializer::from_slice_with_buffers(&mut data, buffers)?; 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/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/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..40f48b55 100644 --- a/src/stage2.rs +++ b/src/stage2.rs @@ -107,13 +107,11 @@ impl<'de> Deserializer<'de> { 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,39 +123,12 @@ 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; - } - }; - } - macro_rules! success { - () => { - unsafe { - res.set_len(r_i); - } - return Ok(()); + res.push($t); }; } + macro_rules! update_char { () => { if i < structural_indexes.len() { @@ -179,12 +150,14 @@ impl<'de> Deserializer<'de> { macro_rules! insert_str { () => { - insert_res!(Node::String(s2try!(Self::parse_str_( - input.as_mut_ptr(), - &input2, - buffer, - idx - )))); + unsafe { + insert_res!(Node::String(Self::parse_str_( + input.as_mut_ptr(), + &input2, + buffer, + idx + )?)); + } }; } @@ -265,12 +238,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 +245,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)); }; } @@ -296,7 +257,7 @@ impl<'de> Deserializer<'de> { stack_ptr.add(depth).write(StackState::Start); } - last_start = r_i; + last_start = res.len(); insert_res!(Node::Object { len: 0, count: 0 }); depth += 1; @@ -322,7 +283,7 @@ impl<'de> Deserializer<'de> { stack_ptr.add(depth).write(StackState::Start); } - last_start = r_i; + last_start = res.len(); insert_res!(Node::Array { len: 0, count: 0 }); depth += 1; @@ -344,7 +305,7 @@ impl<'de> Deserializer<'de> { }; insert_res!(Node::Static(StaticNode::Bool(true))); if i == structural_indexes.len() { - success!(); + return Ok(()); } fail!(ErrorType::TrailingData); } @@ -356,7 +317,7 @@ impl<'de> Deserializer<'de> { }; insert_res!(Node::Static(StaticNode::Bool(false))); if i == structural_indexes.len() { - success!(); + return Ok(()); } fail!(ErrorType::TrailingData); } @@ -368,30 +329,30 @@ impl<'de> Deserializer<'de> { }; insert_res!(Node::Static(StaticNode::Null)); if i == structural_indexes.len() { - success!(); + return Ok(()); } fail!(ErrorType::TrailingData); } b'"' => { insert_str!(); if i == structural_indexes.len() { - success!(); + return Ok(()); } fail!(ErrorType::TrailingData); } b'-' => { - insert_res!(Node::Static(s2try!(Self::parse_number(idx, input2, true)))); + insert_res!(Node::Static(Self::parse_number(idx, input2, true)?)); if i == structural_indexes.len() { - success!(); + return Ok(()); } fail!(ErrorType::TrailingData); } b'0'..=b'9' => { - insert_res!(Node::Static(s2try!(Self::parse_number(idx, input2, false)))); + insert_res!(Node::Static(Self::parse_number(idx, input2, false)?)); if i == structural_indexes.len() { - success!(); + return Ok(()); } fail!(ErrorType::TrailingData); } @@ -437,16 +398,12 @@ impl<'de> Deserializer<'de> { object_continue!(); } b'-' => { - insert_res!(Node::Static(s2try!(Self::parse_number( - idx, input2, true - )))); + insert_res!(Node::Static(Self::parse_number(idx, input2, true)?)); object_continue!(); } b'0'..=b'9' => { - insert_res!(Node::Static(s2try!(Self::parse_number( - idx, input2, false - )))); + insert_res!(Node::Static(Self::parse_number(idx, input2, false)?)); object_continue!(); } @@ -456,7 +413,7 @@ impl<'de> Deserializer<'de> { .add(depth) .write(StackState::Object { last_start, cnt }); } - last_start = r_i; + last_start = res.len(); insert_res!(Node::Object { len: 0, count: 0 }); depth += 1; cnt = 1; @@ -468,7 +425,7 @@ impl<'de> Deserializer<'de> { .add(depth) .write(StackState::Object { last_start, cnt }); } - last_start = r_i; + last_start = res.len(); insert_res!(Node::Array { len: 0, count: 0 }); depth += 1; cnt = 1; @@ -485,22 +442,23 @@ impl<'de> Deserializer<'de> { fail!(ErrorType::Syntax); } depth -= 1; - unsafe { - match *res_ptr.add(last_start) { - Node::Array { - ref mut len, - count: ref mut end, - } - | Node::Object { - ref mut len, - count: ref mut end, - } => { - *len = cnt; - *end = r_i - last_start - 1; - } - _ => unreachable!(), - }; - } + + let r_i = res.len(); + match unsafe { res.get_unchecked_mut(last_start) } { + Node::Array { + ref mut len, + count: ref mut end, + } + | Node::Object { + ref mut len, + count: ref mut end, + } => { + *len = cnt; + *end = r_i - last_start - 1; + } + _ => unreachable!(), + }; + unsafe { match *stack_ptr.add(depth) { StackState::Object { @@ -521,7 +479,7 @@ impl<'de> Deserializer<'de> { } StackState::Start => { if i == structural_indexes.len() { - success!(); + return Ok(()); } fail!(); } @@ -560,17 +518,11 @@ impl<'de> Deserializer<'de> { array_continue!(); } b'-' => { - insert_res!(Node::Static(s2try!(Self::parse_number( - idx, input2, true - )))); - + insert_res!(Node::Static(Self::parse_number(idx, input2, true)?)); array_continue!(); } b'0'..=b'9' => { - insert_res!(Node::Static(s2try!(Self::parse_number( - idx, input2, false - )))); - + insert_res!(Node::Static(Self::parse_number(idx, input2, false)?)); array_continue!(); } b'{' => { @@ -579,7 +531,7 @@ impl<'de> Deserializer<'de> { .add(depth) .write(StackState::Array { last_start, cnt }); } - last_start = r_i; + last_start = res.len(); insert_res!(Node::Object { len: 0, count: 0 }); depth += 1; cnt = 1; @@ -591,7 +543,7 @@ impl<'de> Deserializer<'de> { .add(depth) .write(StackState::Array { last_start, cnt }); } - last_start = r_i; + last_start = res.len(); insert_res!(Node::Array { len: 0, count: 0 }); depth += 1; cnt = 1; diff --git a/src/value/borrowed/serialize.rs b/src/value/borrowed/serialize.rs index bae9c99a..4bcdc46f 100644 --- a/src/value/borrowed/serialize.rs +++ b/src/value/borrowed/serialize.rs @@ -57,7 +57,7 @@ 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() { @@ -67,20 +67,20 @@ trait Generator: BaseGenerator { 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"}") } } @@ -112,19 +112,19 @@ trait Generator: BaseGenerator { // 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,7 +142,7 @@ 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() { @@ -151,15 +151,15 @@ trait FastGenerator: BaseGenerator { // 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"}") } @@ -192,12 +192,12 @@ trait FastGenerator: BaseGenerator { 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/owned/serialize.rs b/src/value/owned/serialize.rs index 3ef60046..cbad98e7 100644 --- a/src/value/owned/serialize.rs +++ b/src/value/owned/serialize.rs @@ -57,7 +57,7 @@ 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() { @@ -67,20 +67,20 @@ trait Generator: BaseGenerator { 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"}") } } @@ -113,20 +113,20 @@ trait Generator: BaseGenerator { 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,7 +144,7 @@ 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() { @@ -153,15 +153,15 @@ trait FastGenerator: BaseGenerator { // 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"}") } @@ -194,12 +194,12 @@ trait FastGenerator: BaseGenerator { 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/trait_impls.rs b/src/value/tape/trait_impls.rs index 126ae616..2615084e 100644 --- a/src/value/tape/trait_impls.rs +++ b/src/value/tape/trait_impls.rs @@ -699,7 +699,7 @@ 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() { @@ -709,20 +709,20 @@ trait Generator: BaseGenerator { 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"}") } } @@ -756,19 +756,19 @@ trait Generator: BaseGenerator { // 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,7 +786,7 @@ 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() { @@ -795,15 +795,15 @@ trait FastGenerator: BaseGenerator { // 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"}") } @@ -837,12 +837,12 @@ trait FastGenerator: BaseGenerator { 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"]") } From 1d419b5d18ff24f0a71a59fb24cdf8b2ec276555 Mon Sep 17 00:00:00 2001 From: "Heinz N. Gies" Date: Fri, 23 Aug 2024 23:16:15 +0200 Subject: [PATCH 02/10] taking a stab Signed-off-by: Heinz N. Gies --- Cargo.toml | 1 + src/impls/avx2/deser.rs | 1 + src/impls/native/deser.rs | 1 + src/impls/neon/deser.rs | 1 + src/impls/portable/deser.rs | 1 + src/impls/simd128/deser.rs | 1 + src/impls/sse42/deser.rs | 1 + src/lib.rs | 15 +++- src/numberparse/correct.rs | 132 ++++++++++++++++++++++++++---------- src/stage2.rs | 107 ++++++++++++++++------------- 10 files changed, 178 insertions(+), 83 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 419b0725..a78e5f16 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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..e1ddc0c7 100644 --- a/src/impls/avx2/deser.rs +++ b/src/impls/avx2/deser.rs @@ -23,6 +23,7 @@ use crate::{ clippy::too_many_lines )] #[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/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..8bda50d8 100644 --- a/src/impls/neon/deser.rs +++ b/src/impls/neon/deser.rs @@ -42,6 +42,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], 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..8ccdb392 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; @@ -547,6 +548,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 +608,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 +623,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 +643,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 +661,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 +674,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 +686,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 +850,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 +862,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 +914,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 +924,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()); diff --git a/src/numberparse/correct.rs b/src/numberparse/correct.rs index b7706256..57d41504 100644 --- a/src/numberparse/correct.rs +++ b/src/numberparse/correct.rs @@ -17,18 +17,17 @@ 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)) - }; -} macro_rules! check_overflow { ($overflowed:ident, $buf:ident, $idx:ident, $start_idx:ident, $end_index:ident) => { if $overflowed { #[cfg(not(feature = "big-int-as-float"))] { - err!($idx, get!($buf, $idx)) + return Err(Error::new_c( + $idx, + get!($buf, $idx) as char, + ErrorType::InvalidNumber, + )); } #[cfg(feature = "big-int-as-float")] { @@ -55,13 +54,18 @@ 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)) + return Err(Error::new_c( + idx, + get!(buf, idx) as char, + ErrorType::InvalidNumber, + )); } } let mut start = idx; @@ -69,11 +73,19 @@ 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)) + return Err(Error::new_c( + idx, + get!(buf, idx) as char, + ErrorType::InvalidNumber, + )); } } else { if !is_integer(get!(buf, idx)) { - err!(idx, get!(buf, idx)) + return Err(Error::new_c( + idx, + get!(buf, idx) as char, + ErrorType::InvalidNumber, + )); } num = u64::from(get!(buf, idx) - b'0'); idx += 1; @@ -96,7 +108,11 @@ impl<'de> Deserializer<'de> { .wrapping_add(u64::from(get!(buf, idx) - b'0')); idx += 1; } else { - err!(idx, get!(buf, idx)) + return Err(Error::new_c( + idx, + get!(buf, idx) as char, + ErrorType::InvalidNumber, + )); } #[cfg(feature = "swar-number-parsing")] @@ -139,7 +155,11 @@ impl<'de> Deserializer<'de> { } } if !is_integer(get!(buf, idx)) { - err!(idx, get!(buf, idx)) + return Err(Error::new_c( + idx, + get!(buf, idx) as char, + ErrorType::InvalidNumber, + )); } let mut exp_number = i64::from(get!(buf, idx) - b'0'); idx += 1; @@ -153,7 +173,11 @@ impl<'de> Deserializer<'de> { } while is_integer(get!(buf, idx)) { if exp_number > 0x0001_0000_0000 { - err!(idx, get!(buf, idx)) + return Err(Error::new_c( + idx, + get!(buf, idx) as char, + ErrorType::InvalidNumber, + )); } exp_number = 10 * exp_number + i64::from(get!(buf, idx) - b'0'); idx += 1; @@ -170,33 +194,43 @@ 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)) + return Err(Error::new_c( + idx, + get!(buf, idx) as char, + ErrorType::InvalidNumber, + )); } - 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)) + Err(Error::new_c( + idx, + get!(buf, idx) as char, + ErrorType::InvalidNumber, + )) } else { - Ok(if negative { + let res = if negative { StaticNode::I64(unsafe { static_cast_i64!(num.wrapping_neg()) }) // -(num as i64) } else { StaticNode::U64(num) - }) + }; + Ok(res) } } } @@ -204,6 +238,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], @@ -237,7 +272,11 @@ fn parse_large_integer( } match (negative, num) { (true, 9_223_372_036_854_775_808) => Ok(StaticNode::I64(i64::MIN)), - (true, 9_223_372_036_854_775_809..=u64::MAX) => err!(idx, get!(buf, idx)), + (true, 9_223_372_036_854_775_809..=u64::MAX) => Err(Error::new_c( + idx, + get!(buf, idx) as char, + ErrorType::InvalidNumber, + )), (true, 0..=9_223_372_036_854_775_807) => Ok(StaticNode::I64(-(num as i64))), (false, _) => Ok(StaticNode::U64(num)), } @@ -246,6 +285,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 +347,7 @@ fn parse_large_integer( clippy::cast_precision_loss, clippy::cast_possible_wrap )] +#[iex::iex] fn f64_from_parts( positive: bool, significand: u64, @@ -321,10 +362,14 @@ fn f64_from_parts( } else { f *= get!(POW10, exponent); } - Ok(StaticNode::F64(if positive { f } else { -f })) - } else if significand == 0 { - Ok(StaticNode::F64(if positive { 0.0 } else { -0.0 })) - } else if (-325..=308).contains(&exponent) { + let res = StaticNode::F64(if positive { f } else { -f }); + return Ok(res); + } + if significand == 0 { + let res = StaticNode::F64(if positive { 0.0 } else { -0.0 }); + return Ok(res); + } + if (-325..=308).contains(&exponent) { let (factor_mantissa, factor_exponent) = get!(POW10_COMPONENTS, exponent + 325); let mut leading_zeroes = u64::from(significand.leading_zeros()); let f = significand << leading_zeroes; @@ -342,7 +387,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 +398,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,33 +411,51 @@ 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)) + Err(Error::new_c( + offset, + get!(slice, offset) as char, + ErrorType::InvalidNumber, + )) + } else { + let res = StaticNode::F64(res); + Ok(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)) + return Err(Error::new_c( + offset, + get!(slice, 0) as char, + ErrorType::InvalidNumber, + )); } Ok(StaticNode::F64(val)) } - Err(_) => err!(offset, get!(slice, offset)), + Err(_) => { + return Err(Error::new_c( + offset, + get!(slice, offset) as char, + ErrorType::InvalidNumber, + )) + } } } diff --git a/src/stage2.rs b/src/stage2.rs index 40f48b55..1b44ac3a 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], @@ -123,12 +126,6 @@ impl<'de> Deserializer<'de> { let mut i: usize = 0; let mut state; - macro_rules! insert_res { - ($t:expr) => { - res.push($t); - }; - } - macro_rules! update_char { () => { if i < structural_indexes.len() { @@ -148,19 +145,6 @@ impl<'de> Deserializer<'de> { }}; } - macro_rules! insert_str { - () => { - unsafe { - insert_res!(Node::String(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. @@ -191,7 +175,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()?; + res.push(Node::String(n)); + } goto!(ObjectKey); } fail!(ErrorType::ExpectedObjectKey); @@ -222,7 +210,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()?; + res.push(Node::String(n)); + } goto!(ObjectKey) } b'}' => { @@ -258,7 +250,7 @@ impl<'de> Deserializer<'de> { } last_start = res.len(); - insert_res!(Node::Object { len: 0, count: 0 }); + res.push(Node::Object { len: 0, count: 0 }); depth += 1; cnt = 1; @@ -266,7 +258,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)?; + res.push(Node::String(n)); + } state = State::ObjectKey; } b'}' => { @@ -284,7 +279,7 @@ impl<'de> Deserializer<'de> { } last_start = res.len(); - insert_res!(Node::Array { len: 0, count: 0 }); + res.push(Node::Array { len: 0, count: 0 }); depth += 1; cnt = 1; @@ -303,7 +298,7 @@ impl<'de> Deserializer<'de> { fail!(ErrorType::ExpectedTrue); } }; - insert_res!(Node::Static(StaticNode::Bool(true))); + res.push(Node::Static(StaticNode::Bool(true))); if i == structural_indexes.len() { return Ok(()); } @@ -315,7 +310,7 @@ impl<'de> Deserializer<'de> { fail!(ErrorType::ExpectedFalse); } }; - insert_res!(Node::Static(StaticNode::Bool(false))); + res.push(Node::Static(StaticNode::Bool(false))); if i == structural_indexes.len() { return Ok(()); } @@ -327,21 +322,25 @@ impl<'de> Deserializer<'de> { fail!(ErrorType::ExpectedNull); } }; - insert_res!(Node::Static(StaticNode::Null)); + res.push(Node::Static(StaticNode::Null)); if i == structural_indexes.len() { return Ok(()); } fail!(ErrorType::TrailingData); } b'"' => { - insert_str!(); + unsafe { + let n = Self::parse_str_(input.as_mut_ptr(), &input2, buffer, idx)?; + res.push(Node::String(n)); + } if i == structural_indexes.len() { return Ok(()); } fail!(ErrorType::TrailingData); } b'-' => { - insert_res!(Node::Static(Self::parse_number(idx, input2, true)?)); + let n = Self::parse_number(idx, input2, true)?; + res.push(Node::Static(n)); if i == structural_indexes.len() { return Ok(()); @@ -349,7 +348,8 @@ impl<'de> Deserializer<'de> { fail!(ErrorType::TrailingData); } b'0'..=b'9' => { - insert_res!(Node::Static(Self::parse_number(idx, input2, false)?)); + let n = Self::parse_number(idx, input2, false)?; + res.push(Node::Static(n)); if i == structural_indexes.len() { return Ok(()); @@ -373,37 +373,42 @@ impl<'de> Deserializer<'de> { update_char!(); match c { b'"' => { - insert_str!(); + unsafe { + let n = Self::parse_str_(input.as_mut_ptr(), &input2, buffer, idx)?; + res.push(Node::String(n)); + } object_continue!(); } b't' => { - insert_res!(Node::Static(StaticNode::Bool(true))); + res.push(Node::Static(StaticNode::Bool(true))); if !is_valid_true_atom(get!(input2, idx..)) { fail!(ErrorType::ExpectedTrue); } object_continue!(); } b'f' => { - insert_res!(Node::Static(StaticNode::Bool(false))); + res.push(Node::Static(StaticNode::Bool(false))); if !is_valid_false_atom(get!(input2, idx..)) { fail!(ErrorType::ExpectedFalse); } object_continue!(); } b'n' => { - insert_res!(Node::Static(StaticNode::Null)); + res.push(Node::Static(StaticNode::Null)); if !is_valid_null_atom(get!(input2, idx..)) { fail!(ErrorType::ExpectedNull); } object_continue!(); } b'-' => { - insert_res!(Node::Static(Self::parse_number(idx, input2, true)?)); + let n = Self::parse_number(idx, input2, true)?; + res.push(Node::Static(n)); object_continue!(); } b'0'..=b'9' => { - insert_res!(Node::Static(Self::parse_number(idx, input2, false)?)); + let n = Self::parse_number(idx, input2, false)?; + res.push(Node::Static(n)); object_continue!(); } @@ -414,7 +419,7 @@ impl<'de> Deserializer<'de> { .write(StackState::Object { last_start, cnt }); } last_start = res.len(); - insert_res!(Node::Object { len: 0, count: 0 }); + res.push(Node::Object { len: 0, count: 0 }); depth += 1; cnt = 1; object_begin!(); @@ -426,7 +431,7 @@ impl<'de> Deserializer<'de> { .write(StackState::Object { last_start, cnt }); } last_start = res.len(); - insert_res!(Node::Array { len: 0, count: 0 }); + res.push(Node::Array { len: 0, count: 0 }); depth += 1; cnt = 1; array_begin!(); @@ -493,36 +498,41 @@ 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)?; + res.push(Node::String(n)); + } array_continue!(); } b't' => { - insert_res!(Node::Static(StaticNode::Bool(true))); + res.push(Node::Static(StaticNode::Bool(true))); if !is_valid_true_atom(get!(input2, idx..)) { fail!(ErrorType::ExpectedTrue); } array_continue!(); } b'f' => { - insert_res!(Node::Static(StaticNode::Bool(false))); + res.push(Node::Static(StaticNode::Bool(false))); if !is_valid_false_atom(get!(input2, idx..)) { fail!(ErrorType::ExpectedFalse); } array_continue!(); } b'n' => { - insert_res!(Node::Static(StaticNode::Null)); + res.push(Node::Static(StaticNode::Null)); if !is_valid_null_atom(get!(input2, idx..)) { fail!(ErrorType::ExpectedNull); } array_continue!(); } b'-' => { - insert_res!(Node::Static(Self::parse_number(idx, input2, true)?)); + let n = Self::parse_number(idx, input2, true)?; + res.push(Node::Static(n)); array_continue!(); } b'0'..=b'9' => { - insert_res!(Node::Static(Self::parse_number(idx, input2, false)?)); + let n = Self::parse_number(idx, input2, false)?; + res.push(Node::Static(n)); array_continue!(); } b'{' => { @@ -532,7 +542,7 @@ impl<'de> Deserializer<'de> { .write(StackState::Array { last_start, cnt }); } last_start = res.len(); - insert_res!(Node::Object { len: 0, count: 0 }); + res.push(Node::Object { len: 0, count: 0 }); depth += 1; cnt = 1; object_begin!(); @@ -544,7 +554,7 @@ impl<'de> Deserializer<'de> { .write(StackState::Array { last_start, cnt }); } last_start = res.len(); - insert_res!(Node::Array { len: 0, count: 0 }); + res.push(Node::Array { len: 0, count: 0 }); depth += 1; cnt = 1; array_begin!(); @@ -561,6 +571,8 @@ impl<'de> Deserializer<'de> { #[cfg(test)] mod test { + use iex::Outcome; + use crate::SIMDJSON_PADDING; use super::*; @@ -638,7 +650,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(()) From e396713150705616411095e9ebf2c9b2893cfe0f Mon Sep 17 00:00:00 2001 From: "Heinz N. Gies" Date: Fri, 23 Aug 2024 23:28:52 +0200 Subject: [PATCH 03/10] Re-add else Signed-off-by: Heinz N. Gies --- src/numberparse/correct.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/numberparse/correct.rs b/src/numberparse/correct.rs index 57d41504..a7f00bd9 100644 --- a/src/numberparse/correct.rs +++ b/src/numberparse/correct.rs @@ -363,13 +363,11 @@ fn f64_from_parts( f *= get!(POW10, exponent); } let res = StaticNode::F64(if positive { f } else { -f }); - return Ok(res); - } - if significand == 0 { + Ok(res) + } else if significand == 0 { let res = StaticNode::F64(if positive { 0.0 } else { -0.0 }); - return Ok(res); - } - if (-325..=308).contains(&exponent) { + Ok(res) + } else if (-325..=308).contains(&exponent) { let (factor_mantissa, factor_exponent) = get!(POW10_COMPONENTS, exponent + 325); let mut leading_zeroes = u64::from(significand.leading_zeros()); let f = significand << leading_zeroes; From 535b5f26f5763129856556f78a42c62814d6201c Mon Sep 17 00:00:00 2001 From: "Heinz N. Gies" Date: Fri, 23 Aug 2024 23:35:19 +0200 Subject: [PATCH 04/10] Fix compilation oopsies Signed-off-by: Heinz N. Gies --- src/lib.rs | 6 ++++-- src/serde.rs | 9 ++++++--- src/value.rs | 3 ++- src/value/borrowed.rs | 3 ++- src/value/owned.rs | 3 ++- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 8ccdb392..f83f706c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -226,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 @@ -236,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 { diff --git a/src/serde.rs b/src/serde.rs index da19b568..0796a39c 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -13,6 +13,7 @@ pub use self::se::*; pub use self::value::*; 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; @@ -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 = Deserializer::from_slice_with_buffers(s, buffers)?; + let mut deserializer = Deserializer::from_slice_with_buffers(s, buffers).into_result()?; T::deserialize(&mut deserializer) } @@ -125,7 +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 = 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) } @@ -168,7 +170,8 @@ where if let Err(e) = rdr.read_to_end(&mut data) { return Err(Error::generic(ErrorType::Io(e))); }; - let mut deserializer = 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/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/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), } From b58d09a52b06c4d41799b66ae6fa70e577c7e94d Mon Sep 17 00:00:00 2001 From: "Heinz N. Gies" Date: Fri, 23 Aug 2024 23:38:23 +0200 Subject: [PATCH 05/10] Bump rust version Signed-off-by: Heinz N. Gies --- .github/workflows/quality.yaml | 19 +++++++++---------- Cargo.toml | 2 +- 2 files changed, 10 insertions(+), 11 deletions(-) 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 a78e5f16..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"] } From 293adfcf6e6c6c7e3c11957fa8052a380d390e5c Mon Sep 17 00:00:00 2001 From: "Heinz N. Gies" Date: Fri, 23 Aug 2024 23:40:03 +0200 Subject: [PATCH 06/10] Try to move things around for clippy Signed-off-by: Heinz N. Gies --- src/impls/avx2/deser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/impls/avx2/deser.rs b/src/impls/avx2/deser.rs index e1ddc0c7..cbe0f124 100644 --- a/src/impls/avx2/deser.rs +++ b/src/impls/avx2/deser.rs @@ -16,7 +16,6 @@ use crate::{ Deserializer, Result, SillyWrapper, }; -#[target_feature(enable = "avx2")] #[allow( clippy::if_not_else, clippy::cast_possible_wrap, @@ -24,6 +23,7 @@ use crate::{ )] #[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], From e05884f971aa8378e8cc9a6c5b7b31cd6273c309 Mon Sep 17 00:00:00 2001 From: "Heinz N. Gies" Date: Sat, 24 Aug 2024 13:54:28 +0200 Subject: [PATCH 07/10] cleanup Signed-off-by: Heinz N. Gies --- src/lib.rs | 10 ++--- src/numberparse/correct.rs | 82 +++++++++------------------------- src/serde/value/borrowed/de.rs | 14 ++---- src/serde/value/owned/de.rs | 7 +-- src/value/borrowed/cmp.rs | 34 +++++++------- src/value/lazy/cmp.rs | 32 ++++++------- src/value/owned/cmp.rs | 34 +++++++------- src/value/tape/cmp.rs | 32 ++++++------- 8 files changed, 97 insertions(+), 148 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f83f706c..14621219 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1126,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/numberparse/correct.rs b/src/numberparse/correct.rs index a7f00bd9..e57dc221 100644 --- a/src/numberparse/correct.rs +++ b/src/numberparse/correct.rs @@ -12,6 +12,12 @@ use crate::safer_unchecked::GetSaferUnchecked; use crate::StaticNode; use crate::{Deserializer, ErrorType, Result}; +macro_rules! err { + ($idx:ident, $num:expr) => { + return Err(Error::new_c($idx, $num as char, ErrorType::InvalidNumber)) + }; +} + macro_rules! get { ($buf:ident, $idx:expr) => { unsafe { *$buf.get_kinda_unchecked($idx as usize) } @@ -23,11 +29,7 @@ macro_rules! check_overflow { if $overflowed { #[cfg(not(feature = "big-int-as-float"))] { - return Err(Error::new_c( - $idx, - get!($buf, $idx) as char, - ErrorType::InvalidNumber, - )); + err!($idx, get!($buf, $idx)); } #[cfg(feature = "big-int-as-float")] { @@ -61,11 +63,7 @@ impl<'de> Deserializer<'de> { if negative { idx += 1; if !is_integer(get!(buf, idx)) { - return Err(Error::new_c( - idx, - get!(buf, idx) as char, - ErrorType::InvalidNumber, - )); + err!(idx, get!(buf, idx)); } } let mut start = idx; @@ -73,19 +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)) { - return Err(Error::new_c( - idx, - get!(buf, idx) as char, - ErrorType::InvalidNumber, - )); + err!(idx, get!(buf, idx)); } } else { if !is_integer(get!(buf, idx)) { - return Err(Error::new_c( - idx, - get!(buf, idx) as char, - ErrorType::InvalidNumber, - )); + err!(idx, get!(buf, idx)); } num = u64::from(get!(buf, idx) - b'0'); idx += 1; @@ -108,11 +98,7 @@ impl<'de> Deserializer<'de> { .wrapping_add(u64::from(get!(buf, idx) - b'0')); idx += 1; } else { - return Err(Error::new_c( - idx, - get!(buf, idx) as char, - ErrorType::InvalidNumber, - )); + err!(idx, get!(buf, idx)); } #[cfg(feature = "swar-number-parsing")] @@ -155,11 +141,7 @@ impl<'de> Deserializer<'de> { } } if !is_integer(get!(buf, idx)) { - return Err(Error::new_c( - idx, - get!(buf, idx) as char, - ErrorType::InvalidNumber, - )); + err!(idx, get!(buf, idx)); } let mut exp_number = i64::from(get!(buf, idx) - b'0'); idx += 1; @@ -173,11 +155,7 @@ impl<'de> Deserializer<'de> { } while is_integer(get!(buf, idx)) { if exp_number > 0x0001_0000_0000 { - return Err(Error::new_c( - idx, - get!(buf, idx) as char, - ErrorType::InvalidNumber, - )); + err!(idx, get!(buf, idx)); } exp_number = 10 * exp_number + i64::from(get!(buf, idx) - b'0'); idx += 1; @@ -202,11 +180,7 @@ impl<'de> Deserializer<'de> { } } if is_structural_or_whitespace(get!(buf, idx)) == 0 { - return Err(Error::new_c( - idx, - get!(buf, idx) as char, - ErrorType::InvalidNumber, - )); + err!(idx, get!(buf, idx)); } Ok(f64_from_parts( !negative, @@ -224,13 +198,11 @@ impl<'de> Deserializer<'de> { ErrorType::InvalidNumber, )) } else { - let res = if negative { + Ok(if negative { StaticNode::I64(unsafe { static_cast_i64!(num.wrapping_neg()) }) - // -(num as i64) } else { StaticNode::U64(num) - }; - Ok(res) + }) } } } @@ -362,11 +334,9 @@ fn f64_from_parts( } else { f *= get!(POW10, exponent); } - let res = StaticNode::F64(if positive { f } else { -f }); - Ok(res) + Ok(StaticNode::F64(if positive { f } else { -f })) } else if significand == 0 { - let res = StaticNode::F64(if positive { 0.0 } else { -0.0 }); - Ok(res) + Ok(StaticNode::F64(if positive { 0.0 } else { -0.0 })) } else if (-325..=308).contains(&exponent) { let (factor_mantissa, factor_exponent) = get!(POW10_COMPONENTS, exponent + 325); let mut leading_zeroes = u64::from(significand.leading_zeros()); @@ -421,8 +391,7 @@ fn f64_from_parts( ErrorType::InvalidNumber, )) } else { - let res = StaticNode::F64(res); - Ok(res) + Ok(StaticNode::F64(res)) } } else { let res = f64_from_parts_slow(slice, offset)?; @@ -438,21 +407,12 @@ fn f64_from_parts_slow(slice: &[u8], offset: usize) -> Result { match unsafe { std::str::from_utf8_unchecked(slice).parse::() } { Ok(val) => { if val.is_infinite() { - return Err(Error::new_c( - offset, - get!(slice, 0) as char, - ErrorType::InvalidNumber, - )); + err!(offset, get!(slice, 0)); } - Ok(StaticNode::F64(val)) } Err(_) => { - return Err(Error::new_c( - offset, - get!(slice, offset) as char, - ErrorType::InvalidNumber, - )) + err!(offset, get!(slice, offset)); } } } 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/owned/de.rs b/src/serde/value/owned/de.rs index e4321c37..6dd1eec2 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() { 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/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/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/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)) } } From 6db11868edd8bd250aa75fddcf090e752cc99ddd Mon Sep 17 00:00:00 2001 From: "Heinz N. Gies" Date: Sat, 24 Aug 2024 14:02:40 +0200 Subject: [PATCH 08/10] make clippy happy Signed-off-by: Heinz N. Gies --- src/serde/value/owned/de.rs | 7 ++----- src/stringparse.rs | 8 ++------ src/value/borrowed/serialize.rs | 16 ++++------------ src/value/owned/serialize.rs | 16 ++++------------ src/value/tape/trait_impls.rs | 16 ++++------------ 5 files changed, 16 insertions(+), 47 deletions(-) diff --git a/src/serde/value/owned/de.rs b/src/serde/value/owned/de.rs index 6dd1eec2..66948fc4 100644 --- a/src/serde/value/owned/de.rs +++ b/src/serde/value/owned/de.rs @@ -670,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/stringparse.rs b/src/stringparse.rs index 6c5fcaac..f35a9f5e 100644 --- a/src/stringparse.rs +++ b/src/stringparse.rs @@ -71,14 +71,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/borrowed/serialize.rs b/src/value/borrowed/serialize.rs index 4bcdc46f..3aec324a 100644 --- a/src/value/borrowed/serialize.rs +++ b/src/value/borrowed/serialize.rs @@ -60,9 +60,7 @@ trait Generator: BaseGenerator { 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!(); }; @@ -106,9 +104,7 @@ 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!(); }; @@ -145,9 +141,7 @@ trait FastGenerator: BaseGenerator { 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!(); }; @@ -185,9 +179,7 @@ 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!(); }; diff --git a/src/value/owned/serialize.rs b/src/value/owned/serialize.rs index cbad98e7..daf416cf 100644 --- a/src/value/owned/serialize.rs +++ b/src/value/owned/serialize.rs @@ -60,9 +60,7 @@ trait Generator: BaseGenerator { 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!(); }; @@ -106,9 +104,7 @@ 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!(); }; @@ -147,9 +143,7 @@ trait FastGenerator: BaseGenerator { 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!(); }; @@ -187,9 +181,7 @@ 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!(); }; diff --git a/src/value/tape/trait_impls.rs b/src/value/tape/trait_impls.rs index 2615084e..fc66df14 100644 --- a/src/value/tape/trait_impls.rs +++ b/src/value/tape/trait_impls.rs @@ -702,9 +702,7 @@ trait Generator: BaseGenerator { 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!(); }; @@ -750,9 +748,7 @@ 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!(); }; @@ -789,9 +785,7 @@ trait FastGenerator: BaseGenerator { 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!(); }; @@ -830,9 +824,7 @@ 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!(); }; From 90bd636b504769703cb292d4fc92106909275a9c Mon Sep 17 00:00:00 2001 From: "Heinz N. Gies" Date: Sat, 24 Aug 2024 14:28:23 +0200 Subject: [PATCH 09/10] Some more iexing Signed-off-by: Heinz N. Gies --- src/impls/neon/deser.rs | 11 +++++------ src/numberparse/approx.rs | 4 ++++ src/stringparse.rs | 2 ++ 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/impls/neon/deser.rs b/src/impls/neon/deser.rs index 8bda50d8..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; @@ -169,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/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/stringparse.rs b/src/stringparse.rs index f35a9f5e..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 From e2cdfb85e361d7d690282714951221721ae258bd Mon Sep 17 00:00:00 2001 From: "Heinz N. Gies" Date: Tue, 27 Aug 2024 23:43:56 +0200 Subject: [PATCH 10/10] Revert some earlier changes to make things faster in stage 2 Signed-off-by: Heinz N. Gies --- src/numberparse/correct.rs | 34 +++----- src/stage2.rs | 160 +++++++++++++++++++++++-------------- 2 files changed, 112 insertions(+), 82 deletions(-) diff --git a/src/numberparse/correct.rs b/src/numberparse/correct.rs index e57dc221..9e3e338f 100644 --- a/src/numberparse/correct.rs +++ b/src/numberparse/correct.rs @@ -12,18 +12,18 @@ use crate::safer_unchecked::GetSaferUnchecked; use crate::StaticNode; use crate::{Deserializer, ErrorType, Result}; -macro_rules! err { - ($idx:ident, $num:expr) => { - return Err(Error::new_c($idx, $num as char, ErrorType::InvalidNumber)) - }; -} - macro_rules! get { ($buf:ident, $idx:expr) => { 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)) + }; +} + macro_rules! check_overflow { ($overflowed:ident, $buf:ident, $idx:ident, $start_idx:ident, $end_index:ident) => { if $overflowed { @@ -192,11 +192,7 @@ impl<'de> Deserializer<'de> { } else if unlikely!(digit_count >= 18) { Ok(parse_large_integer(start_idx, buf, negative, idx)?) } else if is_structural_or_whitespace(get!(buf, idx)) == 0 { - Err(Error::new_c( - idx, - get!(buf, idx) as char, - ErrorType::InvalidNumber, - )) + err!(idx, get!(buf, idx)) } else { Ok(if negative { StaticNode::I64(unsafe { static_cast_i64!(num.wrapping_neg()) }) @@ -244,11 +240,7 @@ fn parse_large_integer( } match (negative, num) { (true, 9_223_372_036_854_775_808) => Ok(StaticNode::I64(i64::MIN)), - (true, 9_223_372_036_854_775_809..=u64::MAX) => Err(Error::new_c( - idx, - get!(buf, idx) as char, - ErrorType::InvalidNumber, - )), + (true, 9_223_372_036_854_775_809..=u64::MAX) => err!(idx, get!(buf, idx)), (true, 0..=9_223_372_036_854_775_807) => Ok(StaticNode::I64(-(num as i64))), (false, _) => Ok(StaticNode::U64(num)), } @@ -385,11 +377,7 @@ fn f64_from_parts( mantissa |= u64::from(!positive) << 63; let res = f64::from_bits(mantissa); if res.is_infinite() { - Err(Error::new_c( - offset, - get!(slice, offset) as char, - ErrorType::InvalidNumber, - )) + err!(offset, get!(slice, offset)) } else { Ok(StaticNode::F64(res)) } @@ -411,9 +399,7 @@ fn f64_from_parts_slow(slice: &[u8], offset: usize) -> Result { } Ok(StaticNode::F64(val)) } - Err(_) => { - err!(offset, get!(slice, offset)); - } + Err(_) => err!(offset, get!(slice, offset)), } } diff --git a/src/stage2.rs b/src/stage2.rs index 1b44ac3a..6f361d82 100644 --- a/src/stage2.rs +++ b/src/stage2.rs @@ -105,6 +105,39 @@ 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(); @@ -126,6 +159,19 @@ impl<'de> Deserializer<'de> { let mut i: usize = 0; let mut state; + macro_rules! insert_res { + ($t:expr) => { + unsafe { + res_ptr.add(*r_i).write($t); + *r_i += 1; + } + }; + } + macro_rules! success { + () => { + return Ok(()); + }; + } macro_rules! update_char { () => { if i < structural_indexes.len() { @@ -178,7 +224,7 @@ impl<'de> Deserializer<'de> { unsafe { let n = Self::parse_str_(input.as_mut_ptr(), &input2, buffer, idx) .into_result()?; - res.push(Node::String(n)); + insert_res!(Node::String(n)); } goto!(ObjectKey); } @@ -213,7 +259,7 @@ impl<'de> Deserializer<'de> { unsafe { let n = Self::parse_str_(input.as_mut_ptr(), &input2, buffer, idx) .into_result()?; - res.push(Node::String(n)); + insert_res!(Node::String(n)); } goto!(ObjectKey) } @@ -247,10 +293,10 @@ impl<'de> Deserializer<'de> { b'{' => { unsafe { stack_ptr.add(depth).write(StackState::Start); + last_start = *r_i; } - last_start = res.len(); - res.push(Node::Object { len: 0, count: 0 }); + insert_res!(Node::Object { len: 0, count: 0 }); depth += 1; cnt = 1; @@ -260,7 +306,7 @@ impl<'de> Deserializer<'de> { b'"' => { unsafe { let n = Self::parse_str_(input.as_mut_ptr(), &input2, buffer, idx)?; - res.push(Node::String(n)); + insert_res!(Node::String(n)); } state = State::ObjectKey; } @@ -276,10 +322,9 @@ impl<'de> Deserializer<'de> { b'[' => { unsafe { stack_ptr.add(depth).write(StackState::Start); + last_start = *r_i; } - - last_start = res.len(); - res.push(Node::Array { len: 0, count: 0 }); + insert_res!(Node::Array { len: 0, count: 0 }); depth += 1; cnt = 1; @@ -298,9 +343,9 @@ impl<'de> Deserializer<'de> { fail!(ErrorType::ExpectedTrue); } }; - res.push(Node::Static(StaticNode::Bool(true))); + insert_res!(Node::Static(StaticNode::Bool(true))); if i == structural_indexes.len() { - return Ok(()); + success!(); } fail!(ErrorType::TrailingData); } @@ -310,9 +355,9 @@ impl<'de> Deserializer<'de> { fail!(ErrorType::ExpectedFalse); } }; - res.push(Node::Static(StaticNode::Bool(false))); + insert_res!(Node::Static(StaticNode::Bool(false))); if i == structural_indexes.len() { - return Ok(()); + success!(); } fail!(ErrorType::TrailingData); } @@ -322,37 +367,37 @@ impl<'de> Deserializer<'de> { fail!(ErrorType::ExpectedNull); } }; - res.push(Node::Static(StaticNode::Null)); + insert_res!(Node::Static(StaticNode::Null)); if i == structural_indexes.len() { - return Ok(()); + success!(); } fail!(ErrorType::TrailingData); } b'"' => { unsafe { let n = Self::parse_str_(input.as_mut_ptr(), &input2, buffer, idx)?; - res.push(Node::String(n)); + insert_res!(Node::String(n)); } if i == structural_indexes.len() { - return Ok(()); + success!(); } fail!(ErrorType::TrailingData); } b'-' => { let n = Self::parse_number(idx, input2, true)?; - res.push(Node::Static(n)); + insert_res!(Node::Static(n)); if i == structural_indexes.len() { - return Ok(()); + success!(); } fail!(ErrorType::TrailingData); } b'0'..=b'9' => { let n = Self::parse_number(idx, input2, false)?; - res.push(Node::Static(n)); + insert_res!(Node::Static(n)); if i == structural_indexes.len() { - return Ok(()); + success!(); } fail!(ErrorType::TrailingData); } @@ -375,26 +420,26 @@ impl<'de> Deserializer<'de> { b'"' => { unsafe { let n = Self::parse_str_(input.as_mut_ptr(), &input2, buffer, idx)?; - res.push(Node::String(n)); + insert_res!(Node::String(n)); } object_continue!(); } b't' => { - res.push(Node::Static(StaticNode::Bool(true))); + insert_res!(Node::Static(StaticNode::Bool(true))); if !is_valid_true_atom(get!(input2, idx..)) { fail!(ErrorType::ExpectedTrue); } object_continue!(); } b'f' => { - res.push(Node::Static(StaticNode::Bool(false))); + insert_res!(Node::Static(StaticNode::Bool(false))); if !is_valid_false_atom(get!(input2, idx..)) { fail!(ErrorType::ExpectedFalse); } object_continue!(); } b'n' => { - res.push(Node::Static(StaticNode::Null)); + insert_res!(Node::Static(StaticNode::Null)); if !is_valid_null_atom(get!(input2, idx..)) { fail!(ErrorType::ExpectedNull); } @@ -402,13 +447,13 @@ impl<'de> Deserializer<'de> { } b'-' => { let n = Self::parse_number(idx, input2, true)?; - res.push(Node::Static(n)); + insert_res!(Node::Static(n)); object_continue!(); } b'0'..=b'9' => { let n = Self::parse_number(idx, input2, false)?; - res.push(Node::Static(n)); + insert_res!(Node::Static(n)); object_continue!(); } @@ -417,9 +462,9 @@ impl<'de> Deserializer<'de> { stack_ptr .add(depth) .write(StackState::Object { last_start, cnt }); + last_start = *r_i; } - last_start = res.len(); - res.push(Node::Object { len: 0, count: 0 }); + insert_res!(Node::Object { len: 0, count: 0 }); depth += 1; cnt = 1; object_begin!(); @@ -429,9 +474,9 @@ impl<'de> Deserializer<'de> { stack_ptr .add(depth) .write(StackState::Object { last_start, cnt }); + last_start = *r_i; } - last_start = res.len(); - res.push(Node::Array { len: 0, count: 0 }); + insert_res!(Node::Array { len: 0, count: 0 }); depth += 1; cnt = 1; array_begin!(); @@ -447,23 +492,22 @@ impl<'de> Deserializer<'de> { fail!(ErrorType::Syntax); } depth -= 1; - - let r_i = res.len(); - match unsafe { res.get_unchecked_mut(last_start) } { - Node::Array { - ref mut len, - count: ref mut end, - } - | Node::Object { - ref mut len, - count: ref mut end, - } => { - *len = cnt; - *end = r_i - last_start - 1; - } - _ => unreachable!(), - }; - + unsafe { + match *res_ptr.add(last_start) { + Node::Array { + ref mut len, + count: ref mut end, + } + | Node::Object { + ref mut len, + count: ref mut end, + } => { + *len = cnt; + *end = *r_i - last_start - 1; + } + _ => unreachable!(), + }; + } unsafe { match *stack_ptr.add(depth) { StackState::Object { @@ -484,7 +528,7 @@ impl<'de> Deserializer<'de> { } StackState::Start => { if i == structural_indexes.len() { - return Ok(()); + success!(); } fail!(); } @@ -500,26 +544,26 @@ impl<'de> Deserializer<'de> { b'"' => { unsafe { let n = Self::parse_str_(input.as_mut_ptr(), &input2, buffer, idx)?; - res.push(Node::String(n)); + insert_res!(Node::String(n)); } array_continue!(); } b't' => { - res.push(Node::Static(StaticNode::Bool(true))); + insert_res!(Node::Static(StaticNode::Bool(true))); if !is_valid_true_atom(get!(input2, idx..)) { fail!(ErrorType::ExpectedTrue); } array_continue!(); } b'f' => { - res.push(Node::Static(StaticNode::Bool(false))); + insert_res!(Node::Static(StaticNode::Bool(false))); if !is_valid_false_atom(get!(input2, idx..)) { fail!(ErrorType::ExpectedFalse); } array_continue!(); } b'n' => { - res.push(Node::Static(StaticNode::Null)); + insert_res!(Node::Static(StaticNode::Null)); if !is_valid_null_atom(get!(input2, idx..)) { fail!(ErrorType::ExpectedNull); } @@ -527,12 +571,12 @@ impl<'de> Deserializer<'de> { } b'-' => { let n = Self::parse_number(idx, input2, true)?; - res.push(Node::Static(n)); + insert_res!(Node::Static(n)); array_continue!(); } b'0'..=b'9' => { let n = Self::parse_number(idx, input2, false)?; - res.push(Node::Static(n)); + insert_res!(Node::Static(n)); array_continue!(); } b'{' => { @@ -540,9 +584,9 @@ impl<'de> Deserializer<'de> { stack_ptr .add(depth) .write(StackState::Array { last_start, cnt }); + last_start = *r_i; } - last_start = res.len(); - res.push(Node::Object { len: 0, count: 0 }); + insert_res!(Node::Object { len: 0, count: 0 }); depth += 1; cnt = 1; object_begin!(); @@ -552,9 +596,9 @@ impl<'de> Deserializer<'de> { stack_ptr .add(depth) .write(StackState::Array { last_start, cnt }); + last_start = *r_i; } - last_start = res.len(); - res.push(Node::Array { len: 0, count: 0 }); + insert_res!(Node::Array { len: 0, count: 0 }); depth += 1; cnt = 1; array_begin!();