parent
04c1fe9df6
commit
16d8b14fcf
|
@ -6,6 +6,7 @@
|
|||
|
||||
use std::borrow::Cow;
|
||||
use std::error;
|
||||
use std::f64;
|
||||
use std::fmt;
|
||||
use std::str;
|
||||
use std::vec;
|
||||
|
@ -882,6 +883,14 @@ impl<'a> Deserializer<'a> {
|
|||
}
|
||||
_ => Err(self.error(at, ErrorKind::NumberInvalid)),
|
||||
}
|
||||
} else if s == "inf" {
|
||||
Ok(Value { e: E::Float(f64::INFINITY), start: start, end: end })
|
||||
} else if s == "-inf" {
|
||||
Ok(Value { e: E::Float(f64::NEG_INFINITY), start: start, end: end })
|
||||
} else if s == "nan" {
|
||||
Ok(Value { e: E::Float(f64::NAN), start: start, end: end })
|
||||
} else if s == "-nan" {
|
||||
Ok(Value { e: E::Float(-f64::NAN), start: start, end: end })
|
||||
} else {
|
||||
self.integer(s).map(|f| Value { e: E::Integer(f), start: start, end: end })
|
||||
}
|
||||
|
|
49
src/ser.rs
49
src/ser.rs
|
@ -737,6 +737,27 @@ impl<'a> Serializer<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
macro_rules! serialize_float {
|
||||
($this:expr, $v:expr) => {{
|
||||
$this.emit_key("float")?;
|
||||
if ($v.is_nan() || $v == 0.0) && $v.is_sign_negative() {
|
||||
drop(write!($this.dst, "-"));
|
||||
}
|
||||
if $v.is_nan() {
|
||||
drop(write!($this.dst, "nan"));
|
||||
} else {
|
||||
drop(write!($this.dst, "{}", $v));
|
||||
}
|
||||
if $v % 1.0 == 0.0 {
|
||||
drop(write!($this.dst, ".0"));
|
||||
}
|
||||
if let State::Table { .. } = $this.state {
|
||||
$this.dst.push_str("\n");
|
||||
}
|
||||
return Ok(());
|
||||
}};
|
||||
}
|
||||
|
||||
impl<'a, 'b> ser::Serializer for &'b mut Serializer<'a> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
@ -785,35 +806,11 @@ impl<'a, 'b> ser::Serializer for &'b mut Serializer<'a> {
|
|||
}
|
||||
|
||||
fn serialize_f32(self, v: f32) -> Result<(), Self::Error> {
|
||||
if !v.is_finite() {
|
||||
return Err(Error::NumberInvalid);
|
||||
}
|
||||
|
||||
self.emit_key("float")?;
|
||||
drop(write!(self.dst, "{}", v));
|
||||
if v % 1.0 == 0.0 {
|
||||
drop(write!(self.dst, ".0"));
|
||||
}
|
||||
if let State::Table { .. } = self.state {
|
||||
self.dst.push_str("\n");
|
||||
}
|
||||
Ok(())
|
||||
serialize_float!(self, v)
|
||||
}
|
||||
|
||||
fn serialize_f64(self, v: f64) -> Result<(), Self::Error> {
|
||||
if !v.is_finite() {
|
||||
return Err(Error::NumberInvalid);
|
||||
}
|
||||
|
||||
self.emit_key("float")?;
|
||||
drop(write!(self.dst, "{}", v));
|
||||
if v % 1.0 == 0.0 {
|
||||
drop(write!(self.dst, ".0"));
|
||||
}
|
||||
if let State::Table { .. } = self.state {
|
||||
self.dst.push_str("\n");
|
||||
}
|
||||
Ok(())
|
||||
serialize_float!(self, v)
|
||||
}
|
||||
|
||||
fn serialize_char(self, v: char) -> Result<(), Self::Error> {
|
||||
|
|
|
@ -4,5 +4,6 @@ use rustc_version::{version, Version};
|
|||
fn main() {
|
||||
if version().unwrap() >= Version::parse("1.20.0").unwrap() {
|
||||
println!(r#"cargo:rustc-cfg=feature="test-quoted-keys-in-macro""#);
|
||||
println!(r#"cargo:rustc-cfg=feature="test-nan-sign""#);
|
||||
}
|
||||
}
|
||||
|
|
79
test-suite/tests/float.rs
Normal file
79
test-suite/tests/float.rs
Normal file
|
@ -0,0 +1,79 @@
|
|||
extern crate toml;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
use toml::Value;
|
||||
|
||||
macro_rules! float_inf_tests {
|
||||
($ty:ty) => {{
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct S {
|
||||
sf1: $ty,
|
||||
sf2: $ty,
|
||||
sf3: $ty,
|
||||
sf4: $ty,
|
||||
sf5: $ty,
|
||||
sf6: $ty,
|
||||
sf7: $ty,
|
||||
sf8: $ty,
|
||||
}
|
||||
let inf: S = toml::from_str(
|
||||
r"
|
||||
# infinity
|
||||
sf1 = inf # positive infinity
|
||||
sf2 = +inf # positive infinity
|
||||
sf3 = -inf # negative infinity
|
||||
|
||||
# not a number
|
||||
sf4 = nan # actual sNaN/qNaN encoding is implementation specific
|
||||
sf5 = +nan # same as `nan`
|
||||
sf6 = -nan # valid, actual encoding is implementation specific
|
||||
|
||||
# zero
|
||||
sf7 = +0.0
|
||||
sf8 = -0.0
|
||||
").expect("Parse infinities.");
|
||||
|
||||
assert!(inf.sf1.is_infinite());
|
||||
assert!(inf.sf1.is_sign_positive());
|
||||
assert!(inf.sf2.is_infinite());
|
||||
assert!(inf.sf2.is_sign_positive());
|
||||
assert!(inf.sf3.is_infinite());
|
||||
assert!(inf.sf3.is_sign_negative());
|
||||
|
||||
assert!(inf.sf4.is_nan());
|
||||
assert!(inf.sf4.is_sign_positive());
|
||||
assert!(inf.sf5.is_nan());
|
||||
assert!(inf.sf5.is_sign_positive());
|
||||
assert!(inf.sf6.is_nan());
|
||||
assert!(inf.sf6.is_sign_negative());
|
||||
|
||||
assert_eq!(inf.sf7, 0.0);
|
||||
assert!(inf.sf7.is_sign_positive());
|
||||
assert_eq!(inf.sf8, 0.0);
|
||||
assert!(inf.sf8.is_sign_negative());
|
||||
|
||||
let s = toml::to_string(&inf).unwrap();
|
||||
assert_eq!(
|
||||
s, "\
|
||||
sf1 = inf
|
||||
sf2 = inf
|
||||
sf3 = -inf
|
||||
sf4 = nan
|
||||
sf5 = nan
|
||||
sf6 = -nan
|
||||
sf7 = 0.0
|
||||
sf8 = -0.0
|
||||
"
|
||||
);
|
||||
|
||||
toml::from_str::<Value>(&s).expect("roundtrip");
|
||||
}};
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "test-nan-sign")]
|
||||
fn float_inf() {
|
||||
float_inf_tests!(f32);
|
||||
float_inf_tests!(f64);
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
extern crate toml;
|
||||
|
||||
use std::f64;
|
||||
|
||||
#[test]
|
||||
fn test_invalid_float_encode() {
|
||||
fn bad(value: toml::Value) {
|
||||
assert!(toml::to_string(&value).is_err());
|
||||
}
|
||||
|
||||
bad(toml::Value::Float(f64::INFINITY));
|
||||
bad(toml::Value::Float(f64::NEG_INFINITY));
|
||||
bad(toml::Value::Float(f64::NAN));
|
||||
}
|
|
@ -10,8 +10,5 @@ fn bad() {
|
|||
bad("a = 1__1");
|
||||
bad("a = 1_");
|
||||
bad("''");
|
||||
bad("a = nan");
|
||||
bad("a = -inf");
|
||||
bad("a = inf");
|
||||
bad("a = 9e99999");
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
{
|
||||
"answer": {"type": "integer", "value": "42"},
|
||||
"neganswer": {"type": "integer", "value": "-42"}
|
||||
"neganswer": {"type": "integer", "value": "-42"},
|
||||
"neg_zero": {"type": "integer", "value": "0"},
|
||||
"pos_zero": {"type": "integer", "value": "0"}
|
||||
}
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
answer = 42
|
||||
neganswer = -42
|
||||
neg_zero = -0
|
||||
pos_zero = +0
|
||||
|
|
Loading…
Reference in a new issue