|
1 |
| -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT |
| 1 | +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT |
2 | 2 | // file at the top-level directory of this distribution and at
|
3 | 3 | // http://rust-lang.org/COPYRIGHT.
|
4 | 4 | //
|
@@ -234,6 +234,7 @@ use std::fmt;
|
234 | 234 | use std::io::MemWriter;
|
235 | 235 | use std::io;
|
236 | 236 | use std::mem::{swap,transmute};
|
| 237 | +use std::num::{FPNaN, FPInfinite}; |
237 | 238 | use std::num;
|
238 | 239 | use std::str::ScalarValue;
|
239 | 240 | use std::str;
|
@@ -349,6 +350,13 @@ fn escape_str(s: &str) -> String {
|
349 | 350 | escaped
|
350 | 351 | }
|
351 | 352 |
|
| 353 | +fn fmt_number_or_null(v: f64) -> String { |
| 354 | + match v.classify() { |
| 355 | + FPNaN | FPInfinite => String::from_str("null"), |
| 356 | + _ => f64::to_str_digits(v, 6u) |
| 357 | + } |
| 358 | +} |
| 359 | + |
352 | 360 | fn spaces(n: uint) -> String {
|
353 | 361 | String::from_char(n, ' ')
|
354 | 362 | }
|
@@ -412,7 +420,7 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
|
412 | 420 | }
|
413 | 421 |
|
414 | 422 | fn emit_f64(&mut self, v: f64) -> EncodeResult {
|
415 |
| - write!(self.wr, "{}", f64::to_str_digits(v, 6u)) |
| 423 | + write!(self.wr, "{}", fmt_number_or_null(v)) |
416 | 424 | }
|
417 | 425 | fn emit_f32(&mut self, v: f32) -> EncodeResult { self.emit_f64(v as f64) }
|
418 | 426 |
|
@@ -608,7 +616,7 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
|
608 | 616 | }
|
609 | 617 |
|
610 | 618 | fn emit_f64(&mut self, v: f64) -> EncodeResult {
|
611 |
| - write!(self.wr, "{}", f64::to_str_digits(v, 6u)) |
| 619 | + write!(self.wr, "{}", fmt_number_or_null(v)) |
612 | 620 | }
|
613 | 621 | fn emit_f32(&mut self, v: f32) -> EncodeResult {
|
614 | 622 | self.emit_f64(v as f64)
|
@@ -1270,7 +1278,7 @@ impl<T: Iterator<char>> Parser<T> {
|
1270 | 1278 | '0' => {
|
1271 | 1279 | self.bump();
|
1272 | 1280 |
|
1273 |
| - // There can be only one leading '0'. |
| 1281 | + // A leading '0' must be the only digit before the decimal point. |
1274 | 1282 | match self.ch_or_null() {
|
1275 | 1283 | '0' .. '9' => return self.error(InvalidNumber),
|
1276 | 1284 | _ => ()
|
@@ -1864,6 +1872,7 @@ impl ::Decoder<DecoderError> for Decoder {
|
1864 | 1872 | // is going to have a string here, as per JSON spec..
|
1865 | 1873 | Ok(FromStr::from_str(s.as_slice()).unwrap())
|
1866 | 1874 | },
|
| 1875 | + Null => Ok(f64::NAN), |
1867 | 1876 | value => {
|
1868 | 1877 | Err(ExpectedError("Number".to_string(),
|
1869 | 1878 | format!("{}", value)))
|
@@ -2185,11 +2194,16 @@ impl ToJson for u64 {
|
2185 | 2194 | }
|
2186 | 2195 |
|
2187 | 2196 | impl ToJson for f32 {
|
2188 |
| - fn to_json(&self) -> Json { Number(*self as f64) } |
| 2197 | + fn to_json(&self) -> Json { (*self as f64).to_json() } |
2189 | 2198 | }
|
2190 | 2199 |
|
2191 | 2200 | impl ToJson for f64 {
|
2192 |
| - fn to_json(&self) -> Json { Number(*self) } |
| 2201 | + fn to_json(&self) -> Json { |
| 2202 | + match self.classify() { |
| 2203 | + FPNaN | FPInfinite => Null, |
| 2204 | + _ => Number(*self) |
| 2205 | + } |
| 2206 | + } |
2193 | 2207 | }
|
2194 | 2208 |
|
2195 | 2209 | impl ToJson for () {
|
@@ -2282,6 +2296,8 @@ mod tests {
|
2282 | 2296 | InvalidSyntax, InvalidNumber, EOFWhileParsingObject, EOFWhileParsingList,
|
2283 | 2297 | EOFWhileParsingValue, EOFWhileParsingString, KeyMustBeAString, ExpectedColon,
|
2284 | 2298 | TrailingCharacters};
|
| 2299 | + use std::f32; |
| 2300 | + use std::f64; |
2285 | 2301 | use std::io;
|
2286 | 2302 | use std::collections::TreeMap;
|
2287 | 2303 |
|
@@ -2335,6 +2351,15 @@ mod tests {
|
2335 | 2351 |
|
2336 | 2352 | assert_eq!(Number(0.5).to_str().into_string(), "0.5".to_string());
|
2337 | 2353 | assert_eq!(Number(0.5).to_pretty_str().into_string(), "0.5".to_string());
|
| 2354 | + |
| 2355 | + assert_eq!(Number(f64::NAN).to_str().into_string(), "null".to_string()); |
| 2356 | + assert_eq!(Number(f64::NAN).to_pretty_str().into_string(), "null".to_string()); |
| 2357 | + |
| 2358 | + assert_eq!(Number(f64::INFINITY).to_str().into_string(), "null".to_string()); |
| 2359 | + assert_eq!(Number(f64::INFINITY).to_pretty_str().into_string(), "null".to_string()); |
| 2360 | + |
| 2361 | + assert_eq!(Number(f64::NEG_INFINITY).to_str().into_string(), "null".to_string()); |
| 2362 | + assert_eq!(Number(f64::NEG_INFINITY).to_pretty_str().into_string(), "null".to_string()); |
2338 | 2363 | }
|
2339 | 2364 |
|
2340 | 2365 | #[test]
|
@@ -2583,6 +2608,7 @@ mod tests {
|
2583 | 2608 | fn test_read_number() {
|
2584 | 2609 | assert_eq!(from_str("+"), Err(SyntaxError(InvalidSyntax, 1, 1)));
|
2585 | 2610 | assert_eq!(from_str("."), Err(SyntaxError(InvalidSyntax, 1, 1)));
|
| 2611 | + assert_eq!(from_str("NaN"), Err(SyntaxError(InvalidSyntax, 1, 1))); |
2586 | 2612 | assert_eq!(from_str("-"), Err(SyntaxError(InvalidNumber, 1, 2)));
|
2587 | 2613 | assert_eq!(from_str("00"), Err(SyntaxError(InvalidNumber, 1, 2)));
|
2588 | 2614 | assert_eq!(from_str("1."), Err(SyntaxError(InvalidNumber, 1, 3)));
|
@@ -2792,6 +2818,22 @@ mod tests {
|
2792 | 2818 | );
|
2793 | 2819 | }
|
2794 | 2820 |
|
| 2821 | + #[deriving(Decodable)] |
| 2822 | + struct FloatStruct { |
| 2823 | + f: f64, |
| 2824 | + a: Vec<f64> |
| 2825 | + } |
| 2826 | + #[test] |
| 2827 | + fn test_decode_struct_with_nan() { |
| 2828 | + let encoded_str = "{\"f\":null,\"a\":[null,123]}"; |
| 2829 | + let json_object = from_str(encoded_str.as_slice()); |
| 2830 | + let mut decoder = Decoder::new(json_object.unwrap()); |
| 2831 | + let after: FloatStruct = Decodable::decode(&mut decoder).unwrap(); |
| 2832 | + assert!(after.f.is_nan()); |
| 2833 | + assert!(after.a.get(0).is_nan()); |
| 2834 | + assert_eq!(after.a.get(1), &123f64); |
| 2835 | + } |
| 2836 | + |
2795 | 2837 | #[test]
|
2796 | 2838 | fn test_decode_option() {
|
2797 | 2839 | let mut decoder = Decoder::new(from_str("null").unwrap());
|
@@ -2833,6 +2875,7 @@ mod tests {
|
2833 | 2875 | }
|
2834 | 2876 |
|
2835 | 2877 | #[deriving(Decodable)]
|
| 2878 | + #[allow(dead_code)] |
2836 | 2879 | struct DecodeStruct {
|
2837 | 2880 | x: f64,
|
2838 | 2881 | y: bool,
|
@@ -3362,6 +3405,8 @@ mod tests {
|
3362 | 3405 | assert_eq!(13.0_f32.to_json(), Number(13.0_f64));
|
3363 | 3406 | assert_eq!(14.0_f64.to_json(), Number(14.0_f64));
|
3364 | 3407 | assert_eq!(().to_json(), Null);
|
| 3408 | + assert_eq!(f32::INFINITY.to_json(), Null); |
| 3409 | + assert_eq!(f64::NAN.to_json(), Null); |
3365 | 3410 | assert_eq!(true.to_json(), Boolean(true));
|
3366 | 3411 | assert_eq!(false.to_json(), Boolean(false));
|
3367 | 3412 | assert_eq!("abc".to_string().to_json(), String("abc".to_string()));
|
|
0 commit comments