Skip to content

Commit 67b123b

Browse files
committed
Runtime removal: refactor tty
This patch continues runtime removal by moving the tty implementations into `sys`. Because this eliminates APIs in `libnative` and `librustrt`, it is a: [breaking-change] This functionality is likely to be available publicly, in some form, from `std` in the future.
1 parent 0bda87d commit 67b123b

File tree

8 files changed

+112
-96
lines changed

8 files changed

+112
-96
lines changed

src/libnative/io/mod.rs

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -99,30 +99,4 @@ impl IoFactory {
9999
}
100100

101101
impl rtio::IoFactory for IoFactory {
102-
#[cfg(unix)]
103-
fn tty_open(&mut self, fd: c_int, _readable: bool)
104-
-> IoResult<Box<rtio::RtioTTY + Send>> {
105-
if unsafe { libc::isatty(fd) } != 0 {
106-
Ok(box file::FileDesc::new(fd, true) as Box<rtio::RtioTTY + Send>)
107-
} else {
108-
Err(IoError {
109-
code: libc::ENOTTY as uint,
110-
extra: 0,
111-
detail: None,
112-
})
113-
}
114-
}
115-
#[cfg(windows)]
116-
fn tty_open(&mut self, fd: c_int, _readable: bool)
117-
-> IoResult<Box<rtio::RtioTTY + Send>> {
118-
if tty::is_tty(fd) {
119-
Ok(box tty::WindowsTTY::new(fd) as Box<rtio::RtioTTY + Send>)
120-
} else {
121-
Err(IoError {
122-
code: libc::ERROR_INVALID_HANDLE as uint,
123-
extra: 0,
124-
detail: None,
125-
})
126-
}
127-
}
128102
}

src/libstd/io/stdio.rs

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use kinds::Send;
3636
use libc;
3737
use option::{Option, Some, None};
3838
use boxed::Box;
39-
use sys::fs::FileDesc;
39+
use sys::{fs, tty};
4040
use result::{Ok, Err};
4141
use rt;
4242
use rt::local::Local;
@@ -74,17 +74,15 @@ use uint;
7474
// tl;dr; TTY works on everything but when windows stdout is redirected, in that
7575
// case pipe also doesn't work, but magically file does!
7676
enum StdSource {
77-
TTY(Box<RtioTTY + Send>),
78-
File(FileDesc),
77+
TTY(tty::TTY),
78+
File(fs::FileDesc),
7979
}
8080

81-
fn src<T>(fd: libc::c_int, readable: bool, f: |StdSource| -> T) -> T {
82-
LocalIo::maybe_raise(|io| {
83-
Ok(match io.tty_open(fd, readable) {
84-
Ok(tty) => f(TTY(tty)),
85-
Err(_) => f(File(FileDesc::new(fd, false))),
86-
})
87-
}).map_err(IoError::from_rtio_error).unwrap()
81+
fn src<T>(fd: libc::c_int, _readable: bool, f: |StdSource| -> T) -> T {
82+
match tty::TTY::new(fd) {
83+
Ok(tty) => f(TTY(tty)),
84+
Err(_) => f(File(fs::FileDesc::new(fd, false))),
85+
}
8886
}
8987

9088
local_data_key!(local_stdout: Box<Writer + Send>)
@@ -278,7 +276,7 @@ impl Reader for StdReader {
278276
// print!'d prompt not being shown until after the user hits
279277
// enter.
280278
flush();
281-
tty.read(buf).map_err(IoError::from_rtio_error)
279+
tty.read(buf).map(|i| i as uint)
282280
},
283281
File(ref mut file) => file.read(buf).map(|i| i as uint),
284282
};
@@ -313,7 +311,7 @@ impl StdWriter {
313311
pub fn winsize(&mut self) -> IoResult<(int, int)> {
314312
match self.inner {
315313
TTY(ref mut tty) => {
316-
tty.get_winsize().map_err(IoError::from_rtio_error)
314+
tty.get_winsize()
317315
}
318316
File(..) => {
319317
Err(IoError {
@@ -335,7 +333,7 @@ impl StdWriter {
335333
pub fn set_raw(&mut self, raw: bool) -> IoResult<()> {
336334
match self.inner {
337335
TTY(ref mut tty) => {
338-
tty.set_raw(raw).map_err(IoError::from_rtio_error)
336+
tty.set_raw(raw)
339337
}
340338
File(..) => {
341339
Err(IoError {
@@ -372,7 +370,7 @@ impl Writer for StdWriter {
372370
let max_size = if cfg!(windows) {8192} else {uint::MAX};
373371
for chunk in buf.chunks(max_size) {
374372
try!(match self.inner {
375-
TTY(ref mut tty) => tty.write(chunk).map_err(IoError::from_rtio_error),
373+
TTY(ref mut tty) => tty.write(chunk),
376374
File(ref mut file) => file.write(chunk),
377375
})
378376
}

src/libstd/sys/common/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ pub fn short_write(n: uint, desc: &'static str) -> IoError {
4848
}
4949
}
5050

51+
pub fn unimpl() -> IoError {
52+
IoError {
53+
kind: io::IoUnavailable,
54+
desc: "operations not yet supported",
55+
detail: None,
56+
}
57+
}
58+
5159
// unix has nonzero values as errors
5260
pub fn mkerr_libc<Int: num::Zero>(ret: Int) -> IoResult<()> {
5361
if !ret.is_zero() {

src/libstd/sys/unix/fs.rs

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -137,25 +137,6 @@ impl FileDesc {
137137
}
138138
}
139139

140-
/*
141-
142-
impl RtioTTY for FileDesc {
143-
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
144-
self.inner_read(buf)
145-
}
146-
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
147-
self.inner_write(buf)
148-
}
149-
fn set_raw(&mut self, _raw: bool) -> IoResult<()> {
150-
Err(super::unimpl())
151-
}
152-
fn get_winsize(&mut self) -> IoResult<(int, int)> {
153-
Err(super::unimpl())
154-
}
155-
fn isatty(&self) -> bool { false }
156-
}
157-
*/
158-
159140
impl Drop for FileDesc {
160141
fn drop(&mut self) {
161142
// closing stdio file handles makes no sense, so never do it. Also, note

src/libstd/sys/unix/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub mod pipe;
3535
pub mod helper_signal;
3636
pub mod process;
3737
pub mod timer;
38+
pub mod tty;
3839

3940
pub mod addrinfo {
4041
pub use sys_common::net::get_host_addresses;

src/libstd/sys/unix/tty.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2014 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.
4+
//
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.
10+
11+
use sys::fs::FileDesc;
12+
use prelude::*;
13+
use libc::{mod, c_int};
14+
use io::{mod, IoResult, IoError};
15+
use sys_common;
16+
17+
pub struct TTY {
18+
pub fd: FileDesc,
19+
}
20+
21+
impl TTY {
22+
pub fn new(fd: c_int) -> IoResult<TTY> {
23+
if unsafe { libc::isatty(fd) } != 0 {
24+
Ok(TTY { fd: FileDesc::new(fd, true) })
25+
} else {
26+
Err(IoError {
27+
kind: io::MismatchedFileTypeForOperation,
28+
desc: "file descriptor is not a TTY",
29+
detail: None,
30+
})
31+
}
32+
}
33+
34+
pub fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
35+
self.fd.read(buf)
36+
}
37+
pub fn write(&mut self, buf: &[u8]) -> IoResult<()> {
38+
self.fd.write(buf)
39+
}
40+
pub fn set_raw(&mut self, _raw: bool) -> IoResult<()> {
41+
Err(sys_common::unimpl())
42+
}
43+
pub fn get_winsize(&mut self) -> IoResult<(int, int)> {
44+
Err(sys_common::unimpl())
45+
}
46+
pub fn isatty(&self) -> bool { false }
47+
}

src/libstd/sys/windows/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ pub mod pipe;
4242
pub mod helper_signal;
4343
pub mod process;
4444
pub mod timer;
45+
pub mod tty;
4546

4647
pub mod addrinfo {
4748
pub use sys_common::net::get_host_addresses;

src/libnative/io/tty_windows.rs renamed to src/libstd/sys/windows/tty.rs

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,16 @@ use super::c::{ENABLE_PROCESSED_INPUT, ENABLE_QUICK_EDIT_MODE};
3333
use libc::{c_int, HANDLE, LPDWORD, DWORD, LPVOID};
3434
use libc::{get_osfhandle, CloseHandle};
3535
use libc::types::os::arch::extra::LPCVOID;
36-
use std::io::MemReader;
37-
use std::ptr;
38-
use std::rt::rtio::{IoResult, IoError, RtioTTY};
39-
use std::str::from_utf8;
36+
use io::{mod, IoError, IoResult, MemReader};
37+
use prelude::*;
38+
use ptr;
39+
use str::from_utf8;
4040

4141
fn invalid_encoding() -> IoError {
4242
IoError {
43-
code: ERROR_ILLEGAL_CHARACTER as uint,
44-
extra: 0,
45-
detail: Some("text was not valid unicode".to_string()),
43+
kind: io::InvalidInput,
44+
desc: "text was not valid unicode",
45+
detail: None,
4646
}
4747
}
4848

@@ -56,40 +56,37 @@ pub fn is_tty(fd: c_int) -> bool {
5656
}
5757
}
5858

59-
pub struct WindowsTTY {
59+
pub struct TTY {
6060
closeme: bool,
6161
handle: HANDLE,
6262
utf8: MemReader,
6363
}
6464

65-
impl WindowsTTY {
66-
pub fn new(fd: c_int) -> WindowsTTY {
67-
// If the file descriptor is one of stdin, stderr, or stdout
68-
// then it should not be closed by us
69-
let closeme = match fd {
70-
0...2 => false,
71-
_ => true,
72-
};
73-
let handle = unsafe { get_osfhandle(fd) as HANDLE };
74-
WindowsTTY {
75-
handle: handle,
76-
utf8: MemReader::new(Vec::new()),
77-
closeme: closeme,
65+
impl TTY {
66+
pub fn new(fd: c_int) -> IoResult<TTY> {
67+
if is_tty(fd) {
68+
// If the file descriptor is one of stdin, stderr, or stdout
69+
// then it should not be closed by us
70+
let closeme = match fd {
71+
0...2 => false,
72+
_ => true,
73+
};
74+
let handle = unsafe { get_osfhandle(fd) as HANDLE };
75+
Ok(TTY {
76+
handle: handle,
77+
utf8: MemReader::new(Vec::new()),
78+
closeme: closeme,
79+
})
80+
} else {
81+
Err(IoError {
82+
kind: io::MismatchedFileTypeForOperation,
83+
desc: "invalid handle provided to function",
84+
detail: None,
85+
})
7886
}
7987
}
80-
}
8188

82-
impl Drop for WindowsTTY {
83-
fn drop(&mut self) {
84-
if self.closeme {
85-
// Nobody cares about the return value
86-
let _ = unsafe { CloseHandle(self.handle) };
87-
}
88-
}
89-
}
90-
91-
impl RtioTTY for WindowsTTY {
92-
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
89+
pub fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
9390
// Read more if the buffer is empty
9491
if self.utf8.eof() {
9592
let mut utf16 = Vec::from_elem(0x1000, 0u16);
@@ -113,7 +110,7 @@ impl RtioTTY for WindowsTTY {
113110
Ok(self.utf8.read(buf).unwrap())
114111
}
115112

116-
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
113+
pub fn write(&mut self, buf: &[u8]) -> IoResult<()> {
117114
let utf16 = match from_utf8(buf) {
118115
Some(utf8) => {
119116
utf8.as_slice().utf16_units().collect::<Vec<u16>>()
@@ -131,7 +128,7 @@ impl RtioTTY for WindowsTTY {
131128
}
132129
}
133130

134-
fn set_raw(&mut self, raw: bool) -> IoResult<()> {
131+
pub fn set_raw(&mut self, raw: bool) -> IoResult<()> {
135132
// FIXME
136133
// Somebody needs to decide on which of these flags we want
137134
match unsafe { SetConsoleMode(self.handle,
@@ -146,7 +143,7 @@ impl RtioTTY for WindowsTTY {
146143
}
147144
}
148145

149-
fn get_winsize(&mut self) -> IoResult<(int, int)> {
146+
pub fn get_winsize(&mut self) -> IoResult<(int, int)> {
150147
// FIXME
151148
// Get console buffer via CreateFile with CONOUT$
152149
// Make a CONSOLE_SCREEN_BUFFER_INFO
@@ -156,5 +153,14 @@ impl RtioTTY for WindowsTTY {
156153
}
157154

158155
// Let us magically declare this as a TTY
159-
fn isatty(&self) -> bool { true }
156+
pub fn isatty(&self) -> bool { true }
157+
}
158+
159+
impl Drop for TTY {
160+
fn drop(&mut self) {
161+
if self.closeme {
162+
// Nobody cares about the return value
163+
let _ = unsafe { CloseHandle(self.handle) };
164+
}
165+
}
160166
}

0 commit comments

Comments
 (0)