transformable/impls/
time.rs1use core::{mem, time::Duration};
2
3use super::Transformable;
4
5const ENCODED_LEN: usize = mem::size_of::<u64>() + mem::size_of::<u32>();
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9pub enum DurationTransformError {
10 EncodeBufferTooSmall,
12 NotEnoughBytes,
14}
15
16impl core::fmt::Display for DurationTransformError {
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"),
24 }
25 }
26}
27
28impl core::error::Error for DurationTransformError {}
29
30impl Transformable for Duration {
31 type Error = DurationTransformError;
32
33 fn encode(&self, dst: &mut [u8]) -> Result<usize, Self::Error> {
34 if dst.len() < self.encoded_len() {
35 return Err(Self::Error::EncodeBufferTooSmall);
36 }
37
38 let buf = encode_duration_unchecked(*self);
39 dst[..ENCODED_LEN].copy_from_slice(&buf);
40 Ok(ENCODED_LEN)
41 }
42
43 #[cfg(feature = "std")]
44 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
45 fn encode_to_writer<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<usize> {
46 let buf = encode_duration_unchecked(*self);
47 let len = buf.len();
48 writer.write_all(&buf).map(|_| len)
49 }
50
51 #[cfg(feature = "async")]
52 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
53 async fn encode_to_async_writer<W: futures_util::io::AsyncWrite + Send + Unpin>(
54 &self,
55 writer: &mut W,
56 ) -> std::io::Result<usize>
57 where
58 Self::Error: Send + Sync + 'static,
59 {
60 use futures_util::io::AsyncWriteExt;
61
62 let buf = encode_duration_unchecked(*self);
63 let len = buf.len();
64 writer.write_all(&buf).await.map(|_| len)
65 }
66
67 fn encoded_len(&self) -> usize {
68 ENCODED_LEN
69 }
70
71 fn decode(src: &[u8]) -> Result<(usize, Self), Self::Error>
72 where
73 Self: Sized,
74 {
75 if src.len() < ENCODED_LEN {
76 return Err(Self::Error::NotEnoughBytes);
77 }
78
79 Ok(decode_duration_unchecked(src))
80 }
81
82 #[cfg(feature = "std")]
83 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
84 fn decode_from_reader<R: std::io::Read>(reader: &mut R) -> std::io::Result<(usize, Self)>
85 where
86 Self: Sized,
87 {
88 let mut buf = [0; ENCODED_LEN];
89 reader.read_exact(&mut buf)?;
90 Ok(decode_duration_unchecked(&buf))
91 }
92
93 #[cfg(feature = "async")]
94 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
95 async fn decode_from_async_reader<R: futures_util::io::AsyncRead + Send + Unpin>(
96 reader: &mut R,
97 ) -> std::io::Result<(usize, Self)>
98 where
99 Self: Sized,
100 Self::Error: Send + Sync + 'static,
101 {
102 use futures_util::AsyncReadExt;
103
104 let mut buf = [0; ENCODED_LEN];
105 reader.read_exact(&mut buf).await?;
106 Ok(decode_duration_unchecked(&buf))
107 }
108}
109
110#[inline]
111const fn encode_duration_unchecked(dur: Duration) -> [u8; ENCODED_LEN] {
112 let secs = dur.as_secs().to_be_bytes();
113 let nanos = dur.subsec_nanos().to_be_bytes();
114 [
115 secs[0], secs[1], secs[2], secs[3], secs[4], secs[5], secs[6], secs[7], nanos[0], nanos[1],
116 nanos[2], nanos[3],
117 ]
118}
119
120#[inline]
121const fn decode_duration_unchecked(src: &[u8]) -> (usize, Duration) {
122 let secs = u64::from_be_bytes([
123 src[0], src[1], src[2], src[3], src[4], src[5], src[6], src[7],
124 ]);
125 let nanos = u32::from_be_bytes([src[8], src[9], src[10], src[11]]);
126 (ENCODED_LEN, Duration::new(secs, nanos))
127}
128
129#[cfg(feature = "std")]
130#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
131pub use system_time::*;
132#[cfg(feature = "std")]
133mod system_time;
134
135#[cfg(feature = "std")]
136#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
137pub use instant::*;
138#[cfg(feature = "std")]
139mod instant;
140
141test_transformable!(Duration => test_duration_transformable(Duration::new(10, 1080)));