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