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 pub fn checked_add(self, rhs: Self) -> Option<Self> {
21 self.0.checked_add(rhs.0).map(TimeInNs)
22 }
23
24 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}