|
| 1 | +use proc_macro2::Span; |
| 2 | +use quote; |
| 3 | +use syn; |
| 4 | + |
| 5 | +use model::*; |
| 6 | +use util::*; |
| 7 | + |
| 8 | +pub fn derive(item: syn::DeriveInput) -> Result<quote::Tokens, Diagnostic> { |
| 9 | + let model = Model::from_item(&item)?; |
| 10 | + |
| 11 | + let struct_name = item.ident; |
| 12 | + let field_ty = model.fields().iter().map(|f| &f.ty).collect::<Vec<_>>(); |
| 13 | + let field_ty = &field_ty; |
| 14 | + let build_expr = model.fields().iter().enumerate().map(|(i, f)| { |
| 15 | + let field_name = &f.name.for_assignment(); |
| 16 | + let i: syn::Index = i.into(); |
| 17 | + // Make sure `row` has a `def_site` span |
| 18 | + let row = quote!(row); |
| 19 | + // https://github.com/rust-lang/rust/issues/47311 |
| 20 | + let span = Span::call_site(); |
| 21 | + quote_spanned!(span=> #field_name: (#row.#i)) |
| 22 | + }); |
| 23 | + |
| 24 | + let (_, ty_generics, _) = item.generics.split_for_impl(); |
| 25 | + let mut generics = item.generics.clone(); |
| 26 | + generics |
| 27 | + .params |
| 28 | + .push(parse_quote!(__DB: diesel::backend::Backend)); |
| 29 | + generics.params.push(parse_quote!(__ST)); |
| 30 | + { |
| 31 | + let where_clause = generics.where_clause.get_or_insert(parse_quote!(where)); |
| 32 | + where_clause |
| 33 | + .predicates |
| 34 | + .push(parse_quote!((#(#field_ty,)*): Queryable<__ST, __DB>)); |
| 35 | + } |
| 36 | + let (impl_generics, _, where_clause) = generics.split_for_impl(); |
| 37 | + |
| 38 | + Ok(wrap_in_dummy_mod( |
| 39 | + model.dummy_mod_name("queryable"), |
| 40 | + quote! { |
| 41 | + use self::diesel::Queryable; |
| 42 | + |
| 43 | + impl #impl_generics Queryable<__ST, __DB> for #struct_name #ty_generics |
| 44 | + #where_clause |
| 45 | + { |
| 46 | + type Row = <(#(#field_ty,)*) as Queryable<__ST, __DB>>::Row; |
| 47 | + |
| 48 | + fn build(row: Self::Row) -> Self { |
| 49 | + let row: (#(#field_ty,)*) = Queryable::build(row); |
| 50 | + Self { |
| 51 | + #(#build_expr,)* |
| 52 | + } |
| 53 | + } |
| 54 | + } |
| 55 | + }, |
| 56 | + )) |
| 57 | +} |
0 commit comments