Skip to content

Commit 077f9ce

Browse files
bors[bot]jordensjaparic
authored
Merge #21
21: rebased PR #12 r=japaric a=japaric closes #12 Co-authored-by: Robert Jördens <rj@quartiq.de> Co-authored-by: Jorge Aparicio <jorge@japaric.io>
2 parents 7c1734d + ba64e95 commit 077f9ce

File tree

3 files changed

+123
-11
lines changed

3 files changed

+123
-11
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@ serde_derive = "1.0.80"
2525
std = ["serde/std"]
2626

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

src/de/mod.rs

Lines changed: 78 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Deserialize JSON data to a Rust data structure
22
3+
use core::str::FromStr;
34
use core::{fmt, str};
45

56
use serde::de::{self, Visitor};
@@ -27,6 +28,9 @@ pub enum Error {
2728
/// EOF while parsing a string.
2829
EofWhileParsingString,
2930

31+
/// EOF while parsing a JSON number.
32+
EofWhileParsingNumber,
33+
3034
/// EOF while parsing a JSON value.
3135
EofWhileParsingValue,
3236

@@ -273,6 +277,29 @@ macro_rules! deserialize_signed {
273277
}};
274278
}
275279

280+
macro_rules! deserialize_fromstr {
281+
($self:ident, $visitor:ident, $typ:ident, $visit_fn:ident, $pattern:expr) => {{
282+
let start = $self.index;
283+
loop {
284+
match $self.peek() {
285+
Some(c) => {
286+
if $pattern.iter().find(|&&d| d == c).is_some() {
287+
$self.eat_char();
288+
} else {
289+
let s = unsafe {
290+
// already checked that it contains only ascii
291+
str::from_utf8_unchecked(&$self.slice[start..$self.index])
292+
};
293+
let v = $typ::from_str(s).or(Err(Error::InvalidNumber))?;
294+
return $visitor.$visit_fn(v);
295+
}
296+
}
297+
None => return Err(Error::EofWhileParsingNumber),
298+
}
299+
}
300+
}};
301+
}
302+
276303
impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
277304
type Error = Error;
278305

@@ -360,18 +387,20 @@ impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> {
360387
deserialize_unsigned!(self, visitor, u64, visit_u64)
361388
}
362389

363-
fn deserialize_f32<V>(self, _visitor: V) -> Result<V::Value>
390+
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
364391
where
365392
V: Visitor<'de>,
366393
{
367-
unreachable!()
394+
self.parse_whitespace().ok_or(Error::EofWhileParsingValue)?;
395+
deserialize_fromstr!(self, visitor, f32, visit_f32, b"0123456789+-.eE")
368396
}
369397

370-
fn deserialize_f64<V>(self, _visitor: V) -> Result<V::Value>
398+
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value>
371399
where
372400
V: Visitor<'de>,
373401
{
374-
unreachable!()
402+
self.parse_whitespace().ok_or(Error::EofWhileParsingValue)?;
403+
deserialize_fromstr!(self, visitor, f64, visit_f64, b"0123456789+-.eE")
375404
}
376405

377406
fn deserialize_char<V>(self, _visitor: V) -> Result<V::Value>
@@ -711,6 +740,51 @@ mod tests {
711740
assert!(crate::from_str::<Temperature>(r#"{ "temperature": -129 }"#).is_err());
712741
}
713742

743+
#[test]
744+
fn struct_f32() {
745+
#[derive(Debug, Deserialize, PartialEq)]
746+
struct Temperature {
747+
temperature: f32,
748+
}
749+
750+
assert_eq!(
751+
crate::from_str(r#"{ "temperature": -17.2 }"#),
752+
Ok(Temperature { temperature: -17.2 })
753+
);
754+
755+
assert_eq!(
756+
crate::from_str(r#"{ "temperature": -0.0 }"#),
757+
Ok(Temperature { temperature: -0. })
758+
);
759+
760+
assert_eq!(
761+
crate::from_str(r#"{ "temperature": -2.1e-3 }"#),
762+
Ok(Temperature {
763+
temperature: -2.1e-3
764+
})
765+
);
766+
767+
assert_eq!(
768+
crate::from_str(r#"{ "temperature": -3 }"#),
769+
Ok(Temperature { temperature: -3. })
770+
);
771+
772+
use core::f32;
773+
774+
assert_eq!(
775+
crate::from_str(r#"{ "temperature": -1e500 }"#),
776+
Ok(Temperature {
777+
temperature: f32::NEG_INFINITY
778+
})
779+
);
780+
781+
assert!(crate::from_str::<Temperature>(r#"{ "temperature": 1e1e1 }"#).is_err());
782+
assert!(crate::from_str::<Temperature>(r#"{ "temperature": -2-2 }"#).is_err());
783+
assert!(crate::from_str::<Temperature>(r#"{ "temperature": 1 1 }"#).is_err());
784+
assert!(crate::from_str::<Temperature>(r#"{ "temperature": 0.0. }"#).is_err());
785+
assert!(crate::from_str::<Temperature>(r#"{ "temperature": ä }"#).is_err());
786+
}
787+
714788
#[test]
715789
fn struct_option() {
716790
#[derive(Debug, Deserialize, PartialEq)]

src/ser/mod.rs

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
//! Serialize a Rust data structure into JSON data
22
3-
use core::fmt;
3+
use core::{fmt, fmt::Write};
44

55
use serde::ser;
66

7-
use heapless::{String, Vec};
7+
use heapless::{consts::*, String, Vec};
88

99
use self::seq::SerializeSeq;
1010
use self::struct_::SerializeStruct;
@@ -123,6 +123,15 @@ macro_rules! serialize_signed {
123123
}};
124124
}
125125

126+
macro_rules! serialize_fmt {
127+
($self:ident, $uxx:ident, $fmt:expr, $v:expr) => {{
128+
let mut s: String<$uxx> = String::new();
129+
write!(&mut s, $fmt, $v).unwrap();
130+
$self.buf.extend_from_slice(s.as_bytes())?;
131+
Ok(())
132+
}};
133+
}
134+
126135
impl<'a, B> ser::Serializer for &'a mut Serializer<B>
127136
where
128137
B: heapless::ArrayLength<u8>,
@@ -187,12 +196,12 @@ where
187196
serialize_unsigned!(self, 20, v)
188197
}
189198

190-
fn serialize_f32(self, _v: f32) -> Result<Self::Ok> {
191-
unreachable!()
199+
fn serialize_f32(self, v: f32) -> Result<Self::Ok> {
200+
serialize_fmt!(self, U16, "{:e}", v)
192201
}
193202

194-
fn serialize_f64(self, _v: f64) -> Result<Self::Ok> {
195-
unreachable!()
203+
fn serialize_f64(self, v: f64) -> Result<Self::Ok> {
204+
serialize_fmt!(self, U32, "{:e}", v)
196205
}
197206

198207
fn serialize_char(self, _v: char) -> Result<Self::Ok> {
@@ -502,6 +511,35 @@ mod tests {
502511
);
503512
}
504513

514+
#[test]
515+
fn struct_f32() {
516+
#[derive(Serialize)]
517+
struct Temperature {
518+
temperature: f32,
519+
}
520+
521+
assert_eq!(
522+
&*crate::to_string::<N, _>(&Temperature { temperature: -20. }).unwrap(),
523+
r#"{"temperature":-2e1}"#
524+
);
525+
526+
assert_eq!(
527+
&*crate::to_string::<N, _>(&Temperature {
528+
temperature: -20345.
529+
})
530+
.unwrap(),
531+
r#"{"temperature":-2.0345e4}"#
532+
);
533+
534+
assert_eq!(
535+
&*crate::to_string::<N, _>(&Temperature {
536+
temperature: -2.3456789012345e-23
537+
})
538+
.unwrap(),
539+
r#"{"temperature":-2.3456788e-23}"#
540+
);
541+
}
542+
505543
#[test]
506544
fn struct_option() {
507545
#[derive(Serialize)]

0 commit comments

Comments
 (0)