1use std::{rc::Rc, sync::Arc};
2
3use super::assignment::impl_assign_via_expr;
4use super::{Expr, List, Value};
5#[cfg(feature = "net")]
6use super::{IpCidr, IpInet, MacAddr6, MacAddr8};
7use toasty_core::stmt;
8
9pub trait IntoExpr<T> {
32 fn into_expr(self) -> Expr<T>;
43
44 fn by_ref(&self) -> Expr<T>;
60}
61
62macro_rules! impl_into_expr_for_copy {
63 ( $( $var:ident($t:ty) ;)* ) => {
64 $(
65 impl IntoExpr<$t> for $t {
66 fn into_expr(self) -> Expr<$t> {
67 Expr::from_value(Value::from(self))
68 }
69
70 fn by_ref(&self) -> Expr<$t> {
71 Expr::from_value(Value::from(self.clone()))
72 }
73 }
74
75 impl_assign_via_expr!($t => $t);
76 )*
77 };
78}
79
80impl_into_expr_for_copy! {
81 Bool(bool);
82 I8(i8);
83 I16(i16);
84 I32(i32);
85 I64(i64);
86 U8(u8);
87 U16(u16);
88 U32(u32);
89 U64(u64);
90 F32(f32);
91 F64(f64);
92 Uuid(uuid::Uuid);
93}
94
95#[cfg(feature = "jiff")]
96impl_into_expr_for_copy! {
97 Timestamp(jiff::Timestamp);
98 Zoned(jiff::Zoned);
99 Date(jiff::civil::Date);
100 Time(jiff::civil::Time);
101 DateTime(jiff::civil::DateTime);
102}
103
104#[cfg(feature = "jiff")]
109impl IntoExpr<jiff::tz::TimeZone> for jiff::tz::TimeZone {
110 fn into_expr(self) -> Expr<jiff::tz::TimeZone> {
111 self.by_ref()
112 }
113
114 fn by_ref(&self) -> Expr<jiff::tz::TimeZone> {
115 let text = crate::schema::jiff::time_zone_to_text(self)
116 .expect("time zone cannot be stored: no IANA identifier, fixed offset, or POSIX rule");
117 Expr::from_value(Value::String(text))
118 }
119}
120
121#[cfg(feature = "jiff")]
122impl_assign_via_expr!(jiff::tz::TimeZone => jiff::tz::TimeZone);
123
124#[cfg(feature = "net")]
125impl_into_expr_for_copy! {
126 Cidr(IpCidr);
127 Inet(IpInet);
128 MacAddr(MacAddr6);
129 MacAddr8(MacAddr8);
130}
131
132impl IntoExpr<isize> for isize {
134 fn into_expr(self) -> Expr<isize> {
135 Expr::from_value(Value::from(self as i64))
136 }
137
138 fn by_ref(&self) -> Expr<isize> {
139 Expr::from_value(Value::from(*self as i64))
140 }
141}
142impl_assign_via_expr!(isize => isize);
143
144impl IntoExpr<usize> for usize {
145 fn into_expr(self) -> Expr<usize> {
146 Expr::from_value(Value::from(self as u64))
147 }
148
149 fn by_ref(&self) -> Expr<usize> {
150 Expr::from_value(Value::from(*self as u64))
151 }
152}
153impl_assign_via_expr!(usize => usize);
154
155impl<T> IntoExpr<T> for Expr<T> {
156 fn into_expr(self) -> Self {
157 self
158 }
159
160 fn by_ref(&self) -> Self {
161 self.clone()
162 }
163}
164impl_assign_via_expr!({T} Expr<T> => T);
165
166impl<T: IntoExpr<T>> IntoExpr<T> for &T {
167 fn into_expr(self) -> Expr<T> {
168 self.by_ref()
169 }
170
171 fn by_ref(&self) -> Expr<T> {
172 (*self).by_ref()
173 }
174}
175impl_assign_via_expr!({T: IntoExpr<T>} &T => T);
176
177impl<T: IntoExpr<T>> IntoExpr<Self> for Option<T> {
178 fn into_expr(self) -> Expr<Self> {
179 match self {
180 Some(value) => value.into_expr().cast(),
181 None => Expr::from_value(Value::Null),
182 }
183 }
184
185 fn by_ref(&self) -> Expr<Self> {
186 match self {
187 Some(value) => value.by_ref().cast(),
188 None => Expr::from_value(Value::Null),
189 }
190 }
191}
192impl_assign_via_expr!({T: IntoExpr<T>} Option<T> => Option<T>);
193
194impl<T: IntoExpr<T>> IntoExpr<Option<T>> for T {
195 fn into_expr(self) -> Expr<Option<T>> {
196 self.into_expr().cast()
197 }
198
199 fn by_ref(&self) -> Expr<Option<T>> {
200 self.by_ref().cast()
201 }
202}
203impl_assign_via_expr!({T: IntoExpr<T>} T => Option<T>);
204
205impl<T: IntoExpr<T>> IntoExpr<Option<T>> for &T {
206 fn into_expr(self) -> Expr<Option<T>> {
207 self.by_ref().cast()
208 }
209
210 fn by_ref(&self) -> Expr<Option<T>> {
211 (*self).by_ref().cast()
212 }
213}
214impl_assign_via_expr!({T: IntoExpr<T>} &T => Option<T>);
215
216impl IntoExpr<String> for &str {
217 fn into_expr(self) -> Expr<String> {
218 Expr::from_value(Value::from(self))
219 }
220
221 fn by_ref(&self) -> Expr<String> {
222 Expr::from_value(Value::from(*self))
223 }
224}
225impl_assign_via_expr!(&str => String);
226
227impl IntoExpr<Option<String>> for &str {
228 fn into_expr(self) -> Expr<Option<String>> {
229 Expr::from_value(Value::from(self))
230 }
231
232 fn by_ref(&self) -> Expr<Option<String>> {
233 Expr::from_value(Value::from(*self))
234 }
235}
236impl_assign_via_expr!(&str => Option<String>);
237
238impl IntoExpr<Self> for String {
239 fn into_expr(self) -> Expr<Self> {
240 Expr::from_value(self.into())
241 }
242
243 fn by_ref(&self) -> Expr<Self> {
244 Expr::from_value(self.into())
245 }
246}
247impl_assign_via_expr!(String => String);
248
249impl IntoExpr<Self> for Vec<u8> {
250 fn into_expr(self) -> Expr<Self> {
251 Expr::from_value(self.into())
252 }
253
254 fn by_ref(&self) -> Expr<Self> {
255 Expr::from_value(self.clone().into())
256 }
257}
258impl_assign_via_expr!(Vec<u8> => Vec<u8>);
259
260#[cfg(feature = "rust_decimal")]
261impl IntoExpr<Self> for rust_decimal::Decimal {
262 fn into_expr(self) -> Expr<Self> {
263 Expr::from_value(self.into())
264 }
265
266 fn by_ref(&self) -> Expr<Self> {
267 Expr::from_value((*self).into())
268 }
269}
270#[cfg(feature = "rust_decimal")]
271impl_assign_via_expr!(rust_decimal::Decimal => rust_decimal::Decimal);
272
273#[cfg(feature = "bigdecimal")]
274impl IntoExpr<Self> for bigdecimal::BigDecimal {
275 fn into_expr(self) -> Expr<Self> {
276 Expr::from_value(self.into())
277 }
278
279 fn by_ref(&self) -> Expr<Self> {
280 Expr::from_value(self.clone().into())
281 }
282}
283#[cfg(feature = "bigdecimal")]
284impl_assign_via_expr!(bigdecimal::BigDecimal => bigdecimal::BigDecimal);
285
286impl<T, U, const N: usize> IntoExpr<List<T>> for [U; N]
287where
288 U: IntoExpr<T>,
289{
290 fn into_expr(self) -> Expr<List<T>> {
291 Expr::from_untyped(stmt::Expr::list(
292 self.into_iter().map(|item| item.into_expr().untyped),
293 ))
294 }
295
296 fn by_ref(&self) -> Expr<List<T>> {
297 Expr::from_untyped(stmt::Expr::list(
298 self.iter().map(|item| U::by_ref(item).untyped),
299 ))
300 }
301}
302impl_assign_via_expr!({T, U: IntoExpr<T>, const N: usize} [U; N] => List<T>);
303
304impl<T, U, const N: usize> IntoExpr<List<T>> for &[U; N]
305where
306 U: IntoExpr<T>,
307{
308 fn into_expr(self) -> Expr<List<T>> {
309 Expr::from_untyped(stmt::Expr::list(
310 self.iter().map(|item| U::by_ref(item).untyped),
311 ))
312 }
313
314 fn by_ref(&self) -> Expr<List<T>> {
315 Expr::from_untyped(stmt::Expr::list(
316 self.iter().map(|item| U::by_ref(item).untyped),
317 ))
318 }
319}
320impl_assign_via_expr!({T, U: IntoExpr<T>, const N: usize} &[U; N] => List<T>);
321
322impl<T, E: IntoExpr<T>> IntoExpr<List<T>> for &[E] {
323 fn into_expr(self) -> Expr<List<T>> {
324 Expr::from_untyped(stmt::Expr::list(
325 self.iter().map(|item| E::by_ref(item).untyped),
326 ))
327 }
328
329 fn by_ref(&self) -> Expr<List<T>> {
330 Expr::from_untyped(stmt::Expr::list(
331 self.iter().map(|item| E::by_ref(item).untyped),
332 ))
333 }
334}
335impl_assign_via_expr!({T, E: IntoExpr<T>} &[E] => List<T>);
336
337impl<T, U> IntoExpr<List<T>> for Vec<U>
338where
339 U: IntoExpr<T>,
340{
341 fn into_expr(self) -> Expr<List<T>> {
342 Expr::from_untyped(stmt::Expr::list(
343 self.into_iter().map(|item| item.into_expr().untyped),
344 ))
345 }
346
347 fn by_ref(&self) -> Expr<List<T>> {
348 Expr::from_untyped(stmt::Expr::list(
349 self.iter().map(|item| item.by_ref().untyped),
350 ))
351 }
352}
353impl_assign_via_expr!({T, U: IntoExpr<T>} Vec<U> => List<T>);
354
355macro_rules! forward_impl {
363 ( $( $ty:ty ,) *) => {
364 $(
365 impl<T> IntoExpr<$ty> for T
366 where
367 T: IntoExpr<T>,
368 {
369 fn into_expr(self) -> Expr<$ty> {
370 <Self as IntoExpr<Self>>::into_expr(self).cast()
371 }
372
373 fn by_ref(&self) -> Expr<$ty> {
374 <Self as IntoExpr<Self>>::by_ref(self).cast()
375 }
376 }
377 ) *
378 };
379}
380
381forward_impl!(Arc<T>, Box<T>, Rc<T>,);
382impl_assign_via_expr!({T: IntoExpr<T>} T => Arc<T>);
383impl_assign_via_expr!({T: IntoExpr<T>} T => Box<T>);
384impl_assign_via_expr!({T: IntoExpr<T>} T => Rc<T>);
385
386macro_rules! ref_smart_ptr_impl {
387 ( $( $ptr:ident ,)* ) => {
388 $(
389 impl<T: IntoExpr<T>> IntoExpr<$ptr<T>> for $ptr<T> {
390 fn into_expr(self) -> Expr<$ptr<T>> {
391 T::by_ref(&self).cast()
392 }
393
394 fn by_ref(&self) -> Expr<$ptr<T>> {
395 T::by_ref(self).cast()
396 }
397 }
398
399 impl<T: IntoExpr<T>> IntoExpr<T> for &$ptr<T> {
400 fn into_expr(self) -> Expr<T> {
401 T::by_ref(self)
402 }
403
404 fn by_ref(&self) -> Expr<T> {
405 T::by_ref(self)
406 }
407 }
408 )*
409 };
410}
411
412ref_smart_ptr_impl!(Arc, Box, Rc,);
413
414macro_rules! impl_into_expr_for_tuple {
415 (! $( $n:tt $t:ident $e:ident )* ) => {
416 impl<$( $t, $e ),*> IntoExpr<($( $t, )*)> for ($( $e, )*)
417 where
418 $( $e: IntoExpr<$t>, )*
419 {
420 fn into_expr(self) -> Expr<($( $t, )*)> {
421 let record = stmt::ExprRecord::from_vec(vec![
422 $( self.$n.into_expr().untyped, )*
423 ]);
424 let untyped = stmt::Expr::Record(record);
425 Expr::from_untyped(untyped)
426 }
427
428 fn by_ref(&self) -> Expr<($( $t, )*)> {
429 let record = stmt::ExprRecord::from_vec(vec![
430 $( self.$n.by_ref().untyped, )*
431 ]);
432 let untyped = stmt::Expr::Record(record);
433 Expr::from_untyped(untyped)
434 }
435 }
436
437 impl_assign_via_expr!({$( $t, $e: IntoExpr<$t> ),*} ($( $e, )*) => ($( $t, )*));
438 };
439
440 (
441 ( $( $n_base:tt $t_base:ident $e_base:ident )* )
442 $n:tt $t:ident $e:ident
443 $( $rest:tt )*
444 ) => {
445 impl_into_expr_for_tuple!(! $( $n_base $t_base $e_base )* $n $t $e);
447
448 impl_into_expr_for_tuple!(
450 ( $( $n_base $t_base $e_base )* $n $t $e )
451 $( $rest )*
452 );
453 };
454
455 ( ( $( $n:tt $t:ident $e:ident )* ) ) => {}
456}
457
458impl_into_expr_for_tuple! {
459 ()
460 0 T0 E0
461 1 T1 E1
462 2 T2 E2
463 3 T3 E3
464 4 T4 E4
465 5 T5 E5
466 6 T6 E6
467 7 T7 E7
468 8 T8 E8
469 9 T9 E9
470}
471
472#[test]
473fn assert_bounds() {
474 fn assert_into_expr<T, E: IntoExpr<T>>() {}
475
476 assert_into_expr::<i64, i64>();
477 assert_into_expr::<(String, String), (&String, &String)>();
478 assert_into_expr::<List<(String, String)>, &[(&String, &String)]>();
479 assert_into_expr::<List<(String, String)>, [(&String, &String); 3]>();
480 assert_into_expr::<List<(String, String)>, &[(&String, &String); 3]>();
481}