taos_query/common/
precision.rs

1use std::{
2    fmt::{self, Display},
3    str::FromStr,
4};
5
6use serde::Deserialize;
7
8#[derive(Debug, thiserror::Error)]
9pub enum PrecisionError {
10    #[error("invalid precision repr: {0}")]
11    Invalid(String),
12}
13
14/// The precision of a timestamp or a database.
15#[repr(i32)]
16#[derive(Debug, Copy, Clone, PartialEq, Eq, serde_repr::Serialize_repr)]
17pub enum Precision {
18    Millisecond = 0,
19    Microsecond,
20    Nanosecond,
21}
22
23impl Default for Precision {
24    fn default() -> Self {
25        Self::Millisecond
26    }
27}
28
29impl PartialEq<str> for Precision {
30    fn eq(&self, other: &str) -> bool {
31        self.as_str() == other
32    }
33}
34
35impl PartialEq<&str> for Precision {
36    fn eq(&self, other: &&str) -> bool {
37        self.as_str() == *other
38    }
39}
40
41impl Precision {
42    pub const fn as_str(&self) -> &'static str {
43        use Precision::*;
44        match self {
45            Millisecond => "ms",
46            Microsecond => "us",
47            Nanosecond => "ns",
48        }
49    }
50
51    pub const fn as_u8(&self) -> u8 {
52        match self {
53            Self::Millisecond => 0,
54            Self::Microsecond => 1,
55            Self::Nanosecond => 2,
56        }
57    }
58    pub const fn from_u8(precision: u8) -> Self {
59        match precision {
60            0 => Self::Millisecond,
61            1 => Self::Microsecond,
62            2 => Self::Nanosecond,
63            _ => panic!("precision integer only allow 0/1/2"),
64        }
65    }
66
67    pub const fn to_seconds_format(self) -> chrono::SecondsFormat {
68        match self {
69            Precision::Millisecond => chrono::SecondsFormat::Millis,
70            Precision::Microsecond => chrono::SecondsFormat::Micros,
71            Precision::Nanosecond => chrono::SecondsFormat::Nanos,
72        }
73    }
74}
75
76macro_rules! _impl_from {
77    ($($ty:ty) *) => {
78        $(impl From<$ty> for Precision {
79            fn from(v: $ty) -> Self {
80                Self::from_u8(v as _)
81            }
82        })*
83    }
84}
85
86_impl_from!(i8 i16 i32 i64 isize u8 u16 u32 u64 usize);
87
88impl Display for Precision {
89    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90        write!(f, "{}", self.as_str())
91    }
92}
93
94impl FromStr for Precision {
95    type Err = PrecisionError;
96
97    fn from_str(s: &str) -> Result<Self, Self::Err> {
98        match s {
99            "ms" => Ok(Precision::Millisecond),
100            "us" => Ok(Precision::Microsecond),
101            "ns" => Ok(Precision::Nanosecond),
102            s => Err(PrecisionError::Invalid(s.to_string())),
103        }
104    }
105}
106
107impl<'de> Deserialize<'de> for Precision {
108    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
109    where
110        D: serde::Deserializer<'de>,
111    {
112        struct PrecisionVisitor;
113
114        impl<'de> serde::de::Visitor<'de> for PrecisionVisitor {
115            type Value = Precision;
116
117            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
118                formatter.write_str("expect integer 0/1/2 or string ms/us/ns")
119            }
120
121            fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
122            where
123                E: serde::de::Error,
124            {
125                self.visit_i32(v as _)
126            }
127            fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
128            where
129                E: serde::de::Error,
130            {
131                self.visit_i32(v as _)
132            }
133
134            fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
135            where
136                E: serde::de::Error,
137            {
138                Precision::try_from(v).map_err(<E as serde::de::Error>::custom)
139            }
140
141            fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
142            where
143                E: serde::de::Error,
144            {
145                self.visit_i32(v as _)
146            }
147
148            fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
149            where
150                E: serde::de::Error,
151            {
152                self.visit_i32(v as _)
153            }
154
155            fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
156            where
157                E: serde::de::Error,
158            {
159                self.visit_i32(v as _)
160            }
161
162            fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
163            where
164                E: serde::de::Error,
165            {
166                self.visit_i32(v as _)
167            }
168
169            fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
170            where
171                E: serde::de::Error,
172            {
173                self.visit_i32(v as _)
174            }
175
176            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
177            where
178                E: serde::de::Error,
179            {
180                Precision::from_str(v).map_err(<E as serde::de::Error>::custom)
181            }
182
183            fn visit_none<E>(self) -> Result<Self::Value, E>
184            where
185                E: serde::de::Error,
186            {
187                Ok(Precision::Millisecond)
188            }
189
190            fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
191            where
192                D: serde::Deserializer<'de>,
193            {
194                deserializer.deserialize_any(self)
195            }
196
197            fn visit_unit<E>(self) -> Result<Self::Value, E>
198            where
199                E: serde::de::Error,
200            {
201                Ok(Precision::Millisecond)
202            }
203        }
204
205        deserializer.deserialize_any(PrecisionVisitor)
206    }
207}
208
209#[cfg(test)]
210mod tests {
211    use serde::{
212        de::{
213            value::{I32Deserializer, StrDeserializer, UnitDeserializer},
214            IntoDeserializer,
215        },
216        Deserialize,
217    };
218
219    use super::Precision;
220
221    #[test]
222    fn de() {
223        type SD<'a> = StrDeserializer<'a, serde::de::value::Error>;
224        let precision = Precision::deserialize::<SD>("ms".into_deserializer()).unwrap();
225        assert_eq!(precision, Precision::Millisecond);
226        let precision = Precision::deserialize::<SD>("us".into_deserializer()).unwrap();
227        assert_eq!(precision, Precision::Microsecond);
228        let precision = Precision::deserialize::<SD>("ns".into_deserializer()).unwrap();
229        assert_eq!(precision, Precision::Nanosecond);
230
231        type I32D = I32Deserializer<serde::de::value::Error>;
232        let precision = Precision::deserialize::<I32D>(0.into_deserializer()).unwrap();
233        assert_eq!(precision, Precision::Millisecond);
234        let precision = Precision::deserialize::<I32D>(1.into_deserializer()).unwrap();
235        assert_eq!(precision, Precision::Microsecond);
236        let precision = Precision::deserialize::<I32D>(2.into_deserializer()).unwrap();
237        assert_eq!(precision, Precision::Nanosecond);
238
239        type UnitD = UnitDeserializer<serde::de::value::Error>;
240        let precision = Precision::deserialize::<UnitD>(().into_deserializer()).unwrap();
241        assert_eq!(precision, Precision::Millisecond);
242
243        let json = serde_json::to_string(&precision).unwrap();
244        assert_eq!(json, "0");
245    }
246}