Skip to content

Commit

Permalink
fix ident consumption and float errors
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelcolvin committed Oct 30, 2023
1 parent 4c57940 commit 9aa16aa
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 35 deletions.
16 changes: 9 additions & 7 deletions src/number_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use num_bigint::BigInt;
use num_traits::cast::ToPrimitive;
use std::ops::Range;

use lexical_core::{format as lexical_format, parse_partial_with_options, Error as LexicalError, ParseFloatOptions};
use lexical_core::{format as lexical_format, parse_partial_with_options, ParseFloatOptions};

use crate::errors::{json_err, JsonResult};

Expand Down Expand Up @@ -62,17 +62,19 @@ pub struct NumberFloat;
impl AbstractNumberDecoder for NumberFloat {
type Output = f64;

fn decode(data: &[u8], index: usize, _first: u8) -> JsonResult<(Self::Output, usize)> {
fn decode(data: &[u8], index: usize, first: u8) -> JsonResult<(Self::Output, usize)> {
let start = index;
const JSON: u128 = lexical_format::JSON;
let options = ParseFloatOptions::new();
match parse_partial_with_options::<f64, JSON>(&data[start..], &options) {
Ok((float, index)) => Ok((float, index + start)),
Err(e) => {
// dbg!(e);
match e {
LexicalError::EmptyExponent(_) => json_err!(EofWhileParsingValue, index),
_ => json_err!(InvalidNumber, index),
Err(_) => {
// it's impossible to work out the right error from LexicalError here, so we parse again
// with NumberRange and use that error
match NumberRange::decode(data, start, first) {
Err(e) => Err(e),
// shouldn't happen
Ok(_) => json_err!(InvalidNumber, index),
}
}
}
Expand Down
47 changes: 23 additions & 24 deletions src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,36 +199,15 @@ impl<'a> Parser<'a> {
}

pub fn consume_true(&mut self) -> JsonResult<()> {
match self.data.get(self.index + 1..self.index + 4) {
Some(s) if s == TRUE_REST => {
self.index += 4;
Ok(())
}
Some(_) => json_err!(ExpectedSomeIdent, self.index),
None => json_err!(EofWhileParsingValue, self.data.len()),
}
self.consume_ident(TRUE_REST)
}

pub fn consume_false(&mut self) -> JsonResult<()> {
match self.data.get(self.index + 1..self.index + 5) {
Some(s) if s == FALSE_REST => {
self.index += 5;
Ok(())
}
Some(_) => json_err!(ExpectedSomeIdent, self.index),
None => json_err!(EofWhileParsingValue, self.data.len()),
}
self.consume_ident(FALSE_REST)
}

pub fn consume_null(&mut self) -> JsonResult<()> {
match self.data.get(self.index + 1..self.index + 4) {
Some(s) if s == NULL_REST => {
self.index += 4;
Ok(())
}
Some(_) => json_err!(ExpectedSomeIdent, self.index),
None => json_err!(EofWhileParsingValue, self.data.len()),
}
self.consume_ident(NULL_REST)
}

pub fn consume_string<'s, 't, D: AbstractStringDecoder<'t>>(
Expand Down Expand Up @@ -268,6 +247,26 @@ impl<'a> Parser<'a> {
}
}

fn consume_ident<const SIZE: usize>(&mut self, expected: [u8; SIZE]) -> JsonResult<()> {
match self.data.get(self.index + 1..self.index + SIZE + 1) {
Some(s) if s == expected => {
self.index += SIZE + 1;
Ok(())
}
_ => {
self.index += 1;
for c in expected.iter() {
match self.data.get(self.index) {
Some(v) if v == c => self.index += 1,
Some(_) => return json_err!(ExpectedSomeIdent, self.index),
_ => break,
}
}
json_err!(EofWhileParsingValue, self.data.len())
}
}
}

fn eat_whitespace(&mut self) -> Option<u8> {
while let Some(next) = self.data.get(self.index) {
match next {
Expand Down
11 changes: 7 additions & 4 deletions tests/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,12 @@ single_tests! {
empty: err => "", "EofWhileParsingValue @ 1:0";
string_unclosed: err => r#""foobar"#, "EofWhileParsingString @ 1:7";
bad_int: err => "-", "EofWhileParsingValue @ 1:1";
bad_true1: err => "truX", "ExpectedSomeIdent @ 1:0";
bad_true1: err => "truX", "ExpectedSomeIdent @ 1:3";
bad_true2: err => "tru", "EofWhileParsingValue @ 1:3";
bad_false1: err => "falsX", "ExpectedSomeIdent @ 1:0";
bad_true3: err => "trX", "ExpectedSomeIdent @ 1:2";
bad_false1: err => "falsX", "ExpectedSomeIdent @ 1:4";
bad_false2: err => "fals", "EofWhileParsingValue @ 1:4";
bad_null1: err => "nulX", "ExpectedSomeIdent @ 1:0";
bad_null1: err => "nulX", "ExpectedSomeIdent @ 1:3";
bad_null2: err => "nul", "EofWhileParsingValue @ 1:3";
object_trailing_comma: err => r#"{"foo": "bar",}"#, "TrailingComma @ 1:15";
array_trailing_comma: err => r#"[1, 2,]"#, "TrailingComma @ 1:7";
Expand All @@ -216,7 +217,9 @@ single_tests! {
array_no_close: err => r#"["#, "EofWhileParsingList @ 1:1";
array_double_close: err => "[1]]", "TrailingCharacters @ 1:3";
double_zero: err => "001", "InvalidNumber @ 1:0";
invalid_float: err => "0E", "EofWhileParsingValue @ 1:0";
invalid_float_e_end: err => "0E", "EofWhileParsingValue @ 1:2";
invalid_float_dot_end: err => "0.", "EofWhileParsingValue @ 1:2";
invalid_float_bracket: err => "2E[", "InvalidNumber @ 1:2";
}

#[test]
Expand Down

0 comments on commit 9aa16aa

Please sign in to comment.