-
Notifications
You must be signed in to change notification settings - Fork 14
/
struct_db.rs
139 lines (122 loc) · 5.19 KB
/
struct_db.rs
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
use proc_macro::{Span, TokenStream};
use quote::quote;
use std::cell::RefCell;
use std::collections::HashSet;
use syn::{parse_macro_input, DeriveInput, Ident};
pub fn struct_db(args: TokenStream, input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
let struct_name = &ast.ident;
let fn_primary_key_def: RefCell<Option<Ident>> = RefCell::new(None);
let fn_secondary_keys_def: RefCell<HashSet<Ident>> = RefCell::new(HashSet::new());
let simple_parser = syn::meta::parser(|meta| {
if meta.path.is_ident("fn_primary_key") {
meta.parse_nested_meta(|meta| {
if let Some(iden) = meta.path.get_ident() {
*fn_primary_key_def.borrow_mut() = Some(iden.clone());
}
Ok(())
})?;
}
if meta.path.is_ident("fn_secondary_key") {
meta.parse_nested_meta(|meta| {
if let Some(iden) = meta.path.get_ident() {
let mut fn_secondary_keys_values = fn_secondary_keys_def.borrow_mut();
fn_secondary_keys_values.insert(iden.clone());
}
Ok(())
})?;
}
return Ok(());
});
if !args.to_string().is_empty() {
parse_macro_input!(args with simple_parser);
}
// Value of the table:
let table_name = struct_name.to_string().to_lowercase();
let primary_key_function_value = fn_primary_key_def
.borrow()
.clone()
.expect("fn_primary_key is required");
let primary_key_name = primary_key_function_value.to_string().to_lowercase();
let fn_secondary_keys_name = fn_secondary_keys_def.borrow().clone();
let fn_secondary_keys_name = fn_secondary_keys_name
.iter()
.map(|fn_secondary_key| {
let fn_secondary_key_name = fn_secondary_key.to_string().to_lowercase();
let secondary_table = format!("{}_{}", table_name, fn_secondary_key_name);
(
Ident::new(&fn_secondary_key_name, Span::call_site().into()),
Ident::new(&secondary_table, Span::call_site().into()),
)
})
.collect::<Vec<(Ident, Ident)>>();
let struct_db_keys_tokens = fn_secondary_keys_name.iter().map(|fn_secondary_key| {
let (fn_secondary_key_name, secondary_table) = fn_secondary_key.clone();
let secondary_table = secondary_table.to_string();
quote! {
secondary_tables_name.insert(#secondary_table, self.#fn_secondary_key_name());
}
});
let struct_db_schema_tokens = fn_secondary_keys_name.iter().map(|fn_secondary_key| {
let (_, secondary_table) = fn_secondary_key.clone();
let secondary_table = secondary_table.to_string();
quote! {
secondary_tables_name.insert(#secondary_table);
}
});
let keys_enum_name_token = Ident::new(&format!("{}Key", struct_name), Span::call_site().into());
let keys_enum_tokens = fn_secondary_keys_name.iter().map(|fn_secondary_key| {
let (fn_secondary_key_name, _) = fn_secondary_key.clone();
quote! {
#fn_secondary_key_name
}
});
let keys_enum_fn_secondary_table_name_tokens =
fn_secondary_keys_name.iter().map(|fn_secondary_key| {
let (fn_key_name, secondary_table) = fn_secondary_key.clone();
let secondary_table = secondary_table.to_string();
quote! {
#keys_enum_name_token::#fn_key_name => #secondary_table,
}
});
let gen = quote! {
#ast
impl struct_db::SDBItem for #struct_name {
fn struct_db_bincode_encode_to_vec(&self) -> Vec<u8> {
struct_db::bincode_encode_to_vec(self).expect("Failed to serialize the struct #struct_name")
}
fn struct_db_bincode_decode_from_slice(slice: &[u8]) -> Self {
struct_db::bincode_decode_from_slice(slice).expect("Failed to deserialize the struct #struct_name").0
}
fn struct_db_schema() -> struct_db::Schema {
let mut secondary_tables_name = std::collections::HashSet::new();
#(#struct_db_schema_tokens)*
struct_db::Schema {
table_name: #table_name,
primary_key: #primary_key_name,
secondary_tables_name: secondary_tables_name,
}
}
fn struct_db_primary_key(&self) -> Vec<u8> {
self.#primary_key_function_value()
}
fn struct_db_keys(&self) -> std::collections::HashMap<&'static str, Vec<u8>> {
let mut secondary_tables_name = std::collections::HashMap::new();
#(#struct_db_keys_tokens)*
secondary_tables_name
}
}
enum #keys_enum_name_token {
#(#keys_enum_tokens),*
}
impl struct_db::KeyDefinition for #keys_enum_name_token {
fn secondary_table_name(&self) -> &'static str {
match self {
#(#keys_enum_fn_secondary_table_name_tokens)*
_ => panic!("Unknown key"),
}
}
}
};
gen.into()
}