use crate::{ConcurrencyExt, Dimension, FileInfo, WallSwitchError, WallSwitchResult};
use blake3::Hasher;
use image::image_dimensions;
use std::{
fs::File,
io::{BufReader, Read},
path::PathBuf,
thread,
};
const BUFFER_SIZE: usize = 64 * 1024;
pub fn probe_image_dimension(path: &PathBuf, _verbose: bool) -> WallSwitchResult<Dimension> {
match image_dimensions(path) {
Ok((width, height)) => Ok(Dimension {
width: width as u64,
height: height as u64,
}),
Err(err) => Err(WallSwitchError::UnableToFind(format!(
"Failed to probe image dimensions for {}: {}",
path.display(),
err
))),
}
}
pub fn compute_hashes_parallel(files: &mut [FileInfo]) {
let chunk_size = files.get_chunk_size(files.len());
thread::scope(|scope| {
for chunk in files.chunks_mut(chunk_size) {
scope.spawn(move || {
for file_info in chunk {
if let Ok(file) = File::open(&file_info.path) {
let reader = BufReader::with_capacity(BUFFER_SIZE, file);
if let Ok(hash) = get_hash(reader) {
file_info.hash = hash;
}
}
}
});
}
});
}
pub fn get_hash(mut reader: impl Read) -> WallSwitchResult<String> {
let mut hasher = Hasher::new();
let mut buffer = [0_u8; BUFFER_SIZE];
loop {
let count = reader.read(&mut buffer)?;
if count == 0 {
break;
}
hasher.update(&buffer[..count]);
}
Ok(hasher.finalize().to_hex().to_string())
}