Skip to main content

os_string_from_bytes

Function os_string_from_bytes 

Source
pub fn os_string_from_bytes(value: Vec<u8>) -> Result<OsString, Vec<u8>>
Expand description

Rebuild an OsString from bytes the parser handed back.

This is the reverse of OsStr::as_encoded_bytes, and it is how a PathBuf field receives a filename the operating system accepts but UTF-8 does not — /tmp/\xff stays /tmp/\xff rather than becoming a different filename with U+FFFD in it.

Where the platform cannot hold those bytes, they are handed back in the Err — as String::from_utf8 does — so the caller can name the value in its error without this having to copy it for a case that is nearly never taken.

§Why this is not unsafe, and why it is not lossless everywhere

On Unix an OsString is an arbitrary byte sequence, so the conversion is total and uses the safe OsStringExt::from_vec. Every byte survives, which is the case that matters: non-UTF-8 filenames are ordinary there.

On Windows the encoding is WTF-8, where not every byte sequence is valid, and the only constructor that accepts one is OsString::from_encoded_bytes_unchecked — whose precondition this function cannot enforce. It takes a Vec<u8> from a safe caller, so there is no way to know the bytes came from as_encoded_bytes rather than from anywhere else, and a safe function with a precondition that can be violated is unsound however carefully its callers behave today.

So on Windows the bytes go through UTF-8, and one that is not valid UTF-8 is refused rather than assumed. What that gives up is a Windows argument containing an unpaired surrogate, which is reported instead of accepted; what it buys is that this crate needs no unsafe at all.