Skip to content

Commit

Permalink
Unrolled build for rust-lang#134622
Browse files Browse the repository at this point in the history
Rollup merge of rust-lang#134622 - ChrisDenton:write-file-utf8, r=Mark-Simulacrum

Windows: Use WriteFile to write to a UTF-8 console

If the console code page is UTF-8 then we can simply write to it without needing to convert to UTF-16 and calling `WriteConsole`.
  • Loading branch information
rust-timer authored Dec 27, 2024
2 parents 42591a4 + 1e3ecd5 commit e10c1d1
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 1 deletion.
1 change: 1 addition & 0 deletions library/std/src/sys/pal/windows/c/bindings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2426,6 +2426,7 @@ Windows.Win32.System.Console.ENABLE_VIRTUAL_TERMINAL_PROCESSING
Windows.Win32.System.Console.ENABLE_WINDOW_INPUT
Windows.Win32.System.Console.ENABLE_WRAP_AT_EOL_OUTPUT
Windows.Win32.System.Console.GetConsoleMode
Windows.Win32.System.Console.GetConsoleOutputCP
Windows.Win32.System.Console.GetStdHandle
Windows.Win32.System.Console.ReadConsoleW
Windows.Win32.System.Console.STD_ERROR_HANDLE
Expand Down
2 changes: 2 additions & 0 deletions library/std/src/sys/pal/windows/c/windows_sys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ windows_targets::link!("kernel32.dll" "system" fn FreeEnvironmentStringsW(penv :
windows_targets::link!("kernel32.dll" "system" fn GetActiveProcessorCount(groupnumber : u16) -> u32);
windows_targets::link!("kernel32.dll" "system" fn GetCommandLineW() -> PCWSTR);
windows_targets::link!("kernel32.dll" "system" fn GetConsoleMode(hconsolehandle : HANDLE, lpmode : *mut CONSOLE_MODE) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn GetConsoleOutputCP() -> u32);
windows_targets::link!("kernel32.dll" "system" fn GetCurrentDirectoryW(nbufferlength : u32, lpbuffer : PWSTR) -> u32);
windows_targets::link!("kernel32.dll" "system" fn GetCurrentProcess() -> HANDLE);
windows_targets::link!("kernel32.dll" "system" fn GetCurrentProcessId() -> u32);
Expand Down Expand Up @@ -3333,6 +3334,7 @@ pub struct XSAVE_FORMAT {
pub XmmRegisters: [M128A; 8],
pub Reserved4: [u8; 224],
}

#[cfg(target_arch = "arm")]
#[repr(C)]
pub struct WSADATA {
Expand Down
24 changes: 23 additions & 1 deletion library/std/src/sys/pal/windows/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,21 +84,43 @@ fn is_console(handle: c::HANDLE) -> bool {
unsafe { c::GetConsoleMode(handle, &mut mode) != 0 }
}

/// Returns true if the attached console's code page is currently UTF-8.
#[cfg(not(target_vendor = "win7"))]
fn is_utf8_console() -> bool {
unsafe { c::GetConsoleOutputCP() == c::CP_UTF8 }
}

#[cfg(target_vendor = "win7")]
fn is_utf8_console() -> bool {
// Windows 7 has a fun "feature" where WriteFile on a console handle will return
// the number of UTF-16 code units written and not the number of bytes from the input string.
// So we always claim the console isn't UTF-8 to trigger the WriteConsole fallback code.
false
}

fn write(handle_id: u32, data: &[u8], incomplete_utf8: &mut IncompleteUtf8) -> io::Result<usize> {
if data.is_empty() {
return Ok(0);
}

let handle = get_handle(handle_id)?;
if !is_console(handle) {
if !is_console(handle) || is_utf8_console() {
unsafe {
let handle = Handle::from_raw_handle(handle);
let ret = handle.write(data);
let _ = handle.into_raw_handle(); // Don't close the handle
return ret;
}
} else {
write_console_utf16(data, incomplete_utf8, handle)
}
}

fn write_console_utf16(
data: &[u8],
incomplete_utf8: &mut IncompleteUtf8,
handle: c::HANDLE,
) -> io::Result<usize> {
if incomplete_utf8.len > 0 {
assert!(
incomplete_utf8.len < 4,
Expand Down

0 comments on commit e10c1d1

Please sign in to comment.