During a lengthy computation, I need to look up some data in a number of different files. I cannot know beforehand how many or which files exactly, but chances are high that each file is used many times (on the order of 100 million times).
In the first version, I opened the file (whose name is an intermediate result of the computation) each time for lookup.
In the second version, I have a HashMap<String, Box<File>>
where I remember already open files and open new ones lazily on demand.
I couldn't manage to handle the mutable stuff that arises from the need to have File
s to be mutable. I got something working, but it looks overly silly:
let path = format!("egtb/{}.egtb", self.signature());
let hentry = hash.get_mut(&self.signature());
let mut file = match hentry {
Some(f) => f,
None => {
let rfile = File::open(&path);
let wtf = Box::new(match rfile {
Err(ioe) => return Err(format!("could not open EGTB file {} ({})", path, ioe)),
Ok(opened) => opened,
});
hash.insert(self.signature(), wtf);
// the following won't work
// wtf
// &wtf
// &mut wtf
// So I came up with the following, but it doesn't feel right, does it?
hash.get_mut(&self.signature()).unwrap()
}
};
Is there a canonical way to get a mut File
from File::open()
or File::create()
? In the manuals, this is always done with:
let mut file = File:open("foo.txt")?;
This means my function would have to return Result<_, io::Error>
and I can't have that.
The problem seems to be that with the hash-lookup Some(f)
gives me a &mut File
but the Ok(f)
from File::open
gives me just a File
, and I don't know how to make a mutable reference from that, so that the match arm's types match. I have no clear idea why the version as above at least compiles, but I'd very much like to learn how to do that without getting the File
from the HashMap
again.