Skip to content

Commit 2f75e92

Browse files
committed
implement deserialize_any
1 parent ca67457 commit 2f75e92

File tree

1 file changed

+131
-3
lines changed

1 file changed

+131
-3
lines changed

src/de/mod.rs

Lines changed: 131 additions & 3 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::marker::PhantomData;
34
use core::str::FromStr;
45
use core::{fmt, str};
56

@@ -384,12 +385,71 @@ macro_rules! deserialize_fromstr {
384385
impl<'a, 'de, 's> de::Deserializer<'de> for &'a mut Deserializer<'de, 's> {
385386
type Error = Error;
386387

387-
/// Unsupported. Can’t parse a value without knowing its expected type.
388-
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value>
388+
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
389389
where
390390
V: Visitor<'de>,
391391
{
392-
Err(Error::AnyIsUnsupported)
392+
enum ParsedNumber {
393+
U64(u64),
394+
I64(i64),
395+
F64(f64),
396+
NAN,
397+
}
398+
399+
impl ParsedNumber {
400+
pub fn from_str(x: &str) -> Result<Self> {
401+
if let Ok(x) = i64::from_str(x) {
402+
return Ok(ParsedNumber::I64(x as i64));
403+
}
404+
405+
if let Ok(x) = u64::from_str(x) {
406+
return Ok(ParsedNumber::U64(x as u64));
407+
}
408+
409+
if let Ok(x) = f64::from_str(x) {
410+
return Ok(ParsedNumber::F64(x as f64));
411+
}
412+
413+
Err(Error::InvalidNumber)
414+
}
415+
}
416+
417+
struct VisitorAdaptor<'de, V>(V, PhantomData<&'de ()>);
418+
419+
impl<'de, V: Visitor<'de>> VisitorAdaptor<'de, V> {
420+
fn visit_number<E>(self, v: ParsedNumber) -> core::result::Result<V::Value, E>
421+
where
422+
E: de::Error,
423+
{
424+
match v {
425+
ParsedNumber::U64(x) => self.0.visit_u64(x),
426+
ParsedNumber::I64(x) => self.0.visit_i64(x),
427+
ParsedNumber::F64(x) => self.0.visit_f64(x),
428+
ParsedNumber::NAN => self.0.visit_f64(f64::NAN),
429+
}
430+
}
431+
}
432+
433+
let peek = self.parse_whitespace().ok_or(Error::EofWhileParsingValue)?;
434+
435+
match peek {
436+
b'n' => self.deserialize_unit(visitor),
437+
b't' | b'f' => self.deserialize_bool(visitor),
438+
b'-' | b'0'..=b'9' => {
439+
let visitor = VisitorAdaptor(visitor, PhantomData);
440+
deserialize_fromstr!(
441+
self,
442+
visitor,
443+
ParsedNumber,
444+
visit_number,
445+
b"0123456789+-.eE"
446+
)
447+
}
448+
b'"' => self.deserialize_str(visitor),
449+
b'[' => self.deserialize_seq(visitor),
450+
b'{' => self.deserialize_map(visitor),
451+
_ => Err(Error::ExpectedSomeValue),
452+
}
393453
}
394454

395455
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
@@ -1486,4 +1546,72 @@ mod tests {
14861546
))
14871547
)
14881548
}
1549+
1550+
#[test]
1551+
fn deserialize_any() {
1552+
#[derive(PartialEq, Debug)]
1553+
enum Any {
1554+
U64(u64),
1555+
I64(i64),
1556+
F64(f64),
1557+
Bool(bool),
1558+
}
1559+
1560+
struct Visitor;
1561+
1562+
impl<'de> super::de::Visitor<'de> for Visitor {
1563+
type Value = Any;
1564+
1565+
fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1566+
write!(formatter, "an Any")
1567+
}
1568+
1569+
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
1570+
where
1571+
E: serde::de::Error,
1572+
{
1573+
Ok(Any::Bool(v))
1574+
}
1575+
1576+
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
1577+
where
1578+
E: serde::de::Error,
1579+
{
1580+
Ok(Any::I64(v))
1581+
}
1582+
1583+
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
1584+
where
1585+
E: serde::de::Error,
1586+
{
1587+
Ok(Any::U64(v))
1588+
}
1589+
1590+
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
1591+
where
1592+
E: serde::de::Error,
1593+
{
1594+
Ok(Any::F64(v))
1595+
}
1596+
}
1597+
1598+
impl<'de> super::de::Deserialize<'de> for Any {
1599+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1600+
where
1601+
D: serde::Deserializer<'de>,
1602+
{
1603+
deserializer.deserialize_any(Visitor)
1604+
}
1605+
}
1606+
1607+
let from_str = |x| crate::from_str::<Any>(x).ok().map(|x| x.0);
1608+
1609+
assert_eq!(from_str("true"), Some(Any::Bool(true)));
1610+
assert_eq!(from_str("false"), Some(Any::Bool(false)));
1611+
assert_eq!(from_str("123"), Some(Any::I64(123)));
1612+
assert_eq!(from_str("-123"), Some(Any::I64(-123)));
1613+
assert_eq!(from_str("18446744073709551615"), Some(Any::U64(u64::MAX)));
1614+
assert_eq!(from_str("123.0"), Some(Any::F64(123.0)));
1615+
assert_eq!(from_str("3.7e-5"), Some(Any::F64(3.7e-5)));
1616+
}
14891617
}

0 commit comments

Comments
 (0)