Skip to content

Commit d66b42e

Browse files
committed
Avoid string allocation when deserializing numbers
1 parent afb5da2 commit d66b42e

File tree

1 file changed

+35
-15
lines changed

1 file changed

+35
-15
lines changed

crates/core/src/util.rs

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@ extern crate alloc;
33
use alloc::format;
44
use alloc::string::String;
55

6-
use serde::Deserialize;
7-
use serde_json as json;
8-
96
#[cfg(not(feature = "getrandom"))]
107
use crate::sqlite;
8+
use serde::de::Visitor;
119

1210
use uuid::Uuid;
1311

@@ -46,25 +44,47 @@ pub fn deserialize_string_to_i64<'de, D>(deserializer: D) -> Result<i64, D::Erro
4644
where
4745
D: serde::Deserializer<'de>,
4846
{
49-
let value = json::Value::deserialize(deserializer)?;
50-
51-
match value {
52-
json::Value::String(s) => s.parse::<i64>().map_err(serde::de::Error::custom),
53-
_ => Err(serde::de::Error::custom("Expected a string.")),
54-
}
47+
deserialize_optional_string_to_i64(deserializer)?
48+
.ok_or_else(|| serde::de::Error::custom("Expected a string."))
5549
}
5650

5751
pub fn deserialize_optional_string_to_i64<'de, D>(deserializer: D) -> Result<Option<i64>, D::Error>
5852
where
5953
D: serde::Deserializer<'de>,
6054
{
61-
let value = json::Value::deserialize(deserializer)?;
62-
63-
match value {
64-
json::Value::Null => Ok(None),
65-
json::Value::String(s) => s.parse::<i64>().map(Some).map_err(serde::de::Error::custom),
66-
_ => Err(serde::de::Error::custom("Expected a string or null.")),
55+
struct ValueVisitor;
56+
57+
impl<'de> Visitor<'de> for ValueVisitor {
58+
type Value = Option<i64>;
59+
60+
fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
61+
formatter.write_str("a string or null")
62+
}
63+
64+
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
65+
where
66+
E: serde::de::Error,
67+
{
68+
v.parse::<i64>().map(Some).map_err(serde::de::Error::custom)
69+
}
70+
71+
fn visit_none<E>(self) -> Result<Self::Value, E>
72+
where
73+
E: serde::de::Error,
74+
{
75+
Ok(None)
76+
}
77+
78+
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
79+
where
80+
D: serde::Deserializer<'de>,
81+
{
82+
deserializer.deserialize_str(self)
83+
}
6784
}
85+
86+
// Using a custom visitor here to avoid an intermediate string allocation
87+
deserializer.deserialize_option(ValueVisitor)
6888
}
6989

7090
// Use getrandom crate to generate UUID.

0 commit comments

Comments
 (0)