1use lazy_static::lazy_static;
2use serde::{Deserialize, Serialize};
3use serde_json::{from_str, to_string_pretty, Value};
4use std::fs::{self, File};
5use std::io::{Read, Write};
6use std::path::{Path, PathBuf};
7use std::sync::Mutex;
8
9lazy_static! {
10 static ref BASE_DIR: Mutex<PathBuf> = Mutex::new(PathBuf::new());
11}
12
13#[derive(Debug, Clone)]
15pub struct JsonDatabase<T> {
16 current_model_name: Option<String>,
17 _marker: std::marker::PhantomData<T>,
18}
19
20impl<T> JsonDatabase<T>
21where
22 T: Serialize + for<'de> Deserialize<'de> + Clone + Identifiable,
23{
24 pub fn new(model_name: Option<&str>) -> Self {
36 JsonDatabase {
37 current_model_name: model_name.map(String::from),
38 _marker: std::marker::PhantomData,
39 }
40 }
41
42 pub fn model(&mut self, model_name: &str) -> &mut Self {
55 self.current_model_name = Some(model_name.to_string());
56 create_directory_if_not_exists(&self.get_model_path(model_name));
57 self
58 }
59
60 fn base_path() -> PathBuf {
62 BASE_DIR.lock().unwrap().clone()
63 }
64
65 fn get_model_path(&self, model_name: &str) -> PathBuf {
71 Self::base_path().join(model_name)
72 }
73
74 fn get_file_path(&self, id: &str) -> PathBuf {
80 let model_name = self
81 .current_model_name
82 .as_ref()
83 .expect("Model name is not specified");
84 self.get_model_path(model_name).join(format!("{}.json", id))
85 }
86
87 fn get_all_files(&self) -> Vec<String> {
89 let model_name = self
90 .current_model_name
91 .as_ref()
92 .expect("Model name is not specified");
93 let model_path = self.get_model_path(model_name);
94 create_directory_if_not_exists(&model_path);
95
96 fs::read_dir(model_path)
97 .expect("Unable to read directory")
98 .filter_map(|entry| {
99 let entry = entry.expect("Unable to get directory entry");
100 let path = entry.path();
101 if path.extension().map_or(false, |ext| ext == "json") {
102 path.file_name()
103 .map(|name| name.to_string_lossy().into_owned())
104 } else {
105 None
106 }
107 })
108 .collect()
109 }
110
111 fn matches_condition(&self, item: &Value, condition: &Value) -> bool {
118 if !condition.is_object() || condition.is_null() {
119 return item == condition;
120 }
121 if !item.is_object() || item.is_null() {
122 return false;
123 }
124
125 condition.as_object().unwrap().iter().all(|(key, value)| {
126 let keys: Vec<&str> = key.split('.').collect();
127 let nested_value = self.get_nested_property(item, &keys);
128 if nested_value.is_object() && value.is_object() {
129 self.matches_condition(nested_value, value)
130 } else {
131 nested_value == value
132 }
133 })
134 }
135
136 fn get_nested_property<'a>(&self, obj: &'a Value, keys: &[&str]) -> &'a Value {
143 keys.iter()
144 .fold(obj, |acc, key| acc.get(*key).unwrap_or(&Value::Null))
145 }
146
147 fn set_nested_property(&self, obj: &mut Value, keys: &[&str], value: Value) {
155 if keys.len() == 1 {
156 obj[keys[0]] = value;
157 } else {
158 let key = keys[0];
159 let next_obj = obj
160 .as_object_mut()
161 .unwrap()
162 .entry(key)
163 .or_insert_with(|| Value::Object(Default::default()));
164 self.set_nested_property(next_obj, &keys[1..], value);
165 }
166 }
167
168 fn update_nested_object(&self, target: &mut Value, source: &Value) {
175 for (key, value) in source.as_object().unwrap().iter() {
176 let keys: Vec<&str> = key.split('.').collect();
177 self.set_nested_property(target, &keys, value.clone());
178 }
179 }
180
181 pub fn create_model(&self, data: T) {
191 let id = data.get_id();
192 if id.is_empty() {
193 panic!("Data must have an id field");
194 }
195 self.create(&id, data);
196 }
197
198 pub fn create(&self, id: &str, data: T) {
205 let file_path = self.get_file_path(id);
206 create_directory_if_not_exists(file_path.parent().unwrap()); write_json_file(&file_path, &data);
208 }
209
210 pub fn find_by_id(&self, id: &str) -> Option<T> {
220 let file_path = self.get_file_path(id);
221 read_json_file(&file_path)
222 }
223
224 pub fn update_by_id(&self, id: &str, data: Value) {
231 let file_path = self.get_file_path(id);
232
233 if let Some(mut existing_data) = self.find_by_id(id) {
234 let mut existing_json = serde_json::to_value(&existing_data).unwrap();
235
236 self.update_nested_object(&mut existing_json, &data);
237 let updated_data: T = serde_json::from_value(existing_json).unwrap();
238 write_json_file(&file_path, &updated_data);
239 }
240 }
241
242 pub fn delete_by_id(&self, id: &str) {
248 let file_path = self.get_file_path(id);
249 if file_path.exists() {
250 fs::remove_file(file_path).expect("Unable to delete file");
251 }
252 }
253
254 pub fn find_all(&self) -> Vec<T> {
260 let files = self.get_all_files();
261 files
262 .into_iter()
263 .filter_map(|file| {
264 read_json_file(
265 &self
266 .get_model_path(self.current_model_name.as_ref().unwrap())
267 .join(file),
268 )
269 })
270 .collect()
271 }
272
273 pub fn find(&self, condition: &Value) -> Vec<T> {
283 self.find_all()
284 .into_iter()
285 .filter(|item| self.matches_condition(&serde_json::to_value(item).unwrap(), condition))
286 .collect()
287 }
288
289 pub fn find_one(&self, condition: &Value) -> Option<T> {
299 self.find_all()
300 .into_iter()
301 .find(|item| self.matches_condition(&serde_json::to_value(item).unwrap(), condition))
302 }
303
304 pub fn count(&self, condition: &Value) -> usize {
314 self.find(condition).len()
315 }
316
317 pub fn update_many(&self, condition: &Value, data: &Value) {
324 let items = self.find(condition);
325 for item in items {
326 let id = item.get_id();
327 self.update_by_id(&id, data.clone());
328 }
329 }
330
331 pub fn delete_many(&self, condition: &Value) {
337 let items = self.find(condition);
338 for item in items {
339 let id = item.get_id();
340 self.delete_by_id(&id);
341 }
342 }
343
344 pub fn push(&self, condition: &Value, array_path: &str, element: &Value) {
352 let items = self.find(condition);
353 for item in items {
354 let id = item.get_id();
355 if let Some(data) = self.find_by_id(&id) {
356 let mut data_json = serde_json::to_value(&data).unwrap();
357 let keys: Vec<&str> = array_path.split('.').collect();
358 let array = self.get_nested_property(&data_json, &keys);
359 if array.is_array() {
360 let mut array = array.as_array().unwrap().clone();
361 array.push(element.clone());
362 self.set_nested_property(&mut data_json, &keys, Value::Array(array));
363 let updated_data: T = serde_json::from_value(data_json).unwrap();
364 self.update_by_id(&id, serde_json::to_value(updated_data).unwrap());
365 }
366 }
367 }
368 }
369
370 pub fn pull(&self, condition: &Value, array_path: &str, pull_condition: &Value) {
378 let items = self.find(condition);
379 for item in items {
380 let id = item.get_id();
381 if let Some(data) = self.find_by_id(&id) {
382 let mut data_json = serde_json::to_value(&data).unwrap();
383 let keys: Vec<&str> = array_path.split('.').collect();
384 let array = self.get_nested_property(&data_json, &keys);
385 if array.is_array() {
386 let new_array: Vec<Value> = array
387 .as_array()
388 .unwrap()
389 .iter()
390 .cloned()
391 .filter(|elem| !self.matches_condition(elem, pull_condition))
392 .collect();
393 self.set_nested_property(&mut data_json, &keys, Value::Array(new_array));
394 let updated_data: T = serde_json::from_value(data_json).unwrap();
395 self.update_by_id(&id, serde_json::to_value(updated_data).unwrap());
396 }
397 }
398 }
399 }
400
401 pub fn update_array(
410 &self,
411 condition: &Value,
412 array_path: &str,
413 array_condition: &Value,
414 updates: &Value,
415 ) {
416 let items = self.find(condition);
417 for item in items {
418 let id = item.get_id();
419 if let Some(data) = self.find_by_id(&id) {
420 let mut data_json = serde_json::to_value(&data).unwrap();
421 let keys: Vec<&str> = array_path.split('.').collect();
422 let array = self.get_nested_property(&data_json, &keys);
423 if array.is_array() {
424 let new_array: Vec<Value> = array
425 .as_array()
426 .unwrap()
427 .iter()
428 .cloned()
429 .map(|elem| {
430 if self.matches_condition(&elem, array_condition) {
431 let mut updated_elem = elem.clone();
432 self.update_nested_object(&mut updated_elem, updates);
433 updated_elem
434 } else {
435 elem
436 }
437 })
438 .collect();
439 self.set_nested_property(&mut data_json, &keys, Value::Array(new_array));
440 let updated_data: T = serde_json::from_value(data_json).unwrap();
441 self.update_by_id(&id, serde_json::to_value(updated_data).unwrap());
442 }
443 }
444 }
445 }
446}
447
448impl JsonDatabase<()> {
449 pub fn set_base_dir(base_dir: &str) {
461 let mut base_path = BASE_DIR.lock().unwrap();
462 *base_path = Path::new(base_dir).to_path_buf();
463 create_directory_if_not_exists(&base_path);
464 }
465}
466
467fn create_directory_if_not_exists(path: &Path) {
473 if !path.exists() {
474 fs::create_dir_all(path).expect("Unable to create directory");
475 }
476}
477
478fn read_json_file<T>(path: &Path) -> Option<T>
488where
489 T: for<'de> Deserialize<'de>,
490{
491 let mut file = File::open(path).ok()?;
492 let mut contents = String::new();
493 file.read_to_string(&mut contents).ok()?;
494 from_str(&contents).ok()
495}
496
497fn write_json_file<T>(path: &Path, data: &T)
504where
505 T: Serialize,
506{
507 let mut file = File::create(path).expect("Unable to create file");
508 let contents = to_string_pretty(data).expect("Unable to serialize data");
509 file.write_all(contents.as_bytes())
510 .expect("Unable to write to file");
511}
512
513pub trait Identifiable {
515 fn get_id(&self) -> String;
517}