elo_test_manager/
lib.rs

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}