Skip to main content

vtcode_commons/
serde_helpers.rs

1//! Serde helper utilities
2
3use serde::{Deserialize, Deserializer};
4use std::fmt::Display;
5use std::str::FromStr;
6
7/// Deserializes a value that can be represented as either its native type or a quoted string.
8/// This is particularly useful for LLM tool calls which sometimes quote numeric arguments.
9pub fn deserialize_maybe_quoted<'de, T, D>(deserializer: D) -> Result<T, D::Error>
10where
11    T: FromStr + Deserialize<'de>,
12    T::Err: Display,
13    D: Deserializer<'de>,
14{
15    #[derive(Deserialize)]
16    #[serde(untagged)]
17    enum MaybeQuoted<T> {
18        Native(T),
19        Quoted(String),
20    }
21
22    match MaybeQuoted::<T>::deserialize(deserializer)? {
23        MaybeQuoted::Native(val) => Ok(val),
24        MaybeQuoted::Quoted(s) => T::from_str(&s).map_err(serde::de::Error::custom),
25    }
26}
27
28/// Deserializes an optional value that can be represented as either its native type or a quoted string.
29pub fn deserialize_opt_maybe_quoted<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
30where
31    T: FromStr + Deserialize<'de>,
32    T::Err: Display,
33    D: Deserializer<'de>,
34{
35    #[derive(Deserialize)]
36    #[serde(untagged)]
37    enum MaybeQuoted<T> {
38        Native(T),
39        Quoted(String),
40        Null,
41    }
42
43    match MaybeQuoted::<T>::deserialize(deserializer)? {
44        MaybeQuoted::Native(val) => Ok(Some(val)),
45        MaybeQuoted::Quoted(s) => T::from_str(&s).map(Some).map_err(serde::de::Error::custom),
46        MaybeQuoted::Null => Ok(None),
47    }
48}