1use std::collections::BTreeMap;
2use std::fmt::Write;
3
4use sha2::{Digest, Sha256};
5
6pub fn compute_source_hash<K: Ord + AsRef<str>, V: AsRef<str>>(
10 sources: &BTreeMap<K, V>,
11) -> Box<str> {
12 let mut hasher = Sha256::new();
13 for (path, content) in sources {
14 update_hash_entry(&mut hasher, path.as_ref(), content.as_ref());
15 }
16 let digest = hasher.finalize();
17 encode_hex_digest(&digest)
18}
19
20pub fn digest_bytes(bytes: &[u8]) -> [u8; 32] {
27 let mut hasher = Sha256::new();
28 hasher.update(bytes);
29 hasher.finalize().into()
30}
31
32fn update_hash_entry(hasher: &mut Sha256, path: &str, content: &str) {
33 let path_bytes = path.as_bytes();
34 let content_bytes = content.as_bytes();
35
36 hasher.update((path_bytes.len() as u64).to_be_bytes());
37 hasher.update(path_bytes);
38 hasher.update((content_bytes.len() as u64).to_be_bytes());
39 hasher.update(content_bytes);
40}
41
42pub fn encode_hex_digest(digest: &[u8]) -> Box<str> {
44 let mut hex: String = String::with_capacity(64);
45 for byte in digest {
46 write!(hex, "{byte:02x}").ok();
48 }
49 Box::from(hex)
50}