light_magic/macros.rs
1/// Joins Data of different `Tables` in the Database together
2///
3/// ```
4/// use light_magic::{
5/// atomic::DataStore,
6/// join,
7/// serde::{Deserialize, Serialize},
8/// table::{PrimaryKey, Table},
9/// };
10///
11/// #[derive(Default, Debug, Serialize, Deserialize)]
12/// struct Database {
13/// user: Table<User>,
14/// criminal: Table<Criminal>,
15/// }
16///
17/// impl DataStore for Database {}
18///
19/// #[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
20/// struct User {
21/// id: usize,
22/// name: String,
23/// kind: String,
24/// }
25///
26/// impl PrimaryKey for User {
27/// type PrimaryKeyType = usize;
28///
29/// fn primary_key(&self) -> &Self::PrimaryKeyType {
30/// &self.id
31/// }
32/// }
33///
34/// #[derive(Default, Debug, Clone, Serialize, Deserialize)]
35/// struct Criminal {
36/// user_name: String,
37/// entry: String,
38/// }
39///
40/// impl PrimaryKey for Criminal {
41/// type PrimaryKeyType = String;
42///
43/// fn primary_key(&self) -> &Self::PrimaryKeyType {
44/// &self.user_name
45/// }
46/// }
47///
48/// let db = Database::open_in_memory();
49/// // Firstly specify the Database which should be used, then the key,
50/// // and lastly the joined items with the field which will be compared with the key
51/// let joined = join!(db.read(), "Nils", user => name, criminal => user_name);
52/// ```
53#[macro_export]
54macro_rules! join {
55 ($db:expr, $key:expr, $($table:ident => $field:ident),* $(,)?) => {{
56 $crate::paste::paste! {
57 let mut combined_results = Vec::new();
58
59 $(
60 let [<$table _results>]: Vec<_> = $db.$table.values()
61 .filter(|val| val.$field == $key)
62 .cloned()
63 .collect();
64 )*
65
66 let len = vec![$([<$table _results>].len()),*].into_iter().min().unwrap_or(0);
67
68 for i in 0..len {
69 combined_results.push((
70 $([<$table _results>][i].clone(),)*
71 ));
72 }
73
74 combined_results
75 }
76 }}
77}