1use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
14#[serde(transparent)]
15pub struct Timestamp(u64);
16
17impl Timestamp {
18 #[must_use]
20 pub const fn from_unix_ms(ms: u64) -> Self {
21 Self(ms)
22 }
23
24 #[must_use]
26 pub const fn as_unix_ms(self) -> u64 {
27 self.0
28 }
29
30 #[must_use]
32 pub const fn plus_ms(self, ms: u64) -> Self {
33 Self(self.0.saturating_add(ms))
34 }
35}
36
37#[cfg(test)]
38mod tests {
39 use super::*;
40
41 #[test]
42 fn ordering_is_chronological() {
43 let earlier = Timestamp::from_unix_ms(1_000);
44 let later = Timestamp::from_unix_ms(2_000);
45 assert!(earlier < later);
46 assert_eq!(earlier.plus_ms(1_000), later);
47 }
48
49 #[test]
50 fn plus_saturates_instead_of_wrapping() {
51 let max = Timestamp::from_unix_ms(u64::MAX);
52 assert_eq!(max.plus_ms(5), max);
53 }
54
55 #[test]
56 fn serde_is_transparent() {
57 let ts = Timestamp::from_unix_ms(42);
58 let json = serde_json::to_string(&ts).unwrap();
59 assert_eq!(json, "42");
60 let back: Timestamp = serde_json::from_str(&json).unwrap();
61 assert_eq!(back, ts);
62 }
63}