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#[inline]
20pub const fn encoded_tz_len(tz: Tz) -> usize {
21 encoded_i16_varint_len(tz as i16)
22}
23
24#[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#[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#[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}