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