use std::fs;
use std::fs::File;
use std::io::Write;
use std::path::Path;
#[cfg(unix)]
use std::os::unix::fs::MetadataExt;
#[cfg(windows)]
use std::os::windows::fs::MetadataExt;
use crate::colors::Colors;
use crate::config::Config;
use anyhow::{Result, Context};
pub struct Cache {
pub path: String,
}
const CACHE_VER: &str = "1.0";
impl Cache {
pub fn new(filename: &Path, c: &Config, cache_path: &Path) -> Result<Self> {
let Some(name) = filename.file_name() else {
anyhow::bail!("Using '..' as a parameter is not supported");
};
let cachepath = format!("{root}/wallust/{back}/{th}/{cs}/{filter}",
root = cache_path.display(), back = c.backend,
th = c.threshold,
cs = c.color_space,
filter = c.filter,
);
fs::create_dir_all(&cachepath)?;
let md = fs::metadata(filename)?;
#[cfg(unix)]
let num = md.ino();
#[cfg(windows)]
let num = md.file_attributes() ;
let hash_name = format!("{}_{}_{}_{}.json",
name.to_string_lossy(),
md.len(),
num,
CACHE_VER,
);
Ok(Self { path: format!("{cachepath}/{hash_name}") })
}
pub fn read(&self) -> Result<Colors> {
let contents = std::fs::read_to_string(&self.path)?;
Ok(serde_json::from_str(&contents)?)
}
pub fn write(&self, colors: &Colors) -> Result<()> {
Ok(File::create(&self.path)?
.write_all(
serde_json::to_string(colors)
.with_context(|| format!("Failed to deserilize from the json cached file: '{}':", &self.path))?
.as_bytes()
)?
)
}
pub fn is_cached(&self) -> bool {
Path::new(&self.path).exists()
}
}