git_internal/internal/pack/
wrapper.rs1use std::io::{self, BufRead, Read};
5
6use sha1::{Digest, Sha1};
7
8use crate::{
9 hash::{HashKind, ObjectHash, get_hash_kind},
10 utils::HashAlgorithm,
11};
12pub struct Wrapper<R> {
22 inner: R,
23 hash: HashAlgorithm,
24 bytes_read: usize,
25}
26
27impl<R> Wrapper<R>
28where
29 R: BufRead,
30{
31 pub fn new(inner: R) -> Self {
37 Self {
38 inner,
39 hash: match get_hash_kind() {
40 HashKind::Sha1 => HashAlgorithm::Sha1(Sha1::new()),
41 HashKind::Sha256 => HashAlgorithm::Sha256(sha2::Sha256::new()),
42 }, bytes_read: 0,
44 }
45 }
46
47 pub fn bytes_read(&self) -> usize {
49 self.bytes_read
50 }
51
52 pub fn final_hash(&self) -> ObjectHash {
56 match &self.hash.clone() {
57 HashAlgorithm::Sha1(hasher) => {
58 let re: [u8; 20] = hasher.clone().finalize().into(); ObjectHash::from_bytes(&re).unwrap()
60 }
61 HashAlgorithm::Sha256(hasher) => {
62 let re: [u8; 32] = hasher.clone().finalize().into(); ObjectHash::from_bytes(&re).unwrap()
64 }
65 }
66 }
67}
68
69impl<R> BufRead for Wrapper<R>
70where
71 R: BufRead,
72{
73 fn fill_buf(&mut self) -> io::Result<&[u8]> {
75 self.inner.fill_buf() }
77
78 fn consume(&mut self, amt: usize) {
83 let buffer = self.inner.fill_buf().expect("Failed to fill buffer");
84 match &mut self.hash {
85 HashAlgorithm::Sha1(hasher) => hasher.update(&buffer[..amt]), HashAlgorithm::Sha256(hasher) => hasher.update(&buffer[..amt]), }
88 self.inner.consume(amt); self.bytes_read += amt;
90 }
91}
92
93impl<R> Read for Wrapper<R>
94where
95 R: BufRead,
96{
97 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
106 let o = self.inner.read(buf)?; match &mut self.hash {
108 HashAlgorithm::Sha1(hasher) => hasher.update(&buf[..o]), HashAlgorithm::Sha256(hasher) => hasher.update(&buf[..o]), }
111 self.bytes_read += o;
112 Ok(o) }
114}
115
116#[cfg(test)]
117mod tests {
118 use std::io::{self, BufReader, Cursor, Read};
119
120 use sha1::{Digest, Sha1};
121
122 use crate::{
123 hash::{HashKind, ObjectHash, set_hash_kind},
124 internal::pack::wrapper::Wrapper,
125 };
126
127 fn wrapper_read(kind: HashKind) {
129 let _guard = set_hash_kind(kind);
130 let data = b"Hello, world!"; let cursor = Cursor::new(data.as_ref());
132 let buf_reader = BufReader::new(cursor);
133 let mut wrapper = Wrapper::new(buf_reader);
134
135 let mut buffer = vec![0; data.len()];
136 wrapper.read_exact(&mut buffer).unwrap();
137
138 assert_eq!(buffer, data);
139 }
140
141 #[test]
143 fn test_wrapper_read() {
144 wrapper_read(HashKind::Sha1);
145 wrapper_read(HashKind::Sha256);
146 }
147
148 fn wrapper_hash_with_kind(kind: HashKind) -> io::Result<()> {
150 let _guard = set_hash_kind(kind);
151 let data = b"Hello, world!";
152 let cursor = Cursor::new(data.as_ref());
153 let buf_reader = BufReader::new(cursor);
154 let mut wrapper = Wrapper::new(buf_reader);
155
156 let mut buffer = vec![0; data.len()];
157 wrapper.read_exact(&mut buffer)?;
158
159 let hash_result = wrapper.final_hash();
160 let expected_hash = match kind {
161 HashKind::Sha1 => ObjectHash::from_bytes(&Sha1::digest(data)).unwrap(),
162 HashKind::Sha256 => ObjectHash::from_bytes(&sha2::Sha256::digest(data)).unwrap(),
163 };
164
165 assert_eq!(hash_result, expected_hash);
166 Ok(())
167 }
168 #[test]
169 fn test_wrapper_hash() -> io::Result<()> {
170 wrapper_hash_with_kind(HashKind::Sha1)?;
171 wrapper_hash_with_kind(HashKind::Sha256)?;
172 Ok(())
173 }
174}