From c4203572121b684e534cbb532123fb847eefbc06 Mon Sep 17 00:00:00 2001 From: "john.burkhardt" Date: Fri, 10 Sep 2021 11:59:12 -0400 Subject: [PATCH 1/2] Adds explicit serialization for f32 to avoid rounding artifacts when promoting f32 to f64 --- src/ser.rs | 11 ++++++++++- tests/test_serde.rs | 10 ++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/ser.rs b/src/ser.rs index 6b7ceb7a..5b2d17f8 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -514,7 +514,16 @@ impl ser::Serializer for SerializerToYaml { } fn serialize_f32(self, v: f32) -> Result { - self.serialize_f64(v as f64) + 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_f64(self, v: f64) -> Result { diff --git a/tests/test_serde.rs b/tests/test_serde.rs index 734998c2..da89b7cc 100644 --- a/tests/test_serde.rs +++ b/tests/test_serde.rs @@ -135,6 +135,16 @@ fn test_float() { assert!(float.is_nan()); } +#[test] +fn test_float32() { + let thing: f32 = 25.6; + let yaml = indoc! {" + --- + 25.6 + "}; + test_serde(&thing, yaml); +} + #[test] fn test_vec() { let thing = vec![1, 2, 3]; From 7d07fe6d7ee449842981bfd71111c7fabe5f7882 Mon Sep 17 00:00:00 2001 From: "john.burkhardt" Date: Fri, 10 Sep 2021 12:13:21 -0400 Subject: [PATCH 2/2] Adds test cases for f32 representations (inf and nan) --- tests/test_serde.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/test_serde.rs b/tests/test_serde.rs index da89b7cc..326f9075 100644 --- a/tests/test_serde.rs +++ b/tests/test_serde.rs @@ -143,6 +143,28 @@ fn test_float32() { 25.6 "}; test_serde(&thing, yaml); + + let thing = f32::INFINITY; + let yaml = indoc! {" + --- + .inf + "}; + test_serde(&thing, yaml); + + let thing = f32::NEG_INFINITY; + let yaml = indoc! {" + --- + -.inf + "}; + test_serde(&thing, yaml); + + let single_float: f32 = serde_yaml::from_str(indoc! {" + --- + .nan + "}) + .unwrap(); + assert!(single_float.is_nan()); + } #[test]