|
1 | 1 | //! Deserialize JSON data to a Rust data structure
|
2 | 2 |
|
| 3 | +use core::marker::PhantomData; |
3 | 4 | use core::str::FromStr;
|
4 | 5 | use core::{fmt, str};
|
5 | 6 |
|
@@ -384,12 +385,71 @@ macro_rules! deserialize_fromstr {
|
384 | 385 | impl<'a, 'de, 's> de::Deserializer<'de> for &'a mut Deserializer<'de, 's> {
|
385 | 386 | type Error = Error;
|
386 | 387 |
|
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> |
389 | 389 | where
|
390 | 390 | V: Visitor<'de>,
|
391 | 391 | {
|
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 | + } |
393 | 453 | }
|
394 | 454 |
|
395 | 455 | fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
|
@@ -1486,4 +1546,72 @@ mod tests {
|
1486 | 1546 | ))
|
1487 | 1547 | )
|
1488 | 1548 | }
|
| 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 | + } |
1489 | 1617 | }
|
0 commit comments