libsurfer/cxxrtl/
timestamp.rs1use std::str::FromStr;
2
3use eyre::{Context, Result};
4use num::BigUint;
5use serde::{Deserialize, Deserializer, Serialize};
6
7#[derive(Debug, Clone)]
8pub struct CxxrtlTimestamp {
9 seconds: BigUint,
10 femtoseconds: BigUint,
11}
12
13impl CxxrtlTimestamp {
14 #[must_use]
15 pub fn zero() -> Self {
16 Self {
17 seconds: BigUint::ZERO,
18 femtoseconds: BigUint::ZERO,
19 }
20 }
21
22 fn from_str(s: &str) -> Result<Self> {
23 let split = s.split('.').collect::<Vec<_>>();
24
25 Ok(CxxrtlTimestamp {
26 seconds: BigUint::from_str(split[0])
27 .with_context(|| format!("When parsing seconds from {s}"))?,
28 femtoseconds: BigUint::from_str(split[1])
29 .with_context(|| format!("When parsing femtoseconds from {s}"))?,
30 })
31 }
32
33 #[must_use]
34 pub fn from_femtoseconds(femto: BigUint) -> Self {
35 Self {
36 seconds: &femto / BigUint::from(1_000_000_000_000_000u64),
37 femtoseconds: &femto % BigUint::from(1_000_000_000_000_000u64),
38 }
39 }
40
41 #[must_use]
42 pub fn as_femtoseconds(&self) -> BigUint {
43 &self.seconds * BigUint::from(1_000_000_000_000_000u64) + &self.femtoseconds
44 }
45}
46
47impl<'de> Deserialize<'de> for CxxrtlTimestamp {
48 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
49 where
50 D: Deserializer<'de>,
51 {
52 let buf = String::deserialize(deserializer)?;
53
54 Self::from_str(&buf).map_err(serde::de::Error::custom)
55 }
56}
57
58impl Serialize for CxxrtlTimestamp {
59 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
60 where
61 S: serde::Serializer,
62 {
63 self.to_string().serialize(serializer)
64 }
65}
66
67impl std::fmt::Display for CxxrtlTimestamp {
68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69 write!(f, "{}.{:015}", self.seconds, self.femtoseconds)
70 }
71}