blob: b8fe2ec267aa05fb6c9059982e051e76278f86f3 [file] [log] [blame]
Ben Striegela605fd02012-08-11 14:08:421#[deny(non_camel_case_types)];
2
Elly Jones656a2af2011-11-07 23:24:443// Rust JSON serialization library
4// Copyright (c) 2011 Google Inc.
Elly Jonesbd726262011-11-07 19:01:285
Gareth Daniel Smithbe014162012-07-04 21:53:126//! json serialization
Brian Anderson95521c42012-03-08 02:17:307
Brian Anderson0c6e4702012-08-26 23:54:318import result::{Result, Ok, Err};
Erick Tryzelaar012dec52012-02-26 00:39:329import io;
Brian Anderson11258312012-08-14 20:38:3510import io::WriterUtil;
Elly Jonesbd726262011-11-07 19:01:2811import map;
Patrick Waltonc9375fe2012-03-08 00:48:5712import map::hashmap;
Patrick Waltondb020ab2012-07-11 22:00:4013import map::map;
Elly Jonesbd726262011-11-07 19:01:2814
Ben Striegela605fd02012-08-11 14:08:4215export Json;
16export Error;
Erick Tryzelaar012dec52012-02-26 00:39:3217export to_writer;
Elly Jones656a2af2011-11-07 23:24:4418export to_str;
Erick Tryzelaar012dec52012-02-26 00:39:3219export from_reader;
Elly Jones656a2af2011-11-07 23:24:4420export from_str;
Erick Tryzelaar012dec52012-02-26 00:39:3221export eq;
Ben Striegela605fd02012-08-11 14:08:4222export ToJson;
Elly Jonesbd726262011-11-07 19:01:2823
Ben Striegela605fd02012-08-11 14:08:4224export Num;
25export String;
26export Boolean;
27export List;
28export Dict;
29export Null;
Elly Jones656a2af2011-11-07 23:24:4430
Gareth Daniel Smithbe014162012-07-04 21:53:1231/// Represents a json value
Ben Striegela605fd02012-08-11 14:08:4232enum Json {
33 Num(float),
34 String(@~str),
35 Boolean(bool),
36 List(@~[Json]),
37 Dict(map::hashmap<~str, Json>),
38 Null,
Elly Jonesbd726262011-11-07 19:01:2839}
40
Ben Striegela605fd02012-08-11 14:08:4241type Error = {
Erick Tryzelaar012dec52012-02-26 00:39:3242 line: uint,
43 col: uint,
Michael Sullivan92743dc2012-07-14 05:57:4844 msg: @~str,
Erick Tryzelaar012dec52012-02-26 00:39:3245};
46
Gareth Daniel Smithbe014162012-07-04 21:53:1247/// Serializes a json value into a io::writer
Ben Striegela605fd02012-08-11 14:08:4248fn to_writer(wr: io::Writer, j: Json) {
Brian Andersonecaf9e32012-08-06 19:34:0849 match j {
Ben Striegela605fd02012-08-11 14:08:4250 Num(n) => wr.write_str(float::to_str(n, 6u)),
51 String(s) => wr.write_str(escape_str(*s)),
52 Boolean(b) => wr.write_str(if b { ~"true" } else { ~"false" }),
53 List(v) => {
Erick Tryzelaar012dec52012-02-26 00:39:3254 wr.write_char('[');
Niko Matsakis6b358752012-03-14 18:03:5655 let mut first = true;
Brian Andersond1fc2b52012-06-30 23:19:0756 for (*v).each |item| {
Erick Tryzelaar012dec52012-02-26 00:39:3257 if !first {
Michael Sullivan92743dc2012-07-14 05:57:4858 wr.write_str(~", ");
Erick Tryzelaar012dec52012-02-26 00:39:3259 }
60 first = false;
61 to_writer(wr, item);
62 };
63 wr.write_char(']');
64 }
Ben Striegela605fd02012-08-11 14:08:4265 Dict(d) => {
Erick Tryzelaar012dec52012-02-26 00:39:3266 if d.size() == 0u {
Michael Sullivan92743dc2012-07-14 05:57:4867 wr.write_str(~"{}");
Brian Andersonb3559362012-08-02 00:30:0568 return;
Erick Tryzelaar012dec52012-02-26 00:39:3269 }
70
Michael Sullivan92743dc2012-07-14 05:57:4871 wr.write_str(~"{ ");
Niko Matsakis6b358752012-03-14 18:03:5672 let mut first = true;
Brian Andersond1fc2b52012-06-30 23:19:0773 for d.each |key, value| {
Erick Tryzelaar012dec52012-02-26 00:39:3274 if !first {
Michael Sullivan92743dc2012-07-14 05:57:4875 wr.write_str(~", ");
Erick Tryzelaar012dec52012-02-26 00:39:3276 }
77 first = false;
Erick Tryzelaarb361f6c2012-06-13 00:20:5178 wr.write_str(escape_str(key));
Michael Sullivan92743dc2012-07-14 05:57:4879 wr.write_str(~": ");
Erick Tryzelaar012dec52012-02-26 00:39:3280 to_writer(wr, value);
81 };
Michael Sullivan92743dc2012-07-14 05:57:4882 wr.write_str(~" }");
Erick Tryzelaar012dec52012-02-26 00:39:3283 }
Ben Striegela605fd02012-08-11 14:08:4284 Null => wr.write_str(~"null")
Erick Tryzelaar012dec52012-02-26 00:39:3285 }
86}
87
Michael Sullivan92743dc2012-07-14 05:57:4888fn escape_str(s: ~str) -> ~str {
89 let mut escaped = ~"\"";
Brian Andersond1fc2b52012-06-30 23:19:0790 do str::chars_iter(s) |c| {
Brian Andersonecaf9e32012-08-06 19:34:0891 match c {
Brian Anderson025d8662012-08-04 02:59:0492 '"' => escaped += ~"\\\"",
93 '\\' => escaped += ~"\\\\",
94 '\x08' => escaped += ~"\\b",
95 '\x0c' => escaped += ~"\\f",
96 '\n' => escaped += ~"\\n",
97 '\r' => escaped += ~"\\r",
98 '\t' => escaped += ~"\\t",
99 _ => escaped += str::from_char(c)
Erick Tryzelaarb361f6c2012-06-13 00:20:51100 }
101 };
102
Michael Sullivan92743dc2012-07-14 05:57:48103 escaped += ~"\"";
Erick Tryzelaarb361f6c2012-06-13 00:20:51104
105 escaped
106}
107
Gareth Daniel Smithbe014162012-07-04 21:53:12108/// Serializes a json value into a string
Ben Striegela605fd02012-08-11 14:08:42109fn to_str(j: Json) -> ~str {
Brian Andersond1fc2b52012-06-30 23:19:07110 io::with_str_writer(|wr| to_writer(wr, j))
Elly Jonesbd726262011-11-07 19:01:28111}
112
Ben Striegela605fd02012-08-11 14:08:42113type Parser_ = {
Brian Anderson11258312012-08-14 20:38:35114 rdr: io::Reader,
Graydon Hoare6e6798c2012-03-27 01:35:18115 mut ch: char,
116 mut line: uint,
117 mut col: uint,
Erick Tryzelaar012dec52012-02-26 00:39:32118};
Elly Jonesbd726262011-11-07 19:01:28119
Ben Striegela605fd02012-08-11 14:08:42120enum Parser {
121 Parser_(Parser_)
Patrick Waltondb020ab2012-07-11 22:00:40122}
123
Ben Striegela605fd02012-08-11 14:08:42124impl Parser {
Erick Tryzelaar012dec52012-02-26 00:39:32125 fn eof() -> bool { self.ch == -1 as char }
Elly Jonesbd726262011-11-07 19:01:28126
Erick Tryzelaar012dec52012-02-26 00:39:32127 fn bump() {
128 self.ch = self.rdr.read_char();
129
130 if self.ch == '\n' {
131 self.line += 1u;
132 self.col = 1u;
133 } else {
134 self.col += 1u;
135 }
Elly Jonesbd726262011-11-07 19:01:28136 }
137
Erick Tryzelaar012dec52012-02-26 00:39:32138 fn next_char() -> char {
139 self.bump();
140 self.ch
Elly Jonesbd726262011-11-07 19:01:28141 }
142
Ben Striegela605fd02012-08-11 14:08:42143 fn error<T>(+msg: ~str) -> Result<T, Error> {
Brian Anderson0c6e4702012-08-26 23:54:31144 Err({ line: self.line, col: self.col, msg: @msg })
Elly Jonesbd726262011-11-07 19:01:28145 }
Elly Jonesbd726262011-11-07 19:01:28146
Ben Striegela605fd02012-08-11 14:08:42147 fn parse() -> Result<Json, Error> {
Brian Andersonecaf9e32012-08-06 19:34:08148 match self.parse_value() {
Brian Anderson0c6e4702012-08-26 23:54:31149 Ok(value) => {
Tycho Sciecf87c32012-02-29 08:47:17150 // Skip trailing whitespaces.
151 self.parse_whitespace();
Erick Tryzelaar012dec52012-02-26 00:39:32152 // Make sure there is no trailing characters.
153 if self.eof() {
Brian Anderson0c6e4702012-08-26 23:54:31154 Ok(value)
Erick Tryzelaar012dec52012-02-26 00:39:32155 } else {
Michael Sullivan92743dc2012-07-14 05:57:48156 self.error(~"trailing characters")
Erick Tryzelaar012dec52012-02-26 00:39:32157 }
158 }
Brian Anderson025d8662012-08-04 02:59:04159 e => e
Elly Jonesbd726262011-11-07 19:01:28160 }
Elly Jonesbd726262011-11-07 19:01:28161 }
Elly Jonesbd726262011-11-07 19:01:28162
Ben Striegela605fd02012-08-11 14:08:42163 fn parse_value() -> Result<Json, Error> {
Erick Tryzelaar012dec52012-02-26 00:39:32164 self.parse_whitespace();
Elly Jonesbd726262011-11-07 19:01:28165
Brian Andersonb3559362012-08-02 00:30:05166 if self.eof() { return self.error(~"EOF while parsing value"); }
Erick Tryzelaar012dec52012-02-26 00:39:32167
Brian Andersonecaf9e32012-08-06 19:34:08168 match self.ch {
Ben Striegela605fd02012-08-11 14:08:42169 'n' => self.parse_ident(~"ull", Null),
170 't' => self.parse_ident(~"rue", Boolean(true)),
171 'f' => self.parse_ident(~"alse", Boolean(false)),
Brian Anderson025d8662012-08-04 02:59:04172 '0' to '9' | '-' => self.parse_number(),
Brian Andersonecaf9e32012-08-06 19:34:08173 '"' => match self.parse_str() {
Ben Striegela605fd02012-08-11 14:08:42174 Ok(s) => Ok(String(s)),
Brian Anderson0c6e4702012-08-26 23:54:31175 Err(e) => Err(e)
Brian Anderson2772b2e2012-08-07 00:14:32176 },
Brian Anderson025d8662012-08-04 02:59:04177 '[' => self.parse_list(),
178 '{' => self.parse_object(),
179 _ => self.error(~"invalid syntax")
Erick Tryzelaar012dec52012-02-26 00:39:32180 }
181 }
182
183 fn parse_whitespace() {
184 while char::is_whitespace(self.ch) { self.bump(); }
185 }
186
Ben Striegela605fd02012-08-11 14:08:42187 fn parse_ident(ident: ~str, value: Json) -> Result<Json, Error> {
Brian Andersond1fc2b52012-06-30 23:19:07188 if str::all(ident, |c| c == self.next_char()) {
Erick Tryzelaar012dec52012-02-26 00:39:32189 self.bump();
Brian Anderson0c6e4702012-08-26 23:54:31190 Ok(value)
Erick Tryzelaar012dec52012-02-26 00:39:32191 } else {
Michael Sullivan92743dc2012-07-14 05:57:48192 self.error(~"invalid syntax")
Erick Tryzelaar012dec52012-02-26 00:39:32193 }
194 }
195
Ben Striegela605fd02012-08-11 14:08:42196 fn parse_number() -> Result<Json, Error> {
Niko Matsakis6b358752012-03-14 18:03:56197 let mut neg = 1f;
Erick Tryzelaar012dec52012-02-26 00:39:32198
199 if self.ch == '-' {
200 self.bump();
Marijn Haverbeke4f826d82011-12-16 09:11:00201 neg = -1f;
Elly Jonesbd726262011-11-07 19:01:28202 }
Elly Jonesbd726262011-11-07 19:01:28203
Brian Andersonecaf9e32012-08-06 19:34:08204 let mut res = match self.parse_integer() {
Brian Anderson0c6e4702012-08-26 23:54:31205 Ok(res) => res,
206 Err(e) => return Err(e)
Erick Tryzelaar012dec52012-02-26 00:39:32207 };
208
209 if self.ch == '.' {
Brian Andersonecaf9e32012-08-06 19:34:08210 match self.parse_decimal(res) {
Brian Anderson0c6e4702012-08-26 23:54:31211 Ok(r) => res = r,
212 Err(e) => return Err(e)
Elly Jonesbd726262011-11-07 19:01:28213 }
Elly Jonesbd726262011-11-07 19:01:28214 }
Erick Tryzelaar012dec52012-02-26 00:39:32215
216 if self.ch == 'e' || self.ch == 'E' {
Brian Andersonecaf9e32012-08-06 19:34:08217 match self.parse_exponent(res) {
Brian Anderson0c6e4702012-08-26 23:54:31218 Ok(r) => res = r,
219 Err(e) => return Err(e)
Erick Tryzelaar012dec52012-02-26 00:39:32220 }
221 }
222
Ben Striegela605fd02012-08-11 14:08:42223 Ok(Num(neg * res))
Elly Jonesbd726262011-11-07 19:01:28224 }
225
Ben Striegela605fd02012-08-11 14:08:42226 fn parse_integer() -> Result<float, Error> {
Niko Matsakis6b358752012-03-14 18:03:56227 let mut res = 0f;
Erick Tryzelaar012dec52012-02-26 00:39:32228
Brian Andersonecaf9e32012-08-06 19:34:08229 match self.ch {
Brian Anderson025d8662012-08-04 02:59:04230 '0' => {
Erick Tryzelaar012dec52012-02-26 00:39:32231 self.bump();
232
233 // There can be only one leading '0'.
Brian Andersonecaf9e32012-08-06 19:34:08234 match self.ch {
Brian Anderson025d8662012-08-04 02:59:04235 '0' to '9' => return self.error(~"invalid number"),
236 _ => ()
Erick Tryzelaar012dec52012-02-26 00:39:32237 }
238 }
Brian Anderson025d8662012-08-04 02:59:04239 '1' to '9' => {
Erick Tryzelaar012dec52012-02-26 00:39:32240 while !self.eof() {
Brian Andersonecaf9e32012-08-06 19:34:08241 match self.ch {
Brian Anderson025d8662012-08-04 02:59:04242 '0' to '9' => {
Erick Tryzelaar012dec52012-02-26 00:39:32243 res *= 10f;
244 res += ((self.ch as int) - ('0' as int)) as float;
245
246 self.bump();
247 }
Brian Anderson025d8662012-08-04 02:59:04248 _ => break
Erick Tryzelaar012dec52012-02-26 00:39:32249 }
250 }
251 }
Brian Anderson025d8662012-08-04 02:59:04252 _ => return self.error(~"invalid number")
Erick Tryzelaar012dec52012-02-26 00:39:32253 }
254
Brian Anderson0c6e4702012-08-26 23:54:31255 Ok(res)
Elly Jonesbd726262011-11-07 19:01:28256 }
257
Ben Striegela605fd02012-08-11 14:08:42258 fn parse_decimal(res: float) -> Result<float, Error> {
Erick Tryzelaar012dec52012-02-26 00:39:32259 self.bump();
260
261 // Make sure a digit follows the decimal place.
Brian Andersonecaf9e32012-08-06 19:34:08262 match self.ch {
Brian Anderson025d8662012-08-04 02:59:04263 '0' to '9' => (),
264 _ => return self.error(~"invalid number")
Erick Tryzelaar012dec52012-02-26 00:39:32265 }
266
Niko Matsakis6b358752012-03-14 18:03:56267 let mut res = res;
268 let mut dec = 1f;
Erick Tryzelaar012dec52012-02-26 00:39:32269 while !self.eof() {
Brian Andersonecaf9e32012-08-06 19:34:08270 match self.ch {
Brian Anderson025d8662012-08-04 02:59:04271 '0' to '9' => {
Marijn Haverbeke4f826d82011-12-16 09:11:00272 dec /= 10f;
Erick Tryzelaar012dec52012-02-26 00:39:32273 res += (((self.ch as int) - ('0' as int)) as float) * dec;
274
275 self.bump();
276 }
Brian Anderson025d8662012-08-04 02:59:04277 _ => break
Elly Jonesbd726262011-11-07 19:01:28278 }
Elly Jonesbd726262011-11-07 19:01:28279 }
Elly Jonesbd726262011-11-07 19:01:28280
Brian Anderson0c6e4702012-08-26 23:54:31281 Ok(res)
Erick Tryzelaar012dec52012-02-26 00:39:32282 }
283
Ben Striegela605fd02012-08-11 14:08:42284 fn parse_exponent(res: float) -> Result<float, Error> {
Erick Tryzelaar012dec52012-02-26 00:39:32285 self.bump();
286
Niko Matsakis6b358752012-03-14 18:03:56287 let mut res = res;
288 let mut exp = 0u;
289 let mut neg_exp = false;
Erick Tryzelaar012dec52012-02-26 00:39:32290
Brian Andersonecaf9e32012-08-06 19:34:08291 match self.ch {
Brian Anderson025d8662012-08-04 02:59:04292 '+' => self.bump(),
293 '-' => { self.bump(); neg_exp = true; }
294 _ => ()
Erick Tryzelaar012dec52012-02-26 00:39:32295 }
296
297 // Make sure a digit follows the exponent place.
Brian Andersonecaf9e32012-08-06 19:34:08298 match self.ch {
Brian Anderson025d8662012-08-04 02:59:04299 '0' to '9' => (),
300 _ => return self.error(~"invalid number")
Erick Tryzelaar012dec52012-02-26 00:39:32301 }
302
303 while !self.eof() {
Brian Andersonecaf9e32012-08-06 19:34:08304 match self.ch {
Brian Anderson025d8662012-08-04 02:59:04305 '0' to '9' => {
Erick Tryzelaar012dec52012-02-26 00:39:32306 exp *= 10u;
307 exp += (self.ch as uint) - ('0' as uint);
308
309 self.bump();
310 }
Brian Anderson025d8662012-08-04 02:59:04311 _ => break
Erick Tryzelaar012dec52012-02-26 00:39:32312 }
313 }
314
315 let exp = float::pow_with_uint(10u, exp);
316 if neg_exp {
317 res /= exp;
318 } else {
319 res *= exp;
320 }
321
Brian Anderson0c6e4702012-08-26 23:54:31322 Ok(res)
Erick Tryzelaar012dec52012-02-26 00:39:32323 }
324
Ben Striegela605fd02012-08-11 14:08:42325 fn parse_str() -> Result<@~str, Error> {
Niko Matsakis6b358752012-03-14 18:03:56326 let mut escape = false;
Michael Sullivan92743dc2012-07-14 05:57:48327 let mut res = ~"";
Erick Tryzelaar012dec52012-02-26 00:39:32328
329 while !self.eof() {
330 self.bump();
331
332 if (escape) {
Brian Andersonecaf9e32012-08-06 19:34:08333 match self.ch {
Brian Anderson025d8662012-08-04 02:59:04334 '"' => str::push_char(res, '"'),
335 '\\' => str::push_char(res, '\\'),
336 '/' => str::push_char(res, '/'),
337 'b' => str::push_char(res, '\x08'),
338 'f' => str::push_char(res, '\x0c'),
339 'n' => str::push_char(res, '\n'),
340 'r' => str::push_char(res, '\r'),
341 't' => str::push_char(res, '\t'),
342 'u' => {
Erick Tryzelaar012dec52012-02-26 00:39:32343 // Parse \u1234.
Niko Matsakis6b358752012-03-14 18:03:56344 let mut i = 0u;
345 let mut n = 0u;
Erick Tryzelaar012dec52012-02-26 00:39:32346 while i < 4u {
Brian Andersonecaf9e32012-08-06 19:34:08347 match self.next_char() {
Brian Anderson025d8662012-08-04 02:59:04348 '0' to '9' => {
Erick Tryzelaar012dec52012-02-26 00:39:32349 n = n * 10u +
350 (self.ch as uint) - ('0' as uint);
351 }
Brian Anderson025d8662012-08-04 02:59:04352 _ => return self.error(~"invalid \\u escape")
Erick Tryzelaar012dec52012-02-26 00:39:32353 }
Niko Matsakis6b358752012-03-14 18:03:56354 i += 1u;
Erick Tryzelaar012dec52012-02-26 00:39:32355 }
356
357 // Error out if we didn't parse 4 digits.
358 if i != 4u {
Brian Andersonb3559362012-08-02 00:30:05359 return self.error(~"invalid \\u escape");
Erick Tryzelaar012dec52012-02-26 00:39:32360 }
361
362 str::push_char(res, n as char);
363 }
Brian Anderson025d8662012-08-04 02:59:04364 _ => return self.error(~"invalid escape")
Erick Tryzelaar012dec52012-02-26 00:39:32365 }
366 escape = false;
367 } else if self.ch == '\\' {
368 escape = true;
369 } else {
370 if self.ch == '"' {
371 self.bump();
Brian Anderson0c6e4702012-08-26 23:54:31372 return Ok(@res);
Erick Tryzelaar012dec52012-02-26 00:39:32373 }
374 str::push_char(res, self.ch);
375 }
376 }
377
Michael Sullivan92743dc2012-07-14 05:57:48378 self.error(~"EOF while parsing string")
Erick Tryzelaar012dec52012-02-26 00:39:32379 }
380
Ben Striegela605fd02012-08-11 14:08:42381 fn parse_list() -> Result<Json, Error> {
Erick Tryzelaar012dec52012-02-26 00:39:32382 self.bump();
383 self.parse_whitespace();
384
Michael Sullivan98e161f2012-06-29 23:26:56385 let mut values = ~[];
Erick Tryzelaar012dec52012-02-26 00:39:32386
387 if self.ch == ']' {
388 self.bump();
Ben Striegela605fd02012-08-11 14:08:42389 return Ok(List(@values));
Erick Tryzelaar012dec52012-02-26 00:39:32390 }
391
Tim Chevalier35400e12012-03-11 04:34:17392 loop {
Brian Andersonecaf9e32012-08-06 19:34:08393 match self.parse_value() {
Brian Anderson0c6e4702012-08-26 23:54:31394 Ok(v) => vec::push(values, v),
Brian Anderson025d8662012-08-04 02:59:04395 e => return e
Erick Tryzelaar012dec52012-02-26 00:39:32396 }
397
398 self.parse_whitespace();
Tim Chevalier35400e12012-03-11 04:34:17399 if self.eof() {
Brian Andersonb3559362012-08-02 00:30:05400 return self.error(~"EOF while parsing list");
Tim Chevalier35400e12012-03-11 04:34:17401 }
Erick Tryzelaar012dec52012-02-26 00:39:32402
Brian Andersonecaf9e32012-08-06 19:34:08403 match self.ch {
Brian Anderson025d8662012-08-04 02:59:04404 ',' => self.bump(),
Ben Striegela605fd02012-08-11 14:08:42405 ']' => { self.bump(); return Ok(List(@values)); }
Brian Anderson025d8662012-08-04 02:59:04406 _ => return self.error(~"expected `,` or `]`")
Erick Tryzelaar012dec52012-02-26 00:39:32407 }
Tim Chevalier35400e12012-03-11 04:34:17408 };
Erick Tryzelaar012dec52012-02-26 00:39:32409 }
410
Ben Striegela605fd02012-08-11 14:08:42411 fn parse_object() -> Result<Json, Error> {
Erick Tryzelaar012dec52012-02-26 00:39:32412 self.bump();
413 self.parse_whitespace();
414
Brian Anderson3864d6d2012-03-14 19:07:23415 let values = map::str_hash();
Erick Tryzelaar012dec52012-02-26 00:39:32416
417 if self.ch == '}' {
418 self.bump();
Ben Striegela605fd02012-08-11 14:08:42419 return Ok(Dict(values));
Erick Tryzelaar012dec52012-02-26 00:39:32420 }
421
422 while !self.eof() {
423 self.parse_whitespace();
424
425 if self.ch != '"' {
Brian Andersonb3559362012-08-02 00:30:05426 return self.error(~"key must be a string");
Erick Tryzelaar012dec52012-02-26 00:39:32427 }
428
Brian Andersonecaf9e32012-08-06 19:34:08429 let key = match self.parse_str() {
Brian Anderson0c6e4702012-08-26 23:54:31430 Ok(key) => key,
431 Err(e) => return Err(e)
Erick Tryzelaar012dec52012-02-26 00:39:32432 };
433
434 self.parse_whitespace();
435
436 if self.ch != ':' {
437 if self.eof() { break; }
Brian Andersonb3559362012-08-02 00:30:05438 return self.error(~"expected `:`");
Erick Tryzelaar012dec52012-02-26 00:39:32439 }
440 self.bump();
441
Brian Andersonecaf9e32012-08-06 19:34:08442 match self.parse_value() {
Brian Anderson0c6e4702012-08-26 23:54:31443 Ok(value) => { values.insert(copy *key, value); }
Brian Anderson025d8662012-08-04 02:59:04444 e => return e
Erick Tryzelaar012dec52012-02-26 00:39:32445 }
446 self.parse_whitespace();
447
Brian Andersonecaf9e32012-08-06 19:34:08448 match self.ch {
Brian Anderson025d8662012-08-04 02:59:04449 ',' => self.bump(),
Ben Striegela605fd02012-08-11 14:08:42450 '}' => { self.bump(); return Ok(Dict(values)); }
Brian Anderson025d8662012-08-04 02:59:04451 _ => {
Erick Tryzelaar012dec52012-02-26 00:39:32452 if self.eof() { break; }
Brian Andersonb3559362012-08-02 00:30:05453 return self.error(~"expected `,` or `}`");
Erick Tryzelaar012dec52012-02-26 00:39:32454 }
455 }
456 }
457
Brian Andersonb3559362012-08-02 00:30:05458 return self.error(~"EOF while parsing object");
Elly Jonesbd726262011-11-07 19:01:28459 }
460}
461
Gareth Daniel Smithbe014162012-07-04 21:53:12462/// Deserializes a json value from an io::reader
Ben Striegela605fd02012-08-11 14:08:42463fn from_reader(rdr: io::Reader) -> Result<Json, Error> {
464 let parser = Parser_({
Erick Tryzelaar012dec52012-02-26 00:39:32465 rdr: rdr,
Graydon Hoare6e6798c2012-03-27 01:35:18466 mut ch: rdr.read_char(),
467 mut line: 1u,
468 mut col: 1u,
Patrick Waltondb020ab2012-07-11 22:00:40469 });
Erick Tryzelaar012dec52012-02-26 00:39:32470
471 parser.parse()
Elly Jonesbd726262011-11-07 19:01:28472}
473
Gareth Daniel Smithbe014162012-07-04 21:53:12474/// Deserializes a json value from a string
Ben Striegela605fd02012-08-11 14:08:42475fn from_str(s: ~str) -> Result<Json, Error> {
Erick Tryzelaar1404a862012-02-29 18:48:57476 io::with_str_reader(s, from_reader)
Erick Tryzelaar012dec52012-02-26 00:39:32477}
478
Gareth Daniel Smithbe014162012-07-04 21:53:12479/// Test if two json values are equal
Ben Striegela605fd02012-08-11 14:08:42480fn eq(value0: Json, value1: Json) -> bool {
Brian Andersonecaf9e32012-08-06 19:34:08481 match (value0, value1) {
Ben Striegela605fd02012-08-11 14:08:42482 (Num(f0), Num(f1)) => f0 == f1,
483 (String(s0), String(s1)) => s0 == s1,
484 (Boolean(b0), Boolean(b1)) => b0 == b1,
485 (List(l0), List(l1)) => vec::all2(*l0, *l1, eq),
486 (Dict(d0), Dict(d1)) => {
Erick Tryzelaar012dec52012-02-26 00:39:32487 if d0.size() == d1.size() {
Niko Matsakis6b358752012-03-14 18:03:56488 let mut equal = true;
Brian Andersond1fc2b52012-06-30 23:19:07489 for d0.each |k, v0| {
Brian Andersonecaf9e32012-08-06 19:34:08490 match d1.find(k) {
Brian Anderson8337fa12012-08-20 19:23:37491 Some(v1) => if !eq(v0, v1) { equal = false },
492 None => equal = false
Erick Tryzelaar012dec52012-02-26 00:39:32493 }
494 };
495 equal
496 } else {
497 false
498 }
499 }
Ben Striegela605fd02012-08-11 14:08:42500 (Null, Null) => true,
Brian Anderson025d8662012-08-04 02:59:04501 _ => false
Erick Tryzelaar012dec52012-02-26 00:39:32502 }
Elly Jonesbd726262011-11-07 19:01:28503}
Brian Anderson6e27b272012-01-18 03:05:07504
Ben Striegela605fd02012-08-11 14:08:42505trait ToJson { fn to_json() -> Json; }
Erick Tryzelaared5af702012-05-28 19:10:32506
Ben Striegela605fd02012-08-11 14:08:42507impl Json: ToJson {
508 fn to_json() -> Json { self }
Erick Tryzelaared5af702012-05-28 19:10:32509}
510
Ben Striegela605fd02012-08-11 14:08:42511impl @Json: ToJson {
512 fn to_json() -> Json { *self }
Erick Tryzelaar11a56c32012-06-13 15:30:54513}
514
Ben Striegela605fd02012-08-11 14:08:42515impl int: ToJson {
516 fn to_json() -> Json { Num(self as float) }
Erick Tryzelaar11a56c32012-06-13 15:30:54517}
518
Ben Striegela605fd02012-08-11 14:08:42519impl i8: ToJson {
520 fn to_json() -> Json { Num(self as float) }
Erick Tryzelaared5af702012-05-28 19:10:32521}
522
Ben Striegela605fd02012-08-11 14:08:42523impl i16: ToJson {
524 fn to_json() -> Json { Num(self as float) }
Erick Tryzelaared5af702012-05-28 19:10:32525}
526
Ben Striegela605fd02012-08-11 14:08:42527impl i32: ToJson {
528 fn to_json() -> Json { Num(self as float) }
Erick Tryzelaared5af702012-05-28 19:10:32529}
530
Ben Striegela605fd02012-08-11 14:08:42531impl i64: ToJson {
532 fn to_json() -> Json { Num(self as float) }
Erick Tryzelaared5af702012-05-28 19:10:32533}
534
Ben Striegela605fd02012-08-11 14:08:42535impl uint: ToJson {
536 fn to_json() -> Json { Num(self as float) }
Erick Tryzelaar11a56c32012-06-13 15:30:54537}
538
Ben Striegela605fd02012-08-11 14:08:42539impl u8: ToJson {
540 fn to_json() -> Json { Num(self as float) }
Erick Tryzelaared5af702012-05-28 19:10:32541}
542
Ben Striegela605fd02012-08-11 14:08:42543impl u16: ToJson {
544 fn to_json() -> Json { Num(self as float) }
Erick Tryzelaared5af702012-05-28 19:10:32545}
546
Ben Striegela605fd02012-08-11 14:08:42547impl u32: ToJson {
548 fn to_json() -> Json { Num(self as float) }
Erick Tryzelaared5af702012-05-28 19:10:32549}
550
Ben Striegela605fd02012-08-11 14:08:42551impl u64: ToJson {
552 fn to_json() -> Json { Num(self as float) }
Erick Tryzelaared5af702012-05-28 19:10:32553}
554
Ben Striegela605fd02012-08-11 14:08:42555impl float: ToJson {
556 fn to_json() -> Json { Num(self) }
Erick Tryzelaared5af702012-05-28 19:10:32557}
558
Ben Striegela605fd02012-08-11 14:08:42559impl f32: ToJson {
560 fn to_json() -> Json { Num(self as float) }
Erick Tryzelaared5af702012-05-28 19:10:32561}
562
Ben Striegela605fd02012-08-11 14:08:42563impl f64: ToJson {
564 fn to_json() -> Json { Num(self as float) }
Erick Tryzelaared5af702012-05-28 19:10:32565}
566
Ben Striegela605fd02012-08-11 14:08:42567impl (): ToJson {
568 fn to_json() -> Json { Null }
Erick Tryzelaared5af702012-05-28 19:10:32569}
570
Ben Striegela605fd02012-08-11 14:08:42571impl bool: ToJson {
572 fn to_json() -> Json { Boolean(self) }
Erick Tryzelaared5af702012-05-28 19:10:32573}
574
Ben Striegela605fd02012-08-11 14:08:42575impl ~str: ToJson {
576 fn to_json() -> Json { String(@copy self) }
Erick Tryzelaarb361f6c2012-06-13 00:20:51577}
578
Ben Striegela605fd02012-08-11 14:08:42579impl @~str: ToJson {
580 fn to_json() -> Json { String(self) }
Erick Tryzelaared5af702012-05-28 19:10:32581}
582
Ben Striegela605fd02012-08-11 14:08:42583impl <A: ToJson, B: ToJson> (A, B): ToJson {
584 fn to_json() -> Json {
Brian Andersonecaf9e32012-08-06 19:34:08585 match self {
Niko Matsakis97452c02012-08-02 22:42:56586 (a, b) => {
Ben Striegela605fd02012-08-11 14:08:42587 List(@~[a.to_json(), b.to_json()])
Niko Matsakis97452c02012-08-02 22:42:56588 }
589 }
Erick Tryzelaared5af702012-05-28 19:10:32590 }
591}
592
Ben Striegela605fd02012-08-11 14:08:42593impl <A: ToJson, B: ToJson, C: ToJson> (A, B, C): ToJson {
Brian Anderson6a0720b2012-08-08 01:10:06594
Ben Striegela605fd02012-08-11 14:08:42595 fn to_json() -> Json {
Brian Andersonecaf9e32012-08-06 19:34:08596 match self {
Niko Matsakis97452c02012-08-02 22:42:56597 (a, b, c) => {
Ben Striegela605fd02012-08-11 14:08:42598 List(@~[a.to_json(), b.to_json(), c.to_json()])
Niko Matsakis97452c02012-08-02 22:42:56599 }
600 }
Erick Tryzelaared5af702012-05-28 19:10:32601 }
602}
603
Ben Striegela605fd02012-08-11 14:08:42604impl <A: ToJson> ~[A]: ToJson {
605 fn to_json() -> Json { List(@self.map(|elt| elt.to_json())) }
Erick Tryzelaared5af702012-05-28 19:10:32606}
607
Ben Striegela605fd02012-08-11 14:08:42608impl <A: ToJson copy> hashmap<~str, A>: ToJson {
609 fn to_json() -> Json {
Erick Tryzelaared5af702012-05-28 19:10:32610 let d = map::str_hash();
Brian Andersond1fc2b52012-06-30 23:19:07611 for self.each() |key, value| {
Erick Tryzelaarb361f6c2012-06-13 00:20:51612 d.insert(copy key, value.to_json());
Erick Tryzelaared5af702012-05-28 19:10:32613 }
Ben Striegela605fd02012-08-11 14:08:42614 Dict(d)
Erick Tryzelaared5af702012-05-28 19:10:32615 }
616}
617
Ben Striegela605fd02012-08-11 14:08:42618impl <A: ToJson> Option<A>: ToJson {
619 fn to_json() -> Json {
Brian Andersonecaf9e32012-08-06 19:34:08620 match self {
Ben Striegela605fd02012-08-11 14:08:42621 None => Null,
Brian Anderson8337fa12012-08-20 19:23:37622 Some(value) => value.to_json()
Erick Tryzelaared5af702012-05-28 19:10:32623 }
624 }
625}
626
Ben Striegela605fd02012-08-11 14:08:42627impl Json: to_str::ToStr {
Michael Sullivan92743dc2012-07-14 05:57:48628 fn to_str() -> ~str { to_str(self) }
Erick Tryzelaared5af702012-05-28 19:10:32629}
630
Ben Striegela605fd02012-08-11 14:08:42631impl Error: to_str::ToStr {
Michael Sullivan92743dc2012-07-14 05:57:48632 fn to_str() -> ~str {
Paul Stansifer29f32b42012-08-23 00:24:52633 fmt!("%u:%u: %s", self.line, self.col, *self.msg)
Erick Tryzelaara8161762012-06-11 15:32:38634 }
635}
636
Brian Anderson6e27b272012-01-18 03:05:07637#[cfg(test)]
638mod tests {
Ben Striegela605fd02012-08-11 14:08:42639 fn mk_dict(items: ~[(~str, Json)]) -> Json {
Brian Anderson3864d6d2012-03-14 19:07:23640 let d = map::str_hash();
Erick Tryzelaar012dec52012-02-26 00:39:32641
Brian Andersond1fc2b52012-06-30 23:19:07642 do vec::iter(items) |item| {
Erick Tryzelaarb361f6c2012-06-13 00:20:51643 let (key, value) = copy item;
Erick Tryzelaar012dec52012-02-26 00:39:32644 d.insert(key, value);
645 };
646
Ben Striegela605fd02012-08-11 14:08:42647 Dict(d)
Brian Anderson6e27b272012-01-18 03:05:07648 }
649
650 #[test]
Erick Tryzelaar012dec52012-02-26 00:39:32651 fn test_write_null() {
Ben Striegela605fd02012-08-11 14:08:42652 assert to_str(Null) == ~"null";
Brian Anderson6e27b272012-01-18 03:05:07653 }
654
655 #[test]
Erick Tryzelaar012dec52012-02-26 00:39:32656 fn test_write_num() {
Ben Striegela605fd02012-08-11 14:08:42657 assert to_str(Num(3f)) == ~"3";
658 assert to_str(Num(3.1f)) == ~"3.1";
659 assert to_str(Num(-1.5f)) == ~"-1.5";
660 assert to_str(Num(0.5f)) == ~"0.5";
Brian Anderson6e27b272012-01-18 03:05:07661 }
662
663 #[test]
Erick Tryzelaar012dec52012-02-26 00:39:32664 fn test_write_str() {
Ben Striegela605fd02012-08-11 14:08:42665 assert to_str(String(@~"")) == ~"\"\"";
666 assert to_str(String(@~"foo")) == ~"\"foo\"";
Brian Anderson6e27b272012-01-18 03:05:07667 }
668
669 #[test]
Erick Tryzelaar012dec52012-02-26 00:39:32670 fn test_write_bool() {
Ben Striegela605fd02012-08-11 14:08:42671 assert to_str(Boolean(true)) == ~"true";
672 assert to_str(Boolean(false)) == ~"false";
Brian Anderson6e27b272012-01-18 03:05:07673 }
674
675 #[test]
Erick Tryzelaar012dec52012-02-26 00:39:32676 fn test_write_list() {
Ben Striegela605fd02012-08-11 14:08:42677 assert to_str(List(@~[])) == ~"[]";
678 assert to_str(List(@~[Boolean(true)])) == ~"[true]";
679 assert to_str(List(@~[
680 Boolean(false),
681 Null,
682 List(@~[String(@~"foo\nbar"), Num(3.5f)])
Michael Sullivan92743dc2012-07-14 05:57:48683 ])) == ~"[false, null, [\"foo\\nbar\", 3.5]]";
Erick Tryzelaar012dec52012-02-26 00:39:32684 }
685
686 #[test]
687 fn test_write_dict() {
Michael Sullivan92743dc2012-07-14 05:57:48688 assert to_str(mk_dict(~[])) == ~"{}";
Ben Striegela605fd02012-08-11 14:08:42689 assert to_str(mk_dict(~[(~"a", Boolean(true))]))
Michael Sullivan92743dc2012-07-14 05:57:48690 == ~"{ \"a\": true }";
Michael Sullivan98e161f2012-06-29 23:26:56691 assert to_str(mk_dict(~[
Ben Striegela605fd02012-08-11 14:08:42692 (~"a", Boolean(true)),
693 (~"b", List(@~[
694 mk_dict(~[(~"c", String(@~"\x0c\r"))]),
695 mk_dict(~[(~"d", String(@~""))])
Michael Sullivan98e161f2012-06-29 23:26:56696 ]))
697 ])) ==
Michael Sullivan92743dc2012-07-14 05:57:48698 ~"{ " +
699 ~"\"a\": true, " +
700 ~"\"b\": [" +
701 ~"{ \"c\": \"\\f\\r\" }, " +
702 ~"{ \"d\": \"\" }" +
703 ~"]" +
704 ~" }";
Erick Tryzelaar012dec52012-02-26 00:39:32705 }
706
707 #[test]
708 fn test_trailing_characters() {
Michael Sullivan92743dc2012-07-14 05:57:48709 assert from_str(~"nulla") ==
Brian Anderson0c6e4702012-08-26 23:54:31710 Err({line: 1u, col: 5u, msg: @~"trailing characters"});
Michael Sullivan92743dc2012-07-14 05:57:48711 assert from_str(~"truea") ==
Brian Anderson0c6e4702012-08-26 23:54:31712 Err({line: 1u, col: 5u, msg: @~"trailing characters"});
Michael Sullivan92743dc2012-07-14 05:57:48713 assert from_str(~"falsea") ==
Brian Anderson0c6e4702012-08-26 23:54:31714 Err({line: 1u, col: 6u, msg: @~"trailing characters"});
Michael Sullivan92743dc2012-07-14 05:57:48715 assert from_str(~"1a") ==
Brian Anderson0c6e4702012-08-26 23:54:31716 Err({line: 1u, col: 2u, msg: @~"trailing characters"});
Michael Sullivan92743dc2012-07-14 05:57:48717 assert from_str(~"[]a") ==
Brian Anderson0c6e4702012-08-26 23:54:31718 Err({line: 1u, col: 3u, msg: @~"trailing characters"});
Michael Sullivan92743dc2012-07-14 05:57:48719 assert from_str(~"{}a") ==
Brian Anderson0c6e4702012-08-26 23:54:31720 Err({line: 1u, col: 3u, msg: @~"trailing characters"});
Erick Tryzelaar012dec52012-02-26 00:39:32721 }
722
723 #[test]
724 fn test_read_identifiers() {
Michael Sullivan92743dc2012-07-14 05:57:48725 assert from_str(~"n") ==
Brian Anderson0c6e4702012-08-26 23:54:31726 Err({line: 1u, col: 2u, msg: @~"invalid syntax"});
Michael Sullivan92743dc2012-07-14 05:57:48727 assert from_str(~"nul") ==
Brian Anderson0c6e4702012-08-26 23:54:31728 Err({line: 1u, col: 4u, msg: @~"invalid syntax"});
Erick Tryzelaar012dec52012-02-26 00:39:32729
Michael Sullivan92743dc2012-07-14 05:57:48730 assert from_str(~"t") ==
Brian Anderson0c6e4702012-08-26 23:54:31731 Err({line: 1u, col: 2u, msg: @~"invalid syntax"});
Michael Sullivan92743dc2012-07-14 05:57:48732 assert from_str(~"truz") ==
Brian Anderson0c6e4702012-08-26 23:54:31733 Err({line: 1u, col: 4u, msg: @~"invalid syntax"});
Erick Tryzelaar012dec52012-02-26 00:39:32734
Michael Sullivan92743dc2012-07-14 05:57:48735 assert from_str(~"f") ==
Brian Anderson0c6e4702012-08-26 23:54:31736 Err({line: 1u, col: 2u, msg: @~"invalid syntax"});
Michael Sullivan92743dc2012-07-14 05:57:48737 assert from_str(~"faz") ==
Brian Anderson0c6e4702012-08-26 23:54:31738 Err({line: 1u, col: 3u, msg: @~"invalid syntax"});
Erick Tryzelaar012dec52012-02-26 00:39:32739
Ben Striegela605fd02012-08-11 14:08:42740 assert from_str(~"null") == Ok(Null);
741 assert from_str(~"true") == Ok(Boolean(true));
742 assert from_str(~"false") == Ok(Boolean(false));
743 assert from_str(~" null ") == Ok(Null);
744 assert from_str(~" true ") == Ok(Boolean(true));
745 assert from_str(~" false ") == Ok(Boolean(false));
Erick Tryzelaar012dec52012-02-26 00:39:32746 }
747
748 #[test]
749 fn test_read_num() {
Michael Sullivan92743dc2012-07-14 05:57:48750 assert from_str(~"+") ==
Brian Anderson0c6e4702012-08-26 23:54:31751 Err({line: 1u, col: 1u, msg: @~"invalid syntax"});
Michael Sullivan92743dc2012-07-14 05:57:48752 assert from_str(~".") ==
Brian Anderson0c6e4702012-08-26 23:54:31753 Err({line: 1u, col: 1u, msg: @~"invalid syntax"});
Erick Tryzelaar012dec52012-02-26 00:39:32754
Michael Sullivan92743dc2012-07-14 05:57:48755 assert from_str(~"-") ==
Brian Anderson0c6e4702012-08-26 23:54:31756 Err({line: 1u, col: 2u, msg: @~"invalid number"});
Michael Sullivan92743dc2012-07-14 05:57:48757 assert from_str(~"00") ==
Brian Anderson0c6e4702012-08-26 23:54:31758 Err({line: 1u, col: 2u, msg: @~"invalid number"});
Michael Sullivan92743dc2012-07-14 05:57:48759 assert from_str(~"1.") ==
Brian Anderson0c6e4702012-08-26 23:54:31760 Err({line: 1u, col: 3u, msg: @~"invalid number"});
Michael Sullivan92743dc2012-07-14 05:57:48761 assert from_str(~"1e") ==
Brian Anderson0c6e4702012-08-26 23:54:31762 Err({line: 1u, col: 3u, msg: @~"invalid number"});
Michael Sullivan92743dc2012-07-14 05:57:48763 assert from_str(~"1e+") ==
Brian Anderson0c6e4702012-08-26 23:54:31764 Err({line: 1u, col: 4u, msg: @~"invalid number"});
Erick Tryzelaar012dec52012-02-26 00:39:32765
Ben Striegela605fd02012-08-11 14:08:42766 assert from_str(~"3") == Ok(Num(3f));
767 assert from_str(~"3.1") == Ok(Num(3.1f));
768 assert from_str(~"-1.2") == Ok(Num(-1.2f));
769 assert from_str(~"0.4") == Ok(Num(0.4f));
770 assert from_str(~"0.4e5") == Ok(Num(0.4e5f));
771 assert from_str(~"0.4e+15") == Ok(Num(0.4e15f));
772 assert from_str(~"0.4e-01") == Ok(Num(0.4e-01f));
773 assert from_str(~" 3 ") == Ok(Num(3f));
Erick Tryzelaar012dec52012-02-26 00:39:32774 }
775
776 #[test]
777 fn test_read_str() {
Michael Sullivan92743dc2012-07-14 05:57:48778 assert from_str(~"\"") ==
Brian Anderson0c6e4702012-08-26 23:54:31779 Err({line: 1u, col: 2u, msg: @~"EOF while parsing string"});
Michael Sullivan92743dc2012-07-14 05:57:48780 assert from_str(~"\"lol") ==
Brian Anderson0c6e4702012-08-26 23:54:31781 Err({line: 1u, col: 5u, msg: @~"EOF while parsing string"});
Erick Tryzelaar012dec52012-02-26 00:39:32782
Ben Striegela605fd02012-08-11 14:08:42783 assert from_str(~"\"\"") == Ok(String(@~""));
784 assert from_str(~"\"foo\"") == Ok(String(@~"foo"));
785 assert from_str(~"\"\\\"\"") == Ok(String(@~"\""));
786 assert from_str(~"\"\\b\"") == Ok(String(@~"\x08"));
787 assert from_str(~"\"\\n\"") == Ok(String(@~"\n"));
788 assert from_str(~"\"\\r\"") == Ok(String(@~"\r"));
789 assert from_str(~"\"\\t\"") == Ok(String(@~"\t"));
790 assert from_str(~" \"foo\" ") == Ok(String(@~"foo"));
Erick Tryzelaar012dec52012-02-26 00:39:32791 }
792
793 #[test]
794 fn test_read_list() {
Michael Sullivan92743dc2012-07-14 05:57:48795 assert from_str(~"[") ==
Brian Anderson0c6e4702012-08-26 23:54:31796 Err({line: 1u, col: 2u, msg: @~"EOF while parsing value"});
Michael Sullivan92743dc2012-07-14 05:57:48797 assert from_str(~"[1") ==
Brian Anderson0c6e4702012-08-26 23:54:31798 Err({line: 1u, col: 3u, msg: @~"EOF while parsing list"});
Michael Sullivan92743dc2012-07-14 05:57:48799 assert from_str(~"[1,") ==
Brian Anderson0c6e4702012-08-26 23:54:31800 Err({line: 1u, col: 4u, msg: @~"EOF while parsing value"});
Michael Sullivan92743dc2012-07-14 05:57:48801 assert from_str(~"[1,]") ==
Brian Anderson0c6e4702012-08-26 23:54:31802 Err({line: 1u, col: 4u, msg: @~"invalid syntax"});
Michael Sullivan92743dc2012-07-14 05:57:48803 assert from_str(~"[6 7]") ==
Brian Anderson0c6e4702012-08-26 23:54:31804 Err({line: 1u, col: 4u, msg: @~"expected `,` or `]`"});
Erick Tryzelaar012dec52012-02-26 00:39:32805
Ben Striegela605fd02012-08-11 14:08:42806 assert from_str(~"[]") == Ok(List(@~[]));
807 assert from_str(~"[ ]") == Ok(List(@~[]));
808 assert from_str(~"[true]") == Ok(List(@~[Boolean(true)]));
809 assert from_str(~"[ false ]") == Ok(List(@~[Boolean(false)]));
810 assert from_str(~"[null]") == Ok(List(@~[Null]));
811 assert from_str(~"[3, 1]") == Ok(List(@~[Num(3f), Num(1f)]));
812 assert from_str(~"\n[3, 2]\n") == Ok(List(@~[Num(3f), Num(2f)]));
Michael Sullivan92743dc2012-07-14 05:57:48813 assert from_str(~"[2, [4, 1]]") ==
Ben Striegela605fd02012-08-11 14:08:42814 Ok(List(@~[Num(2f), List(@~[Num(4f), Num(1f)])]));
Erick Tryzelaar012dec52012-02-26 00:39:32815 }
816
817 #[test]
818 fn test_read_dict() {
Michael Sullivan92743dc2012-07-14 05:57:48819 assert from_str(~"{") ==
Brian Anderson0c6e4702012-08-26 23:54:31820 Err({line: 1u, col: 2u, msg: @~"EOF while parsing object"});
Michael Sullivan92743dc2012-07-14 05:57:48821 assert from_str(~"{ ") ==
Brian Anderson0c6e4702012-08-26 23:54:31822 Err({line: 1u, col: 3u, msg: @~"EOF while parsing object"});
Michael Sullivan92743dc2012-07-14 05:57:48823 assert from_str(~"{1") ==
Brian Anderson0c6e4702012-08-26 23:54:31824 Err({line: 1u, col: 2u, msg: @~"key must be a string"});
Michael Sullivan92743dc2012-07-14 05:57:48825 assert from_str(~"{ \"a\"") ==
Brian Anderson0c6e4702012-08-26 23:54:31826 Err({line: 1u, col: 6u, msg: @~"EOF while parsing object"});
Michael Sullivan92743dc2012-07-14 05:57:48827 assert from_str(~"{\"a\"") ==
Brian Anderson0c6e4702012-08-26 23:54:31828 Err({line: 1u, col: 5u, msg: @~"EOF while parsing object"});
Michael Sullivan92743dc2012-07-14 05:57:48829 assert from_str(~"{\"a\" ") ==
Brian Anderson0c6e4702012-08-26 23:54:31830 Err({line: 1u, col: 6u, msg: @~"EOF while parsing object"});
Erick Tryzelaar012dec52012-02-26 00:39:32831
Michael Sullivan92743dc2012-07-14 05:57:48832 assert from_str(~"{\"a\" 1") ==
Brian Anderson0c6e4702012-08-26 23:54:31833 Err({line: 1u, col: 6u, msg: @~"expected `:`"});
Michael Sullivan92743dc2012-07-14 05:57:48834 assert from_str(~"{\"a\":") ==
Brian Anderson0c6e4702012-08-26 23:54:31835 Err({line: 1u, col: 6u, msg: @~"EOF while parsing value"});
Michael Sullivan92743dc2012-07-14 05:57:48836 assert from_str(~"{\"a\":1") ==
Brian Anderson0c6e4702012-08-26 23:54:31837 Err({line: 1u, col: 7u, msg: @~"EOF while parsing object"});
Michael Sullivan92743dc2012-07-14 05:57:48838 assert from_str(~"{\"a\":1 1") ==
Brian Anderson0c6e4702012-08-26 23:54:31839 Err({line: 1u, col: 8u, msg: @~"expected `,` or `}`"});
Michael Sullivan92743dc2012-07-14 05:57:48840 assert from_str(~"{\"a\":1,") ==
Brian Anderson0c6e4702012-08-26 23:54:31841 Err({line: 1u, col: 8u, msg: @~"EOF while parsing object"});
Erick Tryzelaar012dec52012-02-26 00:39:32842
Michael Sullivan92743dc2012-07-14 05:57:48843 assert eq(result::get(from_str(~"{}")), mk_dict(~[]));
844 assert eq(result::get(from_str(~"{\"a\": 3}")),
Ben Striegela605fd02012-08-11 14:08:42845 mk_dict(~[(~"a", Num(3.0f))]));
Erick Tryzelaar012dec52012-02-26 00:39:32846
Michael Sullivan92743dc2012-07-14 05:57:48847 assert eq(result::get(from_str(~"{ \"a\": null, \"b\" : true }")),
Michael Sullivan98e161f2012-06-29 23:26:56848 mk_dict(~[
Ben Striegela605fd02012-08-11 14:08:42849 (~"a", Null),
850 (~"b", Boolean(true))]));
Michael Sullivan92743dc2012-07-14 05:57:48851 assert eq(result::get(from_str(~"\n{ \"a\": null, \"b\" : true }\n")),
Michael Sullivan98e161f2012-06-29 23:26:56852 mk_dict(~[
Ben Striegela605fd02012-08-11 14:08:42853 (~"a", Null),
854 (~"b", Boolean(true))]));
Michael Sullivan92743dc2012-07-14 05:57:48855 assert eq(result::get(from_str(~"{\"a\" : 1.0 ,\"b\": [ true ]}")),
Michael Sullivan98e161f2012-06-29 23:26:56856 mk_dict(~[
Ben Striegela605fd02012-08-11 14:08:42857 (~"a", Num(1.0)),
858 (~"b", List(@~[Boolean(true)]))
Michael Sullivan98e161f2012-06-29 23:26:56859 ]));
Erick Tryzelaar012dec52012-02-26 00:39:32860 assert eq(result::get(from_str(
Michael Sullivan92743dc2012-07-14 05:57:48861 ~"{" +
862 ~"\"a\": 1.0, " +
863 ~"\"b\": [" +
864 ~"true," +
865 ~"\"foo\\nbar\", " +
866 ~"{ \"c\": {\"d\": null} } " +
867 ~"]" +
868 ~"}")),
Michael Sullivan98e161f2012-06-29 23:26:56869 mk_dict(~[
Ben Striegela605fd02012-08-11 14:08:42870 (~"a", Num(1.0f)),
871 (~"b", List(@~[
872 Boolean(true),
873 String(@~"foo\nbar"),
Michael Sullivan98e161f2012-06-29 23:26:56874 mk_dict(~[
Ben Striegela605fd02012-08-11 14:08:42875 (~"c", mk_dict(~[(~"d", Null)]))
Michael Sullivan98e161f2012-06-29 23:26:56876 ])
877 ]))
878 ]));
Erick Tryzelaar012dec52012-02-26 00:39:32879 }
880
881 #[test]
882 fn test_multiline_errors() {
Michael Sullivan92743dc2012-07-14 05:57:48883 assert from_str(~"{\n \"foo\":\n \"bar\"") ==
Brian Anderson0c6e4702012-08-26 23:54:31884 Err({line: 3u, col: 8u, msg: @~"EOF while parsing object"});
Brian Anderson6e27b272012-01-18 03:05:07885 }
886}