[][src]Macro path_dsl::path

macro_rules! path {
    ( $($other:tt)* ) => { ... };
    () => { ... };

Efficient macro for creating a PathBuf.

General usage documentation is available at the crate root. The following is documentation of the optimizations made and internal implementation details.


The macro is a fairly simple forwarding macro that just matches against the | syntax specified and forwards it on to the Div based implementation. However it does do some small optimizations, including the use of a hidden type called CopylessDSL which allows for the zero-copy optimization be guarenteed. A single / operation on CopylessDSL always produces a PathDSL.

Some example expansions (on a unix-like system):

path!("concat" | "optimization");
Into::<PathBuf>::into(CopylessDSL::new() / "concat/optimization");
// Steals the data from `owning_path`
path!(owning_path | "concat" | "optimization");
Into::<PathBuf>::into(CopylessDSL::new() / owning_path / "concat/optimization");
// Copies the data from `owning_path` because we already have a buffer
path!("concat" | "optimization" | owning_path | "other_thing");
Into::<PathBuf>::into(CopylessDSL::new() / "concat/optimization" / owning_path / "other_thing");

String Literal Concatenation

One of the optimizations made in the macro is the correct concatenation of multiple string literals in a row, as shown above. This is normally not recommended because there are situations where a path with / will not work on a windows machine. To get around this, I have first actually verified that \\ only happens on windows with a ripgrep of the rust codebase (master as of 2019-08-13):

$ rg "MAIN_SEP: .*="
19:pub const MAIN_SEP: char = '/';

19:pub const MAIN_SEP: char = '/';

19:pub const MAIN_SEP: char = '/';

19:pub const MAIN_SEP: char = '/';

19:pub const MAIN_SEP: char = '/';

93:pub const MAIN_SEP: char = '\\';

I then have an internal macro that I define multiple times using #[cfg(windows)] etc. to always give me the correct separator no matter the platform.

Additionally, due to either my inability to write macros well, or an inherent limitation in rust's declarative macros, I can't match on a set of | separated string literals variadically. As a result I have unrolled the combiner out to 16 string literals in a row. This should be enough for basically everyone. If you go above this limit, it will combine them into ceil(N/16) literals not 1. If you need this limit raised, feel free to submit a PR or an issue, but... why? 😃


CopylessDSL is a #[doc(hidden)] class that aids in the zero-copy optimization. It is a very limited form of PathDSL that supports Div on all types PathDSL supports. It will steal the buffer of any moved in owning values. All Div operations return a PathDSL. Additionally all macro invocations are surrounded by a forced conversion to a PathDSL so this type should never be seen in user code.

If this type shows up in user code at all, this is a bug and should be reported.