Skip to main content

diesel_derives/
diesel_for_each_tuple.rs

1use proc_macro2::{Ident, Span, TokenStream};
2use quote::quote;
3
4pub(crate) fn expand(input: ForEachTupleInput) -> TokenStream {
5    let call_side = Span::mixed_site();
6
7    let pairs = (0..input.max_size as usize)
8        .map(|i| {
9            let (t, st, tt) = if i == 0 {
10                // special case these, as #[doc(fake_variadic)]
11                // uses the first generic parameter as `T_n` and `T_n` looks
12                // much better than `T0_n`
13                let t = Ident::new("T", call_side);
14                let st = Ident::new("ST", call_side);
15                let tt = Ident::new("TT", call_side);
16                (t, st, tt)
17            } else {
18                let t = Ident::new(&::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("T{0}", i)) })format!("T{i}"), call_side);
19                let st = Ident::new(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("ST{0}", i))
    })format!("ST{i}"), call_side);
20                let tt = Ident::new(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("TT{0}", i))
    })format!("TT{i}"), call_side);
21                (t, st, tt)
22            };
23            let i = syn::Index::from(i);
24            {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&i, &mut _s);
            _s
        });
    ::quote::__private::push_rarrow(&mut _s);
    ::quote::ToTokens::to_tokens(&t, &mut _s);
    ::quote::__private::push_comma(&mut _s);
    ::quote::ToTokens::to_tokens(&st, &mut _s);
    ::quote::__private::push_comma(&mut _s);
    ::quote::ToTokens::to_tokens(&tt, &mut _s);
    ::quote::__private::push_comma(&mut _s);
    _s
}quote!((#i) -> #t, #st, #tt,)
25        })
26        .collect::<Vec<_>>();
27
28    let mut out = Vec::with_capacity(input.max_size as usize);
29
30    for i in 0..input.max_size {
31        let items = &pairs[0..=i as usize];
32        let tuple = i + 1;
33        out.push({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&tuple, &mut _s);
    ::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 items, i) = items.quote_into_iter();
                let has_iter = has_iter | i;
                <_ as
                        ::quote::__private::CheckHasIterator<true>>::check(has_iter);
                while true {
                    let items =
                        match items.next() {
                            Some(_x) => ::quote::__private::RepInterp(_x),
                            None => break,
                        };
                    ::quote::ToTokens::to_tokens(&items, &mut _s);
                }
            }
            _s
        });
    _s
}quote! {
34            #tuple {
35                #(#items)*
36            }
37        });
38    }
39    let input = input.inner;
40
41    {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&input, &mut _s);
    ::quote::__private::push_bang(&mut _s);
    ::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 out, i) = out.quote_into_iter();
                let has_iter = has_iter | i;
                <_ as
                        ::quote::__private::CheckHasIterator<true>>::check(has_iter);
                while true {
                    let out =
                        match out.next() {
                            Some(_x) => ::quote::__private::RepInterp(_x),
                            None => break,
                        };
                    ::quote::ToTokens::to_tokens(&out, &mut _s);
                }
            }
            _s
        });
    _s
}quote! {
42        #input! {
43            #(#out)*
44        }
45    }
46}
47
48pub struct ForEachTupleInput {
49    inner: Ident,
50    max_size: u16,
51}
52
53impl syn::parse::Parse for ForEachTupleInput {
54    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
55        let inner = input.parse()?;
56        input.parse::<::syn::token::Commasyn::Token![,]>()?;
57        let max_size = if input.peek(syn::Ident) {
58            let macro_ident = input.parse::<syn::Ident>()?;
59            if macro_ident != "env" {
60                return Err(syn::Error::new(
61                    macro_ident.span(),
62                    "only the `env!` macro is expected here",
63                ));
64            }
65            let _bang = input.parse::<::syn::token::Notsyn::Token![!]>()?;
66            let name;
67            match ::syn::__private::parse_parens(&input) {
    ::syn::__private::Ok(parens) => {
        name = parens.content;
        _ = name;
        parens.token
    }
    ::syn::__private::Err(error) => { return ::syn::__private::Err(error); }
};syn::parenthesized!(name in input);
68            let s = name.parse::<syn::LitStr>()?;
69            std::env::var(s.value())
70                .map_err(|_| {
71                    syn::Error::new(
72                        s.span(),
73                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Expected `{0}` to be set as environment variable",
                s.value()))
    })format!("Expected `{}` to be set as environment variable", s.value()),
74                    )
75                })?
76                .parse::<u16>()
77                .map_err(|_| {
78                    syn::Error::new(
79                        s.span(),
80                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Expected `{0}` to be a u16 integer value",
                s.value()))
    })format!("Expected `{}` to be a u16 integer value", s.value()),
81                    )
82                })?
83        } else {
84            input.parse::<syn::LitInt>()?.base10_parse()?
85        };
86        Ok(Self { inner, max_size })
87    }
88}