1use crate::{AsValue, Error, Result, interval::Interval};
2use proc_macro2::TokenStream;
3use quote::{ToTokens, quote};
4use rust_decimal::Decimal;
5use serde_json::Value as JsonValue;
6use std::{collections::HashMap, hash::Hash, mem::discriminant};
7use time::{Date, OffsetDateTime, PrimitiveDateTime, Time};
8use uuid::Uuid;
9
10#[derive(Default, Debug, Clone)]
16pub enum Value {
17 #[default]
19 Null,
20 Boolean(Option<bool>),
21 Int8(Option<i8>),
22 Int16(Option<i16>),
23 Int32(Option<i32>),
24 Int64(Option<i64>),
25 Int128(Option<i128>),
26 UInt8(Option<u8>),
27 UInt16(Option<u16>),
28 UInt32(Option<u32>),
29 UInt64(Option<u64>),
30 UInt128(Option<u128>),
31 Float32(Option<f32>),
32 Float64(Option<f64>),
33 Decimal(Option<Decimal>, u8, u8),
35 Char(Option<char>),
36 Varchar(Option<String>),
37 Blob(Option<Box<[u8]>>),
38 Date(Option<Date>),
39 Time(Option<Time>),
40 Timestamp(Option<PrimitiveDateTime>),
41 TimestampWithTimezone(Option<OffsetDateTime>),
42 Interval(Option<Interval>),
43 Uuid(Option<Uuid>),
44 Array(
46 Option<Box<[Value]>>,
47 Box<Value>,
48 u32,
49 ),
50 List(Option<Vec<Value>>, Box<Value>),
52 Map(
54 Option<HashMap<Value, Value>>,
55 Box<Value>,
56 Box<Value>,
57 ),
58 Json(Option<JsonValue>),
59 Struct(
61 Option<Vec<(String, Value)>>,
62 Vec<(String, Value)>,
63 ),
64 Unknown(Option<String>),
66}
67
68impl Value {
69 pub fn same_type(&self, other: &Self) -> bool {
70 match (self, other) {
71 (Self::Decimal(.., l_width, l_scale), Self::Decimal(.., r_width, r_scale)) => {
72 (*l_width == 0 || *r_width == 0 || l_width == r_width)
73 && (*l_scale == 0 || *r_scale == 0 || l_scale == r_scale)
74 }
75 (Self::Array(.., l_type, l_len), Self::Array(.., r_type, r_len)) => {
76 l_len == r_len && l_type.same_type(&r_type)
77 }
78 (Self::List(.., l), Self::List(.., r)) => l.same_type(r),
79 (Self::Map(.., l_key, l_value), Self::Map(.., r_key, r_value)) => {
80 l_key.same_type(r_key) && l_value.same_type(&r_value)
81 }
82 _ => discriminant(self) == discriminant(other),
83 }
84 }
85
86 pub fn is_null(&self) -> bool {
87 match self {
88 Value::Null
89 | Value::Boolean(None, ..)
90 | Value::Int8(None, ..)
91 | Value::Int16(None, ..)
92 | Value::Int32(None, ..)
93 | Value::Int64(None, ..)
94 | Value::Int128(None, ..)
95 | Value::UInt8(None, ..)
96 | Value::UInt16(None, ..)
97 | Value::UInt32(None, ..)
98 | Value::UInt64(None, ..)
99 | Value::UInt128(None, ..)
100 | Value::Float32(None, ..)
101 | Value::Float64(None, ..)
102 | Value::Decimal(None, ..)
103 | Value::Char(None, ..)
104 | Value::Varchar(None, ..)
105 | Value::Blob(None, ..)
106 | Value::Date(None, ..)
107 | Value::Time(None, ..)
108 | Value::Timestamp(None, ..)
109 | Value::TimestampWithTimezone(None, ..)
110 | Value::Interval(None, ..)
111 | Value::Uuid(None, ..)
112 | Value::Array(None, ..)
113 | Value::List(None, ..)
114 | Value::Map(None, ..)
115 | Value::Json(None, ..)
116 | Value::Json(Some(serde_json::Value::Null), ..)
117 | Value::Struct(None, ..)
118 | Value::Unknown(None, ..) => true,
119 _ => false,
120 }
121 }
122
123 pub fn as_null(&self) -> Value {
124 match self {
125 Value::Null => Value::Null,
126 Value::Boolean(..) => Value::Boolean(None),
127 Value::Int8(..) => Value::Int8(None),
128 Value::Int16(..) => Value::Int16(None),
129 Value::Int32(..) => Value::Int32(None),
130 Value::Int64(..) => Value::Int64(None),
131 Value::Int128(..) => Value::Int128(None),
132 Value::UInt8(..) => Value::UInt8(None),
133 Value::UInt16(..) => Value::UInt16(None),
134 Value::UInt32(..) => Value::UInt32(None),
135 Value::UInt64(..) => Value::UInt64(None),
136 Value::UInt128(..) => Value::UInt128(None),
137 Value::Float32(..) => Value::Float32(None),
138 Value::Float64(..) => Value::Float64(None),
139 Value::Decimal(.., w, s) => Value::Decimal(None, *w, *s),
140 Value::Char(..) => Value::Char(None),
141 Value::Varchar(..) => Value::Varchar(None),
142 Value::Blob(..) => Value::Blob(None),
143 Value::Date(..) => Value::Date(None),
144 Value::Time(..) => Value::Time(None),
145 Value::Timestamp(..) => Value::Timestamp(None),
146 Value::TimestampWithTimezone(..) => Value::TimestampWithTimezone(None),
147 Value::Interval(..) => Value::Interval(None),
148 Value::Uuid(..) => Value::Uuid(None),
149 Value::Array(.., t, len) => Value::Array(None, t.clone(), *len),
150 Value::List(.., t) => Value::List(None, t.clone()),
151 Value::Map(.., k, v) => Value::Map(None, k.clone(), v.clone()),
152 Value::Json(..) => Value::Json(None),
153 Value::Struct(.., t) => Value::Struct(None, t.clone()),
154 Value::Unknown(..) => Value::Unknown(None),
155 }
156 }
157
158 pub fn try_as(self, value: &Value) -> Result<Value> {
159 if self.same_type(value) {
160 return Ok(self);
161 }
162 match value {
163 Value::Boolean(..) => bool::try_from_value(self).map(AsValue::as_value),
164 Value::Int8(..) => i8::try_from_value(self).map(AsValue::as_value),
165 Value::Int16(..) => i16::try_from_value(self).map(AsValue::as_value),
166 Value::Int32(..) => i32::try_from_value(self).map(AsValue::as_value),
167 Value::Int64(..) => i64::try_from_value(self).map(AsValue::as_value),
168 Value::Int128(..) => i128::try_from_value(self).map(AsValue::as_value),
169 Value::UInt8(..) => u8::try_from_value(self).map(AsValue::as_value),
170 Value::UInt16(..) => u16::try_from_value(self).map(AsValue::as_value),
171 Value::UInt32(..) => u32::try_from_value(self).map(AsValue::as_value),
172 Value::UInt64(..) => u64::try_from_value(self).map(AsValue::as_value),
173 Value::UInt128(..) => u128::try_from_value(self).map(AsValue::as_value),
174 Value::Float32(..) => f32::try_from_value(self).map(AsValue::as_value),
175 Value::Float64(..) => f64::try_from_value(self).map(AsValue::as_value),
176 Value::Decimal(..) => Decimal::try_from_value(self).map(AsValue::as_value),
177 Value::Char(..) => char::try_from_value(self).map(AsValue::as_value),
178 Value::Varchar(..) => String::try_from_value(self).map(AsValue::as_value),
179 Value::Blob(..) => Box::<[u8]>::try_from_value(self).map(AsValue::as_value),
180 Value::Date(..) => Date::try_from_value(self).map(AsValue::as_value),
181 Value::Time(..) => Time::try_from_value(self).map(AsValue::as_value),
182 Value::Timestamp(..) => PrimitiveDateTime::try_from_value(self).map(AsValue::as_value),
183 Value::TimestampWithTimezone(..) => {
184 OffsetDateTime::try_from_value(self).map(AsValue::as_value)
185 }
186 Value::Interval(..) => Interval::try_from_value(self).map(AsValue::as_value),
187 Value::Uuid(..) => Uuid::try_from_value(self).map(AsValue::as_value),
188 _ => {
194 return Err(Error::msg(format!(
195 "Cannot convert value {:?} into value {:?}",
196 self, value
197 )));
198 }
199 }
200 }
201}
202
203impl PartialEq for Value {
204 fn eq(&self, other: &Self) -> bool {
205 match (self, other) {
206 (Self::Null, Self::Null) => true,
207 (Self::Boolean(l), Self::Boolean(r)) => l == r,
208 (Self::Int8(l), Self::Int8(r)) => l == r,
209 (Self::Int16(l), Self::Int16(r)) => l == r,
210 (Self::Int32(l), Self::Int32(r)) => l == r,
211 (Self::Int64(l), Self::Int64(r)) => l == r,
212 (Self::Int128(l), Self::Int128(r)) => l == r,
213 (Self::UInt8(l), Self::UInt8(r)) => l == r,
214 (Self::UInt16(l), Self::UInt16(r)) => l == r,
215 (Self::UInt32(l), Self::UInt32(r)) => l == r,
216 (Self::UInt64(l), Self::UInt64(r)) => l == r,
217 (Self::UInt128(l), Self::UInt128(r)) => l == r,
218 (Self::Float32(l), Self::Float32(r)) => {
219 l == r
220 || l.and_then(|l| r.and_then(|r| Some(l.is_nan() && r.is_nan())))
221 .unwrap_or_default()
222 }
223 (Self::Float64(l), Self::Float64(r)) => {
224 l == r
225 || l.and_then(|l| r.and_then(|r| Some(l.is_nan() && r.is_nan())))
226 .unwrap_or_default()
227 }
228 (Self::Decimal(l, l_width, l_scale), Self::Decimal(r, r_width, r_scale)) => {
229 l == r && l_width == r_width && l_scale == r_scale
230 }
231 (Self::Char(l), Self::Char(r)) => l == r,
232 (Self::Varchar(l), Self::Varchar(r)) => l == r,
233 (Self::Blob(l), Self::Blob(r)) => l == r,
234 (Self::Date(l), Self::Date(r)) => l == r,
235 (Self::Time(l), Self::Time(r)) => l == r,
236 (Self::Timestamp(l), Self::Timestamp(r)) => l == r,
237 (Self::TimestampWithTimezone(l), Self::TimestampWithTimezone(r)) => l == r,
238 (Self::Interval(l), Self::Interval(r)) => l == r,
239 (Self::Uuid(l), Self::Uuid(r)) => l == r,
240 (Self::Array(l, ..), Self::Array(r, ..)) => l == r && self.same_type(other),
241 (Self::List(l, ..), Self::List(r, ..)) => l == r && self.same_type(other),
242 (Self::Map(None, ..), Self::Map(None, ..)) => self.same_type(other),
243 (Self::Map(Some(l), ..), Self::Map(Some(r), ..)) => {
244 l.is_empty() == r.is_empty() && self.same_type(other)
245 }
246 (Self::Map(..), Self::Map(..)) => self.same_type(other),
247 (Self::Json(l), Self::Json(r)) => l == r,
248 (Self::Unknown(..), Self::Unknown(..)) => false,
249 _ => false,
250 }
251 }
252}
253
254impl Eq for Value {}
255
256impl Hash for Value {
257 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
258 use Value::*;
259 discriminant(self).hash(state);
260 match self {
261 Null => {}
262 Boolean(v) => v.hash(state),
263 Int8(v) => v.hash(state),
264 Int16(v) => v.hash(state),
265 Int32(v) => v.hash(state),
266 Int64(v) => v.hash(state),
267 Int128(v) => v.hash(state),
268
269 UInt8(v) => v.hash(state),
270 UInt16(v) => v.hash(state),
271 UInt32(v) => v.hash(state),
272 UInt64(v) => v.hash(state),
273 UInt128(v) => v.hash(state),
274 Float32(Some(v)) => {
275 v.to_bits().hash(state);
276 }
277 Float32(None) => None::<u32>.hash(state),
278 Float64(Some(v)) => {
279 v.to_bits().hash(state);
280 }
281 Float64(None) => None::<u64>.hash(state),
282 Decimal(v, width, scale) => {
283 v.hash(state);
284 width.hash(state);
285 scale.hash(state);
286 }
287 Char(v) => v.hash(state),
288 Varchar(v) => v.hash(state),
289 Blob(v) => v.hash(state),
290 Date(v) => v.hash(state),
291 Time(v) => v.hash(state),
292 Timestamp(v) => v.hash(state),
293 TimestampWithTimezone(v) => v.hash(state),
294 Interval(v) => v.hash(state),
295 Uuid(v) => v.hash(state),
296 Array(v, typ, len) => {
297 v.hash(state);
298 typ.hash(state);
299 len.hash(state);
300 }
301 List(v, typ) => {
302 v.hash(state);
303 typ.hash(state);
304 }
305 Map(v, key, val) => {
306 match v {
307 Some(map) => {
308 for (key, val) in map {
309 key.hash(state);
310 val.hash(state);
311 }
312 }
313 None => {}
314 }
315 key.hash(state);
316 val.hash(state);
317 }
318 Json(v) => v.hash(state),
319 Struct(v, t) => {
320 match v {
321 Some(v) => v.hash(state),
322 None => {}
323 }
324 t.hash(state);
325 }
326 Unknown(v) => v.hash(state),
327 }
328 }
329}
330
331#[derive(Default)]
333pub struct TypeDecoded {
334 pub value: Value,
336 pub nullable: bool,
338 pub passive: bool,
340}
341
342pub type CheckPassive = Box<dyn Fn(TokenStream) -> TokenStream>;
343
344impl ToTokens for Value {
345 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
346 let ts = match self {
347 Value::Null => quote!(::tank::Value::Null),
348 Value::Boolean(..) => quote!(::tank::Value::Boolean(None)),
349 Value::Int8(..) => quote!(::tank::Value::Int8(None)),
350 Value::Int16(..) => quote!(::tank::Value::Int16(None)),
351 Value::Int32(..) => quote!(::tank::Value::Int32(None)),
352 Value::Int64(..) => quote!(::tank::Value::Int64(None)),
353 Value::Int128(..) => quote!(::tank::Value::Int128(None)),
354 Value::UInt8(..) => quote!(::tank::Value::UInt8(None)),
355 Value::UInt16(..) => quote!(::tank::Value::UInt16(None)),
356 Value::UInt32(..) => quote!(::tank::Value::UInt32(None)),
357 Value::UInt64(..) => quote!(::tank::Value::UInt64(None)),
358 Value::UInt128(..) => quote!(::tank::Value::UInt128(None)),
359 Value::Float32(..) => quote!(::tank::Value::Float32(None)),
360 Value::Float64(..) => quote!(::tank::Value::Float64(None)),
361 Value::Decimal(.., width, scale) => {
362 quote!(::tank::Value::Decimal(None, #width, #scale))
363 }
364 Value::Char(..) => quote!(tank::Value::Char(None)),
365 Value::Varchar(..) => quote!(::tank::Value::Varchar(None)),
366 Value::Blob(..) => quote!(::tank::Value::Blob(None)),
367 Value::Date(..) => quote!(::tank::Value::Date(None)),
368 Value::Time(..) => quote!(::tank::Value::Time(None)),
369 Value::Timestamp(..) => quote!(::tank::Value::Timestamp(None)),
370 Value::TimestampWithTimezone(..) => quote!(::tank::Value::TimestampWithTimezone(None)),
371 Value::Interval(..) => quote!(::tank::Value::Interval(None)),
372 Value::Uuid(..) => quote!(::tank::Value::Uuid(None)),
373 Value::Array(.., inner, size) => {
374 quote!(::tank::Value::Array(None, Box::new(#inner), #size))
375 }
376 Value::List(.., inner) => {
377 let inner = inner.as_ref().to_token_stream();
378 quote!(::tank::Value::List(None, Box::new(#inner)))
379 }
380 Value::Map(.., key, value) => {
381 let key = key.as_ref().to_token_stream();
382 let value = value.as_ref().to_token_stream();
383 quote!(::tank::Value::Map(None, Box::new(#key), Box::new(#value)))
384 }
385 Value::Json(..) => quote!(::tank::Value::Json(None)),
386 Value::Struct(.., t) => {
387 let values = t.into_iter().map(|(k, v)| quote!((#k.into(), #v)));
388 quote!(::tank::Value::Struct(None, vec!(#(#values),*)))
389 }
390 Value::Unknown(..) => quote!(::tank::Value::Unknown(None)),
391 };
392 tokens.extend(ts);
393 }
394}