varing/chrono_tz/
v010.rs

1use chrono_tz_0_10::{Tz, TZ_VARIANTS};
2
3use crate::{
4  decode_i16_varint, encode_i16_varint_to, encoded_i16_varint_len, utils::Buffer, DecodeError,
5  EncodeError, Varint,
6};
7
8const TZ_VALUES: [i16; TZ_VARIANTS.len()] = const {
9  let mut values = [0; TZ_VARIANTS.len()];
10  let mut i = 0;
11  while i < TZ_VARIANTS.len() {
12    values[i] = TZ_VARIANTS[i] as i16;
13    i += 1;
14  }
15  values
16};
17
18/// Returns the length of the encoded timezone value.
19#[inline]
20pub const fn encoded_tz_len(tz: Tz) -> usize {
21  encoded_i16_varint_len(tz as i16)
22}
23
24/// Encodes the timezone value into the buffer.
25///
26/// Returns the number of bytes written to the buffer.
27#[inline]
28pub const fn encode_tz_to(tz: Tz, buf: &mut [u8]) -> Result<usize, EncodeError> {
29  encode_i16_varint_to(tz as i16, buf)
30}
31
32/// Encodes the timezone value into the buffer.
33#[inline]
34pub const fn encode_tz(tz: Tz) -> Buffer<{ Tz::MAX_ENCODED_LEN + 1 }> {
35  let mut buf = [0; Tz::MAX_ENCODED_LEN + 1];
36  let len = match encode_tz_to(tz, &mut buf) {
37    Ok(len) => len,
38    Err(_) => panic!("Timezone value is larger than buffer capacity, please report bug to https://github.com/al8n/varing/issues"),
39  };
40
41  buf[Tz::MAX_ENCODED_LEN] = len as u8;
42
43  Buffer::new(buf)
44}
45
46/// Decodes the timezone value from the buffer.
47///
48/// Returns the number of bytes read and the decoded timezone value.
49#[inline]
50pub const fn decode_tz(buf: &[u8]) -> Result<(usize, Tz), DecodeError> {
51  match decode_i16_varint(buf) {
52    Ok((len, tz)) => {
53      let mut i = 0;
54      let mut found = None;
55
56      while i < TZ_VALUES.len() {
57        if TZ_VALUES[i] == tz {
58          found = Some(TZ_VARIANTS[i]);
59          break;
60        }
61        i += 1;
62      }
63
64      if let Some(tz) = found {
65        Ok((len, tz))
66      } else {
67        Err(DecodeError::custom("Invalid timezone value"))
68      }
69    }
70    Err(err) => Err(err),
71  }
72}
73
74impl Varint for Tz {
75  const MIN_ENCODED_LEN: usize = i16::MIN_ENCODED_LEN;
76
77  const MAX_ENCODED_LEN: usize = encoded_i16_varint_len(TZ_VALUES.len() as i16);
78
79  #[inline]
80  fn encoded_len(&self) -> usize {
81    encoded_tz_len(*self)
82  }
83
84  #[inline]
85  fn encode(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
86    encode_tz_to(*self, buf)
87  }
88
89  #[inline]
90  fn decode(buf: &[u8]) -> Result<(usize, Self), DecodeError>
91  where
92    Self: Sized,
93  {
94    decode_tz(buf)
95  }
96}
97
98#[cfg(test)]
99mod tests {
100  use quickcheck::Arbitrary;
101
102  use super::{decode_tz, encode_tz, encoded_tz_len, Varint, TZ_VALUES, TZ_VARIANTS};
103
104  #[derive(Debug, Clone, Copy, PartialEq, Eq)]
105  struct Tz(super::Tz);
106
107  impl From<Tz> for super::Tz {
108    fn from(value: Tz) -> Self {
109      value.0
110    }
111  }
112
113  impl Arbitrary for Tz {
114    fn arbitrary(g: &mut quickcheck::Gen) -> Self {
115      let val = (u16::arbitrary(g) % super::TZ_VARIANTS.len() as u16) as i16;
116      let idx = TZ_VALUES.iter().position(|&v| v == val).unwrap();
117      Self(TZ_VARIANTS[idx])
118    }
119  }
120
121  fuzzy!(@varint_into (Tz(super::Tz)));
122  fuzzy!(@const_varint_into (Tz(super::Tz)));
123}