Repository: mdsteele/rust-ar (language: rust)

Issue:
Windows `.lib` files do not use UTF-16.
In d68690d0aff194db4959763d1cb707984fd6a36b, an `OsStr -> UTF-16` encoding step was added on Windows, but neither Rust `.rlib`s nor MSVC `.lib`s appear to use that format.

IME, the names of object files in an archive also tend to be ASCII, so a simple solution would be to revert d68690d0aff194db4959763d1cb707984fd6a36b - however, I haven't checked what MSVC does if you do have unicode in a file name.

I may PR a change here but I first want to make sure I understand what the full spectrum of behaviors is.


Discussion / hints:
Just confirmed (using a file name with some Cyrillic in it) that `LIB.EXE` includes the UTF-8 encoding of a `.obj` file name, so `osstr_to_bytes` should just have a single `cfg(not(unix))` case, only allowing non-UTF-8 on UNIX.
What happens when you use an unpaired surrogate in the filename? Does msvc give an error? Or does it use something like WTF-8 to encode it?
I've done the unpaired surrogate test using [a small Rust program to drive everything](https://gist.github.com/eddyb/a88d71555ece9f8761fa8844a331e950).
The actual compiler doesn't seem to allow invalid UTF-8 in filenames, so I had to rename the input file.
`LIB.EXE` doesn't give an error, but it does encode `U+FFFD` in UTF-8 (`\xEF\xBF\xBD`), instead of my surrogate.

So we could use `to_str_lossy()` if we wanted to mimic that, but an error seems saner than corrupting the input.

Fix patch:
diff --git a/src/lib.rs b/src/lib.rs
index f2b51f8..b73e804 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -81,9 +81,6 @@ use std::os::unix::fs::MetadataExt;
 #[cfg(unix)]
 use std::os::unix::ffi::OsStrExt;
 
-#[cfg(windows)]
-use std::os::windows::ffi::OsStrExt;
-
 // ========================================================================= //
 
 fn read_le_u32(r: &mut impl io::Read) -> io::Result<u32> {
@@ -1102,18 +1099,7 @@ fn osstr_to_bytes(string: &OsStr) -> Result<Vec<u8>> {
     Ok(string.as_bytes().to_vec())
 }
 
-#[cfg(windows)]
-fn osstr_to_bytes(string: &OsStr) -> Result<Vec<u8>> {
-    let mut bytes = Vec::<u8>::new();
-    for wide in string.encode_wide() {
-        // Little-endian:
-        bytes.push((wide & 0xff) as u8);
-        bytes.push((wide >> 8) as u8);
-    }
-    Ok(bytes)
-}
-
-#[cfg(not(any(unix, windows)))]
+#[cfg(not(unix))]
 fn osstr_to_bytes(string: &OsStr) -> Result<Vec<u8>> {
     let utf8: &str = string.to_str().ok_or_else(|| {
         Error::new(ErrorKind::InvalidData, "Non-UTF8 file name")


Test patch: