mirror of
https://github.com/thegeneralist01/archivr
synced 2026-07-22 03:05:32 +02:00
feat(fonts): hash_bytes, get_blob_by_sha256, font_extractor module
- fix(hash): hash raw bytes instead of lossy UTF-8; add hash_bytes - feat(database): add get_blob_by_sha256 lookup - feat(font_extractor): extract embedded font data-URIs from archived HTML
This commit is contained in:
parent
f6d636fce2
commit
22b0a55730
4 changed files with 287 additions and 12 deletions
|
|
@ -1,17 +1,56 @@
|
|||
use anyhow::Result;
|
||||
use sha3::{Digest, Sha3_256};
|
||||
use std::{fs::File, io::Read, path::Path};
|
||||
use std::path::Path;
|
||||
|
||||
pub fn hash_file(path: &Path) -> Result<String> {
|
||||
let mut file = File::open(path)?;
|
||||
let mut buf = Vec::new();
|
||||
file.read_to_end(&mut buf)?;
|
||||
Ok(hash(String::from_utf8_lossy(&buf).to_string()))
|
||||
}
|
||||
|
||||
pub fn hash(path: String) -> String {
|
||||
/// Computes the SHA3-256 hex digest of `data` directly on raw bytes.
|
||||
pub fn hash_bytes(data: &[u8]) -> String {
|
||||
let mut hasher = Sha3_256::new();
|
||||
hasher.update(path.as_bytes());
|
||||
let result = hasher.finalize();
|
||||
hex::encode(result)
|
||||
hasher.update(data);
|
||||
hex::encode(hasher.finalize())
|
||||
}
|
||||
|
||||
/// Reads `path` fully and returns its SHA3-256 hex digest.
|
||||
/// Uses raw bytes — correct for both text and binary files.
|
||||
pub fn hash_file(path: &Path) -> Result<String> {
|
||||
let buf = std::fs::read(path)?;
|
||||
Ok(hash_bytes(&buf))
|
||||
}
|
||||
|
||||
/// Hashes an arbitrary string (used for legacy callers; prefer `hash_bytes`).
|
||||
pub fn hash(s: String) -> String {
|
||||
hash_bytes(s.as_bytes())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn hash_bytes_and_hash_file_agree_on_same_data() {
|
||||
let data = b"hello archivr fonts";
|
||||
let tmp = tempfile::NamedTempFile::new().unwrap();
|
||||
std::fs::write(tmp.path(), data).unwrap();
|
||||
assert_eq!(hash_bytes(data), hash_file(tmp.path()).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hash_bytes_is_stable() {
|
||||
let h = hash_bytes(b"archivr");
|
||||
assert_eq!(h.len(), 64);
|
||||
assert!(h.chars().all(|c| c.is_ascii_hexdigit()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hash_bytes_differs_from_hash_of_lossy_utf8_for_binary_data() {
|
||||
let binary = b"\xff\xfe\xfd";
|
||||
let direct = hash_bytes(binary);
|
||||
let lossy = String::from_utf8_lossy(binary).to_string();
|
||||
let via_old_path = {
|
||||
use sha3::{Digest, Sha3_256};
|
||||
let mut h = Sha3_256::new();
|
||||
h.update(lossy.as_bytes());
|
||||
hex::encode(h.finalize())
|
||||
};
|
||||
assert_ne!(direct, via_old_path);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue