forked from Proxmox/proxmox
login: parse helpers for floats
Of course PVE also stringifies those in the API, duh... Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
2fa645af2e
commit
6ee541d5f2
@ -115,6 +115,7 @@ where
|
||||
|
||||
macro_rules! integer_helper {
|
||||
($ty:ident, $deserialize_name:ident, $trait: ident, $from_name:ident, $visitor:ident) => {
|
||||
#[doc(hidden)]
|
||||
pub trait $trait: Sized + Default {
|
||||
fn $from_name(value: $ty) -> Self;
|
||||
}
|
||||
@ -237,3 +238,134 @@ integer_helper!(i8, deserialize_i8, FromI8, from_i8, I8Visitor);
|
||||
integer_helper!(i16, deserialize_i16, FromI16, from_i16, I16Visitor);
|
||||
integer_helper!(i32, deserialize_i32, FromI32, from_i32, I32Visitor);
|
||||
integer_helper!(i64, deserialize_i64, FromI64, from_i64, I64Visitor);
|
||||
|
||||
// float helpers:
|
||||
|
||||
macro_rules! float_helper {
|
||||
($ty:ident, $deserialize_name:ident, $visitor:ident) => {
|
||||
pub fn $deserialize_name<'de, D, T>(deserializer: D) -> Result<T, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
T: FromF64,
|
||||
{
|
||||
deserializer.deserialize_any($visitor::<T>::new())
|
||||
}
|
||||
|
||||
struct $visitor<T>(std::marker::PhantomData<T>);
|
||||
|
||||
impl<T> $visitor<T> {
|
||||
fn new() -> Self {
|
||||
Self(std::marker::PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, T: FromF64> serde::de::DeserializeSeed<'de> for $visitor<T> {
|
||||
type Value = T;
|
||||
|
||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
$deserialize_name(deserializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, T> serde::de::Visitor<'de> for $visitor<T>
|
||||
where
|
||||
T: FromF64,
|
||||
{
|
||||
type Value = T;
|
||||
|
||||
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str(concat!("a ", stringify!($ty), "-ish..."))
|
||||
}
|
||||
|
||||
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_any(self)
|
||||
}
|
||||
|
||||
fn visit_none<E>(self) -> Result<Self::Value, E> {
|
||||
Ok(Default::default())
|
||||
}
|
||||
|
||||
fn visit_f64<E: serde::de::Error>(self, value: f64) -> Result<Self::Value, E> {
|
||||
Ok(T::from_f64(value))
|
||||
}
|
||||
|
||||
fn visit_i128<E: serde::de::Error>(self, value: i128) -> Result<Self::Value, E> {
|
||||
let conv = value as f64;
|
||||
if conv as i128 == value {
|
||||
Ok(T::from_f64(conv))
|
||||
} else {
|
||||
Err(E::invalid_value(Unexpected::Other("i128"), &self))
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_i64<E: serde::de::Error>(self, value: i64) -> Result<Self::Value, E> {
|
||||
let conv = value as f64;
|
||||
if conv as i64 == value {
|
||||
Ok(T::from_f64(conv))
|
||||
} else {
|
||||
Err(E::invalid_value(Unexpected::Signed(value), &self))
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_u128<E: serde::de::Error>(self, value: u128) -> Result<Self::Value, E> {
|
||||
let conv = value as f64;
|
||||
if conv as u128 == value {
|
||||
Ok(T::from_f64(conv))
|
||||
} else {
|
||||
Err(E::invalid_value(Unexpected::Other("u128"), &self))
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_u64<E: serde::de::Error>(self, value: u64) -> Result<Self::Value, E> {
|
||||
let conv = value as f64;
|
||||
if conv as u64 == value {
|
||||
Ok(T::from_f64(conv))
|
||||
} else {
|
||||
Err(E::invalid_value(Unexpected::Unsigned(value), &self))
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<Self::Value, E> {
|
||||
let value = value
|
||||
.parse()
|
||||
.map_err(|_| E::invalid_value(Unexpected::Str(value), &self))?;
|
||||
self.visit_f64(value)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait FromF64: Sized + Default {
|
||||
fn from_f64(value: f64) -> Self;
|
||||
}
|
||||
|
||||
impl FromF64 for f32 {
|
||||
#[inline(always)]
|
||||
fn from_f64(f: f64) -> f32 {
|
||||
f as f32
|
||||
}
|
||||
}
|
||||
|
||||
impl FromF64 for f64 {
|
||||
#[inline(always)]
|
||||
fn from_f64(f: f64) -> f64 {
|
||||
f
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: FromF64> FromF64 for Option<T> {
|
||||
#[inline(always)]
|
||||
fn from_f64(f: f64) -> Option<T> {
|
||||
Some(T::from_f64(f))
|
||||
}
|
||||
}
|
||||
|
||||
float_helper!(f32, deserialize_f32, F32Visitor);
|
||||
float_helper!(f64, deserialize_f64, F64Visitor);
|
||||
|
Loading…
Reference in New Issue
Block a user