Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass list of paths to a function?

Tags:

rust

I want to pass list of directory names to function, like so:

use std::path::Path;

fn test(dirs: &Vec<Path>) {}

fn main() {
    let dirs = vec![Path::new("/tmp"), Path::new("/var/tmp")];
    test(dirs);
}

But it does not compile:

<anon>:3:5: 4:6 error: the trait bound `[u8]: std::marker::Sized` is not satisfied [E0277]
<anon>:3     fn test(dirs: &Vec<Path>) {
<anon>:4     }
<anon>:3:5: 4:6 help: see the detailed explanation for E0277
<anon>:3:5: 4:6 note: `[u8]` does not have a constant size known at compile-time
<anon>:3:5: 4:6 note: required because it appears within the type `std::sys::os_str::Slice`
<anon>:3:5: 4:6 note: required because it appears within the type `std::ffi::OsStr`
<anon>:3:5: 4:6 note: required because it appears within the type `std::path::Path`
<anon>:3:5: 4:6 note: required by `std::vec::Vec`

Looks like Path not Sized?

How should I fix this, if I do not want to pass Vec<String> to function? Maybe PathBuf? How to implement this in rusty way?

like image 321
user1244932 Avatar asked Jul 03 '16 13:07

user1244932


1 Answers

Indeed, Path is an unsized type, just like str. Pretty much the only sensible way to work with a Path is to take a reference to it: &Path (just like &str). So your example would look like this:

use std::path::Path;

fn test(dirs: &[&Path]) {}

fn main() {
    let dirs = vec![Path::new("/tmp"), Path::new("/var/tmp")];
    test(&dirs);
}

Not that I also changed the &Vec<_> to &[_]. A reference to a Vec is not more powerful than a slice (&[_]), thus the idiomatic way is to pass slices instead of references to vectors.


The above solution is the correct way if you don't want to transfer ownership to the test function. If you want to transfer ownership (including the string buffer actually saving the path data), you should use PathBuf.

like image 101
Lukas Kalbertodt Avatar answered Nov 05 '22 03:11

Lukas Kalbertodt