json/
encoder.rs

1//! JSON ([RFC 7159](http://tools.ietf.org/html/rfc7159)) encoder.
2//!
3//! # Usage example
4//!
5//! ```
6//! use json::Encoder;
7//! use std::io::Cursor;
8//!
9//! let mut e = Encoder::new(Cursor::new(Vec::new()));
10//! let r = e.object().and_then(|()| {
11//!     e.key("key1")?; e.array()?;
12//!         for i in 0 .. 10 {
13//!             e.bool(i % 2 == 0)?
14//!         }
15//!     e.end()?;
16//!     e.key("key2")?; e.string("\"hello world\"")?;
17//!     e.key("key3")?; e.object()?;
18//!         e.key("inner1")?; e.bool(true)?;
19//!         e.key("inner2")?; e.array()?;
20//!             e.string("\u{2764}\u{fe0f}")?;
21//!             e.string("again")?;
22//!             e.bool(false)?;
23//!             e.usize(1024)?;
24//!             e.u8(90)?;
25//!             e.f64(1.23442e-9)?;
26//!             e.null()?;
27//!         e.end()?;
28//!     e.end()?;
29//! e.end()});
30//! assert!(r.is_ok())
31
32use 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
41// ToJson trait /////////////////////////////////////////////////////////////
42
43pub 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
116// Encoder //////////////////////////////////////////////////////////////////
117
118/// JSON encoder over any `Write`-type.
119pub struct Encoder<W> {
120    writer: W,
121    stack: Stack
122}
123
124// Macros ///////////////////////////////////////////////////////////////////
125
126macro_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    /// Begin encoding a new JSON array.
239    ///
240    /// Must be paired with a call to `Encoder::end()`.
241    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    /// Begin encoding a new JSON object.
249    ///
250    /// Must be paired with a call to `Encoder::end()`.
251    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    /// End a JSON array or object.
259    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
292// Encoder Error Type ///////////////////////////////////////////////////////
293
294pub type EncodeResult<A> = Result<A, EncodeError>;
295
296#[derive(Debug)]
297pub enum EncodeError {
298    Io(io::Error),
299    /// A float value such as `NAN` or `INFINITY` was used.
300    InvalidFloat,
301    /// Generic error message.
302    Message(&'static str),
303    /// Some other error trait impl.
304    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
343// Character conversion support /////////////////////////////////////////////
344
345struct 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