How to put a `Path` in constant?

I have a constant path written in unix path path/to/file, but on windows it is path\to\file, how to unify them?
Now my solution is

const GLOB_PATH: &str = cfg!(windows) {
    r"path\to\file"
} else {
    "path/to/file"
};

It works fine now, but I don't know how it present on the system except windows and unix. Is there a more elegant workaround, thanks.

One way is to cheat. The Win32 API tolerates forward slashes; they tend to only cause trouble when passing them to older command-line apps which use /flags instead of unix-like -flags.

2 Likes

Thanks. But I want to solve this problem at programming language level.

Here's a playpen with a macro that will do this.

#[cfg(target_os = "windows")]
macro_rules! path {
    ($($parts:literal),* $(,)?) => {
        concat!("" $(, $parts, )"\\"*)
    };
}

#[cfg(not(target_os = "windows"))]
macro_rules! path {
    ($($parts:literal),* $(,)?) => {
        concat!("" $(, $parts, )"/"*)
    };
}

fn main() {
    let p: &'static str = path!("a", "b", "c");
    println!("path: {:?}", p);
}
4 Likes

You can see some alternative workarounds here.

#[cfg(not(windows))] macro_rules! sep { () => {   "/"  } }
#[cfg(    windows) ] macro_rules! sep { () => { r#"\"# } }

const GLOB_PATH: &str = concat!("path", sep!(), "to", sep!(), "file");

(Edit: Heh, didn't see someone beat me to it.)

2 Likes
use std::path::MAIN_SEPARATOR;
use const_format::formatcp;
const PATH: &str = formatcp!("path{0}to{0}somewhere", MAIN_SEPARATOR);

rustexplorer

8 Likes

Thanks, but it is slightly more complex than @quinedot 's.

Thanks! I didn't know concat!() could work on macros. :grinning:

Concat, just like print family of macros are special in that they expand macros passed to them.

Not sure what you mean, but forward and backward slash cover all modern operating systems. There used to be other ways of doing paths, but none of those have been relevant for the last two decades or so.

Mac OS 9 was probably the last one, it used ":" as the separator, had a very different scheme for absolute/relative paths and to go up a level you used "::". Yes that means you had to be careful pasting paths together, you couldn't harmlessly duplicate the separator as with / on *nix.

3 Likes

Seems weird, I'll be careful.