1extern crate rustc_serialize;
8
9use std::io::{ Read };
10use std::iter::Iterator;
11use rustc_serialize::json::{ Json, Builder };
12
13use std::error::Error;
15use std::{ fmt, io, result, str };
16
17pub struct Iter<R> {
19 inner: R
20}
21
22impl<R: Read> Iter<R> {
23 pub fn new(inner: R) -> Iter<R> {
25 Iter { inner: inner }
26 }
27}
28
29impl<R: Read> Iterator for Iter<R> {
30 type Item = Json;
31
32 fn next(&mut self) -> Option<Json> {
33 let ref mut inner = self.inner;
34 let mut chars = Chars { inner: inner };
35 let mut buf = String::new();
36 while let Some(Ok(c)) = chars.next() {
37 buf.push(c);
38 match c {
39 '}' | ']' =>
40 match Builder::new(buf.chars()).build() {
41 Ok(j) => return Some(j),
42 _ => ()
43 },
44 _ => ()
45 }
46 }
47 None
48 }
49}
50
51static UTF8_CHAR_WIDTH: [u8; 256] = [
541,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
551,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
571,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
591,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
611,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
630,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
650,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
672,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, 4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, ];
71
72#[inline]
73fn utf8_char_width(b: u8) -> usize {
74 return UTF8_CHAR_WIDTH[b as usize] as usize;
75}
76
77struct Chars<R> {
78 inner: R,
79}
80
81#[derive(Debug)]
82enum CharsError {
83 NotUtf8,
84 Other(io::Error),
85}
86
87impl<R: Read> Iterator for Chars<R> {
88 type Item = result::Result<char, CharsError>;
89
90 fn next(&mut self) -> Option<result::Result<char, CharsError>> {
91 let mut buf = [0];
92 let first_byte = match self.inner.read(&mut buf) {
93 Ok(0) => return None,
94 Ok(..) => buf[0],
95 Err(e) => return Some(Err(CharsError::Other(e))),
96 };
97 let width = utf8_char_width(first_byte);
98 if width == 1 { return Some(Ok(first_byte as char)) }
99 if width == 0 { return Some(Err(CharsError::NotUtf8)) }
100 let mut buf = [first_byte, 0, 0, 0];
101 {
102 let mut start = 1;
103 while start < width {
104 match self.inner.read(&mut buf[start..width]) {
105 Ok(0) => return Some(Err(CharsError::NotUtf8)),
106 Ok(n) => start += n,
107 Err(e) => return Some(Err(CharsError::Other(e))),
108 }
109 }
110 }
111 Some(match str::from_utf8(&buf[..width]).ok() {
112 Some(s) => {
113 let v: Vec<char> = s.chars().collect();
114 Ok(v[0])
115 },
116 None => Err(CharsError::NotUtf8),
117 })
118 }
119}
120
121impl Error for CharsError {
122 fn description(&self) -> &str {
123 match *self {
124 CharsError::NotUtf8 => "invalid utf8 encoding",
125 CharsError::Other(ref e) => Error::description(e),
126 }
127 }
128 fn cause(&self) -> Option<&Error> {
129 match *self {
130 CharsError::NotUtf8 => None,
131 CharsError::Other(ref e) => e.cause(),
132 }
133 }
134}
135
136impl fmt::Display for CharsError {
137 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
138 match *self {
139 CharsError::NotUtf8 => {
140 "byte stream did not contain valid utf8".fmt(f)
141 }
142 CharsError::Other(ref e) => e.fmt(f),
143 }
144 }
145}
146
147#[cfg(test)]
148mod tests {
149 use super::Iter;
150 #[cfg(feature = "nightly")]
151 use test::Bencher;
152 use std::io::{ empty, BufReader };
153
154 #[test]
155 fn test_not_json_iter() {
156 let reader = BufReader::new("bogus".as_bytes());
157 assert_eq!(Iter::new(reader).count(), 0);
158 }
159
160 #[test]
161 fn test_empty_iter() {
162 assert_eq!(Iter::new(empty()).count(), 0);
163 }
164
165 #[test]
166 fn test_ary_iter() {
167 let reader = BufReader::new("[][]".as_bytes());
168 assert_eq!(Iter::new(reader).count(), 2)
169 }
170
171 #[test]
172 fn test_obj_iter() {
173 let reader = BufReader::new("{}{}".as_bytes());
174 assert_eq!(Iter::new(reader).count(), 2)
175 }
176
177 #[cfg(feature = "nightly")]
178 #[bench]
179 fn bench_iter(b: &mut Bencher) {
180 b.iter(|| Iter::new(BufReader::new("{'foo':'bar'}{'foo':'baz'}".as_bytes())).count())
181 }
182}