diff options
Diffstat (limited to 'tests/examplefiles/rust_example.rs')
-rw-r--r-- | tests/examplefiles/rust_example.rs | 892 |
1 files changed, 191 insertions, 701 deletions
diff --git a/tests/examplefiles/rust_example.rs b/tests/examplefiles/rust_example.rs index af791fbc..1c0a70c3 100644 --- a/tests/examplefiles/rust_example.rs +++ b/tests/examplefiles/rust_example.rs @@ -1,743 +1,233 @@ - -#[doc = "json serialization"]; - -import result::{result, ok, err}; -import io; -import io::{reader_util, writer_util}; -import map; -import map::hashmap; - -export json; -export error; -export to_writer; -export to_str; -export from_reader; -export from_str; -export eq; - -export num; -export string; -export boolean; -export list; -export dict; -export null; - -#[doc = "Represents a json value"] -enum json { - num(float), - string(str), - boolean(bool), - list([json]), - dict(map::hashmap<str,json>), - null, +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// based on: +// http://shootout.alioth.debian.org/u32/benchmark.php?test=nbody&lang=java + +extern mod std; + +use core::os; + +// Using sqrt from the standard library is way slower than using libc +// directly even though std just calls libc, I guess it must be +// because the the indirection through another dynamic linker +// stub. Kind of shocking. Might be able to make it faster still with +// an llvm intrinsic. +#[nolink] +extern mod libc { + #[legacy_exports]; + fn sqrt(n: float) -> float; } -type error = { - line: uint, - col: uint, - msg: str, -}; - -#[doc = "Serializes a json value into a io::writer"] -fn to_writer(wr: io::writer, j: json) { - alt j { - num(n) { wr.write_str(float::to_str(n, 6u)); } - string(s) { - wr.write_char('"'); - let mut escaped = ""; - str::chars_iter(s) { |c| - alt c { - '"' { escaped += "\\\""; } - '\\' { escaped += "\\\\"; } - '\x08' { escaped += "\\b"; } - '\x0c' { escaped += "\\f"; } - '\n' { escaped += "\\n"; } - '\r' { escaped += "\\r"; } - '\t' { escaped += "\\t"; } - _ { escaped += str::from_char(c); } - } - }; - wr.write_str(escaped); - wr.write_char('"'); - } - boolean(b) { - wr.write_str(if b { "true" } else { "false" }); - } - list(v) { - wr.write_char('['); - let mut first = true; - vec::iter(v) { |item| - if !first { - wr.write_str(", "); - } - first = false; - to_writer(wr, item); - }; - wr.write_char(']'); - } - dict(d) { - if d.size() == 0u { - wr.write_str("{}"); - ret; - } - - wr.write_str("{ "); - let mut first = true; - d.items { |key, value| - if !first { - wr.write_str(", "); - } - first = false; - to_writer(wr, string(key)); - wr.write_str(": "); - to_writer(wr, value); - }; - wr.write_str(" }"); - } - null { - wr.write_str("null"); - } - } +fn main() { + let args = os::args(); + let args = if os::getenv(~"RUST_BENCH").is_some() { + ~[~"", ~"4000000"] + } else if args.len() <= 1u { + ~[~"", ~"100000"] + } else { + args + }; + let n = int::from_str(args[1]).get(); + let mut bodies: ~[Body::props] = NBodySystem::make(); + io::println(fmt!("%f", NBodySystem::energy(bodies))); + let mut i = 0; + while i < n { + NBodySystem::advance(bodies, 0.01); + i += 1; + } + io::println(fmt!("%f", NBodySystem::energy(bodies))); } -#[doc = "Serializes a json value into a string"] -fn to_str(j: json) -> str { - io::with_str_writer { |wr| to_writer(wr, j) } -} +mod NBodySystem { + use Body; -type parser = { - rdr: io::reader, - mut ch: char, - mut line: uint, - mut col: uint, -}; + pub fn make() -> ~[Body::props] { + let mut bodies: ~[Body::props] = + ~[Body::sun(), + Body::jupiter(), + Body::saturn(), + Body::uranus(), + Body::neptune()]; -impl parser for parser { - fn eof() -> bool { self.ch == -1 as char } + let mut px = 0.0; + let mut py = 0.0; + let mut pz = 0.0; - fn bump() { - self.ch = self.rdr.read_char(); + let mut i = 0; + while i < 5 { + px += bodies[i].vx * bodies[i].mass; + py += bodies[i].vy * bodies[i].mass; + pz += bodies[i].vz * bodies[i].mass; - if self.ch == '\n' { - self.line += 1u; - self.col = 1u; - } else { - self.col += 1u; + i += 1; } - } - fn next_char() -> char { - self.bump(); - self.ch - } + // side-effecting + Body::offset_momentum(&mut bodies[0], px, py, pz); - fn error<T>(msg: str) -> result<T, error> { - err({ line: self.line, col: self.col, msg: msg }) + return bodies; } - fn parse() -> result<json, error> { - alt self.parse_value() { - ok(value) { - // Skip trailing whitespaces. - self.parse_whitespace(); - // Make sure there is no trailing characters. - if self.eof() { - ok(value) - } else { - self.error("trailing characters") + pub fn advance(bodies: &mut [Body::props], dt: float) { + let mut i = 0; + while i < 5 { + let mut j = i + 1; + while j < 5 { + advance_one(&mut bodies[i], + &mut bodies[j], dt); + j += 1; } - } - e { e } - } - } - fn parse_value() -> result<json, error> { - self.parse_whitespace(); - - if self.eof() { ret self.error("EOF while parsing value"); } - - alt self.ch { - 'n' { self.parse_ident("ull", null) } - 't' { self.parse_ident("rue", boolean(true)) } - 'f' { self.parse_ident("alse", boolean(false)) } - '0' to '9' | '-' { self.parse_number() } - '"' { - alt self.parse_str() { - ok(s) { ok(string(s)) } - err(e) { err(e) } - } - } - '[' { self.parse_list() } - '{' { self.parse_object() } - _ { self.error("invalid syntax") } + i += 1; } - } - fn parse_whitespace() { - while char::is_whitespace(self.ch) { self.bump(); } - } - - fn parse_ident(ident: str, value: json) -> result<json, error> { - if str::all(ident, { |c| c == self.next_char() }) { - self.bump(); - ok(value) - } else { - self.error("invalid syntax") + i = 0; + while i < 5 { + move_(&mut bodies[i], dt); + i += 1; } } - fn parse_number() -> result<json, error> { - let mut neg = 1f; + pub fn advance_one(bi: &mut Body::props, + bj: &mut Body::props, + dt: float) unsafe { + let dx = bi.x - bj.x; + let dy = bi.y - bj.y; + let dz = bi.z - bj.z; - if self.ch == '-' { - self.bump(); - neg = -1f; - } + let dSquared = dx * dx + dy * dy + dz * dz; - let mut res = alt self.parse_integer() { - ok(res) { res } - err(e) { ret err(e); } - }; + let distance = ::libc::sqrt(dSquared); + let mag = dt / (dSquared * distance); - if self.ch == '.' { - alt self.parse_decimal(res) { - ok(r) { res = r; } - err(e) { ret err(e); } - } - } - - if self.ch == 'e' || self.ch == 'E' { - alt self.parse_exponent(res) { - ok(r) { res = r; } - err(e) { ret err(e); } - } - } + bi.vx -= dx * bj.mass * mag; + bi.vy -= dy * bj.mass * mag; + bi.vz -= dz * bj.mass * mag; - ok(num(neg * res)) + bj.vx += dx * bi.mass * mag; + bj.vy += dy * bi.mass * mag; + bj.vz += dz * bi.mass * mag; } - fn parse_integer() -> result<float, error> { - let mut res = 0f; - - alt self.ch { - '0' { - self.bump(); - - // There can be only one leading '0'. - alt self.ch { - '0' to '9' { ret self.error("invalid number"); } - _ {} - } - } - '1' to '9' { - while !self.eof() { - alt self.ch { - '0' to '9' { - res *= 10f; - res += ((self.ch as int) - ('0' as int)) as float; - - self.bump(); - } - _ { break; } - } - } - } - _ { ret self.error("invalid number"); } - } - - ok(res) + pub fn move_(b: &mut Body::props, dt: float) { + b.x += dt * b.vx; + b.y += dt * b.vy; + b.z += dt * b.vz; } - fn parse_decimal(res: float) -> result<float, error> { - self.bump(); + pub fn energy(bodies: &[Body::props]) -> float unsafe { + let mut dx; + let mut dy; + let mut dz; + let mut distance; + let mut e = 0.0; - // Make sure a digit follows the decimal place. - alt self.ch { - '0' to '9' {} - _ { ret self.error("invalid number"); } - } - - let mut res = res; - let mut dec = 1f; - while !self.eof() { - alt self.ch { - '0' to '9' { - dec /= 10f; - res += (((self.ch as int) - ('0' as int)) as float) * dec; - - self.bump(); - } - _ { break; } - } - } - - ok(res) - } - - fn parse_exponent(res: float) -> result<float, error> { - self.bump(); + let mut i = 0; + while i < 5 { + e += + 0.5 * bodies[i].mass * + (bodies[i].vx * bodies[i].vx + bodies[i].vy * bodies[i].vy + + bodies[i].vz * bodies[i].vz); - let mut res = res; - let mut exp = 0u; - let mut neg_exp = false; + let mut j = i + 1; + while j < 5 { + dx = bodies[i].x - bodies[j].x; + dy = bodies[i].y - bodies[j].y; + dz = bodies[i].z - bodies[j].z; - alt self.ch { - '+' { self.bump(); } - '-' { self.bump(); neg_exp = true; } - _ {} - } - - // Make sure a digit follows the exponent place. - alt self.ch { - '0' to '9' {} - _ { ret self.error("invalid number"); } - } - - while !self.eof() { - alt self.ch { - '0' to '9' { - exp *= 10u; - exp += (self.ch as uint) - ('0' as uint); + distance = ::libc::sqrt(dx * dx + dy * dy + dz * dz); + e -= bodies[i].mass * bodies[j].mass / distance; - self.bump(); - } - _ { break; } + j += 1; } - } - let exp = float::pow_with_uint(10u, exp); - if neg_exp { - res /= exp; - } else { - res *= exp; + i += 1; } + return e; - ok(res) - } - - fn parse_str() -> result<str, error> { - let mut escape = false; - let mut res = ""; - - while !self.eof() { - self.bump(); - - if (escape) { - alt self.ch { - '"' { str::push_char(res, '"'); } - '\\' { str::push_char(res, '\\'); } - '/' { str::push_char(res, '/'); } - 'b' { str::push_char(res, '\x08'); } - 'f' { str::push_char(res, '\x0c'); } - 'n' { str::push_char(res, '\n'); } - 'r' { str::push_char(res, '\r'); } - 't' { str::push_char(res, '\t'); } - 'u' { - // Parse \u1234. - let mut i = 0u; - let mut n = 0u; - while i < 4u { - alt self.next_char() { - '0' to '9' { - n = n * 10u + - (self.ch as uint) - ('0' as uint); - } - _ { ret self.error("invalid \\u escape"); } - } - i += 1u; - } - - // Error out if we didn't parse 4 digits. - if i != 4u { - ret self.error("invalid \\u escape"); - } - - str::push_char(res, n as char); - } - _ { ret self.error("invalid escape"); } - } - escape = false; - } else if self.ch == '\\' { - escape = true; - } else { - if self.ch == '"' { - self.bump(); - ret ok(res); - } - str::push_char(res, self.ch); - } - } - - self.error("EOF while parsing string") - } - - fn parse_list() -> result<json, error> { - self.bump(); - self.parse_whitespace(); - - let mut values = []; - - if self.ch == ']' { - self.bump(); - ret ok(list(values)); - } - - loop { - alt self.parse_value() { - ok(v) { vec::push(values, v); } - e { ret e; } - } - - self.parse_whitespace(); - if self.eof() { - ret self.error("EOF while parsing list"); - } - - alt self.ch { - ',' { self.bump(); } - ']' { self.bump(); ret ok(list(values)); } - _ { ret self.error("expecting ',' or ']'"); } - } - }; - } - - fn parse_object() -> result<json, error> { - self.bump(); - self.parse_whitespace(); - - let values = map::str_hash(); - - if self.ch == '}' { - self.bump(); - ret ok(dict(values)); - } - - while !self.eof() { - self.parse_whitespace(); - - if self.ch != '"' { - ret self.error("key must be a string"); - } - - let key = alt self.parse_str() { - ok(key) { key } - err(e) { ret err(e); } - }; - - self.parse_whitespace(); - - if self.ch != ':' { - if self.eof() { break; } - ret self.error("expecting ':'"); - } - self.bump(); - - alt self.parse_value() { - ok(value) { values.insert(key, value); } - e { ret e; } - } - self.parse_whitespace(); - - alt self.ch { - ',' { self.bump(); } - '}' { self.bump(); ret ok(dict(values)); } - _ { - if self.eof() { break; } - ret self.error("expecting ',' or '}'"); - } - } - } - - ret self.error("EOF while parsing object"); - } -} - -#[doc = "Deserializes a json value from an io::reader"] -fn from_reader(rdr: io::reader) -> result<json, error> { - let parser = { - rdr: rdr, - mut ch: rdr.read_char(), - mut line: 1u, - mut col: 1u, - }; - - parser.parse() -} - -#[doc = "Deserializes a json value from a string"] -fn from_str(s: str) -> result<json, error> { - io::with_str_reader(s, from_reader) -} - -#[doc = "Test if two json values are equal"] -fn eq(value0: json, value1: json) -> bool { - alt (value0, value1) { - (num(f0), num(f1)) { f0 == f1 } - (string(s0), string(s1)) { s0 == s1 } - (boolean(b0), boolean(b1)) { b0 == b1 } - (list(l0), list(l1)) { vec::all2(l0, l1, eq) } - (dict(d0), dict(d1)) { - if d0.size() == d1.size() { - let mut equal = true; - d0.items { |k, v0| - alt d1.find(k) { - some(v1) { - if !eq(v0, v1) { equal = false; } } - none { equal = false; } - } - }; - equal - } else { - false - } - } - (null, null) { true } - _ { false } } } -#[cfg(test)] -mod tests { - fn mk_dict(items: [(str, json)]) -> json { - let d = map::str_hash(); - - vec::iter(items) { |item| - let (key, value) = item; - d.insert(key, value); - }; - - dict(d) - } - - #[test] - fn test_write_null() { - assert to_str(null) == "null"; - } - - #[test] - fn test_write_num() { - assert to_str(num(3f)) == "3"; - assert to_str(num(3.1f)) == "3.1"; - assert to_str(num(-1.5f)) == "-1.5"; - assert to_str(num(0.5f)) == "0.5"; - } - - #[test] - fn test_write_str() { - assert to_str(string("")) == "\"\""; - assert to_str(string("foo")) == "\"foo\""; - } - - #[test] - fn test_write_bool() { - assert to_str(boolean(true)) == "true"; - assert to_str(boolean(false)) == "false"; - } - - #[test] - fn test_write_list() { - assert to_str(list([])) == "[]"; - assert to_str(list([boolean(true)])) == "[true]"; - assert to_str(list([ - boolean(false), - null, - list([string("foo\nbar"), num(3.5f)]) - ])) == "[false, null, [\"foo\\nbar\", 3.5]]"; - } - - #[test] - fn test_write_dict() { - assert to_str(mk_dict([])) == "{}"; - assert to_str(mk_dict([("a", boolean(true))])) == "{ \"a\": true }"; - assert to_str(mk_dict([ - ("a", boolean(true)), - ("b", list([ - mk_dict([("c", string("\x0c\r"))]), - mk_dict([("d", string(""))]) - ])) - ])) == - "{ " + - "\"a\": true, " + - "\"b\": [" + - "{ \"c\": \"\\f\\r\" }, " + - "{ \"d\": \"\" }" + - "]" + - " }"; +mod Body { + use Body; + + pub const PI: float = 3.141592653589793; + pub const SOLAR_MASS: float = 39.478417604357432; + // was 4 * PI * PI originally + pub const DAYS_PER_YEAR: float = 365.24; + + pub type props = + {mut x: float, + mut y: float, + mut z: float, + mut vx: float, + mut vy: float, + mut vz: float, + mass: float}; + + pub fn jupiter() -> Body::props { + return {mut x: 4.84143144246472090e+00, + mut y: -1.16032004402742839e+00, + mut z: -1.03622044471123109e-01, + mut vx: 1.66007664274403694e-03 * DAYS_PER_YEAR, + mut vy: 7.69901118419740425e-03 * DAYS_PER_YEAR, + mut vz: -6.90460016972063023e-05 * DAYS_PER_YEAR, + mass: 9.54791938424326609e-04 * SOLAR_MASS}; + } + + pub fn saturn() -> Body::props { + return {mut x: 8.34336671824457987e+00, + mut y: 4.12479856412430479e+00, + mut z: -4.03523417114321381e-01, + mut vx: -2.76742510726862411e-03 * DAYS_PER_YEAR, + mut vy: 4.99852801234917238e-03 * DAYS_PER_YEAR, + mut vz: 2.30417297573763929e-05 * DAYS_PER_YEAR, + mass: 2.85885980666130812e-04 * SOLAR_MASS}; + } + + pub fn uranus() -> Body::props { + return {mut x: 1.28943695621391310e+01, + mut y: -1.51111514016986312e+01, + mut z: -2.23307578892655734e-01, + mut vx: 2.96460137564761618e-03 * DAYS_PER_YEAR, + mut vy: 2.37847173959480950e-03 * DAYS_PER_YEAR, + mut vz: -2.96589568540237556e-05 * DAYS_PER_YEAR, + mass: 4.36624404335156298e-05 * SOLAR_MASS}; + } + + pub fn neptune() -> Body::props { + return {mut x: 1.53796971148509165e+01, + mut y: -2.59193146099879641e+01, + mut z: 1.79258772950371181e-01, + mut vx: 2.68067772490389322e-03 * DAYS_PER_YEAR, + mut vy: 1.62824170038242295e-03 * DAYS_PER_YEAR, + mut vz: -9.51592254519715870e-05 * DAYS_PER_YEAR, + mass: 5.15138902046611451e-05 * SOLAR_MASS}; + } + + pub fn sun() -> Body::props { + return {mut x: 0.0, + mut y: 0.0, + mut z: 0.0, + mut vx: 0.0, + mut vy: 0.0, + mut vz: 0.0, + mass: SOLAR_MASS}; + } + + pub fn offset_momentum(props: &mut Body::props, + px: float, py: float, pz: float) { + props.vx = -px / SOLAR_MASS; + props.vy = -py / SOLAR_MASS; + props.vz = -pz / SOLAR_MASS; } - #[test] - fn test_trailing_characters() { - assert from_str("nulla") == - err({line: 1u, col: 5u, msg: "trailing characters"}); - assert from_str("truea") == - err({line: 1u, col: 5u, msg: "trailing characters"}); - assert from_str("falsea") == - err({line: 1u, col: 6u, msg: "trailing characters"}); - assert from_str("1a") == - err({line: 1u, col: 2u, msg: "trailing characters"}); - assert from_str("[]a") == - err({line: 1u, col: 3u, msg: "trailing characters"}); - assert from_str("{}a") == - err({line: 1u, col: 3u, msg: "trailing characters"}); - } - - #[test] - fn test_read_identifiers() { - assert from_str("n") == - err({line: 1u, col: 2u, msg: "invalid syntax"}); - assert from_str("nul") == - err({line: 1u, col: 4u, msg: "invalid syntax"}); - - assert from_str("t") == - err({line: 1u, col: 2u, msg: "invalid syntax"}); - assert from_str("truz") == - err({line: 1u, col: 4u, msg: "invalid syntax"}); - - assert from_str("f") == - err({line: 1u, col: 2u, msg: "invalid syntax"}); - assert from_str("faz") == - err({line: 1u, col: 3u, msg: "invalid syntax"}); - - assert from_str("null") == ok(null); - assert from_str("true") == ok(boolean(true)); - assert from_str("false") == ok(boolean(false)); - assert from_str(" null ") == ok(null); - assert from_str(" true ") == ok(boolean(true)); - assert from_str(" false ") == ok(boolean(false)); - } - - #[test] - fn test_read_num() { - assert from_str("+") == - err({line: 1u, col: 1u, msg: "invalid syntax"}); - assert from_str(".") == - err({line: 1u, col: 1u, msg: "invalid syntax"}); - - assert from_str("-") == - err({line: 1u, col: 2u, msg: "invalid number"}); - assert from_str("00") == - err({line: 1u, col: 2u, msg: "invalid number"}); - assert from_str("1.") == - err({line: 1u, col: 3u, msg: "invalid number"}); - assert from_str("1e") == - err({line: 1u, col: 3u, msg: "invalid number"}); - assert from_str("1e+") == - err({line: 1u, col: 4u, msg: "invalid number"}); - - assert from_str("3") == ok(num(3f)); - assert from_str("3.1") == ok(num(3.1f)); - assert from_str("-1.2") == ok(num(-1.2f)); - assert from_str("0.4") == ok(num(0.4f)); - assert from_str("0.4e5") == ok(num(0.4e5f)); - assert from_str("0.4e+15") == ok(num(0.4e15f)); - assert from_str("0.4e-01") == ok(num(0.4e-01f)); - assert from_str(" 3 ") == ok(num(3f)); - } - - #[test] - fn test_read_str() { - assert from_str("\"") == - err({line: 1u, col: 2u, msg: "EOF while parsing string"}); - assert from_str("\"lol") == - err({line: 1u, col: 5u, msg: "EOF while parsing string"}); - - assert from_str("\"\"") == ok(string("")); - assert from_str("\"foo\"") == ok(string("foo")); - assert from_str("\"\\\"\"") == ok(string("\"")); - assert from_str("\"\\b\"") == ok(string("\x08")); - assert from_str("\"\\n\"") == ok(string("\n")); - assert from_str("\"\\r\"") == ok(string("\r")); - assert from_str("\"\\t\"") == ok(string("\t")); - assert from_str(" \"foo\" ") == ok(string("foo")); - } - - #[test] - fn test_read_list() { - assert from_str("[") == - err({line: 1u, col: 2u, msg: "EOF while parsing value"}); - assert from_str("[1") == - err({line: 1u, col: 3u, msg: "EOF while parsing list"}); - assert from_str("[1,") == - err({line: 1u, col: 4u, msg: "EOF while parsing value"}); - assert from_str("[1,]") == - err({line: 1u, col: 4u, msg: "invalid syntax"}); - assert from_str("[6 7]") == - err({line: 1u, col: 4u, msg: "expecting ',' or ']'"}); - - assert from_str("[]") == ok(list([])); - assert from_str("[ ]") == ok(list([])); - assert from_str("[true]") == ok(list([boolean(true)])); - assert from_str("[ false ]") == ok(list([boolean(false)])); - assert from_str("[null]") == ok(list([null])); - assert from_str("[3, 1]") == ok(list([num(3f), num(1f)])); - assert from_str("\n[3, 2]\n") == ok(list([num(3f), num(2f)])); - assert from_str("[2, [4, 1]]") == - ok(list([num(2f), list([num(4f), num(1f)])])); - } - - #[test] - fn test_read_dict() { - assert from_str("{") == - err({line: 1u, col: 2u, msg: "EOF while parsing object"}); - assert from_str("{ ") == - err({line: 1u, col: 3u, msg: "EOF while parsing object"}); - assert from_str("{1") == - err({line: 1u, col: 2u, msg: "key must be a string"}); - assert from_str("{ \"a\"") == - err({line: 1u, col: 6u, msg: "EOF while parsing object"}); - assert from_str("{\"a\"") == - err({line: 1u, col: 5u, msg: "EOF while parsing object"}); - assert from_str("{\"a\" ") == - err({line: 1u, col: 6u, msg: "EOF while parsing object"}); - - assert from_str("{\"a\" 1") == - err({line: 1u, col: 6u, msg: "expecting ':'"}); - assert from_str("{\"a\":") == - err({line: 1u, col: 6u, msg: "EOF while parsing value"}); - assert from_str("{\"a\":1") == - err({line: 1u, col: 7u, msg: "EOF while parsing object"}); - assert from_str("{\"a\":1 1") == - err({line: 1u, col: 8u, msg: "expecting ',' or '}'"}); - assert from_str("{\"a\":1,") == - err({line: 1u, col: 8u, msg: "EOF while parsing object"}); - - assert eq(result::get(from_str("{}")), mk_dict([])); - assert eq(result::get(from_str("{\"a\": 3}")), - mk_dict([("a", num(3.0f))])); - - assert eq(result::get(from_str("{ \"a\": null, \"b\" : true }")), - mk_dict([("a", null), ("b", boolean(true))])); - assert eq(result::get(from_str("\n{ \"a\": null, \"b\" : true }\n")), - mk_dict([("a", null), ("b", boolean(true))])); - assert eq(result::get(from_str("{\"a\" : 1.0 ,\"b\": [ true ]}")), - mk_dict([ - ("a", num(1.0)), - ("b", list([boolean(true)])) - ])); - assert eq(result::get(from_str( - "{" + - "\"a\": 1.0, " + - "\"b\": [" + - "true," + - "\"foo\\nbar\", " + - "{ \"c\": {\"d\": null} } " + - "]" + - "}")), - mk_dict([ - ("a", num(1.0f)), - ("b", list([ - boolean(true), - string("foo\nbar"), - mk_dict([ - ("c", mk_dict([("d", null)])) - ]) - ])) - ])); - } - - #[test] - fn test_multiline_errors() { - assert from_str("{\n \"foo\":\n \"bar\"") == - err({line: 3u, col: 8u, msg: "EOF while parsing object"}); - } } |