Safely and portably? Insofar as I'm aware, there isn't a way. My advice is to demand UTF-8 and just pray it never breaks.
The problem is that the only thing you can really say about a "C string" is that it's NUL-terminated. You can't really say anything meaningful about how it's encoded. At least, not with any real certainty.
Unsafely and/or non-portably? If you're running on Linux (and possibly other modern *NIXen), you can maybe use OsStrExt
to do the conversion. This only works assuming the C string was a valid path in the first place. If it came from some string processing code that wasn't using the same encoding as the filesystem (which these days is generally "arbitrary bytes that look like UTF-8 but might not be")... well, you'll have to convert it yourself, first.
On Windows? Hahahaha. This depends on where the string came from. C strings embedded in an executable can be in a variety of encodings depending on how the code was compiled. If it came from the OS itself, it could be in one of two different encodings: the thread's OEM codepage, or the thread's ANSI codepage. I never worked out how to check which it's set to. If it came from the console, it would be in whatever the console's input encoding was set to when you received it... assuming it wasn't piped in from something else that was using a different encoding (hi there, PowerShell!). All of the above require you to roll your own transcoding code, since Rust itself avoids this by never, ever using non-Unicode APIs on Windows.
Oh, and don't forget that there is no 8-bit encoding that can properly store Windows paths, since Windows paths are "arbitrary 16-bit words that look like UTF-16 but might not be". [1]
... so, like I said: demand UTF-8 and just pray it never breaks, because trying to do it "correctly" leads to madness.
[1]: I should clarify: there is such an encoding: WTF-8, which is what Rust uses for OsStr
and OsString
on Windows. The catch is that nothing else on Windows uses this, so it's never going to be how a C string is encoded.
CString::into_bytes
withOsStringExt
followed byPathBuf::from
on Unix andString
on Windows. – LoverlyCStr
toOsStr
, but I can't find such a function :confused: – VanhooseOsStrExt::from_bytes
such function? AFAICT anOsStr
can be produced from aCStr
usingOsStrExt::from_bytes(cstr.to_bytes())
. This will obviously only work on Unix, but that's unavoidable, since Rust on Windows uses a nativeOsStr
implementation incompatible withchar *
. :/ – AucklandCow
-like enum for C-backed paths. On Unix the enum would expose a cstring-backedOsStr&
and on Windows it would allocate anOsString
and expose its underlyingOsStr&
. – AucklandOsStrExt
. – Loverly