I have this Python code from an existing project that I'm trying to port to Rust as a learning exercise (plus a thing I actually have a use for if I succeed):
class BaseKlazz:
# stuff
# from contextlib import contextmanager
@contextmanager
def set_directory(self, path: str):
orig_dir = os.getcwd()
try:
os.chdir(path)
yield
finally:
os.chdir(org_dir)
class Klazz(BaseKlazz):
# stuff
def funktion():
# do stuff
try:
# rm -rf somedir
# mkdir -p somedir
with self.set_directory(somedir): # <-- How do I port this to Rust?
# do things, maybe write files, maybe more mkdir, maybe write more files
pass
# potentially do more things with original dir
except:
# handle/propagate library/application errors
pass
The original codebase is in Python and therefore makes use of OOP and exceptions, which are not the easiest things to port to Rust, but manageable.
The generators / context managers it uses though, I'm not sure how I can port to rust. I saw this question which suggests I use RAII, but I'm still unsure how to make that work:
pub struct ChdirGuard {
original_path: PathBuf
}
impl ChdirGuard {
pub fn new(target_path: PathBuf) -> ChdirGuard {
let chdir_guard = ChdirGuard {
original_path: std::env::current_dir().unwrap()
};
std::env::set_current_dir(&target_path);
return chdir_guard
}
}
impl Drop for ChdirGuard {
fn drop(&mut self) {
std::env::set_current_dir(&self.original_path)
}
}
struct Klazz {}
impl Klazz {
pub fn funktion(&self) {
// rm -rf somedir + check result of rm, because rust
// mkdir -p somedir + check result of mkdir, because rust
{
let _ = ChdirGuard::new(PathBuf::from("somedir"));
// do things, maybe write files, maybe more mkdir, maybe write more files
}
// potentially do more things with original dir
}
}
Looks a bit jank, certainly not used to seeing a random unnamed block in the middle of a function. Maybe I'm missing something, or is this really the way to do RAII in Rust? Will it work if I .unwrap() and explode, return prematurely from funktion with a Result, etc. ?