Samuel Hapak
Samuel Hapak

Reputation: 7202

How to join Path from multiple parts of different type in Rust?

Documentation provides following example for joining paths:

use std::path::PathBuf;

let path: PathBuf = [r"C:\", "windows", "system32.dll"].iter().collect();

This works when all the components are strings. However, I am trying to write following function:

use std::path::PathBuf;
fn my_path<P: AsRef<Path>>(root: P, dir1: &str, dir2: &str, dir3: &str) -> PathBuf {
    [root, dir1, dir2, dir3].iter().collect()
}

The above obviously doesn't work. I know I can do series of nested joins, but that is, ..., more ugly.

Is there a way to join different path-like components in array?

Upvotes: 3

Views: 1046

Answers (2)

Chayim Friedman
Chayim Friedman

Reputation: 71430

You can convert them to Paths:

fn my_path<P: AsRef<Path>>(root: P, dir1: &str, dir2: &str, dir3: &str) -> PathBuf {
    [
        root.as_ref(),
        Path::new(dir1),
        Path::new(dir2),
        Path::new(dir3),
    ]
    .iter()
    .collect()
}

Or, if the list is long (but this may be less efficient):

fn my_path<P: AsRef<Path>>(root: P, dir1: &str, dir2: &str, dir3: &str) -> PathBuf {
    std::iter::once(root.as_ref())
        .chain([dir1, dir2, dir3].iter().map(Path::new))
        .collect()
}

Upvotes: 0

cafce25
cafce25

Reputation: 27549

You can cast them to dynamic AsRef<Path> objects:

use std::path::{Path, PathBuf};
fn my_path<P: AsRef<Path>>(root: P, dir1: &str, dir2: &str, dir3: &str) -> PathBuf {
    [&root as &dyn AsRef<Path>, &dir1, &dir2, &dir3].iter().collect()
}

or just add the first different object with join:

use std::path::{Path, PathBuf};
fn my_path<P: AsRef<Path>>(root: P, dir1: &str, dir2: &str, dir3: &str) -> PathBuf {
    root.as_ref().join([dir1, dir2, dir3].iter().collect::<PathBuf>())
}

Here it is on Rust Playground

Upvotes: 5

Related Questions