diff --git a/src/lib.rs b/src/lib.rs index 968442c..673e6cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -66,6 +66,14 @@ pub struct Console { raw_guard: Option, } +impl Console { + /// Construct with the normal stdin and stdout file descriptors, for + /// typical use. + pub async fn new_stdio(escape: Option) -> Result { + Console::new(tokio::io::stdin(), tokio::io::stdout(), escape).await + } +} + impl Console { /// Construct with arbitrary [AsyncReadExt] and [AsyncWriteExt] streams, /// supporting use cases where we might be talking to something other than @@ -84,17 +92,7 @@ impl Console { )?); Ok(Self::new_inner(stdin, stdout, escape, raw_guard)) } -} -impl Console { - /// Construct with the normal stdin and stdout file descriptors, for - /// typical use. - pub async fn new_stdio(escape: Option) -> Result { - Console::new(tokio::io::stdin(), tokio::io::stdout(), escape).await - } -} - -impl Console { fn new_inner( stdin: I, stdout: O, @@ -125,8 +123,30 @@ impl Console { /// Write the given bytes to stdout. pub async fn write_stdout(&mut self, bytes: &[u8]) -> Result<(), Error> { - self.stdout.write_all(bytes).await?; - self.stdout.flush().await?; + // windows io in rust fails if any byte sequences aren't valid utf8 + #[cfg(target_family = "windows")] + { + use winapi::shared::minwindef::LPDWORD; + use winapi::um::winnt::{HANDLE, VOID}; + let mut _lp_num_of_chars_written = 0u32; + let res = unsafe { + winapi::um::consoleapi::WriteConsoleA( + self.stdout.as_raw_handle() as HANDLE, + bytes.as_ptr() as *const VOID, + bytes.len() as u32, + (&mut _lp_num_of_chars_written) as LPDWORD, + std::ptr::null_mut::(), + ) + }; + if res == 0 { + return Err(std::io::Error::last_os_error().into()); + } + } + #[cfg(not(target_family = "windows"))] + { + self.stdout.write_all(bytes).await?; + self.stdout.flush().await?; + } Ok(()) }