1use proc_macro2::{Span, TokenStream};
2use quote::quote;
3use syn::{parse_quote, DeriveInput, Ident, Index, Result};
4
5use crate::field::Field;
6use crate::model::Model;
7use crate::util::wrap_in_dummy_mod;
8
9pub fn derive(item: DeriveInput) -> Result<TokenStream> {
10 let model = Model::from_item(&item, false, true)?;
11
12 let struct_name = &item.ident;
13 let field_ty = &model
14 .fields()
15 .iter()
16 .map(Field::ty_for_deserialize)
17 .collect::<Vec<_>>();
18 let build_expr = model.fields().iter().enumerate().map(|(i, f)| {
19 let field_name = &f.name;
20 let i = Index::from(i);
21 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&field_name, &mut _s);
::quote::__private::push_colon(&mut _s);
::quote::__private::push_ident(&mut _s, "row");
::quote::__private::push_dot(&mut _s);
::quote::ToTokens::to_tokens(&i, &mut _s);
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "try_into");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_question(&mut _s);
_s
}quote!(#field_name: row.#i.try_into()?)
26 });
27 let sql_type = &(0..model.fields().len())
28 .map(|i| {
29 let i = Ident::new(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("__ST{0}", i))
})format!("__ST{i}"), Span::mixed_site());
30 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&i, &mut _s);
_s
}quote!(#i)
31 })
32 .collect::<Vec<_>>();
33
34 let (_, ty_generics, _) = item.generics.split_for_impl();
35 let mut generics = item.generics.clone();
36 generics
37 .params
38 .push(::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "__DB");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_ident(&mut _s, "diesel");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "backend");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Backend");
_s
})parse_quote!(__DB: diesel::backend::Backend));
39 for id in 0..model.fields().len() {
40 let ident = Ident::new(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("__ST{0}", id))
})format!("__ST{id}"), Span::mixed_site());
41 generics.params.push(::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&ident, &mut _s);
_s
})parse_quote!(#ident));
42 }
43 {
44 let where_clause = generics.where_clause.get_or_insert(::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "where");
_s
})parse_quote!(where));
45 where_clause
46 .predicates
47 .push(::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut field_ty, i) = field_ty.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let field_ty =
match field_ty.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&field_ty, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
_s
});
::quote::__private::push_colon(&mut _s);
::quote::__private::push_ident(&mut _s, "diesel");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "deserialize");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "FromStaticSqlRow");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut sql_type, i) = sql_type.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let sql_type =
match sql_type.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&sql_type, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
_s
});
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "__DB");
::quote::__private::push_gt(&mut _s);
_s
})parse_quote!((#(#field_ty,)*): diesel::deserialize::FromStaticSqlRow<(#(#sql_type,)*), __DB>));
48 }
49 let (impl_generics, _, where_clause) = generics.split_for_impl();
50
51 Ok(wrap_in_dummy_mod({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "use");
::quote::__private::push_ident(&mut _s, "diesel");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "row");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "Row");
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_underscore(&mut _s);
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "Field");
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_underscore(&mut _s);
_s
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "impl");
::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
::quote::__private::push_ident(&mut _s, "diesel");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "deserialize");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Queryable");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut sql_type, i) = sql_type.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let sql_type =
match sql_type.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&sql_type, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
_s
});
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "__DB");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_ident(&mut _s, "for");
::quote::ToTokens::to_tokens(&struct_name, &mut _s);
::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
::quote::ToTokens::to_tokens(&where_clause, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "type");
::quote::__private::push_ident(&mut _s, "Row");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut field_ty, i) = field_ty.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let field_ty =
match field_ty.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&field_ty, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
_s
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "build");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "row");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut field_ty, i) = field_ty.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let field_ty =
match field_ty.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&field_ty, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
_s
});
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_ident(&mut _s, "diesel");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "deserialize");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Result");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "use");
::quote::__private::push_ident(&mut _s, "std");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "convert");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "TryInto");
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "diesel");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "deserialize");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Result");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Ok");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut build_expr, i) = build_expr.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let build_expr =
match build_expr.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&build_expr, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
_s
});
_s
});
_s
});
_s
});
_s
}quote! {
52 use diesel::row::{Row as _, Field as _};
53
54 impl #impl_generics diesel::deserialize::Queryable<(#(#sql_type,)*), __DB> for #struct_name #ty_generics
55 #where_clause
56 {
57 type Row = (#(#field_ty,)*);
58
59 fn build(row: (#(#field_ty,)*)) -> diesel::deserialize::Result<Self> {
60 use std::convert::TryInto;
61 diesel::deserialize::Result::Ok(Self {
62 #(#build_expr,)*
63 })
64 }
65 }
66 }))
67}