1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
14 use io
::{self, Cursor}
;
20 use sys
::handle
::Handle
;
22 pub struct NoClose(Option
<Handle
>);
31 utf8
: Mutex
<io
::Cursor
<Vec
<u8>>>,
33 pub struct Stdout(Output
);
34 pub struct Stderr(Output
);
36 pub fn get(handle
: c
::DWORD
) -> io
::Result
<Output
> {
37 let handle
= unsafe { c::GetStdHandle(handle) }
;
38 if handle
== c
::INVALID_HANDLE_VALUE
{
39 Err(io
::Error
::last_os_error())
40 } else if handle
.is_null() {
41 Err(io
::Error
::new(io
::ErrorKind
::Other
,
42 "no stdio handle available for this process"))
44 let ret
= NoClose
::new(handle
);
46 match unsafe { c::GetConsoleMode(handle, &mut out) }
{
47 0 => Ok(Output
::Pipe(ret
)),
48 _
=> Ok(Output
::Console(ret
)),
53 fn write(out
: &Output
, data
: &[u8]) -> io
::Result
<usize> {
54 let handle
= match *out
{
55 Output
::Console(ref c
) => c
.get().raw(),
56 Output
::Pipe(ref p
) => return p
.get().write(data
),
58 let utf16
= match str::from_utf8(data
).ok() {
59 Some(utf8
) => utf8
.encode_utf16().collect
::<Vec
<u16>>(),
60 None
=> return Err(invalid_encoding()),
64 c
::WriteConsoleW(handle
,
65 utf16
.as_ptr() as c
::LPCVOID
,
71 // FIXME if this only partially writes the utf16 buffer then we need to
72 // figure out how many bytes of `data` were actually written
73 assert_eq
!(written
as usize, utf16
.len());
78 pub fn new() -> io
::Result
<Stdin
> {
79 get(c
::STD_INPUT_HANDLE
).map(|handle
| {
82 utf8
: Mutex
::new(Cursor
::new(Vec
::new())),
87 pub fn read(&self, buf
: &mut [u8]) -> io
::Result
<usize> {
88 let handle
= match self.handle
{
89 Output
::Console(ref c
) => c
.get().raw(),
90 Output
::Pipe(ref p
) => return p
.get().read(buf
),
92 let mut utf8
= self.utf8
.lock().unwrap();
93 // Read more if the buffer is empty
94 if utf8
.position() as usize == utf8
.get_ref().len() {
95 let mut utf16
= vec
![0u16; 0x1000];
98 c
::ReadConsoleW(handle
,
99 utf16
.as_mut_ptr() as c
::LPVOID
,
104 utf16
.truncate(num
as usize);
105 // FIXME: what to do about this data that has already been read?
106 let data
= match String
::from_utf16(&utf16
) {
107 Ok(utf8
) => utf8
.into_bytes(),
108 Err(..) => return Err(invalid_encoding()),
110 *utf8
= Cursor
::new(data
);
113 // MemReader shouldn't error here since we just filled it
119 pub fn new() -> io
::Result
<Stdout
> {
120 get(c
::STD_OUTPUT_HANDLE
).map(Stdout
)
123 pub fn write(&self, data
: &[u8]) -> io
::Result
<usize> {
129 pub fn new() -> io
::Result
<Stderr
> {
130 get(c
::STD_ERROR_HANDLE
).map(Stderr
)
133 pub fn write(&self, data
: &[u8]) -> io
::Result
<usize> {
138 // FIXME: right now this raw stderr handle is used in a few places because
139 // std::io::stderr_raw isn't exposed, but once that's exposed this impl
141 impl io
::Write
for Stderr
{
142 fn write(&mut self, data
: &[u8]) -> io
::Result
<usize> {
143 Stderr
::write(self, data
)
145 fn flush(&mut self) -> io
::Result
<()> { Ok(()) }
149 fn new(handle
: c
::HANDLE
) -> NoClose
{
150 NoClose(Some(Handle
::new(handle
)))
153 fn get(&self) -> &Handle { self.0.as_ref().unwrap() }
156 impl Drop
for NoClose
{
158 self.0.take().unwrap().into_raw();
163 pub fn handle(&self) -> &Handle
{
164 let nc
= match *self {
165 Output
::Console(ref c
) => c
,
166 Output
::Pipe(ref c
) => c
,
168 nc
.0.as_ref().unwrap()
172 fn invalid_encoding() -> io
::Error
{
173 io
::Error
::new(io
::ErrorKind
::InvalidData
, "text was not valid unicode")