use std::{collections::HashMap, fs, path::Path};
use serde::{Deserialize, Serialize};
use thiserror::Error;
#[derive(Deserialize, Serialize, Clone, Default)]
pub struct Templates(HashMap<String, Vec<String>>);
#[derive(Debug, Error, Deserialize)]
pub enum TemplatesError {
#[error("Template with the same name already exists.")]
AlreadyExists,
#[error("Template not found.")]
TemplateNotFound,
#[error("File system error occurred.")]
FileSystemError,
#[error("Failed to serialize templates data.")]
SerializationError,
#[error("Failed to deserialize templates data.")]
DeserializationError,
#[error("Commands in the template are empty.")]
CommandsAreEmpty,
}
impl Templates {
pub fn new() -> Self {
Self(HashMap::new())
}
pub fn add_template(
&mut self,
name: &str,
commands: Vec<String>,
) -> Result<(), TemplatesError> {
if self.0.contains_key(name) {
return Err(TemplatesError::AlreadyExists);
}
if commands.iter().any(|cmd| cmd.trim().is_empty()) {
return Err(TemplatesError::CommandsAreEmpty);
}
self.0.insert(name.to_string(), commands);
Ok(())
}
pub fn get_template(&self, name: &str) -> Option<&Vec<String>> {
self.0.get(name)
}
pub fn remove_template(&mut self, name: &str) -> Result<(), TemplatesError> {
if self.0.remove(name).is_none() {
return Err(TemplatesError::TemplateNotFound);
}
Ok(())
}
pub fn clear(&mut self) {
self.0.clear()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn list_templates(&self) -> Vec<String> {
self.0.keys().cloned().collect()
}
pub fn load(path: impl AsRef<Path>) -> Result<Self, TemplatesError> {
let content = fs::read_to_string(path).map_err(|_| TemplatesError::FileSystemError)?;
let templates: Self =
serde_json::from_str(&content).map_err(|_| TemplatesError::DeserializationError)?;
Ok(templates)
}
pub fn save(&self, path: impl AsRef<Path>) -> Result<(), TemplatesError> {
let content =
serde_json::to_string_pretty(self).map_err(|_| TemplatesError::SerializationError)?;
fs::write(path, content).map_err(|_| TemplatesError::FileSystemError)
}
}