1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
use crate::ast;
use proc_macro2::{Span, TokenStream};
use quote::quote;

pub(super) fn generate_interning_tables(schema: &ast::DatabaseSchema) -> TokenStream {
    let mut fields = TokenStream::new();
    let mut conversions = TokenStream::new();
    let mut longest = 2;
    for ast::InterningTable {
        ref name,
        ref key,
        ref value,
    } in &schema.interning_tables
    {
        let key_type = &key.name;
        let field = quote! {
            pub #name: InterningTable<#key_type, #value>,
        };
        fields.extend(field);
        if let syn::Type::Tuple(syn::TypeTuple { elems, .. }) = value {
            if longest < elems.len() {
                longest = elems.len();
            }
        }
    }
    let mut args = TokenStream::new();
    let mut type_args = TokenStream::new();
    let mut type_constraints = TokenStream::new();
    for i in 0..longest {
        let arg = syn::Ident::new(&format!("v{}", i), Span::call_site());
        let type_arg = syn::Ident::new(&format!("V{}", i), Span::call_site());
        args.extend(quote! {#arg,});
        type_args.extend(quote! {#type_arg,});
        type_constraints.extend(quote! {
            #type_arg: crate::data_structures::InterningTableValue,
        });
        conversions.extend(quote! {
            impl<K, #type_args> Into<Vec<(K, #type_args)>> for InterningTable<K, (#type_args)>
                where
                    K: crate::data_structures::InterningTableKey,
                    #type_constraints
            {
                fn into(self) -> Vec<(K, #type_args)> {
                    self.contents.into_iter().enumerate().map(|(i, (#args))| {
                        (i.into(), #args)
                    }).collect()
                }
            }

        });
    }
    quote! {
        use crate::data_structures::InterningTable;
        #[derive(Default, Deserialize, Serialize)]
        /// Interning tables.
        pub struct InterningTables {
            #fields
        }
        #conversions
    }
}