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 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
use super::utils::is_copy_type; use crate::ast; use proc_macro2::TokenStream; use quote::quote; pub(super) fn generate_load_save_functions(schema: &ast::DatabaseSchema) -> TokenStream { let load_multifile_relations = load_multifile_relations_function(schema); let load_counters = load_counters_function(); let load_interning_tables = load_multifle_interning_function(schema); let store_multifile_relations = store_multifile_relations_function(schema); let store_counters = store_counters_function(); let store_interning_tables = store_multifle_interning_function(schema); quote! { impl Tables { pub fn load_multifile( database_root: &Path ) -> Result<Tables, Error> { let relations = load_multifile_relations(&database_root.join("relations"))?; let counters = load_counters(&database_root.join("counters.bincode"))?; let interning_tables = load_interning_tables(&database_root.join("interning"))?; Ok(Tables { relations, counters, interning_tables, }) } pub fn load_single_file( tables_file: &Path ) -> Result<Tables, Error> { crate::storage::load(tables_file) } pub fn store_multifile(&self, database_root: &Path) -> Result<(), Error> { let relations_path = database_root.join("relations"); std::fs::create_dir_all(&relations_path)?; store_multifile_relations(&self.relations, &relations_path); let counters_path = database_root.join("counters.bincode"); store_counters(&self.counters, &counters_path); let interning_tables_path = &database_root.join("interning"); std::fs::create_dir_all(&interning_tables_path)?; store_multifile_interning_tables( &self.interning_tables, &interning_tables_path ); Ok(()) } } #load_multifile_relations #load_counters #load_interning_tables #store_multifile_relations #store_counters #store_interning_tables } } fn load_multifile_relations_function(schema: &ast::DatabaseSchema) -> TokenStream { let mut load_fields = TokenStream::new(); for relation in &schema.relations { let relation_hash = relation.get_hash(); let name = &relation.name; let file_name = format!("{}", name); load_fields.extend(quote! { #name: unsafe { Relation::load(#relation_hash, path.join(#file_name)) }?, }); } quote! { fn load_multifile_relations(path: &Path) -> Result<Relations, Error> { Ok(Relations { #load_fields }) } } } fn store_multifile_relations_function(schema: &ast::DatabaseSchema) -> TokenStream { let mut store_fields = TokenStream::new(); for relation in &schema.relations { let name = &relation.name; let relation_hash = relation.get_hash(); let file_name = name.to_string(); store_fields.extend(quote! { unsafe { relations.#name.save(#relation_hash, path.join(#file_name)) } }); } quote! { fn store_multifile_relations( relations: &Relations, path: &Path ) { #store_fields } } } fn load_counters_function() -> TokenStream { quote! { fn load_counters(path: &Path) -> Result<Counters, Error> { crate::storage::load(&path) } } } fn store_counters_function() -> TokenStream { quote! { fn store_counters(counters: &Counters, path: &Path) { crate::storage::save(counters, &path); } } } fn load_multifle_interning_function(schema: &ast::DatabaseSchema) -> TokenStream { let mut load_fields = TokenStream::new(); for table in &schema.interning_tables { let ast::InterningTable { name, value, .. } = table; if is_copy_type(value, schema) { let table_hash = table.get_hash(); let file_name = name.to_string(); load_fields.extend(quote! { #name: unsafe { InterningTable::load(#table_hash, path.join(#file_name))? }, }); } else { let file_name = format!("{}.bincode", name); load_fields.extend(quote! { #name: crate::storage::load(&path.join(#file_name))?, }); } } quote! { fn load_interning_tables(path: &Path) -> Result<InterningTables, Error> { Ok(InterningTables { #load_fields }) } } } fn store_multifle_interning_function(schema: &ast::DatabaseSchema) -> TokenStream { let mut store_fields = TokenStream::new(); for table in &schema.interning_tables { let ast::InterningTable { name, value, .. } = table; if is_copy_type(value, schema) { let table_hash = table.get_hash(); let file_name = name.to_string(); store_fields.extend(quote! { unsafe { interning_tables.#name.save(#table_hash, path.join(#file_name)); } }); } else { let file_name = format!("{}.bincode", name); store_fields.extend(quote! { crate::storage::save(&interning_tables.#name, &path.join(#file_name)); }); } } quote! { fn store_multifile_interning_tables( interning_tables: &InterningTables, path: &Path ) { #store_fields } } }