Description
Proposal
Problem statement
Rust's Path
types require this slash to treat paths as a directory. While methods like push
will always treat the current path as a directory, other methods like set_file_name
and set_extension
won't.
Motivating examples or use cases
It's common for users to write paths while omitting the trailing slash, like so:
windows_path = "C:\\Users\\Me"
unix_path = "/home/me"
When converting these strings to paths via methods like Path::new
, it could be desirable to normalise these into the trailing-slash form to ensure that methods work correctly, like set_file_name
. For example, a method to check for a configuration file in a directory might look like this:
let mut buf = PathBuf::from(some_path_string);
for filename in &[/* ... */] {
buf.set_file_name(filename);
match File::open(&buf) {
Err(err) if err.kind() == io::ErrorKind::NotFound => continue,
res => return res,
}
}
In this case, the set_file_name
call will only work as expected if the initial path is a directory. If it's not, the last component of the directory will be overwritten.
Solution sketch
impl Path {
// whether the path ends in a directory separator
fn has_dir_suffix(&self) -> bool;
// makes this path have a dir suffix, which may involve copying it to a new buffer
fn with_dir_suffix(&self) -> Cow<'_, Path>;
}
impl PathBuf {
// adds or removes a directory separator such that `has_dir_suffix` has the given value
fn set_dir_suffix(&mut self, suffix: bool);
}
Alternatives
As mentioned above, push("")
will be equivalent to set_dir_suffix(true)
, since adding an "empty" component will simply add a trailing slash. However, it's not clear that this will always work as expected, and that's why this method is proposed.
In particular, set_dir_suffix
has some obvious properties that aren't clear from push("")
:
- The result will always have
file_name() == None
- The method is idempotent (calling it multiple times is equivalent to calling it once)
- You can also remove the dir suffix without having to verify these invariants
Links and related work
N/A
What happens now?
This issue contains an API change proposal (or ACP) and is part of the libs-api team feature lifecycle. Once this issue is filed, the libs-api team will review open proposals as capability becomes available. Current response times do not have a clear estimate, but may be up to several months.
Possible responses
The libs team may respond in various different ways. First, the team will consider the problem (this doesn't require any concrete solution or alternatives to have been proposed):
- We think this problem seems worth solving, and the standard library might be the right place to solve it.
- We think that this probably doesn't belong in the standard library.
Second, if there's a concrete solution:
- We think this specific solution looks roughly right, approved, you or someone else should implement this. (Further review will still happen on the subsequent implementation PR.)
- We're not sure this is the right solution, and the alternatives or other materials don't give us enough information to be sure about that. Here are some questions we have that aren't answered, or rough ideas about alternatives we'd want to see discussed.