Change the return type from Vec<&'a Path> to Vec<PathBuf>. References should generally be avoided in return types unless you know you need them. Particularly when learning Rust. In this case, full_path is of type PathBuf already and you are trying to store a reference to it in the Vec but the memory it is referencing will be dropped at the end of each iteration of the loop in _list_files. With that change the code looks like this
fn _list_files(vec: &mut Vec<PathBuf>, path: &Path) {
if metadata(&path).unwrap().is_dir() {
let paths = fs::read_dir(&path).unwrap();
for path_result in paths {
let full_path = path_result.unwrap().path();
if metadata(&full_path).unwrap().is_dir() {
_list_files(vec, &full_path);
} else {
vec.push(full_path);
}
}
}
}
fn list_files(path: &Path) -> Vec<PathBuf> {
let mut vec = Vec::new();
_list_files(&mut vec,&path);
vec
}
Just for good measure. Here's a version that's a bit more idiomatic that gets rid of the unwrap() calls, and instead lets the caller handle errors how they want. Otherwise on an error, unwrap() will cause a panic and end the program.
fn _list_files(vec: &mut Vec<PathBuf>, path: &Path) -> io::Result<()> {
if metadata(&path)?.is_dir() {
let paths = fs::read_dir(&path)?;
for path_result in paths {
let full_path = path_result?.path();
if metadata(&full_path)?.is_dir() {
_list_files(vec, &full_path)?
} else {
vec.push(full_path);
}
}
}
Ok(())
}
fn list_files(path: &Path) -> io::Result<Vec<PathBuf>> {
let mut vec = Vec::new();
_list_files(&mut vec,&path)?;
Ok(vec)
}
What you have looks good. In the standard library, it's common to use AsRef<Path> as the argument type for anything that takes a path. That type is similarly generic over a bunch of types, but doesn't need to take ownership. In your case though, since you're returning Vec<PathBuf>, I think what you have is the best choice.