ssh_key/certificate/
unix_time.rs1use crate::{Error, Result};
4use core::fmt;
5use core::fmt::Formatter;
6use encoding::{Decode, Encode, Reader, Writer};
7
8#[cfg(feature = "std")]
9use std::time::{Duration, SystemTime, UNIX_EPOCH};
10
11pub const MAX_SECS: u64 = i64::MAX as u64;
13
14#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)]
16pub(super) struct UnixTime {
17 secs: u64,
19
20 #[cfg(feature = "std")]
22 time: SystemTime,
23}
24
25impl UnixTime {
26 #[cfg(not(feature = "std"))]
31 pub fn new(secs: u64) -> Result<Self> {
32 if secs <= MAX_SECS {
33 Ok(Self { secs })
34 } else {
35 Err(Error::Time)
36 }
37 }
38
39 #[cfg(feature = "std")]
45 pub fn new(secs: u64) -> Result<Self> {
46 if secs > MAX_SECS {
47 return Err(Error::Time);
48 }
49
50 match UNIX_EPOCH.checked_add(Duration::from_secs(secs)) {
51 Some(time) => Ok(Self { secs, time }),
52 None => Err(Error::Time),
53 }
54 }
55
56 #[cfg(feature = "std")]
58 pub fn now() -> Result<Self> {
59 SystemTime::now().try_into()
60 }
61}
62
63impl Decode for UnixTime {
64 type Error = Error;
65
66 fn decode(reader: &mut impl Reader) -> Result<Self> {
67 u64::decode(reader)?.try_into()
68 }
69}
70
71impl Encode for UnixTime {
72 fn encoded_len(&self) -> encoding::Result<usize> {
73 self.secs.encoded_len()
74 }
75
76 fn encode(&self, writer: &mut impl Writer) -> encoding::Result<()> {
77 self.secs.encode(writer)?;
78 Ok(())
79 }
80}
81
82impl From<UnixTime> for u64 {
83 fn from(unix_time: UnixTime) -> u64 {
84 unix_time.secs
85 }
86}
87
88#[cfg(feature = "std")]
89impl From<UnixTime> for SystemTime {
90 fn from(unix_time: UnixTime) -> SystemTime {
91 unix_time.time
92 }
93}
94
95impl TryFrom<u64> for UnixTime {
96 type Error = Error;
97
98 fn try_from(unix_secs: u64) -> Result<UnixTime> {
99 Self::new(unix_secs)
100 }
101}
102
103#[cfg(feature = "std")]
104impl TryFrom<SystemTime> for UnixTime {
105 type Error = Error;
106
107 fn try_from(time: SystemTime) -> Result<UnixTime> {
108 Self::new(time.duration_since(UNIX_EPOCH)?.as_secs())
109 }
110}
111
112impl fmt::Debug for UnixTime {
113 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
114 write!(f, "{}", self.secs)
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::{UnixTime, MAX_SECS};
121 use crate::Error;
122
123 #[test]
124 fn new_with_max_secs() {
125 assert!(UnixTime::new(MAX_SECS).is_ok());
126 }
127
128 #[test]
129 fn new_over_max_secs_returns_error() {
130 assert_eq!(UnixTime::new(MAX_SECS + 1), Err(Error::Time));
131 }
132}