Skip to content

Commit

Permalink
Eliminate f32-to-f64 casting in arbitrary_precision mode
Browse files Browse the repository at this point in the history
  • Loading branch information
dtolnay committed Mar 27, 2023
1 parent b0990a5 commit 06f3443
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 7 deletions.
18 changes: 18 additions & 0 deletions src/number.rs
Expand Up @@ -279,6 +279,24 @@ impl Number {
}
}

pub(crate) fn from_f32(f: f32) -> Option<Number> {
if f.is_finite() {
let n = {
#[cfg(not(feature = "arbitrary_precision"))]
{
N::Float(f as f64)
}
#[cfg(feature = "arbitrary_precision")]
{
ryu::Buffer::new().format_finite(f).to_owned()
}
};
Some(Number { n })
} else {
None
}
}

#[cfg(feature = "arbitrary_precision")]
/// Not public API. Only tests use this.
#[doc(hidden)]
Expand Down
2 changes: 1 addition & 1 deletion src/value/from.rs
Expand Up @@ -40,7 +40,7 @@ impl From<f32> for Value {
/// let x: Value = f.into();
/// ```
fn from(f: f32) -> Self {
From::from(f as f64)
Number::from_f32(f).map_or(Value::Null, Value::Number)
}
}

Expand Down
9 changes: 4 additions & 5 deletions src/value/ser.rs
@@ -1,6 +1,5 @@
use crate::error::{Error, ErrorCode, Result};
use crate::map::Map;
use crate::number::Number;
use crate::value::{to_value, Value};
use alloc::borrow::ToOwned;
use alloc::string::{String, ToString};
Expand Down Expand Up @@ -149,13 +148,13 @@ impl serde::Serializer for Serializer {
}

#[inline]
fn serialize_f32(self, value: f32) -> Result<Value> {
self.serialize_f64(value as f64)
fn serialize_f32(self, float: f32) -> Result<Value> {
Ok(Value::from(float))
}

#[inline]
fn serialize_f64(self, value: f64) -> Result<Value> {
Ok(Number::from_f64(value).map_or(Value::Null, Value::Number))
fn serialize_f64(self, float: f64) -> Result<Value> {
Ok(Value::from(float))
}

#[inline]
Expand Down
5 changes: 4 additions & 1 deletion tests/regression/issue1004.rs
Expand Up @@ -5,5 +5,8 @@ fn test() {
let float = 5.55f32;
let value = serde_json::to_value(&float).unwrap();
let json = serde_json::to_string(&value).unwrap();
assert_eq!(json, "5.550000190734863"); // FIXME

// If the f32 were cast to f64 by Value before serialization, then this
// would incorrectly serialize as 5.550000190734863.
assert_eq!(json, "5.55");
}

0 comments on commit 06f3443

Please sign in to comment.