diesel_derives/
allow_tables_to_appear_in_same_query.rs

1use proc_macro2::TokenStream;
2use quote::quote;
3use syn::parse::{Parse, ParseStream, Result};
4use syn::punctuated::Punctuated;
5use syn::{Path, Token};
6
7struct AllowTablesToAppearInSameQuery {
8    tables: Punctuated<Path, ::syn::token::CommaToken![,]>,
9}
10
11impl Parse for AllowTablesToAppearInSameQuery {
12    fn parse(input: ParseStream) -> Result<Self> {
13        Ok(AllowTablesToAppearInSameQuery {
14            tables: input.parse_terminated(Path::parse, ::syn::token::CommaToken![,])?,
15        })
16    }
17}
18
19pub fn expand(input: TokenStream) -> TokenStream {
20    let input: AllowTablesToAppearInSameQuery = match syn::parse2(input) {
21        Ok(input) => input,
22        Err(e) => return e.to_compile_error(),
23    };
24
25    let tables: Vec<Path> = input.tables.into_iter().collect();
26    let amount_of_tables = tables.len();
27    let mut left_impls = Vec::with_capacity(amount_of_tables * (amount_of_tables - 1));
28    let mut right_impls = Vec::with_capacity(amount_of_tables * (amount_of_tables - 1));
29
30    for (i, left) in tables.iter().enumerate() {
31        for right in tables.iter().skip(i + 1) {
32            left_impls.push(left);
33            right_impls.push(right);
34
35            left_impls.push(right);
36            right_impls.push(left);
37        }
38    }
39
40    {
    let mut _s = ::quote::__private::TokenStream::new();
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut right_impls, i) = right_impls.quote_into_iter();
        let has_iter = has_iter | i;
        #[allow(unused_mut)]
        let (mut left_impls, i) = left_impls.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let right_impls =
                match right_impls.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            let left_impls =
                match left_impls.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::__private::push_ident(&mut _s, "impl");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "diesel");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "query_source");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "TableNotEqual");
            ::quote::__private::push_lt(&mut _s);
            ::quote::ToTokens::to_tokens(&right_impls, &mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "table");
            ::quote::__private::push_gt(&mut _s);
            ::quote::__private::push_ident(&mut _s, "for");
            ::quote::ToTokens::to_tokens(&left_impls, &mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "table");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                ::quote::__private::TokenStream::new());
        }
    }
    _s
}quote! {
41        #(
42            impl ::diesel::query_source::TableNotEqual<#right_impls::table> for #left_impls::table {}
43        )*
44    }
45}