use std::{
collections::HashMap,
fs::{self, File},
io::{self, BufRead, BufReader, BufWriter, Write},
path::Path,
};
use serde::{Deserialize, Serialize};
use time::OffsetDateTime;
use crate::deser;
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub struct Instance {
last_edit_time: OffsetDateTime,
}
impl Instance {
pub fn new() -> Self {
Self {
last_edit_time: OffsetDateTime::UNIX_EPOCH,
}
}
pub fn last_edit_time(&self) -> OffsetDateTime {
self.last_edit_time
}
pub fn update_last_edit_time(&mut self, now: OffsetDateTime) {
self.last_edit_time = now;
}
}
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub struct State {
instance: HashMap<String, Instance>,
}
impl State {
pub fn new(domains: &Vec<String>) -> Self {
let instance = Instance::new();
let mut map = HashMap::new();
for domain in domains {
if map.insert(domain.clone(), instance.clone()).is_some() {
panic!("duplicated domains")
}
}
Self { instance: map }
}
pub fn instance(&mut self, domain: &str) -> Option<&mut Instance> {
self.instance.get_mut(domain)
}
pub fn new_instance(&mut self, domain: &str) -> Option<&mut Instance> {
let instance = Instance::new();
if self.instance.insert(domain.to_string(), instance).is_some() {
panic!("new instance already exists")
}
self.instance(domain)
}
pub fn load(path: &Path) -> Result<State, deser::Error> {
let f = File::open(path)?;
let reader = BufReader::new(f);
let lines = reader.lines().collect::<io::Result<Vec<String>>>()?;
let text = lines.join("\n");
Ok(toml::from_str(&text)?)
}
pub fn save(&self, path: &Path) -> Result<(), deser::Error> {
let string = toml::to_string(self)?;
let filename = path.file_name();
if filename.is_none() {
panic!("Filename not found: {:?}", path)
}
let filename = filename.unwrap().to_str();
if filename.is_none() {
panic!("Invalid filename: {:?}", path)
}
let mut new_path = path.to_path_buf();
if !new_path.pop() {
panic!("Parent directory not found: {:?}", path)
}
new_path.push(filename.unwrap().to_string() + ".new");
let f = File::create(new_path.clone())?;
let mut writer = BufWriter::new(f);
writer.write_all(string.as_bytes())?;
writer.flush()?;
fs::rename(new_path, path)?;
Ok(())
}
}