use std::{fs, hash::Hasher, io::Read, path::Path};
use anyhow::Result;
use crate::wallpaper::Wallpaper;
use crate::{cache::Cache, wallpaper::unpack};
#[derive(Debug)]
pub struct WallpaperLoader {
cache: Cache,
}
impl WallpaperLoader {
pub fn new() -> Self {
WallpaperLoader {
cache: Cache::find("wallpapers"),
}
}
pub fn load<P: AsRef<Path>>(&mut self, path: P) -> Wallpaper {
let hash = hash_file(&path).expect("wallpaper hashing failed");
let cache_dir = self.cache.entry(&hash);
if cache_dir.read_dir().unwrap().next().is_none() {
unpack(&path, &cache_dir).expect("wallpaper unpacking failed");
}
Wallpaper::load(&cache_dir).expect("malformed wallpaper cache")
}
}
fn hash_file<P: AsRef<Path>>(path: P) -> Result<String> {
const BUFFER_LEN: usize = 1024;
let mut buffer = [0u8; BUFFER_LEN];
let mut file = fs::File::open(&path)?;
let mut hasher = seahash::SeaHasher::new();
loop {
let read_count = file.read(&mut buffer)?;
hasher.write(&buffer[..read_count]);
if read_count != BUFFER_LEN {
break;
}
}
let hash_bytes = hasher.finish();
Ok(format!("{hash_bytes:x}"))
}