1mod core;
4mod ext;
5mod ty;
6
7#[cfg(test)]
8mod tests;
9
10pub use core::*;
11pub use ext::*;
12pub use ty::*;
13
14use std::collections::HashMap;
15
16use ::time::{Date, OffsetDateTime};
17use ::uuid::Uuid;
18use ethnum::{I256, U256};
19
20use crate::error::Error;
21use ext::time::{DateExt, DateTimeExt};
22
23pub trait ChValue: Sized {
25 fn ch_type() -> Type;
27
28 fn into_ch_value(self) -> Value;
30
31 fn from_ch_value(value: Value) -> Result<Self, Error>;
33
34 fn into_sql(self) -> String {
36 self.into_ch_value().to_sql_string()
37 }
38}
39
40impl<T> From<T> for Value
42where
43 T: ChValue,
44{
45 fn from(value: T) -> Self {
46 value.into_ch_value()
47 }
48}
49
50#[derive(Debug, Clone, PartialEq)]
52pub enum Value {
53 UInt8(u8),
55 UInt16(u16),
57 UInt32(u32),
59 UInt64(u64),
61 UInt128(u128),
63 UInt256([u128; 2]),
65 Int8(i8),
67 Int16(i16),
69 Int32(i32),
71 Int64(i64),
73 Int128(i128),
75 Int256([i128; 2]),
77 Float32(f32),
79 Float64(f64),
81 Bool(bool),
88 String(String),
90 UUID([u8; 16]),
92 Date(u16),
94 Date32(i32),
96 DateTime(u32),
98 DateTime64(i64),
100 Enum8(i8),
102 Enum16(i16),
104 Array(Vec<Value>),
106 Tuple(Vec<Value>),
108 Map(HashMap<String, Value>),
110 Nested(HashMap<String, Value>),
112 NullableUInt8(Option<u8>),
114 NullableUInt16(Option<u16>),
116 NullableUInt32(Option<u32>),
118 NullableUInt64(Option<u64>),
120 NullableUInt128(Option<u128>),
122 NullableUInt256(Option<[u128; 2]>),
124 NullableInt8(Option<i8>),
126 NullableInt16(Option<i16>),
128 NullableInt32(Option<i32>),
130 NullableInt64(Option<i64>),
132 NullableInt128(Option<i128>),
134 NullableInt256(Option<[i128; 2]>),
136 NullableFloat32(Option<f32>),
138 NullableFloat64(Option<f64>),
140 NullableBool(Option<bool>),
146 NullableString(Option<String>),
148 NullableUUID(Option<[u8; 16]>),
150 NullableDate(Option<u16>),
152 NullableDate32(Option<i32>),
154 NullableDateTime(Option<u32>),
156 NullableDateTime64(Option<i64>),
158 NullableEnum8(Option<i8>),
160 NullableEnum16(Option<i16>),
162}
163
164impl Value {
165 pub fn try_into<T>(self) -> Result<T, Error>
167 where
168 T: ChValue,
169 {
170 T::from_ch_value(self)
171 }
172
173 pub fn is_same_type_as(&self, ty: &Type) -> bool {
175 match self {
176 Value::UInt8(_) => matches!(ty, Type::UInt8),
177 Value::UInt16(_) => matches!(ty, Type::UInt16),
178 Value::UInt32(_) => matches!(ty, Type::UInt32),
179 Value::UInt64(_) => matches!(ty, Type::UInt64),
180 Value::UInt128(_) => matches!(ty, Type::UInt128),
181 Value::UInt256(_) => matches!(ty, Type::UInt256),
182 Value::Int8(_) => matches!(ty, Type::Int8),
183 Value::Int16(_) => matches!(ty, Type::Int16),
184 Value::Int32(_) => matches!(ty, Type::Int32),
185 Value::Int64(_) => matches!(ty, Type::Int64),
186 Value::Int128(_) => matches!(ty, Type::Int128),
187 Value::Int256(_) => matches!(ty, Type::Int256),
188 Value::Float32(_) => matches!(ty, Type::Float32),
189 Value::Float64(_) => matches!(ty, Type::Float64),
190 Value::Bool(_) => matches!(ty, Type::Bool),
191 Value::String(_) => matches!(ty, Type::String),
192 Value::UUID(_) => matches!(ty, Type::UUID),
193 Value::Date(_) => matches!(ty, Type::Date),
194 Value::Date32(_) => matches!(ty, Type::Date32),
195 Value::DateTime(_) => matches!(ty, Type::DateTime),
196 Value::DateTime64(_) => matches!(ty, Type::DateTime64(_)),
197 Value::Enum8(i) => match ty {
198 Type::Enum8(variants) => variants.values().any(|v| v == i),
199 _ => false,
200 },
201 Value::Enum16(i) => match ty {
202 Type::Enum16(variants) => variants.values().any(|v| v == i),
203 _ => false,
204 },
205 Value::Array(values) => match ty {
206 Type::Array(arr_ty) => values.iter().all(|v| v.is_same_type_as(arr_ty.as_ref())),
207 _ => false,
208 },
209 Value::Tuple(values) => match ty {
210 Type::Tuple(types) => {
211 if values.len() != types.len() {
212 return false;
213 }
214 values.iter().zip(types).all(|(n, t)| n.is_same_type_as(t))
215 }
216 _ => false,
217 },
218 Value::Map(map) => match ty {
219 Type::Map(_key_ty, val_ty) => {
220 map.values().all(|v| v.is_same_type_as(val_ty.as_ref()))
221 }
222 _ => false,
223 },
224 Value::Nested(values) => match ty {
225 Type::Nested(fields) => {
226 let keys = fields.iter().map(|(k, _v)| k.as_str()).collect::<Vec<_>>();
227 values.keys().all(|k| keys.contains(&k.as_str()))
228 && values
229 .iter()
230 .zip(fields)
231 .all(|((_, v), (_, t))| v.is_same_type_as(t))
232 }
233 _ => false,
234 },
235 Value::NullableUInt8(_) => matches!(ty, Type::NullableUInt8),
236 Value::NullableUInt16(_) => matches!(ty, Type::NullableUInt16),
237 Value::NullableUInt32(_) => matches!(ty, Type::NullableUInt32),
238 Value::NullableUInt64(_) => matches!(ty, Type::NullableUInt64),
239 Value::NullableUInt128(_) => matches!(ty, Type::NullableUInt128),
240 Value::NullableUInt256(_) => matches!(ty, Type::NullableUInt256),
241 Value::NullableInt8(_) => matches!(ty, Type::NullableInt8),
242 Value::NullableInt16(_) => matches!(ty, Type::NullableInt16),
243 Value::NullableInt32(_) => matches!(ty, Type::NullableInt32),
244 Value::NullableInt64(_) => matches!(ty, Type::NullableInt64),
245 Value::NullableInt128(_) => matches!(ty, Type::NullableInt128),
246 Value::NullableInt256(_) => matches!(ty, Type::NullableInt256),
247 Value::NullableFloat32(_) => matches!(ty, Type::NullableFloat32),
248 Value::NullableFloat64(_) => matches!(ty, Type::NullableFloat64),
249 Value::NullableBool(_) => matches!(ty, Type::NullableBool),
250 Value::NullableString(_) => matches!(ty, Type::NullableString),
251 Value::NullableUUID(_) => matches!(ty, Type::NullableUUID),
252 Value::NullableDate(_) => matches!(ty, Type::NullableDate),
253 Value::NullableDate32(_) => matches!(ty, Type::NullableDate32),
254 Value::NullableDateTime(_) => matches!(ty, Type::NullableDateTime),
255 Value::NullableDateTime64(_) => matches!(ty, Type::NullableDateTime64(_)),
256 Value::NullableEnum8(_) => matches!(ty, Type::NullableEnum8(_)),
257 Value::NullableEnum16(_) => matches!(ty, Type::NullableEnum16(_)),
258 }
259 }
260
261 pub(crate) fn into_nullable(self) -> Option<Value> {
263 match self {
264 Value::UInt8(v) => Some(Value::NullableUInt8(Some(v))),
265 Value::UInt16(v) => Some(Value::NullableUInt16(Some(v))),
266 Value::UInt32(v) => Some(Value::NullableUInt32(Some(v))),
267 Value::UInt64(v) => Some(Value::NullableUInt64(Some(v))),
268 Value::UInt128(v) => Some(Value::NullableUInt128(Some(v))),
269 Value::UInt256(v) => Some(Value::NullableUInt256(Some(v))),
270 Value::Int8(v) => Some(Value::NullableInt8(Some(v))),
271 Value::Int16(v) => Some(Value::NullableInt16(Some(v))),
272 Value::Int32(v) => Some(Value::NullableInt32(Some(v))),
273 Value::Int64(v) => Some(Value::NullableInt64(Some(v))),
274 Value::Int128(v) => Some(Value::NullableInt128(Some(v))),
275 Value::Int256(v) => Some(Value::NullableInt256(Some(v))),
276 Value::Float32(v) => Some(Value::NullableFloat32(Some(v))),
277 Value::Float64(v) => Some(Value::NullableFloat64(Some(v))),
278 Value::Bool(v) => Some(Value::NullableBool(Some(v))),
279 Value::String(v) => Some(Value::NullableString(Some(v))),
280 Value::UUID(v) => Some(Value::NullableUUID(Some(v))),
281 Value::Date(v) => Some(Value::NullableDate(Some(v))),
282 Value::Date32(v) => Some(Value::NullableDate32(Some(v))),
283 Value::DateTime(v) => Some(Value::NullableDateTime(Some(v))),
284 Value::DateTime64(v) => Some(Value::NullableDateTime64(Some(v))),
285 Value::Enum8(v) => Some(Value::NullableEnum8(Some(v))),
286 Value::Enum16(v) => Some(Value::NullableEnum16(Some(v))),
287 Value::Array(_) => None,
288 Value::Tuple(_) => None,
289 Value::Map(_) => None,
290 Value::Nested(_) => None,
291 _ => Some(self),
293 }
294 }
295}
296
297impl std::fmt::Display for Value {
298 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
299 macro_rules! impl_nullable {
301 ($VAL:expr, $VAR:ident) => {
302 match $VAL {
303 Some(v) => Value::$VAR(v).to_string(),
304 None => "NULL".to_string(),
305 }
306 };
307 }
308
309 let s = match self {
310 Value::UInt8(v) => v.to_string(),
311 Value::UInt16(v) => v.to_string(),
312 Value::UInt32(v) => v.to_string(),
313 Value::UInt64(v) => v.to_string(),
314 Value::UInt128(v) => v.to_string(),
315 Value::UInt256(_) => {
316 let u256 = self.clone().try_into::<U256>().unwrap();
317 u256.to_string()
318 }
319 Value::Int8(v) => v.to_string(),
320 Value::Int16(v) => v.to_string(),
321 Value::Int32(v) => v.to_string(),
322 Value::Int64(v) => v.to_string(),
323 Value::Int128(v) => v.to_string(),
324 Value::Int256(_) => {
325 let i256 = self.clone().try_into::<I256>().unwrap();
326 i256.to_string()
327 }
328 Value::Float32(v) => v.to_string(),
329 Value::Float64(v) => v.to_string(),
330 Value::Bool(v) => v.to_string(),
331 Value::String(v) => v.to_string(),
332 Value::UUID(_) => {
333 let uuid = self.clone().try_into::<Uuid>().unwrap();
334 uuid.to_string()
335 }
336 Value::Date(_) | Value::Date32(_) => {
337 let date = self.clone().try_into::<Date>().unwrap();
338 date.format_yyyy_mm_dd()
339 }
340 Value::DateTime(_) => {
341 let dt = self.clone().try_into::<OffsetDateTime>().unwrap();
342 dt.format_yyyy_mm_dd_hh_mm_ss()
343 }
344 Value::DateTime64(_) => {
345 let dt = self.clone().try_into::<OffsetDateTime>().unwrap();
346 dt.format_yyyy_mm_dd_hh_mm_ss_ns()
347 }
348 Value::Enum8(v) => v.to_string(),
349 Value::Enum16(v) => v.to_string(),
350 Value::Array(v) => {
351 format!(
352 "[{}]",
353 v.iter()
354 .map(|v| v.to_string())
355 .collect::<Vec<_>>()
356 .join(", ")
357 )
358 }
359 Value::Tuple(v) => {
360 format!(
361 "({})",
362 v.iter()
363 .map(|v| v.to_string())
364 .collect::<Vec<_>>()
365 .join(", ")
366 )
367 }
368 Value::Map(v) => {
369 format!(
370 "{{{}}}",
371 v.iter()
372 .map(|(k, v)| format!("{}: {}", k, v))
373 .collect::<Vec<_>>()
374 .join(", ")
375 )
376 }
377 Value::Nested(v) => {
378 format!(
379 "{{{}}}",
380 v.iter()
381 .map(|(k, v)| format!("{}: {}", k, v))
382 .collect::<Vec<String>>()
383 .join(", ")
384 )
385 }
386 Value::NullableUInt8(v) => impl_nullable!(*v, UInt8),
387 Value::NullableUInt16(v) => impl_nullable!(*v, UInt16),
388 Value::NullableUInt32(v) => impl_nullable!(*v, UInt32),
389 Value::NullableUInt64(v) => impl_nullable!(*v, UInt64),
390 Value::NullableUInt128(v) => impl_nullable!(*v, UInt128),
391 Value::NullableUInt256(v) => impl_nullable!(*v, UInt256),
392 Value::NullableInt8(v) => impl_nullable!(*v, Int8),
393 Value::NullableInt16(v) => impl_nullable!(*v, Int16),
394 Value::NullableInt32(v) => impl_nullable!(*v, Int32),
395 Value::NullableInt64(v) => impl_nullable!(*v, Int64),
396 Value::NullableInt128(v) => impl_nullable!(*v, Int128),
397 Value::NullableInt256(v) => impl_nullable!(*v, Int256),
398 Value::NullableFloat32(v) => impl_nullable!(*v, Float32),
399 Value::NullableFloat64(v) => impl_nullable!(*v, Float64),
400 Value::NullableBool(v) => impl_nullable!(*v, Bool),
401 Value::NullableString(v) => impl_nullable!(v.clone(), String),
402 Value::NullableUUID(v) => impl_nullable!(*v, UUID),
403 Value::NullableDate(v) => impl_nullable!(*v, Date),
404 Value::NullableDate32(v) => impl_nullable!(*v, Date32),
405 Value::NullableDateTime(v) => impl_nullable!(*v, DateTime),
406 Value::NullableDateTime64(v) => impl_nullable!(*v, DateTime64),
407 Value::NullableEnum8(v) => impl_nullable!(*v, Enum8),
408 Value::NullableEnum16(v) => impl_nullable!(*v, Enum16),
409 };
410
411 write!(f, "{s}")
412 }
413}