use std::path::{Path, PathBuf}; use std::slice::Iter; use crate::utils::err::Res; enum FileFormat { Json, Yaml } pub struct EntityManager { file_path: PathBuf, list: Vec, } impl EntityManager where E: serde::Serialize + serde::de::DeserializeOwned + Eq + Clone, { /// Open entity pub fn open_or_create>(path: A) -> Res { if !path.as_ref().is_file() { log::warn!("Entities at {:?} does not point to a file, creating a new empty entity container...", path.as_ref()); return Ok(Self { file_path: path.as_ref().to_path_buf(), list: vec![], }); } log::info!("Open existing entity file {:?}", path.as_ref()); let file_content = std::fs::read_to_string(path.as_ref())?; Ok(Self { file_path: path.as_ref().to_path_buf(), list: match Self::file_format(path.as_ref()) { FileFormat::Json => serde_json::from_str(&file_content)?, FileFormat::Yaml => serde_yaml::from_str(&file_content)? }, }) } /// Save the list fn save(&self) -> Res { Ok(std::fs::write( &self.file_path, match Self::file_format(self.file_path.as_ref()) { FileFormat::Json => serde_json::to_string(&self.list)?, FileFormat::Yaml => serde_yaml::to_string(&self.list)?, }, )?) } fn file_format(p: &Path) -> FileFormat { match p.to_string_lossy().ends_with(".json") { true => FileFormat::Json, false => FileFormat::Yaml } } /// Get the number of entries in the list pub fn len(&self) -> usize { self.list.len() } pub fn is_empty(&self) -> bool { self.len() == 0 } /// Insert a new element in the list pub fn insert(&mut self, el: E) -> Res { self.list.push(el); self.save() } /// Replace entries in the list that matches a criteria pub fn replace_entries(&mut self, filter: F, el: &E) -> Res where F: Fn(&E) -> bool, { for i in 0..self.list.len() { if filter(&self.list[i]) { self.list[i] = el.clone(); } } self.save() } /// Iterate over the entries of this entity manager pub fn iter(&self) -> Iter<'_, E> { self.list.iter() } /// Get a cloned list of entries pub fn cloned(&self) -> Vec { self.list.clone() } pub fn update_or_push(&mut self, entry: E) -> Res { let mut found = false; for i in &mut self.list { if i == &entry { *i = entry.clone(); found = true; break; } } if !found { self.list.push(entry); } self.save() } pub fn remove(&mut self, entry: &E) -> Res { self.list.retain(|x| x != entry); self.save() } }