ex3_timestamp/
lib.rs

1use std::fmt::Display;
2use std::ops::{Add, Sub};
3
4#[cfg(feature = "canister")]
5use candid::CandidType;
6use ic_stable_structures::storable::Bound;
7use ic_stable_structures::Storable;
8use serde::{Deserialize, Serialize};
9
10#[derive(
11    Default, Serialize, Clone, Debug, Deserialize, Copy, Ord, PartialOrd, PartialEq, Eq, Hash,
12)]
13#[cfg_attr(feature = "canister", derive(CandidType))]
14#[serde(transparent)]
15pub struct TimeInNs(pub u64);
16
17impl TimeInNs {
18    /// Checked add
19    /// return None if overflow
20    pub fn checked_add(self, rhs: Self) -> Option<Self> {
21        self.0.checked_add(rhs.0).map(TimeInNs)
22    }
23
24    /// Checked sub
25    /// return None if overflow
26    pub fn checked_sub(self, rhs: Self) -> Option<Self> {
27        self.0.checked_sub(rhs.0).map(TimeInNs)
28    }
29}
30
31impl Add for TimeInNs {
32    type Output = TimeInNs;
33
34    fn add(self, rhs: Self) -> Self::Output {
35        TimeInNs(self.0 + rhs.0)
36    }
37}
38
39impl Sub for TimeInNs {
40    type Output = TimeInNs;
41
42    fn sub(self, rhs: Self) -> Self::Output {
43        TimeInNs(self.0 - rhs.0)
44    }
45}
46
47impl Display for TimeInNs {
48    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49        write!(f, "{} ns", self.0)
50    }
51}
52
53#[derive(Serialize, Clone, Debug, Deserialize, Copy, Ord, PartialOrd, PartialEq, Eq, Hash)]
54#[cfg_attr(feature = "canister", derive(CandidType))]
55#[serde(transparent)]
56pub struct TimeInSec(pub u64);
57
58impl From<TimeInNs> for TimeInSec {
59    fn from(ns: TimeInNs) -> Self {
60        TimeInSec(ns.0 / 1_000_000_000)
61    }
62}
63
64impl From<TimeInSec> for TimeInNs {
65    fn from(sec: TimeInSec) -> Self {
66        TimeInNs(sec.0.checked_mul(1_000_000_000).expect("overflow"))
67    }
68}
69
70impl Display for TimeInSec {
71    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72        write!(f, "{} s", self.0)
73    }
74}
75
76impl Storable for TimeInNs {
77    fn to_bytes(&self) -> std::borrow::Cow<[u8]> {
78        self.0.to_le_bytes().to_vec().into()
79    }
80
81    fn from_bytes(bytes: std::borrow::Cow<[u8]>) -> Self {
82        TimeInNs(u64::from_le_bytes(
83            bytes
84                .as_ref()
85                .try_into()
86                .expect("TimeInNs should have 8 bytes"),
87        ))
88    }
89
90    const BOUND: Bound = Bound::Bounded {
91        max_size: 8,
92        is_fixed_size: true,
93    };
94}
95
96impl Storable for TimeInSec {
97    fn to_bytes(&self) -> std::borrow::Cow<[u8]> {
98        self.0.to_le_bytes().to_vec().into()
99    }
100
101    fn from_bytes(bytes: std::borrow::Cow<[u8]>) -> Self {
102        TimeInSec(u64::from_le_bytes(
103            bytes
104                .as_ref()
105                .try_into()
106                .expect("TimeInSec should have 8 bytes"),
107        ))
108    }
109
110    const BOUND: Bound = Bound::Bounded {
111        max_size: 8,
112        is_fixed_size: true,
113    };
114}