std: Implement stdio for std::io
This is an implementation of RFC 899 and adds stdio functionality to the new
`std::io` module. Details of the API can be found on the RFC, but from a high
level:
* `io::{stdin, stdout, stderr}` constructors are now available. There are also
`*_raw` variants for unbuffered and unlocked access.
* All handles are globally shared (excluding raw variants).
* The stderr handle is no longer buffered.
* All handles can be explicitly locked (excluding the raw variants).
The `print!` and `println!` machinery has not yet been hooked up to these
streams just yet. The `std::fmt::output` module has also not yet been
implemented as part of this commit.
This commit is contained in:
parent
8a69110c3b
commit
94d71f8836
20 changed files with 732 additions and 108 deletions
|
|
@ -43,12 +43,16 @@
|
|||
#![feature(box_syntax)]
|
||||
|
||||
use std::ascii::OwnedAsciiExt;
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::io;
|
||||
use std::slice;
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
|
||||
static TABLE: [u8;4] = [ 'A' as u8, 'C' as u8, 'G' as u8, 'T' as u8 ];
|
||||
static TABLE_SIZE: uint = 2 << 16;
|
||||
static TABLE_SIZE: usize = 2 << 16;
|
||||
|
||||
static OCCURRENCES: [&'static str;5] = [
|
||||
"GGT",
|
||||
|
|
@ -73,7 +77,7 @@ impl Code {
|
|||
Code((self.hash() << 2) + (pack_symbol(c) as u64))
|
||||
}
|
||||
|
||||
fn rotate(&self, c: u8, frame: uint) -> Code {
|
||||
fn rotate(&self, c: u8, frame: usize) -> Code {
|
||||
Code(self.push_char(c).hash() & ((1u64 << (2 * frame)) - 1))
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +85,7 @@ impl Code {
|
|||
string.bytes().fold(Code(0u64), |a, b| a.push_char(b))
|
||||
}
|
||||
|
||||
fn unpack(&self, frame: uint) -> String {
|
||||
fn unpack(&self, frame: usize) -> String {
|
||||
let mut key = self.hash();
|
||||
let mut result = Vec::new();
|
||||
for _ in 0..frame {
|
||||
|
|
@ -113,13 +117,13 @@ struct PrintCallback(&'static str);
|
|||
impl TableCallback for PrintCallback {
|
||||
fn f(&self, entry: &mut Entry) {
|
||||
let PrintCallback(s) = *self;
|
||||
println!("{}\t{}", entry.count as int, s);
|
||||
println!("{}\t{}", entry.count, s);
|
||||
}
|
||||
}
|
||||
|
||||
struct Entry {
|
||||
code: Code,
|
||||
count: uint,
|
||||
count: usize,
|
||||
next: Option<Box<Entry>>,
|
||||
}
|
||||
|
||||
|
|
@ -165,20 +169,20 @@ impl Table {
|
|||
let index = key.hash() % (TABLE_SIZE as u64);
|
||||
|
||||
{
|
||||
if self.items[index as uint].is_none() {
|
||||
if self.items[index as usize].is_none() {
|
||||
let mut entry = box Entry {
|
||||
code: key,
|
||||
count: 0,
|
||||
next: None,
|
||||
};
|
||||
c.f(&mut *entry);
|
||||
self.items[index as uint] = Some(entry);
|
||||
self.items[index as usize] = Some(entry);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let entry = self.items[index as uint].as_mut().unwrap();
|
||||
let entry = self.items[index as usize].as_mut().unwrap();
|
||||
if entry.code == key {
|
||||
c.f(&mut **entry);
|
||||
return;
|
||||
|
|
@ -233,10 +237,10 @@ fn pack_symbol(c: u8) -> u8 {
|
|||
}
|
||||
|
||||
fn unpack_symbol(c: u8) -> u8 {
|
||||
TABLE[c as uint]
|
||||
TABLE[c as usize]
|
||||
}
|
||||
|
||||
fn generate_frequencies(mut input: &[u8], frame: uint) -> Table {
|
||||
fn generate_frequencies(mut input: &[u8], frame: usize) -> Table {
|
||||
let mut frequencies = Table::new();
|
||||
if input.len() < frame { return frequencies; }
|
||||
let mut code = Code(0);
|
||||
|
|
@ -256,7 +260,7 @@ fn generate_frequencies(mut input: &[u8], frame: uint) -> Table {
|
|||
frequencies
|
||||
}
|
||||
|
||||
fn print_frequencies(frequencies: &Table, frame: uint) {
|
||||
fn print_frequencies(frequencies: &Table, frame: usize) {
|
||||
let mut vector = Vec::new();
|
||||
for entry in frequencies.iter() {
|
||||
vector.push((entry.count, entry.code));
|
||||
|
|
@ -280,9 +284,9 @@ fn print_occurrences(frequencies: &mut Table, occurrence: &'static str) {
|
|||
frequencies.lookup(Code::pack(occurrence), PrintCallback(occurrence))
|
||||
}
|
||||
|
||||
fn get_sequence<R: Buffer>(r: &mut R, key: &str) -> Vec<u8> {
|
||||
fn get_sequence<R: BufRead>(r: &mut R, key: &str) -> Vec<u8> {
|
||||
let mut res = Vec::new();
|
||||
for l in r.lines().map(|l| l.ok().unwrap())
|
||||
for l in r.lines().map(|l| l.unwrap())
|
||||
.skip_while(|l| key != &l[..key.len()]).skip(1)
|
||||
{
|
||||
res.push_all(l.trim().as_bytes());
|
||||
|
|
@ -291,13 +295,13 @@ fn get_sequence<R: Buffer>(r: &mut R, key: &str) -> Vec<u8> {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let input = if std::env::var_os("RUST_BENCH").is_some() {
|
||||
let fd = std::old_io::File::open(&Path::new("shootout-k-nucleotide.data"));
|
||||
get_sequence(&mut std::old_io::BufferedReader::new(fd), ">THREE")
|
||||
let input = if env::var_os("RUST_BENCH").is_some() {
|
||||
let f = File::open("shootout-k-nucleotide.data").unwrap();
|
||||
get_sequence(&mut io::BufReader::new(f), ">THREE")
|
||||
} else {
|
||||
let mut stdin = std::old_io::stdin();
|
||||
let stdin = io::stdin();
|
||||
let mut stdin = stdin.lock();
|
||||
get_sequence(&mut *stdin, ">THREE")
|
||||
get_sequence(&mut stdin, ">THREE")
|
||||
};
|
||||
let input = Arc::new(input);
|
||||
|
||||
|
|
|
|||
|
|
@ -13,9 +13,8 @@
|
|||
#![feature(box_syntax)]
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use std::old_io::BufferedReader;
|
||||
use std::old_io::stdio::StdReader;
|
||||
use std::old_io;
|
||||
use std::io::prelude::*;
|
||||
use std::io;
|
||||
use std::iter::repeat;
|
||||
use std::num::Int;
|
||||
use std::env;
|
||||
|
|
@ -37,7 +36,7 @@ use std::env;
|
|||
//
|
||||
|
||||
// internal type of sudoku grids
|
||||
type grid = Vec<Vec<u8> > ;
|
||||
type grid = Vec<Vec<u8>>;
|
||||
|
||||
struct Sudoku {
|
||||
grid: grid
|
||||
|
|
@ -55,9 +54,11 @@ impl Sudoku {
|
|||
return Sudoku::new(g)
|
||||
}
|
||||
|
||||
pub fn read(mut reader: &mut BufferedReader<StdReader>) -> Sudoku {
|
||||
pub fn read(reader: &mut BufRead) -> Sudoku {
|
||||
/* assert first line is exactly "9,9" */
|
||||
assert!(reader.read_line().unwrap() == "9,9".to_string());
|
||||
let mut s = String::new();
|
||||
reader.read_line(&mut s).unwrap();
|
||||
assert_eq!(s, "9,9\n");
|
||||
|
||||
let mut g = repeat(vec![0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8])
|
||||
.take(10).collect::<Vec<_>>();
|
||||
|
|
@ -71,7 +72,7 @@ impl Sudoku {
|
|||
if comps.len() == 3 {
|
||||
let row = comps[0].parse::<u8>().unwrap();
|
||||
let col = comps[1].parse::<u8>().unwrap();
|
||||
g[row as uint][col as uint] = comps[2].parse().unwrap();
|
||||
g[row as usize][col as usize] = comps[2].parse().unwrap();
|
||||
}
|
||||
else {
|
||||
panic!("Invalid sudoku file");
|
||||
|
|
@ -80,11 +81,11 @@ impl Sudoku {
|
|||
return Sudoku::new(g)
|
||||
}
|
||||
|
||||
pub fn write(&self, writer: &mut old_io::Writer) {
|
||||
pub fn write(&self, writer: &mut Write) {
|
||||
for row in 0u8..9u8 {
|
||||
write!(writer, "{}", self.grid[row as uint][0]);
|
||||
write!(writer, "{}", self.grid[row as usize][0]);
|
||||
for col in 1u8..9u8 {
|
||||
write!(writer, " {}", self.grid[row as uint][col as uint]);
|
||||
write!(writer, " {}", self.grid[row as usize][col as usize]);
|
||||
}
|
||||
write!(writer, "\n");
|
||||
}
|
||||
|
|
@ -95,7 +96,7 @@ impl Sudoku {
|
|||
let mut work: Vec<(u8, u8)> = Vec::new(); /* queue of uncolored fields */
|
||||
for row in 0u8..9u8 {
|
||||
for col in 0u8..9u8 {
|
||||
let color = self.grid[row as uint][col as uint];
|
||||
let color = self.grid[row as usize][col as usize];
|
||||
if color == 0u8 {
|
||||
work.push((row, col));
|
||||
}
|
||||
|
|
@ -107,7 +108,7 @@ impl Sudoku {
|
|||
while ptr < end {
|
||||
let (row, col) = work[ptr];
|
||||
// is there another color to try?
|
||||
let the_color = self.grid[row as uint][col as uint] +
|
||||
let the_color = self.grid[row as usize][col as usize] +
|
||||
(1 as u8);
|
||||
if self.next_color(row, col, the_color) {
|
||||
// yes: advance work list
|
||||
|
|
@ -130,10 +131,10 @@ impl Sudoku {
|
|||
|
||||
// find first remaining color that is available
|
||||
let next = avail.next();
|
||||
self.grid[row as uint][col as uint] = next;
|
||||
self.grid[row as usize][col as usize] = next;
|
||||
return 0u8 != next;
|
||||
}
|
||||
self.grid[row as uint][col as uint] = 0u8;
|
||||
self.grid[row as usize][col as usize] = 0u8;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -141,9 +142,9 @@ impl Sudoku {
|
|||
fn drop_colors(&mut self, avail: &mut Colors, row: u8, col: u8) {
|
||||
for idx in 0u8..9u8 {
|
||||
/* check same column fields */
|
||||
avail.remove(self.grid[idx as uint][col as uint]);
|
||||
avail.remove(self.grid[idx as usize][col as usize]);
|
||||
/* check same row fields */
|
||||
avail.remove(self.grid[row as uint][idx as uint]);
|
||||
avail.remove(self.grid[row as usize][idx as usize]);
|
||||
}
|
||||
|
||||
// check same block fields
|
||||
|
|
@ -151,7 +152,7 @@ impl Sudoku {
|
|||
let col0 = (col / 3u8) * 3u8;
|
||||
for alt_row in row0..row0 + 3u8 {
|
||||
for alt_col in col0..col0 + 3u8 {
|
||||
avail.remove(self.grid[alt_row as uint][alt_col as uint]);
|
||||
avail.remove(self.grid[alt_row as usize][alt_col as usize]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -165,7 +166,7 @@ static HEADS: u16 = (1u16 << 10) - 1; /* bits 9..0 */
|
|||
impl Colors {
|
||||
fn new(start_color: u8) -> Colors {
|
||||
// Sets bits 9..start_color
|
||||
let tails = !0u16 << start_color as uint;
|
||||
let tails = !0u16 << start_color as usize;
|
||||
return Colors(HEADS & tails);
|
||||
}
|
||||
|
||||
|
|
@ -182,7 +183,7 @@ impl Colors {
|
|||
fn remove(&mut self, color: u8) {
|
||||
if color != 0u8 {
|
||||
let Colors(val) = *self;
|
||||
let mask = !(1u16 << color as uint);
|
||||
let mask = !(1u16 << color as usize);
|
||||
*self = Colors(val & mask);
|
||||
}
|
||||
}
|
||||
|
|
@ -269,15 +270,16 @@ fn check_DEFAULT_SUDOKU_solution() {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let args = env::args();
|
||||
let args = env::args();
|
||||
let use_default = args.len() == 1;
|
||||
let mut sudoku = if use_default {
|
||||
Sudoku::from_vec(&DEFAULT_SUDOKU)
|
||||
} else {
|
||||
let mut stdin = old_io::stdin();
|
||||
let mut stdin = stdin.lock();
|
||||
Sudoku::read(&mut *stdin)
|
||||
let stdin = io::stdin();
|
||||
let mut locked = stdin.lock();
|
||||
Sudoku::read(&mut locked)
|
||||
};
|
||||
sudoku.solve();
|
||||
sudoku.write(&mut old_io::stdout());
|
||||
let out = io::stdout();
|
||||
sudoku.write(&mut out.lock());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,4 +10,5 @@
|
|||
|
||||
fn main() {
|
||||
let _ = std::old_io::stdin();
|
||||
let _ = std::io::stdin();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-fast
|
||||
|
||||
use std::env;
|
||||
use std::old_io;
|
||||
use std::io::prelude::*;
|
||||
use std::io;
|
||||
use std::process::{Command, Stdio};
|
||||
use std::str;
|
||||
|
||||
fn main() {
|
||||
|
|
@ -25,17 +25,19 @@ fn main() {
|
|||
|
||||
fn parent() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let mut p = old_io::process::Command::new(&args[0])
|
||||
.arg("child").spawn().unwrap();
|
||||
p.stdin.as_mut().unwrap().write_str("test1\ntest2\ntest3").unwrap();
|
||||
let mut p = Command::new(&args[0]).arg("child")
|
||||
.stdout(Stdio::capture())
|
||||
.stdin(Stdio::capture())
|
||||
.spawn().unwrap();
|
||||
p.stdin.as_mut().unwrap().write_all(b"test1\ntest2\ntest3").unwrap();
|
||||
let out = p.wait_with_output().unwrap();
|
||||
assert!(out.status.success());
|
||||
let s = str::from_utf8(&out.output).unwrap();
|
||||
assert_eq!(s, "test1\n\ntest2\n\ntest3\n");
|
||||
let s = str::from_utf8(&out.stdout).unwrap();
|
||||
assert_eq!(s, "test1\ntest2\ntest3\n");
|
||||
}
|
||||
|
||||
fn child() {
|
||||
let mut stdin = old_io::stdin();
|
||||
let mut stdin = io::stdin();
|
||||
for line in stdin.lock().lines() {
|
||||
println!("{}", line.unwrap());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,11 +8,10 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
use std::old_io::process;
|
||||
use std::old_io::Command;
|
||||
use std::old_io;
|
||||
use std::env;
|
||||
use std::io::prelude::*;
|
||||
use std::io;
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
|
@ -21,22 +20,23 @@ fn main() {
|
|||
}
|
||||
|
||||
test();
|
||||
|
||||
}
|
||||
|
||||
fn child() {
|
||||
old_io::stdout().write_line("foo").unwrap();
|
||||
old_io::stderr().write_line("bar").unwrap();
|
||||
let mut stdin = old_io::stdin();
|
||||
assert_eq!(stdin.lock().read_line().err().unwrap().kind, old_io::EndOfFile);
|
||||
writeln!(&mut io::stdout(), "foo").unwrap();
|
||||
writeln!(&mut io::stderr(), "bar").unwrap();
|
||||
let mut stdin = io::stdin();
|
||||
let mut s = String::new();
|
||||
stdin.lock().read_line(&mut s).unwrap();
|
||||
assert_eq!(s.len(), 0);
|
||||
}
|
||||
|
||||
fn test() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let mut p = Command::new(&args[0]).arg("child")
|
||||
.stdin(process::Ignored)
|
||||
.stdout(process::Ignored)
|
||||
.stderr(process::Ignored)
|
||||
.stdin(Stdio::capture())
|
||||
.stdout(Stdio::capture())
|
||||
.stderr(Stdio::capture())
|
||||
.spawn().unwrap();
|
||||
assert!(p.wait().unwrap().success());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,11 +17,13 @@
|
|||
// A var moved into a proc, that has a mutable loan path should
|
||||
// not trigger a misleading unused_mut warning.
|
||||
|
||||
use std::io::prelude::*;
|
||||
use std::thread;
|
||||
|
||||
pub fn main() {
|
||||
let mut stdin = std::old_io::stdin();
|
||||
let mut stdin = std::io::stdin();
|
||||
thread::spawn(move|| {
|
||||
let _ = stdin.read_to_end();
|
||||
});
|
||||
let mut v = Vec::new();
|
||||
let _ = stdin.read_to_end(&mut v);
|
||||
}).join().ok().unwrap();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,13 +11,13 @@
|
|||
#![allow(unknown_features)]
|
||||
#![feature(box_syntax)]
|
||||
|
||||
use std::old_io;
|
||||
use std::io::{self, Write};
|
||||
|
||||
fn f(wr: &mut Writer) {
|
||||
wr.write_str("hello").ok().expect("failed");
|
||||
fn f(wr: &mut Write) {
|
||||
wr.write_all(b"hello").ok().expect("failed");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut wr = box old_io::stdout() as Box<Writer + 'static>;
|
||||
let mut wr = box io::stdout() as Box<Write>;
|
||||
f(&mut wr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::old_io;
|
||||
use std::io;
|
||||
|
||||
pub fn main() {
|
||||
let stdout = &mut old_io::stdout() as &mut old_io::Writer;
|
||||
let stdout = &mut io::stdout() as &mut io::Write;
|
||||
stdout.write(b"Hello!");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,30 +16,31 @@
|
|||
// non-ASCII characters. The child process ensures all the strings are
|
||||
// intact.
|
||||
|
||||
use std::old_io;
|
||||
use std::old_io::fs;
|
||||
use std::old_io::Command;
|
||||
use std::io::prelude::*;
|
||||
use std::io;
|
||||
use std::fs;
|
||||
use std::process::Command;
|
||||
use std::os;
|
||||
use std::env;
|
||||
use std::old_path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
fn main() {
|
||||
let my_args = env::args().collect::<Vec<_>>();
|
||||
let my_cwd = os::getcwd().unwrap();
|
||||
let my_cwd = PathBuf::new(os::getcwd().unwrap().as_str().unwrap());
|
||||
let my_env = env::vars().collect::<Vec<_>>();
|
||||
let my_path = Path::new(os::self_exe_name().unwrap());
|
||||
let my_dir = my_path.dir_path();
|
||||
let my_ext = my_path.extension_str().unwrap_or("");
|
||||
let my_path = PathBuf::new(os::self_exe_name().unwrap().as_str().unwrap());
|
||||
let my_dir = my_path.parent().unwrap();
|
||||
let my_ext = my_path.extension().and_then(|s| s.to_str()).unwrap_or("");
|
||||
|
||||
// some non-ASCII characters
|
||||
let blah = "\u03c0\u042f\u97f3\u00e6\u221e";
|
||||
let blah = "\u{3c0}\u{42f}\u{97f3}\u{e6}\u{221e}";
|
||||
|
||||
let child_name = "child";
|
||||
let child_dir = format!("process-spawn-with-unicode-params-{}", blah);
|
||||
|
||||
// parameters sent to child / expected to be received from parent
|
||||
let arg = blah;
|
||||
let cwd = my_dir.join(Path::new(child_dir.clone()));
|
||||
let cwd = my_dir.join(&child_dir);
|
||||
let env = ("RUST_TEST_PROC_SPAWN_UNICODE".to_string(), blah.to_string());
|
||||
|
||||
// am I the parent or the child?
|
||||
|
|
@ -47,24 +48,22 @@ fn main() {
|
|||
|
||||
let child_filestem = Path::new(child_name);
|
||||
let child_filename = child_filestem.with_extension(my_ext);
|
||||
let child_path = cwd.join(child_filename);
|
||||
let child_path = cwd.join(&child_filename);
|
||||
|
||||
// make a separate directory for the child
|
||||
drop(fs::mkdir(&cwd, old_io::USER_RWX).is_ok());
|
||||
assert!(fs::copy(&my_path, &child_path).is_ok());
|
||||
let mut my_env = my_env;
|
||||
my_env.push(env);
|
||||
let _ = fs::create_dir(&cwd);
|
||||
fs::copy(&my_path, &child_path).unwrap();
|
||||
|
||||
// run child
|
||||
let p = Command::new(&child_path)
|
||||
.arg(arg)
|
||||
.cwd(&cwd)
|
||||
.env_set_all(&my_env)
|
||||
.current_dir(&cwd)
|
||||
.env(&env.0, &env.1)
|
||||
.spawn().unwrap().wait_with_output().unwrap();
|
||||
|
||||
// display the output
|
||||
assert!(old_io::stdout().write(&p.output).is_ok());
|
||||
assert!(old_io::stderr().write(&p.error).is_ok());
|
||||
io::stdout().write_all(&p.stdout).unwrap();
|
||||
io::stderr().write_all(&p.stderr).unwrap();
|
||||
|
||||
// make sure the child succeeded
|
||||
assert!(p.status.success());
|
||||
|
|
@ -72,7 +71,7 @@ fn main() {
|
|||
} else { // child
|
||||
|
||||
// check working directory (don't try to compare with `cwd` here!)
|
||||
assert!(my_cwd.ends_with_path(&Path::new(child_dir)));
|
||||
assert!(my_cwd.ends_with(&child_dir));
|
||||
|
||||
// check arguments
|
||||
assert_eq!(&*my_args[1], arg);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue