use sha2::{Digest, Sha256};
#[must_use]
pub fn identify_media_type(bytes: &[u8]) -> Option<&'static str> {
if bytes.len() >= 12 && &bytes[0..4] == b"RIFF" {
match &bytes[8..12] {
b"WEBP" => return Some("image/webp"),
b"WAVE" => return Some("audio/wav"),
b"AVI " => return Some("video/x-msvideo"),
_ => {}
}
}
if bytes.len() >= 8 && &bytes[4..8] == b"ftyp" {
return Some("video/mp4");
}
const SIGNATURES: &[(&[u8], &str)] = &[
(b"\x89PNG\r\n\x1a\n", "image/png"), (b"\xFF\xD8\xFF", "image/jpeg"), (b"GIF87a", "image/gif"), (b"GIF89a", "image/gif"), (b"BM", "image/bmp"), (b"II\x2a\x00", "image/tiff"), (b"MM\x00\x2a", "image/tiff"), (b"%PDF-", "application/pdf"), (b"\x1f\x8b", "application/gzip"), (b"PK\x03\x04", "application/zip"), (b"BZh", "application/x-bzip2"), (b"7z\xbc\xaf\x27\x1c", "application/x-7z-compressed"), (b"SQLite format 3\x00", "application/vnd.sqlite3"), (b"OggS", "application/ogg"), (b"fLaC", "audio/flac"), (b"ID3", "audio/mpeg"), (b"\x25\x21PS", "application/postscript"), (
b"\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1",
"application/x-ole-storage",
), ];
SIGNATURES
.iter()
.find(|(magic, _)| bytes.starts_with(magic))
.map(|(_, mime)| *mime)
}
#[must_use]
pub fn sha256_hex(bytes: &[u8]) -> String {
let digest = Sha256::digest(bytes);
let mut out = String::with_capacity(digest.len() * 2);
for byte in digest {
out.push(char::from_digit(u32::from(byte >> 4), 16).unwrap_or('0'));
out.push(char::from_digit(u32::from(byte & 0x0f), 16).unwrap_or('0'));
}
out
}