1use std::{
5 fmt::{Display, Formatter},
6 str::FromStr,
7};
8
9use serde::{Deserialize, Serialize};
10
11mod get;
12mod promote;
13
14pub use get::GetType;
15
16use crate::Value;
17
18#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
20pub enum Type {
21 Boolean,
23 Float4,
25 Float8,
27 Int1,
29 Int2,
31 Int4,
33 Int8,
35 Int16,
37 Utf8,
39 Uint1,
41 Uint2,
43 Uint4,
45 Uint8,
47 Uint16,
49 Date,
51 DateTime,
53 Time,
55 Duration,
57 IdentityId,
59 Uuid4,
61 Uuid7,
63 Blob,
65 Int,
67 Uint,
69 Decimal,
71 Undefined,
73 Any,
75}
76
77impl Type {
78 pub fn is_number(&self) -> bool {
79 matches!(
80 self,
81 Type::Float4
82 | Type::Float8 | Type::Int1 | Type::Int2
83 | Type::Int4 | Type::Int8 | Type::Int16
84 | Type::Uint1 | Type::Uint2 | Type::Uint4
85 | Type::Uint8 | Type::Uint16 | Type::Int
86 | Type::Uint | Type::Decimal
87 )
88 }
89
90 pub fn is_bool(&self) -> bool {
91 matches!(self, Type::Boolean)
92 }
93
94 pub fn is_signed_integer(&self) -> bool {
95 matches!(self, Type::Int1 | Type::Int2 | Type::Int4 | Type::Int8 | Type::Int16 | Type::Int)
96 }
97
98 pub fn is_unsigned_integer(&self) -> bool {
99 matches!(self, Type::Uint1 | Type::Uint2 | Type::Uint4 | Type::Uint8 | Type::Uint16 | Type::Uint)
100 }
101
102 pub fn is_integer(&self) -> bool {
103 self.is_signed_integer() || self.is_unsigned_integer()
104 }
105
106 pub fn is_floating_point(&self) -> bool {
107 matches!(self, Type::Float4 | Type::Float8)
108 }
109
110 pub fn is_utf8(&self) -> bool {
111 matches!(self, Type::Utf8)
112 }
113
114 pub fn is_temporal(&self) -> bool {
115 matches!(self, Type::Date | Type::DateTime | Type::Time | Type::Duration)
116 }
117
118 pub fn is_uuid(&self) -> bool {
119 matches!(self, Type::Uuid4 | Type::Uuid7)
120 }
121
122 pub fn is_blob(&self) -> bool {
123 matches!(self, Type::Blob)
124 }
125}
126
127impl Type {
128 pub fn to_u8(&self) -> u8 {
129 match self {
130 Type::Undefined => 0,
131 Type::Float4 => 1,
132 Type::Float8 => 2,
133 Type::Int1 => 3,
134 Type::Int2 => 4,
135 Type::Int4 => 5,
136 Type::Int8 => 6,
137 Type::Int16 => 7,
138 Type::Utf8 => 8,
139 Type::Uint1 => 9,
140 Type::Uint2 => 10,
141 Type::Uint4 => 11,
142 Type::Uint8 => 12,
143 Type::Uint16 => 13,
144 Type::Boolean => 14,
145 Type::Date => 15,
146 Type::DateTime => 16,
147 Type::Time => 17,
148 Type::Duration => 18,
149 Type::IdentityId => 19,
150 Type::Uuid4 => 20,
151 Type::Uuid7 => 21,
152 Type::Blob => 22,
153 Type::Int => 23,
154 Type::Decimal {
155 ..
156 } => 24,
157 Type::Uint => 25,
158 Type::Any => 26,
159 }
160 }
161}
162
163impl Type {
164 pub fn from_u8(value: u8) -> Self {
165 match value {
166 0 => Type::Undefined,
167 1 => Type::Float4,
168 2 => Type::Float8,
169 3 => Type::Int1,
170 4 => Type::Int2,
171 5 => Type::Int4,
172 6 => Type::Int8,
173 7 => Type::Int16,
174 8 => Type::Utf8,
175 9 => Type::Uint1,
176 10 => Type::Uint2,
177 11 => Type::Uint4,
178 12 => Type::Uint8,
179 13 => Type::Uint16,
180 14 => Type::Boolean,
181 15 => Type::Date,
182 16 => Type::DateTime,
183 17 => Type::Time,
184 18 => Type::Duration,
185 19 => Type::IdentityId,
186 20 => Type::Uuid4,
187 21 => Type::Uuid7,
188 22 => Type::Blob,
189 23 => Type::Int,
190 24 => Type::Decimal,
191 25 => Type::Uint,
192 26 => Type::Any,
193 _ => unreachable!(),
194 }
195 }
196}
197
198impl Type {
199 pub fn size(&self) -> usize {
200 match self {
201 Type::Boolean => 1,
202 Type::Float4 => 4,
203 Type::Float8 => 8,
204 Type::Int1 => 1,
205 Type::Int2 => 2,
206 Type::Int4 => 4,
207 Type::Int8 => 8,
208 Type::Int16 => 16,
209 Type::Utf8 => 8, Type::Uint1 => 1,
211 Type::Uint2 => 2,
212 Type::Uint4 => 4,
213 Type::Uint8 => 8,
214 Type::Uint16 => 16,
215 Type::Date => 4,
216 Type::DateTime => 12, Type::Time => 8,
218 Type::Duration => 16, Type::IdentityId => 16, Type::Uuid4 => 16,
222 Type::Uuid7 => 16,
223 Type::Blob => 8, Type::Int => 16, Type::Uint => 16, Type::Decimal {
229 ..
230 } => 16, Type::Undefined => 0,
233 Type::Any => 8, }
235 }
236
237 pub fn alignment(&self) -> usize {
238 match self {
239 Type::Boolean => 1,
240 Type::Float4 => 4,
241 Type::Float8 => 8,
242 Type::Int1 => 1,
243 Type::Int2 => 2,
244 Type::Int4 => 4,
245 Type::Int8 => 8,
246 Type::Int16 => 16,
247 Type::Utf8 => 4, Type::Uint1 => 1,
249 Type::Uint2 => 2,
250 Type::Uint4 => 4,
251 Type::Uint8 => 8,
252 Type::Uint16 => 16,
253 Type::Date => 4,
254 Type::DateTime => 8,
255 Type::Time => 8,
256 Type::Duration => 8,
257 Type::IdentityId => 8, Type::Uuid4 => 8,
259 Type::Uuid7 => 8,
260 Type::Blob => 4, Type::Int => 16, Type::Uint => 16, Type::Decimal {
266 ..
267 } => 16, Type::Undefined => 0,
270 Type::Any => 8, }
272 }
273}
274
275impl Display for Type {
276 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
277 match self {
278 Type::Boolean => f.write_str("Boolean"),
279 Type::Float4 => f.write_str("Float4"),
280 Type::Float8 => f.write_str("Float8"),
281 Type::Int1 => f.write_str("Int1"),
282 Type::Int2 => f.write_str("Int2"),
283 Type::Int4 => f.write_str("Int4"),
284 Type::Int8 => f.write_str("Int8"),
285 Type::Int16 => f.write_str("Int16"),
286 Type::Utf8 => f.write_str("Utf8"),
287 Type::Uint1 => f.write_str("Uint1"),
288 Type::Uint2 => f.write_str("Uint2"),
289 Type::Uint4 => f.write_str("Uint4"),
290 Type::Uint8 => f.write_str("Uint8"),
291 Type::Uint16 => f.write_str("Uint16"),
292 Type::Date => f.write_str("Date"),
293 Type::DateTime => f.write_str("DateTime"),
294 Type::Time => f.write_str("Time"),
295 Type::Duration => f.write_str("Duration"),
296 Type::IdentityId => f.write_str("IdentityId"),
297 Type::Uuid4 => f.write_str("Uuid4"),
298 Type::Uuid7 => f.write_str("Uuid7"),
299 Type::Blob => f.write_str("Blob"),
300 Type::Int => f.write_str("Int"),
301 Type::Uint => f.write_str("Uint"),
302 Type::Decimal => f.write_str("Decimal"),
303 Type::Undefined => f.write_str("Undefined"),
304 Type::Any => f.write_str("Any"),
305 }
306 }
307}
308
309impl From<&Value> for Type {
310 fn from(value: &Value) -> Self {
311 match value {
312 Value::Undefined => Type::Undefined,
313 Value::Boolean(_) => Type::Boolean,
314 Value::Float4(_) => Type::Float4,
315 Value::Float8(_) => Type::Float8,
316 Value::Int1(_) => Type::Int1,
317 Value::Int2(_) => Type::Int2,
318 Value::Int4(_) => Type::Int4,
319 Value::Int8(_) => Type::Int8,
320 Value::Int16(_) => Type::Int16,
321 Value::Utf8(_) => Type::Utf8,
322 Value::Uint1(_) => Type::Uint1,
323 Value::Uint2(_) => Type::Uint2,
324 Value::Uint4(_) => Type::Uint4,
325 Value::Uint8(_) => Type::Uint8,
326 Value::Uint16(_) => Type::Uint16,
327 Value::Date(_) => Type::Date,
328 Value::DateTime(_) => Type::DateTime,
329 Value::Time(_) => Type::Time,
330 Value::Duration(_) => Type::Duration,
331 Value::IdentityId(_) => Type::IdentityId,
332 Value::Uuid4(_) => Type::Uuid4,
333 Value::Uuid7(_) => Type::Uuid7,
334 Value::Blob(_) => Type::Blob,
335 Value::Int(_) => Type::Int,
336 Value::Uint(_) => Type::Uint,
337 Value::Decimal(_) => Type::Decimal,
338 Value::Any(_) => Type::Any,
339 }
340 }
341}
342
343impl FromStr for Type {
344 type Err = ();
345
346 fn from_str(s: &str) -> Result<Self, Self::Err> {
347 match s.to_uppercase().as_str() {
348 "BOOL" | "BOOLEAN" => Ok(Type::Boolean),
349 "FLOAT4" => Ok(Type::Float4),
350 "FLOAT8" => Ok(Type::Float8),
351 "INT1" => Ok(Type::Int1),
352 "INT2" => Ok(Type::Int2),
353 "INT4" => Ok(Type::Int4),
354 "INT8" => Ok(Type::Int8),
355 "INT16" => Ok(Type::Int16),
356 "UTF8" | "TEXT" => Ok(Type::Utf8),
357 "UINT1" => Ok(Type::Uint1),
358 "UINT2" => Ok(Type::Uint2),
359 "UINT4" => Ok(Type::Uint4),
360 "UINT8" => Ok(Type::Uint8),
361 "UINT16" => Ok(Type::Uint16),
362 "DATE" => Ok(Type::Date),
363 "DATETIME" => Ok(Type::DateTime),
364 "TIME" => Ok(Type::Time),
365 "DURATION" | "INTERVAL" => Ok(Type::Duration),
366 "IDENTITYID" | "IDENTITY_ID" => Ok(Type::IdentityId),
367 "UUID4" => Ok(Type::Uuid4),
368 "UUID7" => Ok(Type::Uuid7),
369 "BLOB" => Ok(Type::Blob),
370 "INT" => Ok(Type::Int),
371 "UINT" => Ok(Type::Uint),
372 "DECIMAL" => Ok(Type::Decimal),
373 "UNDEFINED" => Ok(Type::Undefined),
374 "ANY" => Ok(Type::Any),
375 _ => Err(()),
376 }
377 }
378}