Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce how much code is generated #745

Open
wants to merge 34 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
1a739c1
refactor: Factor out whitespace skipping into helpers
Jun 30, 2020
b01ff91
refactor: Add next_char_or_error
Jul 2, 2020
fcd4dc1
Move more non-generic code out of the generic path
Jul 2, 2020
57dc798
Move eat_char into the _until function
Jul 2, 2020
b9540a7
Move even more code out of the generic deserialize_struct
Jul 2, 2020
3e0d096
Move recursion checking out of the generic path
Jul 2, 2020
b63097f
Factor out non-generic parts of next_element_seed
Jul 2, 2020
3c327b0
Factor out non-generic parts of next_key_seed
Jul 2, 2020
4e98512
Use try_with!
Jul 2, 2020
e6216e6
Move non-generic code out of deserialize_any
Jul 2, 2020
1ca5734
s/field/element/
Jul 2, 2020
061247b
Avoid using map in generic functions
Jul 2, 2020
52259b9
refactor: Add helpers for serializing begin/end key/object
Jul 2, 2020
87d36a5
Move out code from the generic string deserialization methods
Jul 3, 2020
322f8c4
Shrink deserialize_struct a bit more
Jul 3, 2020
5d5ad07
refactor: Factor out the duplicated variant serialization
Jan 4, 2021
33ef802
refactor: add begin/end_string helpers
Jan 4, 2021
5cf7a6f
refactor: Avoid a tri! in commonly instantiated code
Jan 4, 2021
cacd1b7
refactor: Various shortenings
Jan 4, 2021
6fd698c
Further extract code out of deserialize_any
Jan 5, 2021
9f16c61
refactor: Extract parse_option
Jan 5, 2021
d28a020
Shorten unit deserializing
Jan 5, 2021
f77905a
Extract helpers to reduce map_err calls
Jan 5, 2021
760ccb2
refactor: Remove unnecessary tri! calls
Jan 5, 2021
9956638
refactor: Extract a less generic part of deserialize_number
Jan 5, 2021
0f15688
refactor: Extract code from deserialize_enum
Jan 5, 2021
60cdfbd
refactor: De-duplicate the recursion checking
Jan 5, 2021
4de41fd
Add an OptionResult enum
Jan 11, 2021
9e56187
inline
Jan 11, 2021
010eb7c
Extract prefixes for deserialize_seq and map
Jan 12, 2021
2067058
Reuse Deserialzer::parse_str
Jan 12, 2021
0fa7a8f
Remove end_map, end_seq
Jan 12, 2021
f595267
Fix check_recursion_prefix
Jan 12, 2021
60e4ac2
Fix clippy
Jan 12, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Move non-generic code out of deserialize_any
  • Loading branch information
Markus Westerlind authored and Markus Westerlind committed Jul 4, 2022
commit e6216e6804257d1b9f37a4c86d99431a0e862709
177 changes: 103 additions & 74 deletions src/de.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,39 @@
//! Deserialize JSON data to a Rust data structure.

use crate::error::{Error, ErrorCode, Result};
#[cfg(feature = "float_roundtrip")]
use crate::lexical;
use crate::number::Number;
use crate::read::{self, Fused, Reference};
use alloc::string::String;
use alloc::vec::Vec;
use alloc::{string::String, vec::Vec};
#[cfg(feature = "float_roundtrip")]
use core::iter;
use core::iter::FusedIterator;
use core::marker::PhantomData;
use core::result;
use core::str::FromStr;
use serde::de::{self, Expected, Unexpected};
use serde::{forward_to_deserialize_any, serde_if_integer128};
use core::{iter::FusedIterator, marker::PhantomData, result, str::FromStr};

use serde::{
de::{self, Expected, Unexpected},
forward_to_deserialize_any, serde_if_integer128,
};

#[cfg(feature = "float_roundtrip")]
use crate::lexical;
#[cfg(feature = "arbitrary_precision")]
use crate::number::NumberDeserializer;

pub use crate::read::{Read, SliceRead, StrRead};

#[cfg(feature = "std")]
pub use crate::read::IoRead;
pub use crate::read::{Read, SliceRead, StrRead};
use crate::{
error::{Error, ErrorCode, Result},
number::Number,
read::{self, Fused, Reference},
};

macro_rules! try_with {
($e:expr, $wrap:expr) => {
match $e {
core::result::Result::Ok(val) => val,
core::result::Result::Err(err) => return $wrap(err),
}
};
($e:expr, $wrap:expr,) => {
try_with!($e, $wrap)
};
}

//////////////////////////////////////////////////////////////////////////////

Expand Down Expand Up @@ -172,6 +183,16 @@ macro_rules! check_recursion {
};
}

enum AnyResult {
Null,
Bool(bool),
Number(bool),
String,
Array,
Map,
Error(Error),
}

impl<'de, R: Read<'de>> Deserializer<R> {
/// The `Deserializer::end` method should be called after a value has been fully deserialized.
/// This allows the `Deserializer` to validate that the input stream is at the end or that it
Expand Down Expand Up @@ -290,6 +311,57 @@ impl<'de, R: Read<'de>> Deserializer<R> {
Error::syntax(reason, position.line, position.column)
}

fn parse_any_prefix(&mut self) -> AnyResult {
match try_with!(self.parse_whitespace_in_value(), AnyResult::Error) {
b'n' => {
self.eat_char();
try_with!(self.parse_ident(b"ull"), AnyResult::Error);
AnyResult::Null
}
b't' => {
self.eat_char();
try_with!(self.parse_ident(b"rue"), AnyResult::Error);
AnyResult::Bool(true)
}
b'f' => {
self.eat_char();
try_with!(self.parse_ident(b"alse"), AnyResult::Error);
AnyResult::Bool(false)
}
b'-' => {
self.eat_char();
AnyResult::Number(false)
}
b'0'..=b'9' => AnyResult::Number(true),
b'"' => {
self.eat_char();
self.scratch.clear();
AnyResult::String
}
b'[' => {
self.eat_char();
if_checking_recursion_limit! {
self.remaining_depth -= 1;
if self.remaining_depth == 0 {
return AnyResult::Error(self.error(ErrorCode::RecursionLimitExceeded));
}
}
AnyResult::Array
}
b'{' => {
self.eat_char();
if_checking_recursion_limit! {
self.remaining_depth -= 1;
if self.remaining_depth == 0 {
return AnyResult::Error(self.error(ErrorCode::RecursionLimitExceeded));
}
}
AnyResult::Map
}
_ => AnyResult::Error(self.peek_error(ErrorCode::ExpectedSomeValue)),
}
}

fn parse_struct_prefix(&mut self, exp: &dyn Expected) -> StructResult {
match self.parse_whitespace_in_value() {
Ok(b'[') => {
Expand Down Expand Up @@ -1357,62 +1429,31 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer<R> {
where
V: de::Visitor<'de>,
{
let peek = tri!(self.parse_whitespace_in_value());

let value = match peek {
b'n' => {
self.eat_char();
tri!(self.parse_ident(b"ull"));
visitor.visit_unit()
}
b't' => {
self.eat_char();
tri!(self.parse_ident(b"rue"));
visitor.visit_bool(true)
}
b'f' => {
self.eat_char();
tri!(self.parse_ident(b"alse"));
visitor.visit_bool(false)
}
b'-' => {
self.eat_char();
tri!(self.parse_any_number(false)).visit(visitor)
}
b'0'..=b'9' => tri!(self.parse_any_number(true)).visit(visitor),
b'"' => {
self.eat_char();
self.scratch.clear();
match tri!(self.read.parse_str(&mut self.scratch)) {
Reference::Borrowed(s) => visitor.visit_borrowed_str(s),
Reference::Copied(s) => visitor.visit_str(s),
}
}
b'[' => {
self.eat_char();
check_recursion! {
self;
let ret = visitor.visit_seq(SeqAccess::new(self));
}
let value = match self.parse_any_prefix() {
AnyResult::Null => visitor.visit_unit(),
AnyResult::Bool(b) => visitor.visit_bool(b),
AnyResult::Number(positive) => tri!(self.parse_any_number(positive)).visit(visitor),
AnyResult::String => match tri!(self.read.parse_str(&mut self.scratch)) {
Reference::Borrowed(s) => visitor.visit_borrowed_str(s),
Reference::Copied(s) => visitor.visit_str(s),
},
AnyResult::Array => {
let ret = visitor.visit_seq(SeqAccess::new(self));

match (ret, self.end_seq()) {
match (ret, self.end_recursion_and_seq()) {
(Ok(ret), Ok(())) => Ok(ret),
(Err(err), _) | (_, Err(err)) => Err(err),
}
}
b'{' => {
self.eat_char();
check_recursion! {
self;
let ret = visitor.visit_map(MapAccess::new(self));
}
AnyResult::Map => {
let ret = visitor.visit_map(MapAccess::new(self));

match (ret, self.end_map()) {
match (ret, self.end_recursion_and_map()) {
(Ok(ret), Ok(())) => Ok(ret),
(Err(err), _) | (_, Err(err)) => Err(err),
}
}
_ => Err(self.peek_error(ErrorCode::ExpectedSomeValue)),
AnyResult::Error(err) => Err(err),
};

match value {
Expand Down Expand Up @@ -1851,18 +1892,6 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer<R> {
}
}

macro_rules! try_with {
($e:expr, $wrap:expr) => {
match $e {
crate::lib::Result::Ok(val) => val,
crate::lib::Result::Err(err) => return $wrap(err),
}
};
($e:expr, $wrap:expr,) => {
try_with!($e, $wrap)
};
}

struct SeqAccess<'a, R: 'a> {
de: &'a mut Deserializer<R>,
first: bool,
Expand Down