As a Rust beginner, I would like to know how I could improve the following points considering the function below:
- Handling
Path
andPathBuf
types correctly; - Performance;
- Rust writing style in general.
Here is the function, decorated with a full working example:
use std::env;
use std::path::{Path, PathBuf};
const RUSV_FILENAME: &str = ".rusv.json";
/**
* Find a rusv file in the current or parent directories of the given directory.
*/
fn find_rusv_file(starting_directory: &Path) -> Option<PathBuf> {
let mut directory = starting_directory;
let rusv_filename = Path::new(&RUSV_FILENAME);
loop {
let filepath: PathBuf = [
directory,
rusv_filename
].iter().collect();
if filepath.is_file() {
return Some(filepath);
}
match directory.parent() {
Some(parent) => directory = parent,
None => return None,
}
}
}
fn main() -> std::io::Result<()> {
let path = env::current_dir()?;
match find_rusv_file(&path) {
Some(filepath) => println!("Rusv file was found: {:?}", filepath),
None => println!("No rusv file was found."),
};
Ok(())
}
My question is not about:
- Creating a more generic function (e.g. by giving the filename as an argument);
- Anything related to the
main()
function.
1 Answer 1
Handling Path and PathBuf types correctly;
My concern is that you recreate PathBuf
every time, I don't see the point to have a buffer if you don't use it.
Performance;
I think it's ok, you search one file in particular the time you take creating the string is cheap compare to system call. So I don't think read_dir
is better on your case. This could be benchmarked.
Rust writing style in general.
You are using return
, on your case maybe use break
to make your function SESE (single entry single exit).
Path::new(&RUSV_FILENAME);
the reference is not needed Path::new(RUSV_FILENAME);
.
fn find_rusv_file(starting_directory: &Path) -> Option<PathBuf> {
let mut path: PathBuf = starting_directory.into();
let file = Path::new(RUSV_FILENAME);
loop {
path.push(file);
if path.is_file() {
break Some(path);
}
if !(path.pop() && path.pop()) { // remove file && remove parent
break None;
}
}
}