fix: add proper epoch serialization
This commit is contained in:
parent
dc81c21ea9
commit
6090b2b47f
8 changed files with 95 additions and 35 deletions
64
src/utils/hifitime_serde.rs
Normal file
64
src/utils/hifitime_serde.rs
Normal file
|
@ -0,0 +1,64 @@
|
|||
use std::fmt;
|
||||
use std::fmt::{Formatter, Write};
|
||||
use hifitime::Epoch;
|
||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
#[derive(PartialOrd, PartialEq, Ord, Eq, Clone, Copy, Debug, Default)]
|
||||
#[repr(transparent)]
|
||||
pub struct EpochUTC(pub Epoch);
|
||||
|
||||
impl From<Epoch> for EpochUTC {
|
||||
#[inline]
|
||||
fn from(value: Epoch) -> Self {
|
||||
EpochUTC(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for EpochUTC {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_f64(self.0.to_unix_seconds())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for EpochUTC {
|
||||
fn deserialize<D>(deserializer: D) -> Result<EpochUTC, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct EpochVisitor;
|
||||
|
||||
impl<'de> de::Visitor<'de> for EpochVisitor {
|
||||
type Value = EpochUTC;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||
formatter.write_str("a string or a float")
|
||||
}
|
||||
|
||||
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E> where E: de::Error {
|
||||
return Ok(Epoch::from_unix_seconds(v as f64).into())
|
||||
}
|
||||
|
||||
fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E> where E: de::Error {
|
||||
return Ok(Epoch::from_unix_seconds(v as f64).into())
|
||||
}
|
||||
|
||||
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E> where E: de::Error {
|
||||
return Ok(Epoch::from_unix_seconds(v).into())
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<EpochUTC, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
return Ok(Epoch::from_unix_seconds(
|
||||
value.parse().map_err(de::Error::custom)?
|
||||
).into())
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_any(EpochVisitor)
|
||||
}
|
||||
}
|
86
src/utils/mod.rs
Normal file
86
src/utils/mod.rs
Normal file
|
@ -0,0 +1,86 @@
|
|||
//! Глобальный модуль для вспомогательных типов и утилит.
|
||||
//!
|
||||
|
||||
|
||||
mod hifitime_serde;
|
||||
|
||||
use phf::phf_map;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub use hifitime_serde::EpochUTC;
|
||||
|
||||
|
||||
/// Поддерживаемые типы.
|
||||
///
|
||||
/// TODO: Решить необходимо ли к данным прикреплять единицы измерения.
|
||||
/// TODO: Сейчас вообще сомнительно оставлять ли это или нет.
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||
#[repr(u64)]
|
||||
pub enum SupportedUnit {
|
||||
Celsius, // Needs verification > -273.15
|
||||
Percentage, // Needs verification >= 100 && <= 0
|
||||
MillimeterHg, // Needs verification
|
||||
UVIndex, // Needs verification
|
||||
Boolean, // Needs verification and possible parsing
|
||||
Kbps,
|
||||
Volume,
|
||||
KWh,
|
||||
Amps,
|
||||
Volts,
|
||||
Watts,
|
||||
Seconds,
|
||||
Hertz,
|
||||
}
|
||||
|
||||
impl Serialize for SupportedUnit {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(match self {
|
||||
SupportedUnit::Celsius => "C",
|
||||
SupportedUnit::Percentage => "%",
|
||||
SupportedUnit::MillimeterHg => "mmHg",
|
||||
SupportedUnit::UVIndex => "UV",
|
||||
SupportedUnit::Boolean => "bool",
|
||||
SupportedUnit::Kbps => "Kbps",
|
||||
SupportedUnit::Volume => "m3",
|
||||
SupportedUnit::Amps => "A",
|
||||
SupportedUnit::Volts => "V",
|
||||
SupportedUnit::Watts => "W",
|
||||
SupportedUnit::Seconds => "s",
|
||||
SupportedUnit::KWh => "KWh",
|
||||
SupportedUnit::Hertz => "Hz",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for SupportedUnit {
|
||||
fn deserialize<'a, D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let color_str = Cow::<'a, str>::deserialize(deserializer)?;
|
||||
match STR_TO_UNITS.get(color_str.as_ref()) {
|
||||
Some(v) => Ok(v.clone()),
|
||||
None => Err(serde::de::Error::custom("Invalid unit")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Таблица преобразования текстового представления единиц в значения [SupportedUnit].
|
||||
static STR_TO_UNITS: phf::Map<&'static str, SupportedUnit> = phf_map! {
|
||||
"C" => SupportedUnit::Celsius,
|
||||
"%" => SupportedUnit::Percentage,
|
||||
"mmHg" => SupportedUnit::MillimeterHg,
|
||||
"UV" => SupportedUnit::UVIndex,
|
||||
"bool" => SupportedUnit::Boolean,
|
||||
"Kbps" => SupportedUnit::Kbps,
|
||||
"m3" => SupportedUnit::Volume,
|
||||
"A" => SupportedUnit::Amps,
|
||||
"V" => SupportedUnit::Volts,
|
||||
"W" => SupportedUnit::Watts,
|
||||
"s" => SupportedUnit::Seconds,
|
||||
"KWh" => SupportedUnit::KWh,
|
||||
};
|
Loading…
Add table
Reference in a new issue