Skip to content

Commit 7b7ce78

Browse files
committed
0.8.0 fixes #40, #41, #44
1 parent a38799e commit 7b7ce78

File tree

3 files changed

+75
-45
lines changed

3 files changed

+75
-45
lines changed

src/codegen.rs

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -76,36 +76,23 @@ pub trait Generator {
7676
self.write_char(b'-');
7777
}
7878

79-
if num > 1e19 || num < 1e-15 {
80-
write!(self.get_buffer(), "{:e}", num).unwrap();
79+
let fract = num.fract();
80+
81+
if fract > 0.0 {
82+
if num < 1e-15 {
83+
write!(self.get_buffer(), "{:e}", num).unwrap();
84+
} else {
85+
write!(self.get_buffer(), "{}", num).unwrap();
86+
}
8187
return;
8288
}
8389

84-
let start = self.current_index();
85-
86-
self.write_digits_from_u64(num as u64);
87-
88-
let mut fract = num.fract();
89-
90-
if fract < 1e-16 {
90+
if num > 1e19 || num < 1e-15 {
91+
write!(self.get_buffer(), "{:e}", num).unwrap();
9192
return;
9293
}
9394

94-
let mut length = self.current_index() - start;
95-
96-
fract *= 10.0;
97-
98-
self.write_char(b'.');
99-
self.write_char((fract as u8) + b'0');
100-
fract = fract.fract();
101-
length += 2;
102-
103-
while length < 17 && fract > 1e-15 {
104-
fract *= 10.0;
105-
self.write_char((fract as u8) + b'0');
106-
fract = fract.fract();
107-
length += 1;
108-
}
95+
self.write_digits_from_u64(num as u64);
10996
}
11097

11198
fn write_json(&mut self, json: &JsonValue) {

src/parser.rs

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ macro_rules! sequence {
99
$(
1010
match $parser.next_byte() {
1111
Some($ch) => {},
12-
Some(ch) => return Err($parser.unexpected_character_error(ch)),
12+
Some(ch) => return Err($parser.unexpected_character(ch)),
1313
None => return Err(JsonError::UnexpectedEndOfJson)
1414
}
1515
)*
@@ -62,7 +62,7 @@ macro_rules! expect {
6262

6363
match ch {
6464
$byte => {},
65-
_ => return Err($parser.unexpected_character_error(ch))
65+
_ => return Err($parser.unexpected_character(ch))
6666
}
6767
})
6868
}
@@ -77,7 +77,7 @@ macro_rules! expect_one_of {
7777
$(
7878
$byte => $then,
7979
)*
80-
_ => return Err($parser.unexpected_character_error(ch))
80+
_ => return Err($parser.unexpected_character(ch))
8181
}
8282

8383
})
@@ -106,7 +106,7 @@ macro_rules! expect_string {
106106
b't' => b'\t',
107107
b'r' => b'\r',
108108
b'n' => b'\n',
109-
_ => return Err($parser.unexpected_character_error(ch))
109+
_ => return Err($parser.unexpected_character(ch))
110110
};
111111
$parser.buffer.push(ch);
112112
},
@@ -133,10 +133,22 @@ macro_rules! expect_value {
133133
b'[' => JsonValue::Array(try!($parser.read_array())),
134134
b'{' => JsonValue::Object(try!($parser.read_object())),
135135
b'"' => JsonValue::String(expect_string!($parser)),
136-
b'0' ... b'9' => JsonValue::Number(try!($parser.read_number(ch, false))),
136+
b'0' => {
137+
let num = try!($parser.read_number_with_fraction(0.0, false));
138+
JsonValue::Number(num)
139+
},
140+
b'1' ... b'9' => {
141+
let num = try!($parser.read_number(ch, false));
142+
JsonValue::Number(num)
143+
},
137144
b'-' => {
138145
let ch = try!($parser.expect_byte());
139-
JsonValue::Number(try!($parser.read_number(ch, true)))
146+
let num = match ch {
147+
b'0' => try!($parser.read_number_with_fraction(0.0, true)),
148+
b'1' ... b'9' => try!($parser.read_number(ch, true)),
149+
_ => return Err($parser.unexpected_character(ch))
150+
};
151+
JsonValue::Number(num)
140152
}
141153
b't' => {
142154
sequence!($parser, b'r', b'u', b'e');
@@ -150,7 +162,7 @@ macro_rules! expect_value {
150162
sequence!($parser, b'u', b'l', b'l');
151163
JsonValue::Null
152164
},
153-
_ => return Err($parser.unexpected_character_error(ch))
165+
_ => return Err($parser.unexpected_character(ch))
154166
}
155167
})
156168
}
@@ -190,7 +202,7 @@ impl<'a> Parser<'a> {
190202
}
191203
}
192204

193-
fn unexpected_character_error(&self, byte: u8) -> JsonError {
205+
fn unexpected_character(&self, byte: u8) -> JsonError {
194206
let pos = self.source_position_from_index(self.current_index);
195207
let ch = char::from_u32(byte as u32).unwrap_or('?');
196208

@@ -237,7 +249,7 @@ impl<'a> Parser<'a> {
237249
b'0' ... b'9' => (ch - b'0') as u32,
238250
b'a' ... b'f' => (ch + 10 - b'a') as u32,
239251
b'A' ... b'F' => (ch + 10 - b'A') as u32,
240-
ch => return Err(self.unexpected_character_error(ch)),
252+
ch => return Err(self.unexpected_character(ch)),
241253
})
242254
}
243255

@@ -296,6 +308,11 @@ impl<'a> Parser<'a> {
296308
// u64 into freshly converted f64
297309
read_num!(self, digit, num = num * 10.0 + digit as f64);
298310

311+
self.read_number_with_fraction(num, is_negative)
312+
}
313+
314+
fn read_number_with_fraction(&mut self, mut num: f64, is_negative: bool)
315+
-> JsonResult<f64> {
299316
if let Some(b'.') = self.peek_byte() {
300317
self.left_over = None;
301318
let mut precision = -1;
@@ -308,7 +325,6 @@ impl<'a> Parser<'a> {
308325

309326
match self.checked_next_byte() {
310327
Some(b'e') | Some(b'E') => {
311-
let mut e = 0;
312328
let sign = match self.next_byte() {
313329
Some(b'-') => -1,
314330
Some(b'+') => 1,
@@ -318,6 +334,12 @@ impl<'a> Parser<'a> {
318334
},
319335
};
320336

337+
let ch = try!(self.checked_expect_byte());
338+
let mut e = match ch {
339+
b'0' ... b'9' => (ch - b'0') as i32,
340+
_ => return Err(self.unexpected_character(ch)),
341+
};
342+
321343
read_num!(self, digit, e = e * 10 + digit as i32);
322344

323345
num *= 10f64.powi(e * sign);
@@ -380,12 +402,18 @@ impl<'a> Parser<'a> {
380402
}
381403

382404
fn ensure_end(&mut self) -> JsonResult<()> {
383-
let ch = self.next_byte();
405+
let ch = self.checked_next_byte();
406+
384407
if let Some(ch) = ch {
385408
match ch {
386409
// whitespace
387-
9 ... 13 | 32 => return self.ensure_end(),
388-
_ => return Err(self.unexpected_character_error(ch))
410+
9 ... 13 | 32 => while let Some(ch) = self.next_byte() {
411+
match ch {
412+
9 ... 13 | 32 => {},
413+
_ => return Err(self.unexpected_character(ch))
414+
}
415+
},
416+
_ => return Err(self.unexpected_character(ch))
389417
}
390418
}
391419

tests/lib.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -131,15 +131,15 @@ fn stringify_number() {
131131
assert_eq!(stringify(3.141592653589793), "3.141592653589793");
132132
}
133133

134-
// #[test]
135-
// fn stringify_precise_positive_number() {
136-
// assert_eq!(JsonValue::Number(1.2345f64).dump(), "1.2345");
137-
// }
134+
#[test]
135+
fn stringify_precise_positive_number() {
136+
assert_eq!(JsonValue::Number(1.2345f64).dump(), "1.2345");
137+
}
138138

139-
// #[test]
140-
// fn stringify_precise_negative_number() {
141-
// assert_eq!(JsonValue::Number(-1.2345f64).dump(), "-1.2345");
142-
// }
139+
#[test]
140+
fn stringify_precise_negative_number() {
141+
assert_eq!(JsonValue::Number(-1.2345f64).dump(), "-1.2345");
142+
}
143143

144144
#[test]
145145
fn stringify_zero() {
@@ -341,6 +341,16 @@ fn parse_negative_integer() {
341341
assert_eq!(parse("-42").unwrap(), -42);
342342
}
343343

344+
#[test]
345+
fn parse_number_with_leading_zero() {
346+
assert!(parse("01").is_err());
347+
}
348+
349+
#[test]
350+
fn parse_negative_number_with_leading_zero() {
351+
assert!(parse("-01").is_err());
352+
}
353+
344354
#[test]
345355
fn parse_number_with_e() {
346356
assert_eq!(parse("5e2").unwrap(), 500);
@@ -359,6 +369,11 @@ fn parse_number_with_negative_e() {
359369
assert_eq!(parse("5E-2").unwrap(), 0.05);
360370
}
361371

372+
#[test]
373+
fn parse_number_with_invalid_e() {
374+
assert!(parse("0e").is_err());
375+
}
376+
362377
#[test]
363378
fn parse_large_number() {
364379
assert_eq!(parse("18446744073709551616").unwrap(), 18446744073709552000f64);

0 commit comments

Comments
 (0)