Skip to main content

libsurfer/cxxrtl/
timestamp.rs

1use 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}