1use std::{
2 fmt::{self, Display},
3 str::FromStr,
4};
5
6use serde::de::Visitor;
7
8#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, serde_repr::Serialize_repr)]
35#[repr(u8)]
36#[non_exhaustive]
37#[derive(Default)]
38pub enum Ty {
39 #[doc(hidden)]
43 #[default]
44 Null = 0,
45 Bool = 1,
47 TinyInt = 2,
49 SmallInt = 3,
51 Int = 4,
53 BigInt = 5, UTinyInt = 11, USmallInt = 12, UInt = 13, UBigInt = 14, Float = 6, Double = 7, Timestamp = 9, VarChar = 8,
73 NChar = 10, Json = 15, VarBinary = 16, #[doc(hidden)]
82 Decimal, #[doc(hidden)]
85 Blob, #[doc(hidden)]
88 MediumBlob, Geometry, }
93
94impl<'de> serde::Deserialize<'de> for Ty {
95 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
96 where
97 D: serde::Deserializer<'de>,
98 {
99 struct TyVisitor;
100
101 impl<'de> Visitor<'de> for TyVisitor {
102 type Value = Ty;
103
104 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
105 formatter.write_str("invalid TDengine type")
106 }
107 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
108 where
109 E: serde::de::Error,
110 {
111 Ok(Ty::from_u8(v as u8))
112 }
113
114 fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
115 where
116 E: serde::de::Error,
117 {
118 Ok(Ty::from_u8(v))
119 }
120
121 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
122 where
123 E: serde::de::Error,
124 {
125 Ok(Ty::from_u8(v as u8))
126 }
127
128 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
129 where
130 E: serde::de::Error,
131 {
132 Ty::from_str(v).map_err(<E as serde::de::Error>::custom)
133 }
134
135 fn visit_none<E>(self) -> Result<Self::Value, E>
136 where
137 E: serde::de::Error,
138 {
139 Ok(Ty::Null)
140 }
141
142 fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
143 where
144 D: serde::Deserializer<'de>,
145 {
146 deserializer.deserialize_any(self)
147 }
148
149 fn visit_unit<E>(self) -> Result<Self::Value, E>
150 where
151 E: serde::de::Error,
152 {
153 Ok(Ty::Null)
154 }
155 }
156
157 deserializer.deserialize_any(TyVisitor)
158 }
159}
160
161impl FromStr for Ty {
162 type Err = &'static str;
163 fn from_str(s: &str) -> Result<Self, Self::Err> {
164 match s.to_lowercase().as_str() {
165 "timestamp" => Ok(Ty::Timestamp),
166 "bool" => Ok(Ty::Bool),
167 "tinyint" => Ok(Ty::TinyInt),
168 "smallint" => Ok(Ty::SmallInt),
169 "int" => Ok(Ty::Int),
170 "bigint" => Ok(Ty::BigInt),
171 "tinyint unsigned" => Ok(Ty::UTinyInt),
172 "smallint unsigned" => Ok(Ty::USmallInt),
173 "int unsigned" => Ok(Ty::UInt),
174 "bigint unsigned" => Ok(Ty::UBigInt),
175 "float" => Ok(Ty::Float),
176 "double" => Ok(Ty::Double),
177 "binary" | "varchar" => Ok(Ty::VarChar),
178 "nchar" => Ok(Ty::NChar),
179 "json" => Ok(Ty::Json),
180 "varbinary" => Ok(Ty::VarBinary),
181 "decimal" => Ok(Ty::Decimal),
182 "blob" => Ok(Ty::Blob),
183 "mediumblob" => Ok(Ty::MediumBlob),
184 "geometry" => Ok(Ty::Geometry),
185 _ => Err("not a valid data type string"),
186 }
187 }
188}
189
190impl Ty {
191 pub const fn is_null(&self) -> bool {
193 matches!(self, Ty::Null)
194 }
195
196 pub const fn is_var_type(&self) -> bool {
198 use Ty::*;
199 matches!(self, VarChar | VarBinary | NChar | Geometry)
200 }
201
202 pub const fn is_json(&self) -> bool {
209 matches!(self, Ty::Json)
210 }
211
212 pub const fn is_primitive(&self) -> bool {
214 use Ty::*;
215 matches!(
216 self,
217 Bool | TinyInt
218 | SmallInt
219 | Int
220 | BigInt
221 | UTinyInt
222 | USmallInt
223 | UInt
224 | UBigInt
225 | Float
226 | Double
227 | Timestamp
228 | Decimal
229 )
230 }
231
232 pub const fn fixed_length(&self) -> usize {
234 use Ty::*;
235 match self {
236 Bool => 1,
237 TinyInt => 1,
238 SmallInt => 2,
239 Int => 4,
240 BigInt => 8,
241 Float => 4,
242 Double => 8,
243 Timestamp => 8,
244 UTinyInt => 1,
245 USmallInt => 2,
246 UInt => 4,
247 UBigInt => 8,
248 Decimal => 16,
249 _ => 0,
250 }
251 }
252
253 pub const fn name(&self) -> &'static str {
255 use Ty::*;
256 match self {
257 Null => "NULL",
258 Bool => "BOOL",
259 TinyInt => "TINYINT",
260 SmallInt => "SMALLINT",
261 Int => "INT",
262 BigInt => "BIGINT",
263 Float => "FLOAT",
264 Double => "DOUBLE",
265 VarChar => "BINARY",
266 Timestamp => "TIMESTAMP",
267 NChar => "NCHAR",
268 UTinyInt => "TINYINT UNSIGNED",
269 USmallInt => "SMALLINT UNSIGNED",
270 UInt => "INT UNSIGNED",
271 UBigInt => "BIGINT UNSIGNED",
272 Json => "JSON",
273 VarBinary => "VARBINARY",
274 Decimal => "DECIMAL",
275 Blob => "BLOB",
276 MediumBlob => "MEDIUMBLOB",
277 Geometry => "GEOMETRY",
278 }
279 }
280
281 pub const fn lowercase_name(&self) -> &'static str {
282 use Ty::*;
283 match self {
284 Null => "null",
285 Bool => "bool",
286 TinyInt => "tinyint",
287 SmallInt => "smallint",
288 Int => "int",
289 BigInt => "bigint",
290 Float => "float",
291 Double => "double",
292 VarChar => "binary",
293 Timestamp => "timestamp",
294 NChar => "nchar",
295 UTinyInt => "tinyint unsigned",
296 USmallInt => "smallint unsigned",
297 UInt => "int unsigned",
298 UBigInt => "bigint unsigned",
299 Json => "json",
300 VarBinary => "varbinary",
301 Decimal => "decimal",
302 Blob => "blob",
303 MediumBlob => "mediumblob",
304 Geometry => "geometry",
305 }
306 }
307
308 #[inline]
310 pub(crate) const fn as_variant_str(&self) -> &'static str {
311 use Ty::*;
312 macro_rules! _var_str {
313 ($($v:ident) *) => {
314 match self {
315 $($v => stringify!($v),) *
316 }
317 }
318 }
319 _var_str!(
320 Null Bool TinyInt SmallInt Int BigInt UTinyInt USmallInt UInt UBigInt
321 Float Double VarChar NChar Timestamp Json VarBinary Decimal Blob MediumBlob Geometry
322 )
323 }
324
325 #[inline]
326 const fn from_u8(v: u8) -> Self {
327 use Ty::*;
328 match v {
329 0 => Null,
330 1 => Bool,
331 2 => TinyInt,
332 3 => SmallInt,
333 4 => Int,
334 5 => BigInt,
335 6 => Float,
336 7 => Double,
337 8 => VarChar,
338 9 => Timestamp,
339 10 => NChar,
340 11 => UTinyInt,
341 12 => USmallInt,
342 13 => UInt,
343 14 => UBigInt,
344 15 => Json,
345 16 => VarBinary,
346 17 => Decimal,
347 18 => Blob,
348 19 => MediumBlob,
349 20 => Geometry,
350 _ => panic!("unknown data type"),
351 }
352 }
353}
354impl From<u8> for Ty {
355 #[inline]
356 fn from(v: u8) -> Self {
357 unsafe { std::mem::transmute(v) }
358 }
359}
360
361impl Display for Ty {
362 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
363 write!(f, "{}", self.name())
364 }
365}
366macro_rules! _impl_from_primitive {
367 ($($ty:ty) *) => {
368 $(
369 impl From<$ty> for Ty {
370 #[inline]
371 fn from(v: $ty) -> Self {
372 Self::from_u8(v as _)
373 }
374 }
375 )*
376 }
377}
378
379_impl_from_primitive!(i8 i16 i32 i64 u16 u32 u64);