use bladvak::eframe::egui;
use bladvak::errors::ErrorManager;
use base16ct::HexDisplay;
use md5::Md5;
use sha1::{Digest, Sha1};
use sha2::{Sha256, Sha512};
use crate::selection::Selection;
#[derive(Debug)]
struct Hashes {
sha1: String,
sha256: String,
sha512: String,
md5: String,
}
#[derive(Debug)]
struct HashData {
file: Hashes,
selection: Option<Hashes>,
}
#[derive(Debug, Default, serde::Deserialize, serde::Serialize)]
pub(crate) struct Hashing {
pub(crate) is_open: bool,
#[serde(skip)]
data: Option<HashData>,
}
impl Hashing {
pub(crate) fn new() -> Self {
Self {
is_open: false,
..Self::default()
}
}
pub(crate) fn reset(&mut self) {
self.data = None;
}
pub(crate) fn selection_stale(&mut self) {
if let Some(data) = &mut self.data {
data.selection = None;
}
}
pub(crate) fn window_title() -> &'static str {
"Hashing"
}
fn calculate_hashes(binary_data: &[u8]) -> Hashes {
let sha1 = format!("{:x}", HexDisplay(&Sha1::digest(binary_data)));
let sha256 = format!("{:x}", HexDisplay(&Sha256::digest(binary_data)));
let sha512 = format!("{:x}", HexDisplay(&Sha512::digest(binary_data)));
let md5 = format!("{:x}", HexDisplay(&Md5::digest(binary_data)));
Hashes {
sha1,
sha256,
sha512,
md5,
}
}
fn calculate_hashes_selection(binary_data: &[u8], selection: &Selection) -> Option<Hashes> {
if let Some(range) = selection.range
&& let Some(slice) = binary_data.get(range.0..=range.1)
{
Some(Self::calculate_hashes(slice))
} else {
None
}
}
fn calculate_hash_data(binary_data: &[u8], selection: &Selection) -> HashData {
HashData {
file: Self::calculate_hashes(binary_data),
selection: Self::calculate_hashes_selection(binary_data, selection),
}
}
pub(crate) fn ui(
&mut self,
binary_data: &[u8],
selection: &Selection,
ui: &mut egui::Ui,
_error_manager: &mut ErrorManager,
) {
if self.is_open {
let mut is_open = self.is_open;
if let Some(data) = &mut self.data {
if selection.range.is_some() && data.selection.is_none() {
data.selection = Self::calculate_hashes_selection(binary_data, selection);
}
egui::Window::new(Self::window_title())
.open(&mut is_open)
.vscroll(true)
.show(ui.ctx(), |ui| {
ui.label("File hashes:");
ui.label("sha1");
ui.label(&data.file.sha1);
ui.separator();
ui.label("sha256");
ui.label(&data.file.sha256);
ui.separator();
ui.label("sha512");
ui.label(&data.file.sha512);
ui.separator();
ui.label("md5");
ui.label(&data.file.md5);
if let Some(select) = &data.selection {
ui.separator();
ui.label("Selection hashes");
ui.label("sha1");
ui.label(&select.sha1);
ui.separator();
ui.label("sha256");
ui.label(&select.sha256);
ui.separator();
ui.label("sha512");
ui.label(&select.sha512);
ui.separator();
ui.label("md5");
ui.label(&select.md5);
}
});
self.is_open = is_open;
} else if binary_data.is_empty() {
egui::Window::new(Self::window_title())
.open(&mut is_open)
.vscroll(true)
.show(ui.ctx(), |ui| {
ui.label("File is empty");
});
self.is_open = is_open;
} else {
self.data = Some(Self::calculate_hash_data(binary_data, selection));
}
}
}
}