I'm trying to build an abstraction over a file, where the content is stored in memory and a hash is computed before writing it out to the filesystem, which should happen in the close() method.
use std::path::PathBuf;
use sha2::{Digest, Sha256};
fn main() {
    let mut fwh = FileWithHash::new(PathBuf::from("somepath.txt"));
    fwh.write("first line\n");
    fwh.write("second line\n");
    fwh.close();
}
struct FileWithHash {
    path: PathBuf,
    hash: Option<String>,
    content: Vec<String>,
    pub hasher: Sha256,
}
impl FileWithHash {
    pub fn new(path: PathBuf) -> FileWithHash {
        FileWithHash {
            path,
            hash: None,
            content: Vec::new(),
            hasher: Sha256::new(),
        }
    }
    pub fn write(&mut self, content: &str) {
        self.hasher.update(content.as_bytes());
        self.content.push(content.to_string());
    }
    pub fn close(&mut self) {
        // compute the final hash
        // signature: fn finalize(self) -> Output<Self>;
        // it consumes self
        // error: cannot move out of `self.hasher` which is behind a mutable reference
        self.hash = Some(format!("{:x}", self.hasher.finalize()));
        // write the file the path
        // ...
    }
}
the problem I have is that the self.hasher.finalize() method consumes the hasher which is part of self, which is itself &mut. I think I understand why this doesn't work, but I cannot come up with a reasonable fix.
I've tried extracting the logic into a function like
    pub fn compute_hash(hasher: Sha256) -> String {
        format!("{:x}", hasher.finalize())
    }
but then I run into issues with partially moved values (makes sense).
Any ideas about what the proper pattern should be here?
Thanks for your help.
@justinas, I've tried the Option suggestion.
the methods become
pub fn write(&mut self, content: String) {
        match &mut self.hasher {
            Some(h) => h.update(content.as_bytes()),
            None => {}
        }
       
        self.size = self.size + content.len();
        self.content.push(content);
    }
    pub fn close(&mut self) {
        self.hash = Some(format!("{:x}", self.hasher.take().unwrap().finalize()));
        // write the file the path
        // ...
    }
Does this look OK to you?