transformable/impls/time/
system_time.rs1use std::time::{SystemTime, SystemTimeError, UNIX_EPOCH};
2
3use super::*;
4
5#[derive(Debug, Clone)]
7pub enum SystemTimeTransformError {
8 EncodeBufferTooSmall,
10 NotEnoughBytes,
12 InvalidSystemTime(SystemTimeError),
14}
15
16impl core::fmt::Display for SystemTimeTransformError {
17 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
18 match self {
19 Self::EncodeBufferTooSmall => write!(
20 f,
21 "buffer is too small, use `Transformable::encoded_len` to pre-allocate a buffer with enough space"
22 ),
23 Self::NotEnoughBytes => write!(f, "not enough bytes to decode system time"),
24 Self::InvalidSystemTime(e) => write!(f, "{e}"),
25 }
26 }
27}
28
29impl core::error::Error for SystemTimeTransformError {}
30
31impl Transformable for SystemTime {
32 type Error = SystemTimeTransformError;
33
34 fn encode(&self, dst: &mut [u8]) -> Result<usize, Self::Error> {
35 if dst.len() < self.encoded_len() {
36 return Err(Self::Error::EncodeBufferTooSmall);
37 }
38
39 let buf = encode_duration_unchecked(
40 self
41 .duration_since(UNIX_EPOCH)
42 .map_err(Self::Error::InvalidSystemTime)?,
43 );
44 dst[..ENCODED_LEN].copy_from_slice(&buf);
45 Ok(ENCODED_LEN)
46 }
47
48 #[cfg(feature = "std")]
49 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
50 fn encode_to_writer<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<usize> {
51 let mut buf = [0u8; ENCODED_LEN];
52 self
53 .encode(&mut buf)
54 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
55 writer.write_all(&buf).map(|_| ENCODED_LEN)
56 }
57
58 #[cfg(feature = "async")]
59 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
60 async fn encode_to_async_writer<W: futures_util::io::AsyncWrite + Send + Unpin>(
61 &self,
62 writer: &mut W,
63 ) -> std::io::Result<usize>
64 where
65 Self::Error: Send + Sync + 'static,
66 {
67 use futures_util::AsyncWriteExt;
68
69 let mut buf = [0u8; ENCODED_LEN];
70 self
71 .encode(&mut buf)
72 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
73 writer.write_all(&buf).await.map(|_| ENCODED_LEN)
74 }
75
76 fn encoded_len(&self) -> usize {
77 ENCODED_LEN
78 }
79
80 fn decode(src: &[u8]) -> Result<(usize, Self), Self::Error>
81 where
82 Self: Sized,
83 {
84 if src.len() < ENCODED_LEN {
85 return Err(Self::Error::NotEnoughBytes);
86 }
87
88 let (readed, dur) = decode_duration_unchecked(src);
89 Ok((readed, UNIX_EPOCH + dur))
90 }
91
92 #[cfg(feature = "std")]
93 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
94 fn decode_from_reader<R: std::io::Read>(reader: &mut R) -> std::io::Result<(usize, Self)>
95 where
96 Self: Sized,
97 {
98 let mut buf = [0; ENCODED_LEN];
99 reader.read_exact(&mut buf)?;
100 let (readed, dur) = decode_duration_unchecked(&buf);
101 Ok((readed, UNIX_EPOCH + dur))
102 }
103
104 #[cfg(feature = "async")]
105 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
106 async fn decode_from_async_reader<R: futures_util::io::AsyncRead + Send + Unpin>(
107 reader: &mut R,
108 ) -> std::io::Result<(usize, Self)>
109 where
110 Self: Sized,
111 Self::Error: Send + Sync + 'static,
112 {
113 use futures_util::AsyncReadExt;
114
115 let mut buf = [0; ENCODED_LEN];
116 reader.read_exact(&mut buf).await?;
117 let (readed, dur) = decode_duration_unchecked(&buf);
118 Ok((readed, UNIX_EPOCH + dur))
119 }
120}
121
122test_transformable!(SystemTime => test_systemtime_transformable({
123 let now = SystemTime::now();
124 std::thread::sleep(std::time::Duration::from_millis(10));
125 now
126}));