[][src]Macro path_dsl::path

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

Efficient macro for creating a PathDSL.

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

Expansion

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 no-copy-on-first-argument-move optimization be guarenteed. A single / operation on CopylessDSL immediately produces a PathDSL always.

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

This example is not tested
path!("concat" | "optimization");
(CopylessDSL::new() / "concat/optimization").into::<PathDSL>();
This example is not tested
// Steals the data from `owning_path`
path!(owning_path | "concat" | "optimization");
(CopylessDSL::new() / owning_path / "concat/optimization").into::<PathDSL>();
This example is not tested
// Copies the data from `owning_path` because we already have a buffer
path!("concat" | "optimization" | owning_path | "other_thing");
(CopylessDSL::new() / "concat/optimization" / owning_path / "other_thing").into::<PathDSL>();

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: .*="
rust\src\libstd\sys\sgx\path.rs
19:pub const MAIN_SEP: char = '/';

rust\src\libstd\sys\unix\path.rs
19:pub const MAIN_SEP: char = '/';

rust\src\libstd\sys\wasi\path.rs
19:pub const MAIN_SEP: char = '/';

rust\src\libstd\sys\vxworks\path.rs
19:pub const MAIN_SEP: char = '/';

rust\src\libstd\sys\wasm\path.rs
19:pub const MAIN_SEP: char = '/';

rust\src\libstd\sys\windows\path.rs
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

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.