const_varint/
duration.rs

1use super::{
2  decode_u128_varint, encode_u128_varint, encode_u128_varint_to, encoded_u128_varint_len,
3  DecodeError, EncodeError, U128VarintBuffer, Varint,
4};
5
6use core::time::Duration;
7
8/// A buffer for storing LEB128 encoded [`Duration`] value.
9pub type DurationBuffer = U128VarintBuffer;
10
11/// Returns the encoded length of the value in LEB128 variable length format.
12/// The returned value will be in range [`Duration::ENCODED_LEN_RANGE`].
13#[inline]
14pub const fn encoded_duration_len(duration: &Duration) -> usize {
15  // Use lower 96 bits: 64 for seconds, 32 for nanos
16  let value = ((duration.as_secs() as u128) << 32) | (duration.subsec_nanos() as u128);
17  encoded_u128_varint_len(value)
18}
19
20/// Encodes a `Duration` value into LEB128 variable length format, and writes it to the buffer.
21#[inline]
22pub const fn encode_duration(duration: &Duration) -> DurationBuffer {
23  // Use lower 96 bits: 64 for seconds, 32 for nanos
24  let value = ((duration.as_secs() as u128) << 32) | (duration.subsec_nanos() as u128);
25  encode_u128_varint(value)
26}
27
28/// Encodes a `Duration` value into LEB128 variable length format, and writes it to the buffer.
29#[inline]
30pub const fn encode_duration_to(duration: &Duration, buf: &mut [u8]) -> Result<usize, EncodeError> {
31  // Use lower 96 bits: 64 for seconds, 32 for nanos
32  let value = ((duration.as_secs() as u128) << 32) | (duration.subsec_nanos() as u128);
33  encode_u128_varint_to(value, buf)
34}
35
36/// Decodes a `Duration` in LEB128 encoded format from the buffer.
37///
38/// Returns the bytes readed and the decoded value if successful.
39#[inline]
40pub const fn decode_duration(buf: &[u8]) -> Result<(usize, Duration), DecodeError> {
41  match decode_u128_varint(buf) {
42    Ok((bytes_read, value)) => {
43      let secs = (value >> 32) as u64; // get upper 64 bits
44      let nanos = (value & 0xFFFFFFFF) as u32; // get lower 32 bits
45      Ok((bytes_read, Duration::new(secs, nanos)))
46    }
47    Err(e) => Err(e),
48  }
49}
50
51impl Varint for Duration {
52  const MIN_ENCODED_LEN: usize = u128::MIN_ENCODED_LEN;
53  const MAX_ENCODED_LEN: usize = u128::MAX_ENCODED_LEN;
54
55  #[inline]
56  fn encoded_len(&self) -> usize {
57    encoded_duration_len(self)
58  }
59
60  #[inline]
61  fn encode(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
62    encode_duration_to(self, buf)
63  }
64
65  #[inline]
66  fn decode(buf: &[u8]) -> Result<(usize, Self), DecodeError>
67  where
68    Self: Sized,
69  {
70    decode_duration(buf)
71  }
72}
73
74#[cfg(test)]
75mod tests {
76  use super::*;
77
78  use quickcheck_macros::quickcheck;
79
80  #[quickcheck]
81  fn encode_decode_duration(value: Duration) -> bool {
82    let encoded = encode_duration(&value);
83    if encoded.len() != encoded_duration_len(&value)
84      || (encoded.len() > <Duration>::MAX_ENCODED_LEN)
85    {
86      return false;
87    }
88
89    if let Ok((bytes_read, decoded)) = decode_duration(&encoded) {
90      value == decoded && encoded.len() == bytes_read
91    } else {
92      false
93    }
94  }
95
96  #[quickcheck]
97  fn encode_decode_duration_varint(value: Duration) -> bool {
98    let mut buf = [0; <Duration>::MAX_ENCODED_LEN];
99    let Ok(encoded_len) = value.encode(&mut buf) else {
100      return false;
101    };
102    if encoded_len != value.encoded_len() || (value.encoded_len() > <Duration>::MAX_ENCODED_LEN) {
103      return false;
104    }
105
106    if let Ok((bytes_read, decoded)) = <Duration>::decode(&buf) {
107      value == decoded && encoded_len == bytes_read
108    } else {
109      false
110    }
111  }
112}