[−][src]Macro path_dsl::path
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.
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
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: .*="
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.