struct_to_json_db/
lib.rs

1pub use struct_to_json_db_macro::auto_json_db; 
2use std::fs;
3use std::path::Path;
4use std::io::Write; 
5use rand::Rng;
6use magic_crypt::{ new_magic_crypt, MagicCryptTrait};
7pub use paste::paste;
8use lazy_static::lazy_static;
9use std::sync::Mutex;
10
11pub fn read_string_from_txt(filename: &str) -> String {
12    let file_contents = fs::read_to_string(filename).unwrap_or_default();
13    file_contents
14}
15pub fn write_string_to_txt(filename: &str, content: String) {
16    
17    let mut file = fs::OpenOptions::new()
18        .write(true)
19        .create(true)
20        .truncate(true)
21        .open(filename)
22        .unwrap();
23    file.write_all(content.as_bytes()).unwrap();
24}
25pub fn write_string_to_txt_encript(filename: &str, content: String,encript:&str) {
26    write_string_to_txt(filename, string_to_crypt(content,encript));
27}
28pub fn read_string_from_txt_encript(filename: &str,encript:&str) -> String {
29    let file_contents = read_string_from_txt(filename);
30    crypt_to_string(file_contents,encript)
31}
32fn string_to_crypt(s: String,encript:&str) -> String {
33    let mc = new_magic_crypt!(encript, 256);
34    mc.encrypt_str_to_base64(s)
35}
36fn crypt_to_string(s: String,encript:&str) -> String {
37    let mc = new_magic_crypt!(encript, 256);
38    match mc.decrypt_base64_to_string(&s) {
39        Ok(r) => r,
40        Err(_) => s,
41    }
42}
43
44pub fn unique_id() -> (u64,u64) {
45    let start = std::time::SystemTime::now();
46    let timestamp = start.duration_since(std::time::UNIX_EPOCH).unwrap().as_nanos() as u64 ;
47    let random_number = rand::thread_rng().gen::<u64>();
48    (random_number,timestamp)
49}
50pub fn make_folder_if_not_exist(path:&str){
51    let path = Path::new(path);
52    if !path.exists() {
53        let _ = fs::create_dir_all(path) ;
54    }
55}
56 
57pub fn remove_file_by_path(path: &str) {
58    let path = Path::new(path);
59    if path.exists() {
60        let _ = fs::remove_file(path);
61    }  
62}
63pub fn remove_all_files_by_path(path: &str)  {
64    // Convert the input string to a Path
65    let path = Path::new(path);
66    if path.exists() {
67        // Remove the directory and all its contents (files and subdirectories)
68        let _ = fs::remove_dir_all(path);
69    }  
70}
71
72use sha2::{Sha256, Digest};
73pub fn string_to_unique_id(input: &str) -> String {
74    // Create a SHA-256 hasher
75    let mut hasher = Sha256::new();
76
77    // Feed the input string into the hasher
78    hasher.update(input.as_bytes()); // Explicitly convert to bytes
79
80    // Finalize the hash and get the result as a byte array
81    let hash_result = hasher.finalize();
82
83    // Convert the byte array to a hexadecimal string
84    hash_result
85        .iter()
86        .map(|byte| format!("{:02x}", byte))
87        .collect()
88}
89
90
91#[macro_export]
92macro_rules! json_db_get_by {
93    ($first:ident, $second:ident:$second_type:expr) => {
94        struct_to_json_db::paste! {
95            |all_data:&HashMap<u64, [<$first>]>,byval:[<$second_type>]|->Vec<(u64,[<$first>])>{
96                all_data.iter().filter_map(|(id, obj)| {
97                    if obj.[<$second>] == byval {
98                        Some((id.clone(), obj.clone()))
99                    } else {
100                        None
101                    }
102                    }).collect()      
103            }
104        }
105    };
106}
107pub fn set_struct_json_path(path_str:&str){
108    *DB_STRUCT_JSON_PATH.lock().unwrap() = String::from(path_str);
109} 
110pub fn get_struct_json_path() -> String {
111    DB_STRUCT_JSON_PATH.lock().unwrap().clone()
112}
113
114lazy_static! {
115    static ref DB_STRUCT_JSON_PATH: Mutex<String> = Mutex::new(String::from("./local_db/"));
116}
117#[macro_export]
118macro_rules! auto_json_db_config {
119    ($path_str:expr) => {
120        use struct_to_json_db::*;
121        use serde::{Deserialize, Serialize}; 
122    };
123}
124
125#[macro_export]
126macro_rules! auto_json_db_single{
127    ($struct:ident) => {
128        struct_to_json_db::paste! {
129            impl [<$struct>] {
130                pub fn save(&self) {
131                    let file_path =get_struct_json_path() + "/" + stringify!($struct) + ".json";
132                    let json_data = serde_json::to_string(self).unwrap();
133                    write_string_to_txt(&file_path, json_data);
134                }
135                pub fn load()->Self{
136                    let file_path = get_struct_json_path() + "/" + stringify!($struct) + ".json";
137                    let file_contents = read_string_from_txt(&file_path);
138                    if file_contents.is_empty() {
139                        [<$struct>]::default()
140
141                    }else{
142                        let r = serde_json::from_str(&file_contents).ok();
143                        r.unwrap_or_default()
144                    }
145                    
146                }
147            }
148        }
149    };
150    ($struct:ident, $pass:literal) => {
151        struct_to_json_db::paste! {
152           
153            impl [<$struct>] {
154                pub fn save(&self) {
155                    let file_path = get_struct_json_path() + "/" + stringify!($struct) + ".json";
156                    let json_data = serde_json::to_string(self).unwrap();
157                    write_string_to_txt_encript(&file_path, json_data,$pass);
158                }
159                pub fn load()->Self{
160                    let file_path = get_struct_json_path() + "/" + stringify!($struct) + ".json";
161                    let file_contents = read_string_from_txt_encript(&file_path,$pass);
162                    if file_contents.is_empty() {
163                        [<$struct>]::default()
164                    }else{
165                        let r = serde_json::from_str(&file_contents).ok();
166                        r.unwrap_or_default()
167                    }
168                    
169                }
170            }        
171            
172        }
173    };
174}
175#[macro_export]
176macro_rules! auto_json_db_one_file{
177    ($struct:ident) => {
178        struct_to_json_db::paste! {
179            impl [<$struct>] {
180                pub fn save(&self) {
181                    let mut data = Self::load();
182                    let is_available = data.iter().any(|i| i == self);
183                    if !is_available {
184                        data.push(self.clone());
185                        let file_path = get_struct_json_path() + "/" + stringify!($struct) + ".json";
186                        let json_data = serde_json::to_string(&data).unwrap();
187                        write_string_to_txt(&file_path, json_data);
188                    }
189                }
190                pub fn remove(&self){
191                    let mut data = Self::load();
192                    let is_available = data.iter().any(|i| i == self);
193                    if is_available {
194                        data.retain(|i| i != self);
195                        let file_path = get_struct_json_path() + "/" + stringify!($struct) + ".json";
196                        let json_data = serde_json::to_string(&data).unwrap();
197                        write_string_to_txt(&file_path, json_data);
198                    }
199                }
200                pub fn save_all(data:&Vec<Self>){
201                    let file_path = get_struct_json_path() + "/" + stringify!($struct) + ".json";
202                    let json_data = serde_json::to_string(data).unwrap();
203                    write_string_to_txt(&file_path, json_data);
204                }
205                pub fn load()->Vec<Self>{
206                    let file_path = get_struct_json_path() + "/" + stringify!($struct) + ".json";
207                    let file_contents = read_string_from_txt(&file_path);
208                    if file_contents.is_empty() {
209                        vec![]
210                    }else{
211                        let r = serde_json::from_str(&file_contents).ok();
212                        r.unwrap_or(vec![])
213                    }
214                    
215                }
216            } 
217        } 
218    }
219}
220
221#[macro_export]
222macro_rules! json_db_relation {
223    ($first:ident=$field:ident, $second:ident) => {
224        struct_to_json_db::paste! {
225            impl [<$first>] {
226                pub fn [<get_ $field>](&self)->Vec<[<$second>]>{
227                    let data = [<$second>]::get_by_ids(&self.[<$field>]);
228                    data
229                }
230                pub fn [<set_ $field>](&mut self,v:&Vec<[<$second>]>){
231                    self.[<$field>] = v.iter().map(|item| item.idx).collect();
232                    self.save();
233                } 
234            }           
235        }
236    };
237    ($first:ident=$field:ident, $second:ident,"1:1") => {
238        struct_to_json_db::paste! {
239            impl [<$first>] {
240                pub fn [<get_ $field>](&self)->Option<[<$second>]>{
241                    let data = [<$second>]::get_by_id(self.[<$field>]);
242                    data
243                }
244                pub fn [<set_ $field>](&mut self,v:&[<$second>]){
245                    self.[<$field>] = v.idx;
246                    self.save();
247                } 
248            }           
249        }
250    };
251    
252}
253
254 
255
256#[macro_export]
257macro_rules! mapping_json_struct {
258    (
259        $(#[$meta:meta])*
260        $vis:vis struct $name:ident {
261            $($field_vis:vis $field_name:ident : $field_type:ty),*
262            $(,)?
263        }
264    ) => {
265        paste! {
266            $(#[$meta])*
267            
268            $vis struct [<Behalf $name>] {
269                $($field_vis $field_name : $field_type),*
270            }
271
272            impl [<Behalf $name>] {
273                // Implement the `load` function
274                $vis fn to(&self) -> [<$name>] {
275                    [<$name>] {
276                        $($field_name: self.$field_name.clone()),*
277                    }
278                }
279            }
280
281            impl From<$name> for [<Behalf $name>] {
282                fn from(item: $name) -> Self {
283                    let now_idx = struct_to_json_db::unique_id(); 
284                    [<Behalf $name>] {
285                        idx: now_idx.0^now_idx.1,
286                        created_at: now_idx.1,
287                        $($field_name: item.$field_name),*
288                    }
289                }
290                
291            }
292
293        }
294    };
295}