1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use proc_macro2::{self, Ident, Span};
use syn;
use meta::*;
use util::*;
pub fn derive(item: syn::DeriveInput) -> Result<proc_macro2::TokenStream, Diagnostic> {
let dummy_mod = format!("_impl_as_expression_for_{}", item.ident,).to_lowercase();
let flags =
MetaItem::with_name(&item.attrs, "diesel").unwrap_or_else(|| MetaItem::empty("diesel"));
let is_sized = !flags.has_flag("not_sized");
let sql_types = MetaItem::all_with_name(&item.attrs, "sql_type");
let any_sql_types = !sql_types.is_empty();
let sql_types = sql_types
.into_iter()
.filter_map(|attr| attr.ty_value().map_err(Diagnostic::emit).ok());
let (impl_generics, ..) = item.generics.split_for_impl();
let lifetimes = item.generics.lifetimes().collect::<Vec<_>>();
let ty_params = item.generics.type_params().collect::<Vec<_>>();
let struct_ty = ty_for_foreign_derive(&item, &flags)?;
let tokens = sql_types.map(|sql_type| {
let lifetimes = &lifetimes;
let ty_params = &ty_params;
let tokens = quote!(
impl<'expr, #(#lifetimes,)* #(#ty_params,)*> AsExpression<#sql_type>
for &'expr #struct_ty
{
type Expression = Bound<#sql_type, Self>;
fn as_expression(self) -> Self::Expression {
Bound::new(self)
}
}
impl<'expr, #(#lifetimes,)* #(#ty_params,)*> AsExpression<Nullable<#sql_type>>
for &'expr #struct_ty
{
type Expression = Bound<Nullable<#sql_type>, Self>;
fn as_expression(self) -> Self::Expression {
Bound::new(self)
}
}
impl<'expr2, 'expr, #(#lifetimes,)* #(#ty_params,)*> AsExpression<#sql_type>
for &'expr2 &'expr #struct_ty
{
type Expression = Bound<#sql_type, Self>;
fn as_expression(self) -> Self::Expression {
Bound::new(self)
}
}
impl<'expr2, 'expr, #(#lifetimes,)* #(#ty_params,)*> AsExpression<Nullable<#sql_type>>
for &'expr2 &'expr #struct_ty
{
type Expression = Bound<Nullable<#sql_type>, Self>;
fn as_expression(self) -> Self::Expression {
Bound::new(self)
}
}
impl<#(#lifetimes,)* #(#ty_params,)* __DB> diesel::serialize::ToSql<Nullable<#sql_type>, __DB>
for #struct_ty
where
__DB: diesel::backend::Backend,
Self: ToSql<#sql_type, __DB>,
{
fn to_sql<W: std::io::Write>(&self, out: &mut Output<W, __DB>) -> serialize::Result {
ToSql::<#sql_type, __DB>::to_sql(self, out)
}
}
);
if is_sized {
quote!(
#tokens
impl#impl_generics AsExpression<#sql_type> for #struct_ty {
type Expression = Bound<#sql_type, Self>;
fn as_expression(self) -> Self::Expression {
Bound::new(self)
}
}
impl#impl_generics AsExpression<Nullable<#sql_type>> for #struct_ty {
type Expression = Bound<Nullable<#sql_type>, Self>;
fn as_expression(self) -> Self::Expression {
Bound::new(self)
}
}
)
} else {
tokens
}
});
if any_sql_types {
Ok(wrap_in_dummy_mod(
Ident::new(&dummy_mod, Span::call_site()),
quote! {
use diesel::expression::AsExpression;
use diesel::expression::bound::Bound;
use diesel::sql_types::Nullable;
use diesel::serialize::{self, ToSql, Output};
#(#tokens)*
},
))
} else {
Ok(quote!())
}
}