1use md5::{Digest as Md5Digest, Md5};
5use sha1::Sha1;
6use sha2::Sha256;
7use std::fs::File;
8use std::io::{self, BufReader, Read};
9use std::path::Path;
10
11use crate::models::{GitSha1, Md5Digest as Md5DigestType, Sha1Digest, Sha256Digest};
12
13pub fn calculate_sha1(content: &[u8]) -> Sha1Digest {
14 let digest = Sha1::digest(content);
15 Sha1Digest::from_bytes(digest.into())
16}
17
18pub fn calculate_md5(content: &[u8]) -> Md5DigestType {
19 let digest = Md5::digest(content);
20 Md5DigestType::from_bytes(digest.into())
21}
22
23pub fn calculate_sha256(content: &[u8]) -> Sha256Digest {
24 let digest = Sha256::digest(content);
25 Sha256Digest::from_bytes(digest.into())
26}
27
28pub fn calculate_sha1_git(content: &[u8]) -> GitSha1 {
29 let mut payload = Vec::with_capacity(content.len() + 32);
30 payload.extend_from_slice(format!("blob {}\0", content.len()).as_bytes());
31 payload.extend_from_slice(content);
32 let digest = Sha1::digest(&payload);
33 GitSha1::from_bytes(digest.into())
34}
35
36pub fn calculate_file_hashes(
37 path: &Path,
38 size: u64,
39) -> io::Result<(Sha1Digest, Md5DigestType, Sha256Digest, GitSha1)> {
40 let file = File::open(path)?;
41 let mut reader = BufReader::new(file);
42 let mut sha1 = Sha1::new();
43 let mut md5 = Md5::new();
44 let mut sha256 = Sha256::new();
45 let mut git_sha1 = Sha1::new();
46 let mut buffer = [0_u8; 64 * 1024];
47
48 git_sha1.update(format!("blob {}\0", size).as_bytes());
49
50 loop {
51 let read = reader.read(&mut buffer)?;
52 if read == 0 {
53 break;
54 }
55
56 let chunk = &buffer[..read];
57 sha1.update(chunk);
58 md5.update(chunk);
59 sha256.update(chunk);
60 git_sha1.update(chunk);
61 }
62
63 Ok((
64 Sha1Digest::from_bytes(sha1.finalize().into()),
65 Md5DigestType::from_bytes(md5.finalize().into()),
66 Sha256Digest::from_bytes(sha256.finalize().into()),
67 GitSha1::from_bytes(git_sha1.finalize().into()),
68 ))
69}