Skip to content
This repository has been archived by the owner on Mar 25, 2024. It is now read-only.

Commit

Permalink
Merge pull request #88 from frewsxcv/frewsxcv-f64-ser
Browse files Browse the repository at this point in the history
Improved serialization/deserialization for floating point numbers.
  • Loading branch information
dtolnay authored Jan 21, 2018
2 parents f9406c1 + 595c2cd commit 18725af
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 4 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ readme = "README.md"
keywords = ["yaml", "serde"]

[dependencies]
dtoa = "0.4"
linked-hash-map = "0.5"
num-traits = "0.1.37"
serde = "1.0"
Expand Down
11 changes: 11 additions & 0 deletions src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//! This module provides YAML deserialization with the type `Deserializer`.

use std::collections::BTreeMap;
use std::f64;
use std::fmt;
use std::io;
use std::str;
Expand Down Expand Up @@ -490,6 +491,16 @@ fn visit_untagged_str<'de, V>(visitor: V, v: &str) -> Result<V::Value>
if let Ok(n) = v.parse() {
return visitor.visit_i64(n);
}
match v.trim_left_matches('+') {
".inf" | ".Inf" | ".INF" => return visitor.visit_f64(f64::INFINITY),
_ => (),
}
if v == "-.inf" || v == "-.Inf" || v == "-.INF" {
return visitor.visit_f64(f64::NEG_INFINITY);
}
if v == ".nan" || v == ".NaN" || v == ".NAN" {
return visitor.visit_f64(f64::NAN);
}
if let Ok(n) = v.parse() {
return visitor.visit_f64(n);
}
Expand Down
5 changes: 3 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
//!
//! // Serialize it to a YAML string.
//! let s = serde_yaml::to_string(&map).unwrap();
//! assert_eq!(s, "---\nx: 1\n\"y\": 2");
//! assert_eq!(s, "---\nx: 1.0\n\"y\": 2.0");
//!
//! // Deserialize it back to a Rust type.
//! let deserialized_map: BTreeMap<String, f64> = serde_yaml::from_str(&s).unwrap();
Expand All @@ -53,7 +53,7 @@
//! let point = Point { x: 1.0, y: 2.0 };
//!
//! let s = serde_yaml::to_string(&point).unwrap();
//! assert_eq!(s, "---\nx: 1\n\"y\": 2");
//! assert_eq!(s, "---\nx: 1.0\n\"y\": 2.0");
//!
//! let deserialized_point: Point = serde_yaml::from_str(&s).unwrap();
//! assert_eq!(point, deserialized_point);
Expand All @@ -78,6 +78,7 @@
empty_enum,
))]

extern crate dtoa;
extern crate linked_hash_map;
extern crate num_traits;
#[macro_use]
Expand Down
13 changes: 11 additions & 2 deletions src/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
//!
//! This module provides YAML serialization with the type `Serializer`.

use std::{fmt, io};
use std::{fmt, io, num, str};

use yaml_rust::{yaml, Yaml, YamlEmitter};

Expand Down Expand Up @@ -73,7 +73,16 @@ impl ser::Serializer for Serializer {
}

fn serialize_f64(self, v: f64) -> Result<Yaml> {
Ok(Yaml::Real(v.to_string()))
Ok(Yaml::Real(match v.classify() {
num::FpCategory::Infinite if v.is_sign_positive() => ".inf".into(),
num::FpCategory::Infinite => "-.inf".into(),
num::FpCategory::Nan => ".nan".into(),
_ => {
let mut buf = vec![];
::dtoa::write(&mut buf, v).unwrap();
::std::str::from_utf8(&buf).unwrap().into()
}
}))
}

fn serialize_char(self, value: char) -> Result<Yaml> {
Expand Down
24 changes: 24 additions & 0 deletions tests/test_serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ extern crate serde_yaml;
extern crate unindent;
use unindent::unindent;

use std::f64;
use std::fmt::Debug;
use std::collections::BTreeMap;

Expand Down Expand Up @@ -73,6 +74,29 @@ fn test_float() {
---
25.6");
test_serde(&thing, &yaml);

let thing = 25.;
let yaml = unindent("
---
25.0");
test_serde(&thing, &yaml);

let thing = f64::INFINITY;
let yaml = unindent("
---
.inf");
test_serde(&thing, &yaml);

let thing = f64::NEG_INFINITY;
let yaml = unindent("
---
-.inf");
test_serde(&thing, &yaml);

let float: f64 = serde_yaml::from_str(&unindent("
---
.nan")).unwrap();
assert!(float.is_nan());
}

#[test]
Expand Down

0 comments on commit 18725af

Please sign in to comment.