Description
Path::components
is incorrect on Redox. I would like to develop the solution
here: #51537.
The following is a description of the problem.
Suppose you have the following path:
file:/home/user/foo/bar.txt
You split the path into components using Path::components
Path::new("file:/home/user/foo/bar.txt").components().collect::<Vec<()>>()
In Linux, this would be equivalent to the following:
vec![
Component::Normal("file:"),
Component::Normal("home"),
Component::Normal("user"),
Component::Normal("foo"),
Component::Normal("bar.txt"),
]
Joining the components with the current directory would give you a path such as
this:
./file:/home/user/foo/bar.txt
In Redox, we want to be able to get from the original path to components back to
the original path without any modifications. Here are examples of this usage of
Path::components
:
https://github.com/uutils/coreutils/search?q=components
In Redox, we have the following options for the file:
component:
Component::Normal("file:")
Component::Normal("file:")
followed byComponent::RootDir
Component::Prefix(Prefix::Verbatim("file:"))
Component::Prefix(Prefix::Scheme("file:"))
Option 1
Component::Normal("file:")
The path mentioned above would end up being the following after being rebuilt
from its components:
./file:/home/user/foo/bar.txt
This is the old way of doing things. It not only makes Path::components
useless on Redox. Canonicalizing a path will always add a scheme like file:
to the beginning, so it is likely that path handling will be incorrect.
Absolute paths would always be interpreted as relative.
❌ This option is unusable for Redox.
Option 2
Component::Normal("file:")
followed by Component::RootDir
This would preserve the original meaning of the path, such that it could be
rebuilt from its components as follows:
file:/home/user/foo/bar.txt
However, this may require a large amount of work to handle, as it seems likely
that code exists that only checks the first component for being
Component::RootDir
or Component::Prefix
in order to identify an absolute
path.
The documentation for Prefix
provides one such example, which has likely
inspired similar usage:
https://doc.rust-lang.org/std/path/enum.Prefix.html#examples
❌ This option would likely break the expectations of many consumers of the
Prefix
enum.
Option 3
Component::Prefix(Prefix::Verbatim("file:"))
This option preserves the original meaning of the path, a rebuilt path would be
this:
file:/home/user/foo/bar.txt
This, however, is overloading a variant meant to be used on Windows, for a path
looking like this:
\\?\home\user\foo\bar.txt
This means different code will be needed when running on Redox to correctly
parse paths to components and turn components into paths.
✔️ This does leave the enum untouched, while allowing for the
correct parsing of paths on Redox. The only downside is a possible lack of
clarity due to overloading the meaning of the Prefix::Verbatim
variant.
Option 4
Component::Prefix(Prefix::Scheme("file:"))
This option also preserves the original meaning of the path, a rebuilt path
would be this:
file:/home/user/foo/bar.txt
This is the most clear option, having separate code to handle specifically the
Redox scheme abstraction.
This has the downside of changing a stable enum, Prefix
. There is, however,
the possibility of having the extra enum variant be
#[cfg(target_os = "redox")]
, so as to preserve the Prefix
enum on other
platforms.
✔️ This option could be used to have correct path parsing
without affecting the stability of the Prefix
enum on non-Redox platforms,
if a cfg
attribute is used.
Conclusion
Potentially the Prefix
enum would be done different after a major version bump,
perhaps using extension traits that are platform specific. I would think that
there would be an opaque Prefix
struct, and something like .into_os_prefix()
would provide you with an os-specific enum to match against.
For the time being, options 3 and 4 seem to be possible, with some caveats, and
would allow code using stable Rust to quickly do-the-right-thing on Redox.