Search code examples
arraysstringrustidioms

Idiomatic way to pass an array of `OsStr`


What is the idiomatic way to pass or represent a &[&OsStr]? This way seems to have a lot of unnecessary text:

fn foo(file: &OsStr) {
    Command::new("bar")
        .args(&[OsStr::new("baz"), OsStr::new("qux"), file])
        .spawn();
}

This way looks cleaner, and is how it is done in some of the documentation. However, the file.to_str().unwrap() is distracting, and it is strange to convert an OsStr to a str just to convert it back to a OsStr.

fn foo(file: &OsStr) {
    Command::new("bar")
        .args(&["baz", "qux", file.to_str().unwrap()])
        .spawn();
}

Is there a third option?


Solution

  • Since your main complaint with the first version is that it is too verbose, here is an attempt to reduce the verbosity using a macro:

    macro_rules! args {
        ($($a:expr),*) => { 
            &[
                $(<AsRef<OsStr>>::as_ref(&$a),)*
            ]
        }
    }
    
    
    pub fn foo(file: &OsStr) -> Result<Child> {
        Command::new("bar")
            .args(args!["baz", "qux", file])
            .spawn()
    }
    

    I don't know whether this would be "idiomatic", but that's mostly a matter of preference in cases like this. I personally wouldn't mind the verbosity too much, but maybe slightly shorten the args list to

    &["baz".as_ref(), "qux".as_ref(), file]