1use std::{borrow::Cow, rc::Rc, sync::Arc};
2
3#[cfg(feature = "chrono")]
4use chrono::{DateTime, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime, Utc};
5use quex::{
6 Date as QuexDate, DateTime as QuexDateTime, DateTimeTz as QuexDateTimeTz, Encode,
7 Time as QuexTime,
8};
9#[cfg(feature = "serde_json")]
10use serde_json::Value as JsonValue;
11#[cfg(feature = "uuid")]
12use uuid::Uuid;
13
14use crate::{
15 BigInt, Blob, Bool, Date, Double, Float, Int, Nullable, Text, Time, Timestamp, UBigInt, UInt,
16 expression::{AsExpression, Expression},
17 lower::LowerCtx,
18 param::encode_param,
19 ty::TypeMeta,
20};
21
22pub trait DefaultMeta {
24 type Meta: TypeMeta;
25}
26
27pub trait Compatible<T: TypeMeta>: Encode {}
29
30#[doc(hidden)]
32pub trait LowerCompatible<T: TypeMeta> {
33 fn lower_compatible(&self, ctx: &mut LowerCtx) -> usize;
34}
35
36impl<T> DefaultMeta for Option<T>
37where
38 T: DefaultMeta,
39{
40 type Meta = Nullable<T::Meta>;
41}
42
43impl<T> DefaultMeta for &T
44where
45 T: DefaultMeta + ?Sized,
46{
47 type Meta = T::Meta;
48}
49
50impl<T, U> Compatible<T> for &U
51where
52 T: TypeMeta,
53 U: Compatible<T> + ?Sized,
54{
55}
56
57impl<T, V> LowerCompatible<T> for V
58where
59 T: TypeMeta,
60 V: Compatible<T> + ?Sized,
61{
62 fn lower_compatible(&self, ctx: &mut LowerCtx) -> usize {
63 let param = encode_param(self, ctx.data);
64 ctx.lower_param(param)
65 }
66}
67
68macro_rules! impl_text_lower_compatible {
69 ($($ty:ty),+ $(,)?) => {
70 $(
71 impl LowerCompatible<Text> for $ty {
72 fn lower_compatible(&self, ctx: &mut LowerCtx) -> usize {
73 let param = encode_param(self.as_ref(), ctx.data);
74 ctx.lower_param(param)
75 }
76 }
77
78 impl LowerCompatible<Nullable<Text>> for $ty {
79 fn lower_compatible(&self, ctx: &mut LowerCtx) -> usize {
80 let param = encode_param(self.as_ref(), ctx.data);
81 ctx.lower_param(param)
82 }
83 }
84 )+
85 };
86}
87
88impl_text_lower_compatible!(Box<str>, Arc<str>, Rc<str>, Cow<'_, str>);
89
90macro_rules! impl_blob_lower_compatible {
91 ($($ty:ty),+ $(,)?) => {
92 $(
93 impl LowerCompatible<Blob> for $ty {
94 fn lower_compatible(&self, ctx: &mut LowerCtx) -> usize {
95 let param = encode_param(self.as_ref(), ctx.data);
96 ctx.lower_param(param)
97 }
98 }
99
100 impl LowerCompatible<Nullable<Blob>> for $ty {
101 fn lower_compatible(&self, ctx: &mut LowerCtx) -> usize {
102 let param = encode_param(self.as_ref(), ctx.data);
103 ctx.lower_param(param)
104 }
105 }
106 )+
107 };
108}
109
110impl_blob_lower_compatible!(Box<[u8]>, Arc<[u8]>, Rc<[u8]>, Cow<'_, [u8]>);
111
112impl<T, U> AsExpression<T> for &U
113where
114 T: TypeMeta,
115 U: AsExpression<T> + ?Sized,
116{
117 type Expression<'e>
118 = U::Expression<'e>
119 where
120 Self: 'e;
121
122 fn as_expression<'e>(&'e self) -> Self::Expression<'e> {
123 U::as_expression(*self)
124 }
125}
126
127macro_rules! impl_default_meta {
128 ($meta:ty => $($ty:ty),+ $(,)?) => {
129 $(impl DefaultMeta for $ty {
130 type Meta = $meta;
131 })+
132 };
133}
134
135impl_default_meta!(Text => String, str, Box<str>, Arc<str>, Rc<str>, Cow<'_, str>);
136impl_default_meta!(Blob => Vec<u8>, [u8], Box<[u8]>, Arc<[u8]>, Rc<[u8]>, Cow<'_, [u8]>);
137impl_default_meta!(Bool => bool);
138impl_default_meta!(Int => i8, i16, i32);
139impl_default_meta!(BigInt => i64);
140impl_default_meta!(UInt => u8, u16, u32);
141impl_default_meta!(UBigInt => u64);
142impl_default_meta!(Float => f32);
143impl_default_meta!(Double => f64);
144impl_default_meta!(Date => QuexDate);
145impl_default_meta!(Time => QuexTime);
146impl_default_meta!(Timestamp => QuexDateTime, QuexDateTimeTz);
147#[cfg(feature = "chrono")]
148impl_default_meta!(Date => NaiveDate);
149#[cfg(feature = "chrono")]
150impl_default_meta!(Time => NaiveTime);
151#[cfg(feature = "chrono")]
152impl_default_meta!(Timestamp => NaiveDateTime, DateTime<Utc>, DateTime<FixedOffset>);
153#[cfg(feature = "uuid")]
154impl_default_meta!(Text => Uuid);
155#[cfg(feature = "serde_json")]
156impl_default_meta!(Text => JsonValue);
157
158macro_rules! impl_compatible_exact {
159 ($sql:ty => $($ty:ty),+ $(,)?) => {
160 $(
161 impl Compatible<$sql> for $ty {}
162 impl Compatible<Nullable<$sql>> for $ty {}
163 )+
164 };
165}
166
167impl_compatible_exact!(Int => i8, i16, i32);
168impl_compatible_exact!(BigInt => i64);
169impl_compatible_exact!(UInt => u8, u16, u32);
170impl_compatible_exact!(UBigInt => u64);
171impl_compatible_exact!(Bool => bool);
172impl_compatible_exact!(Float => f32);
173impl_compatible_exact!(Double => f64);
174impl_compatible_exact!(Date => QuexDate);
175impl_compatible_exact!(Time => QuexTime);
176impl_compatible_exact!(Timestamp => QuexDateTime, QuexDateTimeTz);
177
178macro_rules! impl_compatible_bigint_widen {
179 ($($ty:ty),+ $(,)?) => {
180 $(
181 impl Compatible<BigInt> for $ty {}
182 impl Compatible<Nullable<BigInt>> for $ty {}
183 )+
184 };
185}
186
187impl_compatible_bigint_widen!(i8, i16, i32);
188
189impl Compatible<Double> for f32 {}
190impl Compatible<Nullable<Double>> for f32 {}
191
192macro_rules! impl_text_compatible {
193 ($($ty:ty),+ $(,)?) => {
194 $(
195 impl Compatible<Text> for $ty {}
196 impl Compatible<Nullable<Text>> for $ty {}
197 )+
198 };
199}
200
201impl_text_compatible!(str, String);
202
203macro_rules! impl_blob_compatible {
204 ($($ty:ty),+ $(,)?) => {
205 $(
206 impl Compatible<Blob> for $ty {}
207 impl Compatible<Nullable<Blob>> for $ty {}
208 )+
209 };
210}
211
212impl_blob_compatible!([u8], Vec<u8>);
213
214#[cfg(feature = "chrono")]
215impl Compatible<Date> for NaiveDate {}
216#[cfg(feature = "chrono")]
217impl Compatible<Nullable<Date>> for NaiveDate {}
218#[cfg(feature = "chrono")]
219impl Compatible<Time> for NaiveTime {}
220#[cfg(feature = "chrono")]
221impl Compatible<Nullable<Time>> for NaiveTime {}
222#[cfg(feature = "chrono")]
223impl Compatible<Timestamp> for NaiveDateTime {}
224#[cfg(feature = "chrono")]
225impl Compatible<Nullable<Timestamp>> for NaiveDateTime {}
226#[cfg(feature = "chrono")]
227impl Compatible<Timestamp> for DateTime<FixedOffset> {}
228#[cfg(feature = "chrono")]
229impl Compatible<Nullable<Timestamp>> for DateTime<FixedOffset> {}
230#[cfg(feature = "chrono")]
231impl Compatible<Timestamp> for DateTime<Utc> {}
232#[cfg(feature = "chrono")]
233impl Compatible<Nullable<Timestamp>> for DateTime<Utc> {}
234
235#[cfg(feature = "uuid")]
236impl Compatible<Text> for Uuid {}
237#[cfg(feature = "uuid")]
238impl Compatible<Nullable<Text>> for Uuid {}
239
240#[cfg(feature = "serde_json")]
241impl Compatible<Text> for JsonValue {}
242#[cfg(feature = "serde_json")]
243impl Compatible<Nullable<Text>> for JsonValue {}
244
245impl<T, V> Compatible<Nullable<T>> for Option<V>
246where
247 T: TypeMeta,
248 V: Compatible<T>,
249{
250}
251
252pub struct TypedParam<'e, T: TypeMeta, V: ?Sized> {
253 value: &'e V,
254 marker: std::marker::PhantomData<T>,
255}
256
257impl<'e, T: TypeMeta, V: ?Sized> TypedParam<'e, T, V> {
258 pub fn new(value: &'e V) -> Self {
259 Self {
260 value,
261 marker: std::marker::PhantomData,
262 }
263 }
264}
265
266impl<T, V> Expression for TypedParam<'_, T, V>
267where
268 T: TypeMeta,
269 V: Compatible<T> + ?Sized,
270{
271 type Type = T;
272
273 fn lower(&self, ctx: &mut LowerCtx) -> usize {
274 self.value.lower_compatible(ctx)
275 }
276}
277
278macro_rules! impl_as_expression {
279 ($sql:ty => $($ty:ty),+ $(,)?) => {
280 $(
281 impl AsExpression<$sql> for $ty {
282 type Expression<'e>
283 = TypedParam<'e, $sql, $ty>
284 where
285 Self: 'e;
286
287 fn as_expression<'e>(&'e self) -> Self::Expression<'e> {
288 TypedParam::new(self)
289 }
290 }
291
292 impl AsExpression<Nullable<$sql>> for $ty {
293 type Expression<'e>
294 = TypedParam<'e, Nullable<$sql>, $ty>
295 where
296 Self: 'e;
297
298 fn as_expression<'e>(&'e self) -> Self::Expression<'e> {
299 TypedParam::new(self)
300 }
301 }
302 )+
303 };
304}
305
306impl_as_expression!(Bool => bool);
307impl_as_expression!(Int => i8, i16, i32);
308impl_as_expression!(BigInt => i8, i16, i32, i64);
309impl_as_expression!(UInt => u8, u16, u32);
310impl_as_expression!(UBigInt => u64);
311impl_as_expression!(Float => f32);
312impl_as_expression!(Double => f32, f64);
313impl_as_expression!(Text => str, String);
314impl_as_expression!(Blob => [u8], Vec<u8>);
315impl_as_expression!(Date => QuexDate);
316impl_as_expression!(Time => QuexTime);
317impl_as_expression!(Timestamp => QuexDateTime, QuexDateTimeTz);
318#[cfg(feature = "chrono")]
319impl_as_expression!(Date => NaiveDate);
320#[cfg(feature = "chrono")]
321impl_as_expression!(Time => NaiveTime);
322#[cfg(feature = "chrono")]
323impl_as_expression!(Timestamp => NaiveDateTime, DateTime<Utc>, DateTime<FixedOffset>);
324#[cfg(feature = "uuid")]
325impl_as_expression!(Text => Uuid);
326#[cfg(feature = "serde_json")]
327impl_as_expression!(Text => JsonValue);
328
329impl<T, V> AsExpression<Nullable<T>> for Option<V>
330where
331 T: TypeMeta,
332 V: Compatible<T>,
333{
334 type Expression<'e>
335 = TypedParam<'e, Nullable<T>, Option<V>>
336 where
337 Self: 'e;
338
339 fn as_expression<'e>(&'e self) -> Self::Expression<'e> {
340 TypedParam::new(self)
341 }
342}