use serde::Deserializer;
pub(crate) fn string_or_number<'de, D>(d: D) -> Result<String, D::Error>
where
D: Deserializer<'de>,
{
d.deserialize_any(StringOrNumberVisitor)
}
struct StringOrNumberVisitor;
impl<'de> serde::de::Visitor<'de> for StringOrNumberVisitor {
type Value = String;
fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("a string or number")
}
#[inline]
fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<String, E> {
Ok(v.to_owned())
}
#[inline]
fn visit_string<E: serde::de::Error>(self, v: String) -> Result<String, E> {
Ok(v)
}
#[inline]
fn visit_u64<E: serde::de::Error>(self, v: u64) -> Result<String, E> {
Ok(v.to_string())
}
#[inline]
fn visit_i64<E: serde::de::Error>(self, v: i64) -> Result<String, E> {
Ok(v.to_string())
}
#[inline]
fn visit_f64<E: serde::de::Error>(self, v: f64) -> Result<String, E> {
Ok(v.to_string())
}
#[inline]
fn visit_bool<E: serde::de::Error>(self, v: bool) -> Result<String, E> {
Ok(v.to_string())
}
}
pub(crate) fn opt_string_or_number<'de, D>(d: D) -> Result<Option<String>, D::Error>
where
D: Deserializer<'de>,
{
d.deserialize_any(OptStringOrNumberVisitor)
}
struct OptStringOrNumberVisitor;
impl<'de> serde::de::Visitor<'de> for OptStringOrNumberVisitor {
type Value = Option<String>;
fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("a string, number, or null")
}
#[inline]
fn visit_none<E: serde::de::Error>(self) -> Result<Option<String>, E> {
Ok(None)
}
#[inline]
fn visit_unit<E: serde::de::Error>(self) -> Result<Option<String>, E> {
Ok(None)
}
fn visit_some<D2: Deserializer<'de>>(self, d: D2) -> Result<Option<String>, D2::Error> {
string_or_number(d).map(Some)
}
#[inline]
fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Option<String>, E> {
Ok(Some(v.to_owned()))
}
#[inline]
fn visit_string<E: serde::de::Error>(self, v: String) -> Result<Option<String>, E> {
Ok(Some(v))
}
#[inline]
fn visit_u64<E: serde::de::Error>(self, v: u64) -> Result<Option<String>, E> {
Ok(Some(v.to_string()))
}
#[inline]
fn visit_i64<E: serde::de::Error>(self, v: i64) -> Result<Option<String>, E> {
Ok(Some(v.to_string()))
}
#[inline]
fn visit_f64<E: serde::de::Error>(self, v: f64) -> Result<Option<String>, E> {
Ok(Some(v.to_string()))
}
}
pub(crate) fn string_or_number_i64<'de, D>(d: D) -> Result<i64, D::Error>
where
D: Deserializer<'de>,
{
d.deserialize_any(I64Visitor)
}
struct I64Visitor;
impl<'de> serde::de::Visitor<'de> for I64Visitor {
type Value = i64;
fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("an i64 as a number or string")
}
#[inline]
fn visit_i64<E: serde::de::Error>(self, v: i64) -> Result<i64, E> {
Ok(v)
}
#[inline]
fn visit_u64<E: serde::de::Error>(self, v: u64) -> Result<i64, E> {
i64::try_from(v).map_err(|_| E::custom("u64 out of i64 range"))
}
#[inline]
fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<i64, E> {
v.parse::<i64>().map_err(E::custom)
}
#[inline]
fn visit_string<E: serde::de::Error>(self, v: String) -> Result<i64, E> {
v.parse::<i64>().map_err(E::custom)
}
}