git_internal/
utils.rs

1use crate::hash::{HashKind, ObjectHash, get_hash_kind};
2use sha1::{Digest, Sha1};
3use std::io;
4use std::io::{BufRead, Read};
5pub fn read_bytes(file: &mut impl Read, len: usize) -> io::Result<Vec<u8>> {
6    let mut buf = vec![0; len];
7    file.read_exact(&mut buf)?;
8    Ok(buf)
9}
10
11pub fn read_sha(file: &mut impl Read) -> io::Result<ObjectHash> {
12    ObjectHash::from_stream(file)
13}
14
15/// A lightweight wrapper that counts bytes read from the underlying reader.
16/// replace deflate.intotal() in decompress_data
17pub struct CountingReader<R> {
18    pub inner: R,
19    pub bytes_read: u64,
20}
21
22impl<R> CountingReader<R> {
23    /// Creates a new `CountingReader` wrapping the given reader.
24    pub fn new(inner: R) -> Self {
25        Self {
26            inner,
27            bytes_read: 0,
28        }
29    }
30}
31
32impl<R: Read> Read for CountingReader<R> {
33    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
34        let n = self.inner.read(buf)?;
35        self.bytes_read += n as u64;
36        Ok(n)
37    }
38}
39
40impl<R: BufRead> BufRead for CountingReader<R> {
41    fn fill_buf(&mut self) -> io::Result<&[u8]> {
42        self.inner.fill_buf()
43    }
44
45    fn consume(&mut self, amt: usize) {
46        self.bytes_read += amt as u64;
47        self.inner.consume(amt);
48    }
49}
50/// a hash abstraction to support both SHA1 and SHA256
51/// which for stream hashing handle use (e.g. Sha1::new())
52/// `std::io::Write` trait to update the hash state
53#[derive(Clone)]
54pub enum HashAlgorithm {
55    Sha1(Sha1),
56    Sha256(sha2::Sha256),
57    // Future: support other hash algorithms
58}
59impl HashAlgorithm {
60    /// Update hash with data
61    pub fn update(&mut self, data: &[u8]) {
62        match self {
63            HashAlgorithm::Sha1(hasher) => hasher.update(data),
64            HashAlgorithm::Sha256(hasher) => hasher.update(data),
65        }
66    }
67    /// Finalize and get hash result
68    pub fn finalize(self) -> Vec<u8> {
69        match self {
70            HashAlgorithm::Sha1(hasher) => hasher.finalize().to_vec(),
71            HashAlgorithm::Sha256(hasher) => hasher.finalize().to_vec(),
72        }
73    }
74    pub fn new() -> Self {
75        match get_hash_kind() {
76            HashKind::Sha1 => HashAlgorithm::Sha1(Sha1::new()),
77            HashKind::Sha256 => HashAlgorithm::Sha256(sha2::Sha256::new()),
78        }
79    }
80}
81impl std::io::Write for HashAlgorithm {
82    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
83        self.update(buf);
84        Ok(buf.len())
85    }
86    fn flush(&mut self) -> io::Result<()> {
87        Ok(())
88    }
89}
90impl Default for HashAlgorithm {
91    fn default() -> Self {
92        Self::new()
93    }
94}