git_internal/internal/pack/
wrapper.rs1use std::io::{self, BufRead, Read};
2
3use sha1::{Digest, Sha1};
4
5use crate::hash::SHA1;
6
7pub struct Wrapper<R> {
16 inner: R,
17 hash: Sha1,
18 bytes_read: usize,
19}
20
21impl<R> Wrapper<R>
22where
23 R: BufRead,
24{
25 pub fn new(inner: R) -> Self {
31 Self {
32 inner,
33 hash: Sha1::new(), bytes_read: 0,
35 }
36 }
37
38 pub fn bytes_read(&self) -> usize {
39 self.bytes_read
40 }
41
42 pub fn final_hash(&self) -> SHA1 {
46 let re: [u8; 20] = self.hash.clone().finalize().into(); SHA1(re)
48 }
49}
50
51impl<R> BufRead for Wrapper<R>
52where
53 R: BufRead,
54{
55 fn fill_buf(&mut self) -> io::Result<&[u8]> {
57 self.inner.fill_buf() }
59
60 fn consume(&mut self, amt: usize) {
65 let buffer = self.inner.fill_buf().expect("Failed to fill buffer");
66 self.hash.update(&buffer[..amt]); self.inner.consume(amt); self.bytes_read += amt;
69 }
70}
71
72impl<R> Read for Wrapper<R>
73where
74 R: BufRead,
75{
76 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
85 let o = self.inner.read(buf)?; self.hash.update(&buf[..o]); self.bytes_read += o;
88 Ok(o) }
90}
91
92#[cfg(test)]
93mod tests {
94 use std::io::{self, BufReader, Cursor, Read};
95
96 use sha1::{Digest, Sha1};
97
98 use crate::internal::pack::wrapper::Wrapper;
99
100 #[test]
101 fn test_wrapper_read() -> io::Result<()> {
102 let data = b"Hello, world!"; let cursor = Cursor::new(data.as_ref());
104 let buf_reader = BufReader::new(cursor);
105 let mut wrapper = Wrapper::new(buf_reader);
106
107 let mut buffer = vec![0; data.len()];
108 wrapper.read_exact(&mut buffer)?;
109
110 assert_eq!(buffer, data);
111 Ok(())
112 }
113
114 #[test]
115 fn test_wrapper_hash() -> io::Result<()> {
116 let data = b"Hello, world!";
117 let cursor = Cursor::new(data.as_ref());
118 let buf_reader = BufReader::new(cursor);
119 let mut wrapper = Wrapper::new(buf_reader);
120
121 let mut buffer = vec![0; data.len()];
122 wrapper.read_exact(&mut buffer)?;
123
124 let hash_result = wrapper.final_hash();
125 let mut hasher = Sha1::new();
126 hasher.update(data);
127 let expected_hash: [u8; 20] = hasher.finalize().into();
128
129 assert_eq!(hash_result.0, expected_hash);
130 Ok(())
131 }
132}