Skip to content

Commit dbf3a6d

Browse files
committed
0.7.1 parse numbers without relaying on Rust’s parsing from strings
1 parent f68cf72 commit dbf3a6d

File tree

1 file changed

+31
-26
lines changed

1 file changed

+31
-26
lines changed

src/parser.rs

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -109,25 +109,13 @@ impl<'a> Tokenizer<'a> {
109109
.or(Err(JsonError::FailedUtf8Parsing))
110110
}
111111

112-
fn read_digits_to_buffer(&mut self) {
113-
while let Some(&ch) = self.source.peek() {
114-
match ch {
115-
b'0' ... b'9' => {
116-
self.buffer.push(ch);
117-
self.source.next();
118-
},
119-
_ => break
120-
}
121-
}
122-
}
123-
124112
fn read_number(&mut self, first: u8) -> JsonResult<f64> {
125113
let mut num = if first == b'-' { 0 } else { (first - b'0') as u64 };
126114

127115
while let Some(&ch) = self.source.peek() {
128116
match ch {
129117
b'0' ... b'9' => {
130-
num = (num * 10) + (ch - b'0') as u64;
118+
num = num * 10 + (ch - b'0') as u64;
131119
},
132120
_ => break
133121
}
@@ -143,38 +131,55 @@ impl<'a> Tokenizer<'a> {
143131
})
144132
}
145133

146-
self.buffer.clear();
147-
self.buffer.extend_from_slice(num.to_string().as_bytes());
134+
let mut num = num as f64;
148135

149136
if let Some(&b'.') = self.source.peek() {
150-
self.buffer.push(b'.');
151137
self.source.next();
152-
self.read_digits_to_buffer();
138+
139+
let mut precision = -1;
140+
while let Some(&ch) = self.source.peek() {
141+
match ch {
142+
b'0' ... b'9' => {
143+
num += ((ch - b'0') as f64) * 10f64.powi(precision);
144+
precision -= 1;
145+
},
146+
_ => break
147+
}
148+
self.source.next();
149+
}
153150
}
154151

155152
match self.source.peek() {
156153
Some(&b'e') | Some(&b'E') => {
157-
self.buffer.push(b'e');
158154
self.source.next();
159-
match self.source.peek() {
155+
156+
let mut e = 0;
157+
let sign = match self.source.peek() {
160158
Some(&b'-') => {
161-
self.buffer.push(b'-');
162159
self.source.next();
160+
-1
163161
},
164162
Some(&b'+') => {
165-
self.buffer.push(b'+');
166163
self.source.next();
164+
1
167165
},
168-
_ => {}
166+
_ => 1
167+
};
168+
169+
while let Some(&ch) = self.source.peek() {
170+
match ch {
171+
b'0' ... b'9' => e = e * 10 + (ch - b'0') as i32,
172+
_ => break
173+
}
174+
self.source.next();
169175
}
170-
self.read_digits_to_buffer();
176+
177+
num *= 10f64.powi(e * sign);
171178
},
172179
_ => {}
173180
}
174181

175-
str::from_utf8(&self.buffer).ok()
176-
.and_then(|slice| slice.parse::<f64>().ok())
177-
.ok_or(JsonError::FailedUtf8Parsing)
182+
Ok(if first == b'-' { num * -1.0 } else { num })
178183
}
179184

180185
fn next(&mut self) -> JsonResult<Token> {

0 commit comments

Comments
 (0)