Skip to content

Commit 8cf992c

Browse files
jordensjaparic
authored andcommitted
ser/de for f32 using lexical-core
1 parent 7c1734d commit 8cf992c

File tree

3 files changed

+84
-7
lines changed

3 files changed

+84
-7
lines changed

Cargo.toml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,18 @@ heapless = "0.5.0"
1616

1717
[dependencies.serde]
1818
default-features = false
19-
version = "1.0.80"
19+
version = "1.0.91"
20+
21+
[dependencies.lexical-core]
22+
default-features = false
23+
features = ["ryu"]
24+
version = "0.4.0"
2025

2126
[dev-dependencies]
22-
serde_derive = "1.0.80"
27+
serde_derive = "1.0.91"
2328

2429
[features]
2530
std = ["serde/std"]
2631

2732
[badges]
28-
maintenance = { status = "looking-for-maintainer" }
33+
maintenance = { status = "looking-for-maintainer" }

src/de/mod.rs

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use core::{fmt, str};
44

55
use serde::de::{self, Visitor};
66

7+
use lexical_core::{try_atof32_lossy_slice, ErrorCode};
8+
79
use self::enum_::UnitVariantAccess;
810
use self::map::MapAccess;
911
use self::seq::SeqAccess;
@@ -27,6 +29,9 @@ pub enum Error {
2729
/// EOF while parsing a string.
2830
EofWhileParsingString,
2931

32+
/// EOF while parsing a JSON number.
33+
EofWhileParsingNumber,
34+
3035
/// EOF while parsing a JSON value.
3136
EofWhileParsingValue,
3237

@@ -360,11 +365,20 @@ impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
360365
deserialize_unsigned!(self, visitor, u64, visit_u64)
361366
}
362367

363-
fn deserialize_f32<V>(self, _visitor: V) -> Result<V::Value>
368+
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
364369
where
365370
V: Visitor<'de>,
366371
{
367-
unreachable!()
372+
self.parse_whitespace().ok_or(Error::EofWhileParsingValue)?;
373+
let r = try_atof32_lossy_slice(&self.slice[self.index..]);
374+
match r.error.code {
375+
ErrorCode::Success | ErrorCode::InvalidDigit => {
376+
self.index += r.error.index;
377+
visitor.visit_f32(r.value)
378+
},
379+
ErrorCode::Empty => Err(Error::EofWhileParsingNumber),
380+
_ => Err(Error::InvalidNumber)
381+
}
368382
}
369383

370384
fn deserialize_f64<V>(self, _visitor: V) -> Result<V::Value>
@@ -711,6 +725,46 @@ mod tests {
711725
assert!(crate::from_str::<Temperature>(r#"{ "temperature": -129 }"#).is_err());
712726
}
713727

728+
#[test]
729+
fn struct_f32() {
730+
#[derive(Debug, Deserialize, PartialEq)]
731+
struct Temperature {
732+
temperature: f32,
733+
}
734+
735+
assert_eq!(
736+
crate::from_str(r#"{ "temperature": -17.2 }"#),
737+
Ok(Temperature { temperature: -17.2 })
738+
);
739+
740+
assert_eq!(
741+
crate::from_str(r#"{ "temperature": -0.0 }"#),
742+
Ok(Temperature { temperature: -0. })
743+
);
744+
745+
assert_eq!(
746+
crate::from_str(r#"{ "temperature": -2.1e-3 }"#),
747+
Ok(Temperature { temperature: -2.1e-3 })
748+
);
749+
750+
assert_eq!(
751+
crate::from_str(r#"{ "temperature": -3 }"#),
752+
Ok(Temperature { temperature: -3. })
753+
);
754+
755+
use core::f32;
756+
757+
assert_eq!(
758+
crate::from_str(r#"{ "temperature": -1e500 }"#),
759+
Ok(Temperature { temperature: f32::NEG_INFINITY })
760+
);
761+
762+
assert!(crate::from_str::<Temperature>(r#"{ "temperature": 1e1e1 }"#).is_err());
763+
assert!(crate::from_str::<Temperature>(r#"{ "temperature": -2-2 }"#).is_err());
764+
assert!(crate::from_str::<Temperature>(r#"{ "temperature": 1 1 }"#).is_err());
765+
assert!(crate::from_str::<Temperature>(r#"{ "temperature": 0.0. }"#).is_err());
766+
}
767+
714768
#[test]
715769
fn struct_option() {
716770
#[derive(Debug, Deserialize, PartialEq)]

src/ser/mod.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use serde::ser;
66

77
use heapless::{String, Vec};
88

9+
use lexical_core::{f32toa_slice, MAX_F32_SIZE};
10+
911
use self::seq::SerializeSeq;
1012
use self::struct_::SerializeStruct;
1113

@@ -187,8 +189,10 @@ where
187189
serialize_unsigned!(self, 20, v)
188190
}
189191

190-
fn serialize_f32(self, _v: f32) -> Result<Self::Ok> {
191-
unreachable!()
192+
fn serialize_f32(self, v: f32) -> Result<Self::Ok> {
193+
let mut s: [u8; MAX_F32_SIZE] = [0; MAX_F32_SIZE];
194+
self.buf.extend_from_slice(f32toa_slice(v, &mut s))?;
195+
Ok(())
192196
}
193197

194198
fn serialize_f64(self, _v: f64) -> Result<Self::Ok> {
@@ -502,6 +506,20 @@ mod tests {
502506
);
503507
}
504508

509+
#[test]
510+
fn struct_f32() {
511+
#[derive(Serialize)]
512+
struct Temperature {
513+
temperature: f32,
514+
}
515+
516+
assert_eq!(
517+
&*crate::to_string::<N, _>(&Temperature { temperature: -20. }).unwrap(),
518+
r#"{"temperature":-20.0}"#
519+
);
520+
}
521+
522+
505523
#[test]
506524
fn struct_option() {
507525
#[derive(Serialize)]

0 commit comments

Comments
 (0)