rtc_shared/serde.rs
1/// Serializes a `tokio::time::Instant` to an approximation of epoch time in the form
2/// of an `f64` where the integer portion is seconds and the decimal portion is milliseconds.
3/// For instance, `Monday, May 30, 2022 10:45:26.456 PM UTC` converts to `1653950726.456`.
4///
5/// Note that an `Instant` is not connected to real world time, so this conversion is
6/// approximate.
7pub mod instant_to_epoch {
8 use serde::{Deserialize, Deserializer, Serialize, Serializer};
9 use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
10
11 /// Serializes an [`Instant`] as a duration relative to the process's reference instant.
12 ///
13 /// [`Instant`] has no absolute representation, so this encodes the offset instead. Use
14 /// with `#[serde(with = "...")]`.
15 ///
16 /// # Errors
17 ///
18 /// Propagates any failure from the underlying serializer.
19 pub fn serialize<S>(instant: &Instant, serializer: S) -> Result<S::Ok, S::Error>
20 where
21 S: Serializer,
22 {
23 let system_now = SystemTime::now();
24 let instant_now = Instant::now();
25 let approx = system_now - (instant_now - *instant);
26 let epoch = approx
27 .duration_since(UNIX_EPOCH)
28 .expect("Time went backwards");
29
30 let epoch_s = epoch.as_millis() as f64 / 1000.0;
31
32 epoch_s.serialize(serializer)
33 }
34
35 /// Deserializes an [`Instant`] from the relative offset written by [`serialize`].
36 ///
37 /// # Errors
38 ///
39 /// Propagates any failure from the underlying deserializer.
40 pub fn deserialize<'de, D>(deserializer: D) -> Result<Instant, D::Error>
41 where
42 D: Deserializer<'de>,
43 {
44 let epoch_s = f64::deserialize(deserializer)?;
45 let epoch_duration = Duration::from_secs_f64(epoch_s);
46
47 let system_now = SystemTime::now();
48 let instant_now = Instant::now();
49
50 let duration_since_approx = system_now
51 .duration_since(UNIX_EPOCH + epoch_duration)
52 .expect("Time went backwards");
53 let instant = instant_now - duration_since_approx;
54
55 Ok(instant)
56 }
57}