Исправление сериализации Epoch #13
1294
Cargo.lock
generated
|
@ -1,5 +1,8 @@
|
|||
use crate::ingest_protocol::{
|
||||
parser::{parse_mac_address, parse_packet},
|
||||
SensorValue,
|
||||
};
|
||||
use hifitime::Epoch;
|
||||
use crate::ingest_protocol::parser::{parse_mac_address, parse_packet};
|
||||
|
||||
#[test]
|
||||
fn test_asd() {
|
||||
|
@ -16,13 +19,17 @@ fn test_asd() {
|
|||
"#
|
||||
.trim();
|
||||
let packet = parse_packet(asd).unwrap().1;
|
||||
assert!(serde_json::to_string_pretty(&packet).unwrap()
|
||||
assert!(serde_json::to_string_pretty(&packet)
|
||||
.unwrap()
|
||||
.contains(r#""time": 1000000.0"#));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mac() {
|
||||
assert_eq!(parse_mac_address("12-34-AA-12-55-AA").unwrap(), ("", [18, 52, 170, 18, 85, 170]) );
|
||||
assert_eq!(
|
||||
parse_mac_address("12-34-AA-12-55-AA").unwrap(),
|
||||
("", [18, 52, 170, 18, 85, 170])
|
||||
);
|
||||
|
||||
dbg!(Epoch::now().unwrap().to_unix_seconds());
|
||||
|
||||
|
@ -40,3 +47,42 @@ fn test_packet() {
|
|||
|
||||
println!("{:#?}", parse_packet(inp));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hex_parsing() {
|
||||
let inp = r#"
|
||||
{"mac": "T1", "value": "123", "time": "665B514B"}
|
||||
"#
|
||||
.trim();
|
||||
|
||||
let sensor_value: SensorValue = serde_json::from_str(inp).unwrap();
|
||||
assert_eq!(
|
||||
sensor_value.time.unwrap().0.to_unix_seconds(),
|
||||
1717260619.0,
|
||||
"hex text"
|
||||
);
|
||||
|
||||
let inp = r#"
|
||||
{"mac": "T1", "value": "123", "time": 1717260619}
|
||||
"#
|
||||
.trim();
|
||||
|
||||
let sensor_value: SensorValue = serde_json::from_str(inp).unwrap();
|
||||
assert_eq!(
|
||||
sensor_value.time.unwrap().0.to_unix_seconds(),
|
||||
1717260619.0,
|
||||
"integer test"
|
||||
);
|
||||
|
||||
let inp = r#"
|
||||
{"mac": "T1", "value": "123", "time": 1717260619.0}
|
||||
"#
|
||||
.trim();
|
||||
|
||||
let sensor_value: SensorValue = serde_json::from_str(inp).unwrap();
|
||||
assert_eq!(
|
||||
sensor_value.time.unwrap().0.to_unix_seconds(),
|
||||
1717260619.0,
|
||||
"float test"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::fmt;
|
||||
use std::fmt::{Formatter, Write};
|
||||
use hifitime::Epoch;
|
||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::fmt;
|
||||
use std::fmt::{Formatter, Write};
|
||||
|
||||
#[derive(PartialOrd, PartialEq, Ord, Eq, Clone, Copy, Debug, Default)]
|
||||
#[repr(transparent)]
|
||||
|
@ -16,8 +16,8 @@ impl From<Epoch> for EpochUTC {
|
|||
|
||||
impl Serialize for EpochUTC {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_f64(self.0.to_unix_seconds())
|
||||
}
|
||||
|
@ -25,8 +25,8 @@ impl Serialize for EpochUTC {
|
|||
|
||||
impl<'de> Deserialize<'de> for EpochUTC {
|
||||
fn deserialize<D>(deserializer: D) -> Result<EpochUTC, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct EpochVisitor;
|
||||
|
||||
|
@ -34,28 +34,40 @@ impl<'de> Deserialize<'de> for EpochUTC {
|
|||
type Value = EpochUTC;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||
formatter.write_str("a string or a float")
|
||||
formatter.write_str(
|
||||
"a (string, representing a timestamp in decimal or hexadecimal form) or a decimal",
|
||||
DarkCat09 marked this conversation as resolved
Outdated
|
||||
)
|
||||
}
|
||||
|
||||
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,
|
||||
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
return Ok(Epoch::from_unix_seconds(
|
||||
value.parse().map_err(de::Error::custom)?
|
||||
).into())
|
||||
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<Self::Value, E>
|
||||
where
|
||||
DarkCat09 marked this conversation as resolved
Outdated
DarkCat09
commented
API народмона также разрешает отправлять юникс-время в 16-ричном виде. Предполагаю, растовый API народмона также разрешает отправлять юникс-время в 16-ричном виде. Предполагаю, растовый `parse()` по умолчанию парсит только decimal и выдаст ошибку на hex. Верно?
nm17
commented
Чаво? Это где написано? Впервые слышу. > API народмона также разрешает отправлять юникс-время в 16-ричном виде.
Чаво? Это где написано? Впервые слышу.
DarkCat09
commented
А вот) А вот)
nm17
commented
А, хорошо подметил. Тогда доделаю как смогу. А, хорошо подметил. Тогда доделаю как смогу.
DarkCat09
commented
Предполагаю, что пользуются этим не один-два человека, экономить трафик все хотят. Реализацию я вижу вида:
Честно не понимаю, как они это на своём сервере на баш-скриптах обрабатывают. Гениальный API. Предполагаю, что пользуются этим не один-два человека, экономить трафик все хотят. Реализацию я вижу вида:
1. попытаться распарсить 10-ричное число
2. получилось – проверить, не прошедший ли timestamp указан, и если да – проверить то же самое с 16-ричной конвертацией, скорее всего так получится правильное время
3. не получилось – парсим как hex
Честно не понимаю, как они это на своём сервере на баш-скриптах обрабатывают. Гениальный API.
DarkCat09
commented
[То же самое написал в тг-чате] Ещё можно, знаешь, смотреть по префиксу таймстемпа. Например, сейчас префикс 1717 в десятеричном и 0x665 в хексе. Через N секунд обновляем префиксы, если нужно. Когда приходит time от девайса, пробуем распарсить как десятиричное число, и если получается – то сравниваем по префиксам. Иначе пробуем парсить как хекс. [То же самое написал в тг-чате]
Ещё можно, знаешь, смотреть по префиксу таймстемпа.
Например, сейчас префикс 1717 в десятеричном и 0x665 в хексе.
1717228768
0x665ad4e0
Через N секунд обновляем префиксы, если нужно.
Когда приходит time от девайса, пробуем распарсить как десятиричное число, и если получается – то сравниваем по префиксам. Иначе пробуем парсить как хекс.
nm17
commented
Мне кажется легче всего отличить по длине строки. 8 символов => значит hex. Мне кажется легче всего отличить по длине строки. 8 символов => значит hex.
DarkCat09
commented
Но ведь когда-то будет не 8 символов, а больше) Но ведь когда-то будет не 8 символов, а больше)
Обновлять надо. Похоже на мой вариант с префиксами, кстати. Да, по длине проще.
nm17
commented
Это произойдёт 7 Февраля 2106г. в 06:28:15 UTC, так что сойдёт. > Но ведь когда-то будет не 8 символов, а больше)
Это произойдёт 7 Февраля 2106г. в 06:28:15 UTC, так что сойдёт.
nm17
commented
Заметка: байты эти в BE, а не LE Заметка: байты эти в BE, а не LE
|
||||
E: de::Error,
|
||||
{
|
||||
if value.len() == 8 {
|
||||
let bytes = hex::decode(value).map_err(de::Error::custom)?;
|
||||
|
||||
return Ok(Epoch::from_unix_seconds(u32::from_be_bytes(
|
||||
bytes.as_slice().try_into().unwrap(),
|
||||
) as f64)
|
||||
.into());
|
||||
}
|
||||
return Ok(
|
||||
Epoch::from_unix_seconds(value.parse().map_err(de::Error::custom)?).into(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
string representing a timestamp in a decimal or hex number
Не, совсем не звучит. "Строка, представляющая из себя таймстамп в цифре(?) или шестнадцатеричное число". Сейчас подправлю чтобы точно не было сомнений.