transformable/impls/time/
system_time.rs

1use std::time::{SystemTime, SystemTimeError, UNIX_EPOCH};
2
3use super::*;
4
5/// Error returned by [`SystemTime`] when transforming.
6#[derive(Debug, Clone)]
7pub enum SystemTimeTransformError {
8  /// The buffer is too small to encode the value.
9  EncodeBufferTooSmall,
10  /// NotEnoughBytes binary data.
11  NotEnoughBytes,
12  /// Invalid system time.
13  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}));