atmosphere_macros/derive/
bindings.rs

1use proc_macro2::TokenStream;
2use quote::quote;
3use syn::Ident;
4
5use crate::schema::table::Table;
6
7pub fn bindings(table: &Table) -> TokenStream {
8    let col = Ident::new("col", proc_macro2::Span::call_site());
9    let query = Ident::new("query", proc_macro2::Span::call_site());
10
11    let mut binds = TokenStream::new();
12
13    {
14        let field = &table.primary_key.name.field();
15
16        binds.extend(quote!(
17            if #col.field() == Self::PRIMARY_KEY.field {
18                use ::atmosphere::Bindable;
19                return Ok(#query.dyn_bind(&self.#field));
20            }
21        ));
22    }
23
24    for fk in &table.foreign_keys {
25        let field = fk.name.field();
26
27        binds.extend(quote!(
28            if #col.field() == stringify!(#field) {
29                use ::atmosphere::Bindable;
30                return Ok(#query.dyn_bind(&self.#field));
31            }
32        ));
33    }
34
35    for data in &table.data_columns {
36        let field = data.name.field();
37
38        if data.modifiers.json {
39            binds.extend(quote!(
40                if #col.field() == stringify!(#field) {
41                    use ::atmosphere::Bindable;
42                    use ::atmosphere::sqlx::types::Json;
43                    return Ok(#query.dyn_bind(Json(&self.#field)));
44                }
45            ));
46        } else {
47            binds.extend(quote!(
48                if #col.field() == stringify!(#field) {
49                    use ::atmosphere::Bindable;
50                    return Ok(#query.dyn_bind(&self.#field));
51                }
52            ));
53        }
54    }
55
56    for ts in &table.timestamp_columns {
57        let field = ts.name.field();
58
59        binds.extend(quote!(
60            if #col.field() == stringify!(#field) {
61                use ::atmosphere::Bindable;
62                return Ok(#query.dyn_bind(&self.#field));
63            }
64        ));
65    }
66
67    let ident = &table.ident;
68
69    quote!(
70        #[automatically_derived]
71        impl ::atmosphere::Bind for #ident {
72            fn bind<
73                'q,
74                Q: ::atmosphere::Bindable<'q>
75            >(
76                &'q self,
77                #col: &'q ::atmosphere::Column<Self>,
78                #query: Q
79            ) -> ::atmosphere::Result<Q> {
80                #binds
81
82                Err(::atmosphere::Error::Bind(
83                    ::atmosphere::bind::BindError::Unknown(#col.field())
84                ))
85            }
86        }
87    )
88}