Skip to content

Commit 06accaf

Browse files
committed
auto merge of #7704 : glinscott/rust/json_iter, r=erickt
This is much faster for strings, and eventually when there is a buffered reader of some sort, will be much faster for files. Reading example.json 100 times before was around 1.18s. After: - reading from string 0.68s - reading from file 1.08s (extra time is all in io::Reader) Also: - fixes #7611 - error when parsing strings and we hit EOF - updates definition of whitespace in json should only be the 4 ascii whitespace chars
2 parents 6ea0c77 + f091a1e commit 06accaf

File tree

1 file changed

+26
-40
lines changed

1 file changed

+26
-40
lines changed

src/libextra/json.rs

+26-40
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,10 @@
1616

1717
//! json serialization
1818
19-
20-
use std::char;
19+
use std::iterator;
2120
use std::float;
2221
use std::hashmap::HashMap;
23-
use std::io::{WriterUtil, ReaderUtil};
22+
use std::io::WriterUtil;
2423
use std::io;
2524
use std::str;
2625
use std::to_str;
@@ -481,24 +480,17 @@ pub fn to_pretty_str(json: &Json) -> ~str {
481480
io::with_str_writer(|wr| to_pretty_writer(wr, json))
482481
}
483482

484-
static BUF_SIZE : uint = 64000;
485-
486-
#[allow(missing_doc)]
487-
pub struct Parser {
488-
priv rdr: @io::Reader,
489-
priv buf: ~[char],
490-
priv buf_idx: uint,
483+
pub struct Parser<T> {
484+
priv rdr: ~T,
491485
priv ch: char,
492486
priv line: uint,
493487
priv col: uint,
494488
}
495489

496-
/// Decode a json value from an io::reader
497-
pub fn Parser(rdr: @io::Reader) -> Parser {
490+
/// Decode a json value from an Iterator<char>
491+
pub fn Parser<T : iterator::Iterator<char>>(rdr: ~T) -> Parser<T> {
498492
let mut p = Parser {
499493
rdr: rdr,
500-
buf: rdr.read_chars(BUF_SIZE),
501-
buf_idx: 0,
502494
ch: 0 as char,
503495
line: 1,
504496
col: 0,
@@ -507,7 +499,7 @@ pub fn Parser(rdr: @io::Reader) -> Parser {
507499
p
508500
}
509501

510-
impl Parser {
502+
impl<T: iterator::Iterator<char>> Parser<T> {
511503
pub fn parse(&mut self) -> Result<Json, Error> {
512504
match self.parse_value() {
513505
Ok(value) => {
@@ -525,30 +517,20 @@ impl Parser {
525517
}
526518
}
527519

528-
impl Parser {
520+
impl<T : iterator::Iterator<char>> Parser<T> {
529521
fn eof(&self) -> bool { self.ch == -1 as char }
530522

531523
fn bump(&mut self) {
532-
if self.eof() {
533-
return;
534-
}
535-
536-
self.col += 1u;
537-
538-
if self.buf_idx >= self.buf.len() {
539-
self.buf = self.rdr.read_chars(BUF_SIZE);
540-
if self.buf.len() == 0 {
541-
self.ch = -1 as char;
542-
return;
543-
}
544-
self.buf_idx = 0;
524+
match self.rdr.next() {
525+
Some(ch) => self.ch = ch,
526+
None() => self.ch = -1 as char,
545527
}
546-
self.ch = self.buf[self.buf_idx];
547-
self.buf_idx += 1;
548528

549529
if self.ch == '\n' {
550530
self.line += 1u;
551531
self.col = 1u;
532+
} else {
533+
self.col += 1u;
552534
}
553535
}
554536

@@ -583,7 +565,10 @@ impl Parser {
583565
}
584566

585567
fn parse_whitespace(&mut self) {
586-
while char::is_whitespace(self.ch) { self.bump(); }
568+
while self.ch == ' ' ||
569+
self.ch == '\n' ||
570+
self.ch == '\t' ||
571+
self.ch == '\r' { self.bump(); }
587572
}
588573

589574
fn parse_ident(&mut self, ident: &str, value: Json) -> Result<Json, Error> {
@@ -727,8 +712,11 @@ impl Parser {
727712
let mut escape = false;
728713
let mut res = ~"";
729714

730-
while !self.eof() {
715+
loop {
731716
self.bump();
717+
if self.eof() {
718+
return self.error(~"EOF while parsing string");
719+
}
732720

733721
if (escape) {
734722
match self.ch {
@@ -783,8 +771,6 @@ impl Parser {
783771
res.push_char(self.ch);
784772
}
785773
}
786-
787-
self.error(~"EOF while parsing string")
788774
}
789775

790776
fn parse_list(&mut self) -> Result<Json, Error> {
@@ -870,15 +856,15 @@ impl Parser {
870856

871857
/// Decodes a json value from an @io::Reader
872858
pub fn from_reader(rdr: @io::Reader) -> Result<Json, Error> {
873-
let mut parser = Parser(rdr);
859+
let s = str::from_bytes(rdr.read_whole_stream());
860+
let mut parser = Parser(~s.iter());
874861
parser.parse()
875862
}
876863

877864
/// Decodes a json value from a string
878865
pub fn from_str(s: &str) -> Result<Json, Error> {
879-
do io::with_str_reader(s) |rdr| {
880-
from_reader(rdr)
881-
}
866+
let mut parser = Parser(~s.iter());
867+
parser.parse()
882868
}
883869

884870
/// A structure to decode JSON to values in rust.
@@ -1744,7 +1730,7 @@ mod tests {
17441730
assert_eq!(v, 0.4e-01f);
17451731
}
17461732
1747-
// FIXME: #7611: xfailed for now
1733+
#[test]
17481734
fn test_read_str() {
17491735
assert_eq!(from_str("\""),
17501736
Err(Error {line: 1u, col: 2u, msg: @~"EOF while parsing string"

0 commit comments

Comments
 (0)