about summary refs log tree commit diff
diff options
context:
space:
mode:
authoronur-ozkan <work@onurozkan.dev>2023-10-14 22:52:05 +0300
committeronur-ozkan <work@onurozkan.dev>2023-10-14 22:52:05 +0300
commit3be453d0bb854e190e1da914d7660b1e24501494 (patch)
tree9838815f5125ac38ce8837ea01db0c2398a1f6f7
parent7ed044c075fc0e7ad2574d3144ca00ba14608d8f (diff)
downloadrust-3be453d0bb854e190e1da914d7660b1e24501494.tar.gz
rust-3be453d0bb854e190e1da914d7660b1e24501494.zip
optimize file read in Config::verify
`Config::verify` refactored to improve the efficiency and
memory usage of file hashing.

Signed-off-by: onur-ozkan <work@onurozkan.dev>
-rw-r--r--src/bootstrap/download.rs38
1 files changed, 28 insertions, 10 deletions
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index 8e9614ec89a..2a0dec75599 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -320,25 +320,43 @@ impl Config {
     }
 
     /// Returns whether the SHA256 checksum of `path` matches `expected`.
-    fn verify(&self, path: &Path, expected: &str) -> bool {
+    pub(crate) fn verify(&self, path: &Path, expected: &str) -> bool {
         use sha2::Digest;
 
         self.verbose(&format!("verifying {}", path.display()));
+
+        if self.dry_run() {
+            return false;
+        }
+
         let mut hasher = sha2::Sha256::new();
-        // FIXME: this is ok for rustfmt (4.1 MB large at time of writing), but it seems memory-intensive for rustc and larger components.
-        // Consider using streaming IO instead?
-        let contents = if self.dry_run() { vec![] } else { t!(fs::read(path)) };
-        hasher.update(&contents);
-        let found = hex::encode(hasher.finalize().as_slice());
-        let verified = found == expected;
-        if !verified && !self.dry_run() {
+
+        let file = t!(File::open(path));
+        let mut reader = BufReader::new(file);
+
+        loop {
+            let buffer = t!(reader.fill_buf());
+            let l = buffer.len();
+            // break if EOF
+            if l == 0 {
+                break;
+            }
+            hasher.update(buffer);
+            reader.consume(l);
+        }
+
+        let checksum = hex::encode(hasher.finalize().as_slice());
+        let verified = checksum == expected;
+
+        if !verified {
             println!(
                 "invalid checksum: \n\
-                found:    {found}\n\
+                found:    {checksum}\n\
                 expected: {expected}",
             );
         }
-        return verified;
+
+        verified
     }
 }