use std::fs::{File, OpenOptions}; use std::io::{Read, Write, Error}; use std::path::{Path, PathBuf}; use rocket::request::FromForm; use crate::store::model::Model; use std::collections::HashMap; pub mod model; pub mod form; /// Store instance #[derive(Debug)] pub struct Store { path : PathBuf, pub model: Model, pub items : HashMap, pub index : Indexes, } /// Indexes loaded from the indexes file #[derive(Serialize,Deserialize,Debug,Default)] pub struct Indexes { pub free_enums : HashMap>, pub free_tags : HashMap>, } /// Struct loaded from the repositroy config file #[derive(Serialize,Deserialize,Debug)] struct RepositoryConfig { pub model : Model, } const REPO_CONFIG_FILE : &'static str = "repository.yaml"; const REPO_DATA_FILE : &'static str = "data.json"; const REPO_INDEX_FILE : &'static str = "index.json"; impl Store { pub fn new(path: impl AsRef) -> Self { let file = load_file(path.as_ref().join(REPO_CONFIG_FILE)); let repository_config : RepositoryConfig = serde_yaml::from_str(&file) .expect("Error parsing repository config file."); let items = load_file_or(path.as_ref().join(REPO_DATA_FILE), "{}"); let indexes = load_file_or(path.as_ref().join(REPO_INDEX_FILE), "{}"); Store { path: path.as_ref().into(), model: repository_config.model, items: serde_json::from_str(&items).expect("Error parsing data file."), index: serde_json::from_str(&indexes).unwrap_or_default(), } } pub fn persist(&self) { let mut file = OpenOptions::new() .write(true) .create(true) .truncate(true) .open(self.path.join(REPO_DATA_FILE)) .expect("Error opening data file for writing."); let serialized = serde_json::to_string(&self.items).expect("Error serialize."); file.write(serialized.as_bytes()).expect("Error write data file"); } } fn load_file(path: impl AsRef) -> String { let mut file= File::open(&path).expect(&format!("Error opening file {}", path.as_ref().display())); let mut buf = String::new(); file.read_to_string(&mut buf).expect(&format!("Error reading file {}", path.as_ref().display())); buf } fn load_file_or(file : impl AsRef, def : impl Into) -> String { let mut file = match File::open(file) { Ok(file) => file, Err(_) => return def.into() }; let mut buf = String::new(); if file.read_to_string(&mut buf).is_err() { return def.into(); } buf }