1pub mod files {
2 pub mod several {
3 use std::collections::HashMap;
4 use std::{fs, thread};
5 use std::collections::hash_map::Iter;
6 use std::thread::JoinHandle;
7 use serde::de::DeserializeOwned;
8 use serde::Serialize;
9 use serde_json::Error;
10 use std::path::{PathBuf};
11 use std::ffi::OsString;
12
13 pub trait IdEntity {
14 fn get_id(&self) -> String;
15 fn new(name: &str) -> Self;
16 fn get_folder_name() -> &'static str;
17 }
18
19 pub struct SeveralFilesObject<T> {
20 id_to_file_entities: HashMap<String, T>,
21 handles: Vec<JoinHandle<()>>
22 }
23
24 impl<T: IdEntity + Send + Clone + Serialize + DeserializeOwned> SeveralFilesObject<T> {
25 pub fn new() -> SeveralFilesObject<T> {
26 let mut s = SeveralFilesObject {
27 id_to_file_entities: HashMap::new(),
28 handles: Vec::new()
29 };
30 s.load();
31 return s;
32 }
33
34 pub fn get_or_create(&mut self, id: &str) -> String {
35 let entity = self.get(id);
36 match entity {
37 Some(entity) => entity.get_id(),
38 None => self.create(id)
39 }
40 }
41
42 pub fn contains(&self, id: &str) -> bool {
43 return self.id_to_file_entities.contains_key(&id.to_lowercase());
44 }
45
46 pub fn create(&mut self, id: &str) -> String {
47 let entity = T::new(id);
48 let id = entity.get_id();
49 self.id_to_file_entities.insert(id.to_lowercase(), entity);
50 self.update(&id);
51 return id;
52 }
53
54 pub fn get_mut(&mut self, id: &str) -> Option<&mut T> {
55 return self.id_to_file_entities.get_mut(&id.to_lowercase());
56 }
57
58 pub fn get(&self, id: &str) -> Option<&T> {
59 return self.id_to_file_entities.get(&id.to_lowercase());
60 }
61
62 fn path_to_entity(path: PathBuf, file_name: OsString) -> Option<T> {
63 let json = fs::read_to_string(path.clone());
64 match json {
65 Ok(json) => {
66 let entity: Result<T, Error> = serde_json::from_str(&json);
67 match entity {
68 Ok(entity) => {
69 match file_name.eq_ignore_ascii_case(entity.get_id() + ".json") {
70 true => {
71 return Some(entity);
72 },
73 false => {
74 {
75 println!("Le nom du fichier '{}' ne correspond pas à l'id de l'entité '{}' !", path.display(), entity.get_id());
76 }
77 }
78 }
79 }
80 Err(err) => {
81 println!("{}", err);
82 }
83 }
84 }
85 Err(err) => {
86 println!("{}", err);
87 }
88 }
89
90 return None;
91 }
92
93 pub fn get_thread_safe(id: &str) -> Option<T> {
94 let path = String::from("entities/") + T::get_folder_name() + "/" + &id.to_lowercase() + ".json";
95
96 return SeveralFilesObject::path_to_entity(PathBuf::from(path), OsString::from(id.to_lowercase() + ".json"));
97 }
98
99 pub fn get_entities(&self) -> Iter<String, T> {
100 self.id_to_file_entities.iter()
101 }
102
103 pub fn update(&mut self, id: &str) {
104 let entity = self.id_to_file_entities.get(&id.to_lowercase());
105 match entity {
106 Some(entity) => {
107 let json = serde_json::to_string_pretty(&entity);
108 match json {
109 Ok(json) => {
110 let path = String::from("entities/") + T::get_folder_name() + "/" + &entity.get_id().to_lowercase() + ".json";
111 println!("Mise à jour de l'entité d'id {}", entity.get_id());
112 let handle = thread::spawn(move || {
113 let res = fs::create_dir_all(String::from("entities/") + T::get_folder_name());
114 match res {
115 Ok(_) => {
116 let res = fs::write(path, json);
117 match res {
118 Ok(_) => {}
119 Err(err) => println!("{}", err)
120 }
121 }
122 Err(err) => println!("{}", err)
123 }
124 });
125 self.handles.push(handle);
126 }
127 Err(err) => println!("{}", err)
128 }
129 },
130 None => ()
131 }
132 }
133
134 pub fn wait_handles(self) {
135 for handle in self.handles {
136 handle.join().unwrap();
137 }
138 }
139
140 fn load(&mut self) {
141 let path = String::from("entities/") + T::get_folder_name();
142 let folder = fs::read_dir(path);
143 match folder {
144 Ok(folder) => {
145 for file in folder {
146 match file {
147 Ok(file) => {
148 if file.path().is_file() && file.path().display().to_string().ends_with(".json") {
149 let entity: Option<T> = SeveralFilesObject::path_to_entity(file.path(), file.file_name());
150 match entity {
151 Some(entity) => {
152 self.id_to_file_entities.insert(entity.get_id().to_lowercase(), entity);
153 },
154 None => {}
155 }
156 }
157 }
158 Err(err) => println!("{}", err)
159 }
160 }
161 }
162 Err(_) => {}
163 }
164 }
165 }
166 }
167}