1use std::borrow::{Borrow, Cow};
33use std::error::Error;
34use std::fmt;
35use std::io::{self, Write};
36use std::str::Chars;
37
38use ast::Json;
39use stack::{Stack, Scope};
40
41pub trait ToJson {
44 fn encode<W: Write>(&self, e: &mut Encoder<W>) -> EncodeResult<()>;
45}
46
47macro_rules! instance {
48 ($name: ident) => {
49 impl ToJson for $name {
50 fn encode<W: Write>(&self, e: &mut Encoder<W>) -> EncodeResult<()> {
51 e.$name(*self)
52 }
53 }
54 }
55}
56
57instance!(bool);
58instance!(u8);
59instance!(u16);
60instance!(u32);
61instance!(u64);
62instance!(usize);
63instance!(i8);
64instance!(i16);
65instance!(i32);
66instance!(i64);
67instance!(isize);
68instance!(f64);
69
70impl ToJson for str {
71 fn encode<W: Write>(&self, e: &mut Encoder<W>) -> EncodeResult<()> {
72 e.string(self)
73 }
74}
75
76impl ToJson for String {
77 fn encode<W: Write>(&self, e: &mut Encoder<W>) -> EncodeResult<()> {
78 e.string(self.as_str())
79 }
80}
81
82impl ToJson for Json {
83 fn encode<W: Write>(&self, e: &mut Encoder<W>) -> EncodeResult<()> {
84 e.encode(self)
85 }
86}
87
88impl<'a, T: ToJson> ToJson for &'a T {
89 fn encode<W: Write>(&self, e: &mut Encoder<W>) -> EncodeResult<()> {
90 (*self).encode(e)
91 }
92}
93
94impl<'a, T: ToJson + Clone> ToJson for Cow<'a, T> {
95 fn encode<W: Write>(&self, e: &mut Encoder<W>) -> EncodeResult<()> {
96 (**self).encode(e)
97 }
98}
99
100impl<T: ToJson> ToJson for Option<T> {
101 fn encode<W: Write>(&self, e: &mut Encoder<W>) -> EncodeResult<()> {
102 e.optional(self.as_ref())
103 }
104}
105
106impl<'a, T: ToJson> ToJson for &'a [T] {
107 fn encode<W: Write>(&self, e: &mut Encoder<W>) -> EncodeResult<()> {
108 e.array()?;
109 for x in *self {
110 x.encode(e)?
111 }
112 e.end()
113 }
114}
115
116pub struct Encoder<W> {
120 writer: W,
121 stack: Stack
122}
123
124macro_rules! number {
127 ($name: ident, f64) => {
128 pub fn $name(&mut self, x: f64) -> EncodeResult<()> {
129 if x.is_nan() || x.is_infinite() {
130 return Err(EncodeError::InvalidFloat)
131 }
132 self.comma_array()?;
133 self.writer.write_all(x.to_string().as_bytes())?;
134 Ok(())
135 }
136 };
137 ($name: ident, $ty: ty) => {
138 pub fn $name(&mut self, x: $ty) -> EncodeResult<()> {
139 self.comma_array()?;
140 self.writer.write_all(x.to_string().as_bytes())?;
141 Ok(())
142 }
143 }
144}
145
146impl<W: Write> Encoder<W> {
147 pub fn new(w: W) -> Encoder<W> {
148 Encoder { writer: w, stack: Stack::new() }
149 }
150
151 pub fn into_writer(self) -> W {
152 self.writer
153 }
154
155 pub fn writer_mut(&mut self) -> &mut W {
156 &mut self.writer
157 }
158
159 pub fn to_json<T: ToJson>(&mut self, t: T) -> EncodeResult<()> {
160 t.encode(self)
161 }
162
163 pub fn encode(&mut self, j: &Json) -> EncodeResult<()> {
164 match *j {
165 Json::Null => self.null()?,
166 Json::Bool(x) => self.bool(x)?,
167 Json::Number(x) => self.f64(x)?,
168 Json::String(ref x) => self.string(x.as_ref())?,
169 Json::Array(ref xs) => {
170 self.array()?;
171 for x in xs {
172 self.encode(x)?
173 }
174 self.end()?
175 }
176 Json::Object(ref xs) => {
177 self.object()?;
178 for (k, v) in xs {
179 self.key(k.as_ref())?;
180 self.encode(v)?
181 }
182 self.end()?
183 }
184 }
185 Ok(())
186 }
187
188 number!(u8, u8);
189 number!(u16, u16);
190 number!(u32, u32);
191 number!(u64, u64);
192 number!(usize, usize);
193
194 number!(i8, i8);
195 number!(i16, i16);
196 number!(i32, i32);
197 number!(i64, i64);
198 number!(isize, isize);
199
200 number!(f64, f64);
201
202 pub fn bool(&mut self, x: bool) -> EncodeResult<()> {
203 self.comma_array()?;
204 self.writer.write_all(if x { b"true" } else { b"false" })?;
205 Ok(())
206 }
207
208 pub fn null(&mut self) -> EncodeResult<()> {
209 self.comma_array()?;
210 self.writer.write_all(b"null")?;
211 Ok(())
212 }
213
214 pub fn optional<T: ToJson>(&mut self, val: Option<T>) -> EncodeResult<()> {
215 match val {
216 None => self.null(),
217 Some(ref v) => self.to_json(v)
218 }
219 }
220
221 pub fn string<S: Borrow<str>>(&mut self, s: S) -> EncodeResult<()> {
222 self.comma_array()?;
223 self.writer.write_all(b"\"")?;
224 for x in Bytes::new(EscapedChars::new(s.borrow())) {
225 self.writer.write_all(&[x])?;
226 }
227 self.writer.write_all(b"\"")?;
228 Ok(())
229 }
230
231 pub fn key<S: Borrow<str>>(&mut self, key: S) -> EncodeResult<()> {
232 self.comma_object()?;
233 self.string(key.borrow())?;
234 self.writer.write_all(b":")?;
235 Ok(())
236 }
237
238 pub fn array(&mut self) -> EncodeResult<()> {
242 self.comma_array()?;
243 self.writer.write_all(b"[")?;
244 self.stack.push(Scope::A(false));
245 Ok(())
246 }
247
248 pub fn object(&mut self) -> EncodeResult<()> {
252 self.comma_array()?;
253 self.writer.write_all(b"{")?;
254 self.stack.push(Scope::O(false));
255 Ok(())
256 }
257
258 pub fn end(&mut self) -> EncodeResult<()> {
260 match self.stack.pop() {
261 Some(Scope::A(_)) =>
262 self.writer.write_all(b"]").map_err(From::from),
263 Some(Scope::O(_)) =>
264 self.writer.write_all(b"}").map_err(From::from),
265 None => Ok(())
266 }
267 }
268
269 fn comma_array(&mut self) -> EncodeResult<()> {
270 match self.stack.top() {
271 Some(Scope::A(true)) => self.writer.write_all(b",").map_err(From::from),
272 Some(Scope::A(false)) => {
273 self.stack.set();
274 Ok(())
275 }
276 _ => Ok(())
277 }
278 }
279
280 fn comma_object(&mut self) -> EncodeResult<()> {
281 match self.stack.top() {
282 Some(Scope::O(true)) => self.writer.write_all(b",").map_err(From::from),
283 Some(Scope::O(false)) => {
284 self.stack.set();
285 Ok(())
286 }
287 _ => Ok(())
288 }
289 }
290}
291
292pub type EncodeResult<A> = Result<A, EncodeError>;
295
296#[derive(Debug)]
297pub enum EncodeError {
298 Io(io::Error),
299 InvalidFloat,
301 Message(&'static str),
303 Other(Box<Error + Send + Sync>)
305}
306
307impl fmt::Display for EncodeError {
308 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
309 match *self {
310 EncodeError::Io(ref e) => write!(f, "i/o: {:?}", e),
311 EncodeError::InvalidFloat => write!(f, "invalid f64 (NaN | Infinity)"),
312 EncodeError::Message(m) => write!(f, "error: {}", m),
313 EncodeError::Other(ref e) => write!(f, "other: {}", e)
314 }
315 }
316}
317
318impl Error for EncodeError {
319 fn description(&self) -> &str {
320 match *self {
321 EncodeError::Io(_) => "i/o error",
322 EncodeError::InvalidFloat => "invalid float value (e.g. NAN or INFINITY)",
323 EncodeError::Message(_) => "generic error message",
324 EncodeError::Other(_) => "other error"
325 }
326 }
327
328 fn cause(&self) -> Option<&Error> {
329 match *self {
330 EncodeError::Io(ref e) => Some(e),
331 EncodeError::Other(ref e) => Some(&**e),
332 _ => None
333 }
334 }
335}
336
337impl From<io::Error> for EncodeError {
338 fn from(e: io::Error) -> EncodeError {
339 EncodeError::Io(e)
340 }
341}
342
343struct EscapedChars<'r> {
346 source: Chars<'r>,
347 buffer: [u8; 5],
348 index: Option<(usize, usize)>
349}
350
351impl<'r> EscapedChars<'r> {
352 fn new(s: &'r str) -> EscapedChars<'r> {
353 EscapedChars {
354 source: s.chars(),
355 buffer: [0; 5],
356 index: None
357 }
358 }
359
360 fn chr(x: u8) -> u8 {
361 match x {
362 0x0 ... 0x9 => b'0' + x,
363 0xA ... 0xF => b'A' + x - 0xA,
364 _ => panic!("{} > 0xF", x)
365 }
366 }
367}
368
369impl<'r> Iterator for EscapedChars<'r> {
370 type Item = char;
371
372 fn next(&mut self) -> Option<char> {
373 match self.index {
374 None => (),
375 Some((i, e)) =>
376 if i < e {
377 self.index = Some((i + 1, e));
378 return Some(self.buffer[i] as char)
379 } else {
380 self.index = None
381 }
382 }
383 match self.source.next() {
384 Some(x@'\\') | Some(x@'"') => {
385 self.buffer[0] = x as u8;
386 self.index = Some((0, 1));
387 Some('\\')
388 }
389 Some('\n') => {
390 self.buffer[0] = b'n';
391 self.index = Some((0, 1));
392 Some('\\')
393 }
394 Some('\t') => {
395 self.buffer[0] = b't';
396 self.index = Some((0, 1));
397 Some('\\')
398 }
399 Some('\r') => {
400 self.buffer[0] = b'r';
401 self.index = Some((0, 1));
402 Some('\\')
403 }
404 Some(x@'\x00' ... '\x1F') | Some(x@'\x7F') => {
405 self.buffer[0] = b'u';
406 self.buffer[1] = b'0';
407 self.buffer[2] = b'0';
408 self.buffer[3] = Self::chr(x as u8 >> 4);
409 self.buffer[4] = Self::chr(x as u8 & 0x0F);
410 self.index = Some((0, 5));
411 Some('\\')
412 }
413 x => x
414 }
415 }
416}
417
418struct Bytes<I> {
419 src: I,
420 buf: [u8; 4],
421 pos: usize,
422 end: usize
423}
424
425impl<I> Bytes<I> {
426 pub fn new(i: I) -> Bytes<I> {
427 Bytes {
428 src: i,
429 buf: [0; 4],
430 pos: 0,
431 end: 0
432 }
433 }
434}
435
436impl<I: Iterator<Item=char>> Iterator for Bytes<I> {
437 type Item = u8;
438
439 fn next(&mut self) -> Option<u8> {
440 if self.pos == self.end {
441 match self.src.next() {
442 Some(c) => {
443 self.end = c.encode_utf8(&mut self.buf).len();
444 debug_assert!(self.end > 0);
445 self.pos = 0
446 }
447 None => return None
448 }
449 }
450 let x = self.buf[self.pos];
451 self.pos += 1;
452 Some(x)
453 }
454}
455