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