From 54093a1929b5ccb238b55ea25db15fd24437aa07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Haudebourg?= Date: Thu, 15 Feb 2024 16:47:20 +0100 Subject: [PATCH] Handle arbitrary number precision with serde correctly. --- Cargo.toml | 2 +- src/serde/de.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a45fd83..d90f6fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "json-syntax" -version = "0.11.4" +version = "0.11.5" edition = "2021" authors = ["Timothée Haudebourg "] description = "Strict JSON parsing and mapping library" diff --git a/src/serde/de.rs b/src/serde/de.rs index c8f345e..c6cedbc 100644 --- a/src/serde/de.rs +++ b/src/serde/de.rs @@ -124,13 +124,73 @@ impl<'de> Deserialize<'de> for Value { where V: MapAccess<'de>, { - let mut object = Object::new(); + const NUMBER_TOKEN: &str = "$serde_json::private::Number"; - while let Some((key, value)) = visitor.next_entry()? { - object.insert(key, value); + enum MapTag { + Number, + None(Key) } - Ok(Value::Object(object)) + impl<'de> Deserialize<'de> for MapTag { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de> + { + struct Visitor; + + impl<'de> serde::de::Visitor<'de> for Visitor { + type Value = MapTag; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a string key") + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error + { + if v == NUMBER_TOKEN { + Ok(MapTag::Number) + } else { + Ok(MapTag::None(v.into())) + } + } + + fn visit_string(self, v: String) -> Result + where + E: serde::de::Error + { + if v == NUMBER_TOKEN { + Ok(MapTag::Number) + } else { + Ok(MapTag::None(v.into())) + } + } + } + + deserializer.deserialize_string(Visitor) + } + } + + match visitor.next_key()? { + Some(MapTag::Number) => { + let value = visitor.next_value()?; + Ok(Value::Number(value)) + } + Some(MapTag::None(key)) => { + let mut object = Object::new(); + + object.insert(key, visitor.next_value()?); + while let Some((key, value)) = visitor.next_entry()? { + object.insert(key, value); + } + + Ok(Value::Object(object)) + } + None => { + Ok(Value::Object(Object::new())) + } + } } }