Skip to content

Commit 06f3443

Browse files
committed
Eliminate f32-to-f64 casting in arbitrary_precision mode
1 parent b0990a5 commit 06f3443

File tree

4 files changed

+27
-7
lines changed

4 files changed

+27
-7
lines changed

src/number.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,24 @@ impl Number {
279279
}
280280
}
281281

282+
pub(crate) fn from_f32(f: f32) -> Option<Number> {
283+
if f.is_finite() {
284+
let n = {
285+
#[cfg(not(feature = "arbitrary_precision"))]
286+
{
287+
N::Float(f as f64)
288+
}
289+
#[cfg(feature = "arbitrary_precision")]
290+
{
291+
ryu::Buffer::new().format_finite(f).to_owned()
292+
}
293+
};
294+
Some(Number { n })
295+
} else {
296+
None
297+
}
298+
}
299+
282300
#[cfg(feature = "arbitrary_precision")]
283301
/// Not public API. Only tests use this.
284302
#[doc(hidden)]

src/value/from.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ impl From<f32> for Value {
4040
/// let x: Value = f.into();
4141
/// ```
4242
fn from(f: f32) -> Self {
43-
From::from(f as f64)
43+
Number::from_f32(f).map_or(Value::Null, Value::Number)
4444
}
4545
}
4646

src/value/ser.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use crate::error::{Error, ErrorCode, Result};
22
use crate::map::Map;
3-
use crate::number::Number;
43
use crate::value::{to_value, Value};
54
use alloc::borrow::ToOwned;
65
use alloc::string::{String, ToString};
@@ -149,13 +148,13 @@ impl serde::Serializer for Serializer {
149148
}
150149

151150
#[inline]
152-
fn serialize_f32(self, value: f32) -> Result<Value> {
153-
self.serialize_f64(value as f64)
151+
fn serialize_f32(self, float: f32) -> Result<Value> {
152+
Ok(Value::from(float))
154153
}
155154

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

161160
#[inline]

tests/regression/issue1004.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,8 @@ fn test() {
55
let float = 5.55f32;
66
let value = serde_json::to_value(&float).unwrap();
77
let json = serde_json::to_string(&value).unwrap();
8-
assert_eq!(json, "5.550000190734863"); // FIXME
8+
9+
// If the f32 were cast to f64 by Value before serialization, then this
10+
// would incorrectly serialize as 5.550000190734863.
11+
assert_eq!(json, "5.55");
912
}

0 commit comments

Comments
 (0)