How to update a mutable message digest in a loop (borrow checker error)

I am writing an application that needs to calculate a sha256 digest of some data. The typical way I would do this would be to use a for loop, but since the digest is mutable, I'm running into problems with the borrow checker with the code below. I have no idea how to solve it. Can anyone provide assistance please?

I understand why the problem is occurring (if my understanding is correct, it's multiple borrows of a mutable reference without leaving the loop scope, which is not allowed). I just don't know how to fix it. For other solutions I would collect the values in a vector, then iterate over the vector. In this case, the code needs to run for a value specified by the user. I don't want to collect 10 billion i64 values in a vector before I start iterating.

Note that I haven't managed to compile the code yet, so there may be additional compilation issues. Any assistance would be appreciated.

use std::env;
use std::time::{SystemTime, UNIX_EPOCH};
use sha2::{Sha256,Digest};
use sha2::digest::{Reset, Update};

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() != 2 {
        println!("Usage: {} num", args[0]);
        std::process::exit(1);
    }

    let val: i64 = args[1].parse().unwrap();
    let mut hasher = Sha256::new();

    let start_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis();
    let mut count: i64 = 0;
    for j in 0 .. val {
        count = count + j + 1;
        let count_string = count.to_string();
        let bytes = count_string.as_bytes();
        Digest::update(&mut hasher, bytes);
        if (j % 1000) == 0 {
            let result = hasher.finalize();
            if result.len() != 32 {
                println!("Error with sha256 algorithm");
            } else {
                Digest::reset(&mut hasher);
            }
        }
    }
    let end_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis();

    let diff = end_time - start_time;
    println!("count is {} and time taken was {}ms", count, diff);
}

And the compiler says:

error[E0382]: borrow of moved value: `hasher`
  --> src/main.rs:22:24
   |
14 |     let mut hasher = Sha256::new();
   |         ---------- move occurs because `hasher` has type `CoreWrapper<CtVariableCoreWrapper<Sha256VarCore, UInt<UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>, B0>>>`, which does not implement the `Copy` trait
...
22 |         Digest::update(&mut hasher, bytes);
   |                        ^^^^^^^^^^^ value borrowed here after move
23 |         if (j % 1000) == 0 {
24 |             let result = hasher.finalize();
   |                                 ---------- `hasher` moved due to this method call, in previous iteration of loop
   |
note: this function takes ownership of the receiver `self`, which moves `hasher`
  --> /home/fali/.cargo/registry/src/github.com-1ecc6299db9ec823/digest-0.10.3/src/digest.rs:30:17
   |
30 |     fn finalize(self) -> Output<Self>;
   |                 ^^^^

The finalize method destroys the thing you call it on. You could try cloning it first with hasher.clone().finalize() to just destroy a clone instead. If you want to reset it, do that instead:

let result = hasher.finalize();
hasher = Sha256::new();

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.