diff options
69 files changed, 820 insertions, 898 deletions
diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index a2bb3defe31..50e74a13ee2 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -20,7 +20,6 @@ #![feature(std_misc)] #![feature(test)] #![feature(core)] -#![feature(io)] #![feature(net)] #![feature(path_ext)] @@ -34,7 +33,6 @@ extern crate log; use std::env; use std::fs; -use std::old_io; use std::path::{Path, PathBuf}; use std::thunk::Thunk; use getopts::{optopt, optflag, reqopt}; @@ -246,7 +244,11 @@ pub fn run_tests(config: &Config) { // sadly osx needs some file descriptor limits raised for running tests in // parallel (especially when we have lots and lots of child processes). // For context, see #8904 - old_io::test::raise_fd_limit(); + #[allow(deprecated)] + fn raise_fd_limit() { + std::old_io::test::raise_fd_limit(); + } + raise_fd_limit(); // Prevent issue #21352 UAC blocking .exe containing 'patch' etc. on Windows // If #11207 is resolved (adding manifest to .exe) this becomes unnecessary env::set_var("__COMPAT_LAYER", "RunAsInvoker"); diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 04714b50fc0..475c0410135 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -26,7 +26,6 @@ use std::io::BufReader; use std::io::prelude::*; use std::iter::repeat; use std::net::TcpStream; -use std::old_io::timer; use std::path::{Path, PathBuf}; use std::process::{Command, Output, ExitStatus}; use std::str; @@ -452,7 +451,11 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { .expect(&format!("failed to exec `{:?}`", config.adb_path)); loop { //waiting 1 second for gdbserver start - timer::sleep(Duration::milliseconds(1000)); + #[allow(deprecated)] + fn sleep() { + ::std::old_io::timer::sleep(Duration::milliseconds(1000)); + } + sleep(); if TcpStream::connect("127.0.0.1:5039").is_ok() { break } diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index 5f6bfd196f0..0e080459344 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -48,13 +48,14 @@ //! //! ```rust //! use std::borrow::IntoCow; +//! use std::io::Write; //! use graphviz as dot; //! //! type Nd = int; //! type Ed = (int,int); //! struct Edges(Vec<Ed>); //! -//! pub fn render_to<W:Writer>(output: &mut W) { +//! pub fn render_to<W: Write>(output: &mut W) { //! let edges = Edges(vec!((0,1), (0,2), (1,3), (2,3), (3,4), (4,4))); //! dot::render(&edges, output).unwrap() //! } @@ -94,10 +95,10 @@ //! ``` //! //! ```no_run -//! # pub fn render_to<W:Writer>(output: &mut W) { unimplemented!() } +//! # pub fn render_to<W:std::io::Write>(output: &mut W) { unimplemented!() } //! pub fn main() { -//! use std::old_io::File; -//! let mut f = File::create(&Path::new("example1.dot")); +//! use std::fs::File; +//! let mut f = File::create("example1.dot").unwrap(); //! render_to(&mut f) //! } //! ``` @@ -148,13 +149,14 @@ //! //! ```rust //! use std::borrow::IntoCow; +//! use std::io::Write; //! use graphviz as dot; //! //! type Nd = uint; //! type Ed<'a> = &'a (uint, uint); //! struct Graph { nodes: Vec<&'static str>, edges: Vec<(uint,uint)> } //! -//! pub fn render_to<W:Writer>(output: &mut W) { +//! pub fn render_to<W: Write>(output: &mut W) { //! let nodes = vec!("{x,y}","{x}","{y}","{}"); //! let edges = vec!((0,1), (0,2), (1,3), (2,3)); //! let graph = Graph { nodes: nodes, edges: edges }; @@ -186,10 +188,10 @@ //! ``` //! //! ```no_run -//! # pub fn render_to<W:Writer>(output: &mut W) { unimplemented!() } +//! # pub fn render_to<W:std::io::Write>(output: &mut W) { unimplemented!() } //! pub fn main() { -//! use std::old_io::File; -//! let mut f = File::create(&Path::new("example2.dot")); +//! use std::fs::File; +//! let mut f = File::create("example2.dot").unwrap(); //! render_to(&mut f) //! } //! ``` @@ -204,13 +206,14 @@ //! //! ```rust //! use std::borrow::IntoCow; +//! use std::io::Write; //! use graphviz as dot; //! //! type Nd<'a> = (uint, &'a str); //! type Ed<'a> = (Nd<'a>, Nd<'a>); //! struct Graph { nodes: Vec<&'static str>, edges: Vec<(uint,uint)> } //! -//! pub fn render_to<W:Writer>(output: &mut W) { +//! pub fn render_to<W: Write>(output: &mut W) { //! let nodes = vec!("{x,y}","{x}","{y}","{}"); //! let edges = vec!((0,1), (0,2), (1,3), (2,3)); //! let graph = Graph { nodes: nodes, edges: edges }; @@ -250,10 +253,10 @@ //! ``` //! //! ```no_run -//! # pub fn render_to<W:Writer>(output: &mut W) { unimplemented!() } +//! # pub fn render_to<W:std::io::Write>(output: &mut W) { unimplemented!() } //! pub fn main() { -//! use std::old_io::File; -//! let mut f = File::create(&Path::new("example3.dot")); +//! use std::fs::File; +//! let mut f = File::create("example3.dot").unwrap(); //! render_to(&mut f) //! } //! ``` @@ -277,12 +280,12 @@ html_root_url = "http://doc.rust-lang.org/nightly/")] #![feature(int_uint)] #![feature(collections)] -#![feature(old_io)] use self::LabelText::*; use std::borrow::{IntoCow, Cow}; -use std::old_io; +use std::io::prelude::*; +use std::io; /// The text for a graphviz label on a node or edge. pub enum LabelText<'a> { @@ -529,26 +532,26 @@ pub fn default_options() -> Vec<RenderOption> { vec![] } /// Renders directed graph `g` into the writer `w` in DOT syntax. /// (Simple wrapper around `render_opts` that passes a default set of options.) -pub fn render<'a, N:Clone+'a, E:Clone+'a, G:Labeller<'a,N,E>+GraphWalk<'a,N,E>, W:Writer>( +pub fn render<'a, N:Clone+'a, E:Clone+'a, G:Labeller<'a,N,E>+GraphWalk<'a,N,E>, W:Write>( g: &'a G, - w: &mut W) -> old_io::IoResult<()> { + w: &mut W) -> io::Result<()> { render_opts(g, w, &[]) } /// Renders directed graph `g` into the writer `w` in DOT syntax. /// (Main entry point for the library.) -pub fn render_opts<'a, N:Clone+'a, E:Clone+'a, G:Labeller<'a,N,E>+GraphWalk<'a,N,E>, W:Writer>( +pub fn render_opts<'a, N:Clone+'a, E:Clone+'a, G:Labeller<'a,N,E>+GraphWalk<'a,N,E>, W:Write>( g: &'a G, w: &mut W, - options: &[RenderOption]) -> old_io::IoResult<()> + options: &[RenderOption]) -> io::Result<()> { - fn writeln<W:Writer>(w: &mut W, arg: &[&str]) -> old_io::IoResult<()> { - for &s in arg { try!(w.write_str(s)); } - w.write_char('\n') + fn writeln<W:Write>(w: &mut W, arg: &[&str]) -> io::Result<()> { + for &s in arg { try!(w.write_all(s.as_bytes())); } + write!(w, "\n") } - fn indent<W:Writer>(w: &mut W) -> old_io::IoResult<()> { - w.write_str(" ") + fn indent<W:Write>(w: &mut W) -> io::Result<()> { + w.write_all(b" ") } try!(writeln(w, &["digraph ", g.graph_id().as_slice(), " {"])); @@ -589,7 +592,8 @@ mod tests { use self::NodeLabels::*; use super::{Id, Labeller, Nodes, Edges, GraphWalk, render}; use super::LabelText::{self, LabelStr, EscStr}; - use std::old_io::IoResult; + use std::io; + use std::io::prelude::*; use std::borrow::IntoCow; use std::iter::repeat; @@ -738,10 +742,12 @@ mod tests { } } - fn test_input(g: LabelledGraph) -> IoResult<String> { + fn test_input(g: LabelledGraph) -> io::Result<String> { let mut writer = Vec::new(); render(&g, &mut writer).unwrap(); - (&mut &*writer).read_to_string() + let mut s = String::new(); + try!(Read::read_to_string(&mut &*writer, &mut s)); + Ok(s) } // All of the tests use raw-strings as the format for the expected outputs, @@ -853,9 +859,10 @@ r#"digraph hasse_diagram { edge(1, 3, ";"), edge(2, 3, ";" ))); render(&g, &mut writer).unwrap(); - let r = (&mut &*writer).read_to_string(); + let mut r = String::new(); + Read::read_to_string(&mut &*writer, &mut r).unwrap(); - assert_eq!(r.unwrap(), + assert_eq!(r, r#"digraph syntax_tree { N0[label="if test {\l branch1\l} else {\l branch2\l}\lafterward\l"]; N1[label="branch1"]; diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index 3b6e1d04691..b03d77db4ec 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -174,14 +174,14 @@ #![feature(box_syntax)] #![feature(int_uint)] #![feature(core)] -#![feature(old_io)] #![feature(std_misc)] +#![feature(io)] use std::boxed; use std::cell::RefCell; use std::fmt; -use std::old_io::LineBufferedWriter; -use std::old_io; +use std::io::{self, Stderr}; +use std::io::prelude::*; use std::mem; use std::env; use std::ptr; @@ -237,9 +237,7 @@ pub trait Logger { fn log(&mut self, record: &LogRecord); } -struct DefaultLogger { - handle: LineBufferedWriter<old_io::stdio::StdWriter>, -} +struct DefaultLogger { handle: Stderr } /// Wraps the log level with fmt implementations. #[derive(Copy, PartialEq, PartialOrd, Debug)] @@ -300,7 +298,7 @@ pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) { let mut logger = LOCAL_LOGGER.with(|s| { s.borrow_mut().take() }).unwrap_or_else(|| { - box DefaultLogger { handle: old_io::stderr() } as Box<Logger + Send> + box DefaultLogger { handle: io::stderr() } as Box<Logger + Send> }); logger.log(&LogRecord { level: LogLevel(level), diff --git a/src/librbml/io.rs b/src/librbml/io.rs deleted file mode 100644 index bf4b5ee2c0e..00000000000 --- a/src/librbml/io.rs +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::old_io::{IoError, IoResult, SeekStyle}; -use std::old_io; -use std::slice; -use std::iter::repeat; - -const BUF_CAPACITY: uint = 128; - -fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64> { - // compute offset as signed and clamp to prevent overflow - let pos = match seek { - old_io::SeekSet => 0, - old_io::SeekEnd => end, - old_io::SeekCur => cur, - } as i64; - - if offset + pos < 0 { - Err(IoError { - kind: old_io::InvalidInput, - desc: "invalid seek to a negative offset", - detail: None - }) - } else { - Ok((offset + pos) as u64) - } -} - -/// Writes to an owned, growable byte vector that supports seeking. -/// -/// # Examples -/// -/// ```rust -/// # #![allow(unused_must_use)] -/// use rbml::io::SeekableMemWriter; -/// -/// let mut w = SeekableMemWriter::new(); -/// w.write(&[0, 1, 2]); -/// -/// assert_eq!(w.unwrap(), [0, 1, 2]); -/// ``` -pub struct SeekableMemWriter { - buf: Vec<u8>, - pos: uint, -} - -impl SeekableMemWriter { - /// Create a new `SeekableMemWriter`. - #[inline] - pub fn new() -> SeekableMemWriter { - SeekableMemWriter::with_capacity(BUF_CAPACITY) - } - /// Create a new `SeekableMemWriter`, allocating at least `n` bytes for - /// the internal buffer. - #[inline] - pub fn with_capacity(n: uint) -> SeekableMemWriter { - SeekableMemWriter { buf: Vec::with_capacity(n), pos: 0 } - } - - /// Acquires an immutable reference to the underlying buffer of this - /// `SeekableMemWriter`. - /// - /// No method is exposed for acquiring a mutable reference to the buffer - /// because it could corrupt the state of this `MemWriter`. - #[inline] - pub fn get_ref<'a>(&'a self) -> &'a [u8] { &self.buf } - - /// Unwraps this `SeekableMemWriter`, returning the underlying buffer - #[inline] - pub fn unwrap(self) -> Vec<u8> { self.buf } -} - -impl Writer for SeekableMemWriter { - #[inline] - fn write_all(&mut self, buf: &[u8]) -> IoResult<()> { - if self.pos == self.buf.len() { - self.buf.push_all(buf) - } else { - // Make sure the internal buffer is as least as big as where we - // currently are - let difference = self.pos as i64 - self.buf.len() as i64; - if difference > 0 { - self.buf.extend(repeat(0).take(difference as uint)); - } - - // Figure out what bytes will be used to overwrite what's currently - // there (left), and what will be appended on the end (right) - let cap = self.buf.len() - self.pos; - let (left, right) = if cap <= buf.len() { - (&buf[..cap], &buf[cap..]) - } else { - let result: (_, &[_]) = (buf, &[]); - result - }; - - // Do the necessary writes - if left.len() > 0 { - slice::bytes::copy_memory(&mut self.buf[self.pos..], left); - } - if right.len() > 0 { - self.buf.push_all(right); - } - } - - // Bump us forward - self.pos += buf.len(); - Ok(()) - } -} - -impl Seek for SeekableMemWriter { - #[inline] - fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) } - - #[inline] - fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> { - let new = try!(combine(style, self.pos, self.buf.len(), pos)); - self.pos = new as uint; - Ok(()) - } -} - -#[cfg(test)] -mod tests { - extern crate test; - use super::SeekableMemWriter; - use std::old_io; - use std::iter::repeat; - use test::Bencher; - - #[test] - fn test_seekable_mem_writer() { - let mut writer = SeekableMemWriter::new(); - assert_eq!(writer.tell(), Ok(0)); - writer.write_all(&[0]).unwrap(); - assert_eq!(writer.tell(), Ok(1)); - writer.write_all(&[1, 2, 3]).unwrap(); - writer.write_all(&[4, 5, 6, 7]).unwrap(); - assert_eq!(writer.tell(), Ok(8)); - let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; - assert_eq!(writer.get_ref(), b); - - writer.seek(0, old_io::SeekSet).unwrap(); - assert_eq!(writer.tell(), Ok(0)); - writer.write_all(&[3, 4]).unwrap(); - let b: &[_] = &[3, 4, 2, 3, 4, 5, 6, 7]; - assert_eq!(writer.get_ref(), b); - - writer.seek(1, old_io::SeekCur).unwrap(); - writer.write_all(&[0, 1]).unwrap(); - let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 7]; - assert_eq!(writer.get_ref(), b); - - writer.seek(-1, old_io::SeekEnd).unwrap(); - writer.write_all(&[1, 2]).unwrap(); - let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2]; - assert_eq!(writer.get_ref(), b); - - writer.seek(1, old_io::SeekEnd).unwrap(); - writer.write_all(&[1]).unwrap(); - let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]; - assert_eq!(writer.get_ref(), b); - } - - #[test] - fn seek_past_end() { - let mut r = SeekableMemWriter::new(); - r.seek(10, old_io::SeekSet).unwrap(); - assert!(r.write_all(&[3]).is_ok()); - } - - #[test] - fn seek_before_0() { - let mut r = SeekableMemWriter::new(); - assert!(r.seek(-1, old_io::SeekSet).is_err()); - } - - fn do_bench_seekable_mem_writer(b: &mut Bencher, times: uint, len: uint) { - let src: Vec<u8> = repeat(5).take(len).collect(); - - b.bytes = (times * len) as u64; - b.iter(|| { - let mut wr = SeekableMemWriter::new(); - for _ in 0..times { - wr.write_all(&src).unwrap(); - } - - let v = wr.unwrap(); - assert_eq!(v.len(), times * len); - assert!(v.iter().all(|x| *x == 5)); - }); - } - - #[bench] - fn bench_seekable_mem_writer_001_0000(b: &mut Bencher) { - do_bench_seekable_mem_writer(b, 1, 0) - } - - #[bench] - fn bench_seekable_mem_writer_001_0010(b: &mut Bencher) { - do_bench_seekable_mem_writer(b, 1, 10) - } - - #[bench] - fn bench_seekable_mem_writer_001_0100(b: &mut Bencher) { - do_bench_seekable_mem_writer(b, 1, 100) - } - - #[bench] - fn bench_seekable_mem_writer_001_1000(b: &mut Bencher) { - do_bench_seekable_mem_writer(b, 1, 1000) - } - - #[bench] - fn bench_seekable_mem_writer_100_0000(b: &mut Bencher) { - do_bench_seekable_mem_writer(b, 100, 0) - } - - #[bench] - fn bench_seekable_mem_writer_100_0010(b: &mut Bencher) { - do_bench_seekable_mem_writer(b, 100, 10) - } - - #[bench] - fn bench_seekable_mem_writer_100_0100(b: &mut Bencher) { - do_bench_seekable_mem_writer(b, 100, 100) - } - - #[bench] - fn bench_seekable_mem_writer_100_1000(b: &mut Bencher) { - do_bench_seekable_mem_writer(b, 100, 1000) - } -} diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index d71bcdf2924..5d1fbc32f14 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -123,10 +123,9 @@ html_root_url = "http://doc.rust-lang.org/nightly/", html_playground_url = "http://play.rust-lang.org/")] -#![feature(collections)] +#![feature(io)] #![feature(core)] #![feature(int_uint)] -#![feature(old_io)] #![feature(rustc_private)] #![feature(staged_api)] @@ -143,8 +142,6 @@ pub use self::Error::*; use std::str; use std::fmt; -pub mod io; - /// Common data structures #[derive(Clone, Copy)] pub struct Doc<'a> { @@ -228,7 +225,7 @@ pub enum Error { IntTooBig(uint), InvalidTag(uint), Expected(String), - IoError(std::old_io::IoError), + IoError(std::io::Error), ApplicationError(String) } @@ -840,8 +837,8 @@ pub mod reader { pub mod writer { use std::mem; use std::num::Int; - use std::old_io::{Writer, Seek}; - use std::old_io; + use std::io::prelude::*; + use std::io::{self, SeekFrom, Cursor}; use std::slice::bytes; use std::num::ToPrimitive; @@ -849,35 +846,31 @@ pub mod writer { EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsOpaque, NUM_IMPLICIT_TAGS, NUM_TAGS }; - use super::io::SeekableMemWriter; use serialize; - pub type EncodeResult = old_io::IoResult<()>; + pub type EncodeResult = io::Result<()>; // rbml writing pub struct Encoder<'a> { - pub writer: &'a mut SeekableMemWriter, - size_positions: Vec<uint>, + pub writer: &'a mut Cursor<Vec<u8>>, + size_positions: Vec<u64>, relax_limit: u64, // do not move encoded bytes before this position } - fn write_tag<W: Writer>(w: &mut W, n: uint) -> EncodeResult { + fn write_tag<W: Write>(w: &mut W, n: uint) -> EncodeResult { if n < 0xf0 { w.write_all(&[n as u8]) } else if 0x100 <= n && n < NUM_TAGS { w.write_all(&[0xf0 | (n >> 8) as u8, n as u8]) } else { - Err(old_io::IoError { - kind: old_io::OtherIoError, - desc: "invalid tag", - detail: Some(format!("{}", n)) - }) + Err(io::Error::new(io::ErrorKind::Other, "invalid tag", + Some(n.to_string()))) } } - fn write_sized_vuint<W: Writer>(w: &mut W, n: uint, size: uint) -> EncodeResult { + fn write_sized_vuint<W: Write>(w: &mut W, n: uint, size: uint) -> EncodeResult { match size { 1 => w.write_all(&[0x80 | (n as u8)]), 2 => w.write_all(&[0x40 | ((n >> 8) as u8), n as u8]), @@ -885,28 +878,22 @@ pub mod writer { n as u8]), 4 => w.write_all(&[0x10 | ((n >> 24) as u8), (n >> 16) as u8, (n >> 8) as u8, n as u8]), - _ => Err(old_io::IoError { - kind: old_io::OtherIoError, - desc: "int too big", - detail: Some(format!("{}", n)) - }) + _ => Err(io::Error::new(io::ErrorKind::Other, + "int too big", Some(n.to_string()))) } } - fn write_vuint<W: Writer>(w: &mut W, n: uint) -> EncodeResult { + fn write_vuint<W: Write>(w: &mut W, n: uint) -> EncodeResult { if n < 0x7f { return write_sized_vuint(w, n, 1); } if n < 0x4000 { return write_sized_vuint(w, n, 2); } if n < 0x200000 { return write_sized_vuint(w, n, 3); } if n < 0x10000000 { return write_sized_vuint(w, n, 4); } - Err(old_io::IoError { - kind: old_io::OtherIoError, - desc: "int too big", - detail: Some(format!("{}", n)) - }) + Err(io::Error::new(io::ErrorKind::Other, "int too big", + Some(n.to_string()))) } impl<'a> Encoder<'a> { - pub fn new(w: &'a mut SeekableMemWriter) -> Encoder<'a> { + pub fn new(w: &'a mut Cursor<Vec<u8>>) -> Encoder<'a> { Encoder { writer: w, size_positions: vec!(), @@ -931,24 +918,26 @@ pub mod writer { try!(write_tag(self.writer, tag_id)); // Write a placeholder four-byte size. - self.size_positions.push(try!(self.writer.tell()) as uint); + let cur_pos = try!(self.writer.seek(SeekFrom::Current(0))); + self.size_positions.push(cur_pos); let zeroes: &[u8] = &[0, 0, 0, 0]; self.writer.write_all(zeroes) } pub fn end_tag(&mut self) -> EncodeResult { let last_size_pos = self.size_positions.pop().unwrap(); - let cur_pos = try!(self.writer.tell()); - try!(self.writer.seek(last_size_pos as i64, old_io::SeekSet)); - let size = cur_pos as uint - last_size_pos - 4; + let cur_pos = try!(self.writer.seek(SeekFrom::Current(0))); + try!(self.writer.seek(SeekFrom::Start(last_size_pos))); + let size = (cur_pos - last_size_pos - 4) as usize; // relax the size encoding for small tags (bigger tags are costly to move). // we should never try to move the stable positions, however. const RELAX_MAX_SIZE: uint = 0x100; - if size <= RELAX_MAX_SIZE && last_size_pos >= self.relax_limit as uint { + if size <= RELAX_MAX_SIZE && last_size_pos >= self.relax_limit { // we can't alter the buffer in place, so have a temporary buffer let mut buf = [0u8; RELAX_MAX_SIZE]; { + let last_size_pos = last_size_pos as usize; let data = &self.writer.get_ref()[last_size_pos+4..cur_pos as uint]; bytes::copy_memory(&mut buf, data); } @@ -959,7 +948,7 @@ pub mod writer { } else { // overwrite the size with an overlong encoding and skip past the data try!(write_sized_vuint(self.writer, size, 4)); - try!(self.writer.seek(cur_pos as i64, old_io::SeekSet)); + try!(self.writer.seek(SeekFrom::Start(cur_pos))); } debug!("End tag (size = {:?})", size); @@ -1074,7 +1063,7 @@ pub mod writer { /// Returns the current position while marking it stable, i.e. /// generated bytes so far woundn't be affected by relaxation. pub fn mark_stable_position(&mut self) -> u64 { - let pos = self.writer.tell().unwrap(); + let pos = self.writer.seek(SeekFrom::Current(0)).unwrap(); if self.relax_limit < pos { self.relax_limit = pos; } @@ -1090,11 +1079,9 @@ pub mod writer { } else if let Some(v) = v.to_u32() { self.wr_tagged_raw_u32(EsSub32 as uint, v) } else { - Err(old_io::IoError { - kind: old_io::OtherIoError, - desc: "length or variant id too big", - detail: Some(format!("{}", v)) - }) + Err(io::Error::new(io::ErrorKind::Other, + "length or variant id too big", + Some(v.to_string()))) } } @@ -1108,7 +1095,7 @@ pub mod writer { } impl<'a> serialize::Encoder for Encoder<'a> { - type Error = old_io::IoError; + type Error = io::Error; fn emit_nil(&mut self) -> EncodeResult { Ok(()) @@ -1339,12 +1326,10 @@ pub mod writer { #[cfg(test)] mod tests { use super::{Doc, reader, writer}; - use super::io::SeekableMemWriter; use serialize::{Encodable, Decodable}; - use std::option::Option; - use std::option::Option::{None, Some}; + use std::io::Cursor; #[test] fn test_vuint_at() { @@ -1398,7 +1383,7 @@ mod tests { fn test_option_int() { fn test_v(v: Option<int>) { debug!("v == {:?}", v); - let mut wr = SeekableMemWriter::new(); + let mut wr = Cursor::new(Vec::new()); { let mut rbml_w = writer::Encoder::new(&mut wr); let _ = v.encode(&mut rbml_w); diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 444b050952f..60102040bca 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -31,7 +31,6 @@ #![feature(core)] #![feature(hash)] #![feature(int_uint)] -#![feature(old_io)] #![feature(libc)] #![feature(old_path)] #![feature(quote)] diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 611d8bc27d1..10461e3d2ae 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -30,6 +30,8 @@ use util::nodemap::{FnvHashMap, NodeMap, NodeSet}; use serialize::Encodable; use std::cell::RefCell; use std::hash::{Hash, Hasher, SipHasher}; +use std::io::prelude::*; +use std::io::{Cursor, SeekFrom}; use syntax::abi; use syntax::ast::{self, DefId, NodeId}; use syntax::ast_map::{PathElem, PathElems}; @@ -47,7 +49,6 @@ use syntax::visit::Visitor; use syntax::visit; use syntax; use rbml::writer::Encoder; -use rbml::io::SeekableMemWriter; /// A borrowed version of `ast::InlinedItem`. pub enum InlinedItemRef<'a> { @@ -1530,7 +1531,7 @@ fn encode_info_for_items(ecx: &EncodeContext, // Path and definition ID indexing fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn: F) where - F: FnMut(&mut SeekableMemWriter, &T), + F: FnMut(&mut Cursor<Vec<u8>>, &T), T: Hash, { let mut buckets: Vec<Vec<entry<T>>> = (0..256u16).map(|_| Vec::new()).collect(); @@ -1551,8 +1552,8 @@ fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn: rbml_w.start_tag(tag_index_buckets_bucket_elt); assert!(elt.pos < 0xffff_ffff); { - let wr: &mut SeekableMemWriter = rbml_w.writer; - wr.write_be_u32(elt.pos as u32); + let wr: &mut Cursor<Vec<u8>> = rbml_w.writer; + write_be_u32(wr, elt.pos as u32); } write_fn(rbml_w.writer, &elt.val); rbml_w.end_tag(); @@ -1563,17 +1564,26 @@ fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn: rbml_w.start_tag(tag_index_table); for pos in &bucket_locs { assert!(*pos < 0xffff_ffff); - let wr: &mut SeekableMemWriter = rbml_w.writer; - wr.write_be_u32(*pos as u32); + let wr: &mut Cursor<Vec<u8>> = rbml_w.writer; + write_be_u32(wr, *pos as u32); } rbml_w.end_tag(); rbml_w.end_tag(); } -fn write_i64(writer: &mut SeekableMemWriter, &n: &i64) { - let wr: &mut SeekableMemWriter = writer; +fn write_i64(writer: &mut Cursor<Vec<u8>>, &n: &i64) { + let wr: &mut Cursor<Vec<u8>> = writer; assert!(n < 0x7fff_ffff); - wr.write_be_u32(n as u32); + write_be_u32(wr, n as u32); +} + +fn write_be_u32(w: &mut Write, u: u32) { + w.write_all(&[ + (u >> 24) as u8, + (u >> 16) as u8, + (u >> 8) as u8, + (u >> 0) as u8, + ]); } fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) { @@ -1929,13 +1939,13 @@ fn encode_dylib_dependency_formats(rbml_w: &mut Encoder, ecx: &EncodeContext) { pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2 ]; pub fn encode_metadata(parms: EncodeParams, krate: &ast::Crate) -> Vec<u8> { - let mut wr = SeekableMemWriter::new(); + let mut wr = Cursor::new(Vec::new()); encode_metadata_inner(&mut wr, parms, krate); // RBML compacts the encoded bytes whenever appropriate, // so there are some garbages left after the end of the data. - let metalen = wr.tell().unwrap() as uint; - let mut v = wr.unwrap(); + let metalen = wr.seek(SeekFrom::Current(0)).unwrap() as uint; + let mut v = wr.into_inner(); v.truncate(metalen); assert_eq!(v.len(), metalen); @@ -1965,7 +1975,7 @@ pub fn encode_metadata(parms: EncodeParams, krate: &ast::Crate) -> Vec<u8> { return v; } -fn encode_metadata_inner(wr: &mut SeekableMemWriter, +fn encode_metadata_inner(wr: &mut Cursor<Vec<u8>>, parms: EncodeParams, krate: &ast::Crate) { struct Stats { @@ -2032,64 +2042,64 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter, encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash); encode_dylib_dependency_formats(&mut rbml_w, &ecx); - let mut i = rbml_w.writer.tell().unwrap(); + let mut i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); encode_attributes(&mut rbml_w, &krate.attrs); - stats.attr_bytes = rbml_w.writer.tell().unwrap() - i; + stats.attr_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; - i = rbml_w.writer.tell().unwrap(); + i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); encode_crate_deps(&mut rbml_w, ecx.cstore); - stats.dep_bytes = rbml_w.writer.tell().unwrap() - i; + stats.dep_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode the language items. - i = rbml_w.writer.tell().unwrap(); + i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); encode_lang_items(&ecx, &mut rbml_w); - stats.lang_item_bytes = rbml_w.writer.tell().unwrap() - i; + stats.lang_item_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode the native libraries used - i = rbml_w.writer.tell().unwrap(); + i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); encode_native_libraries(&ecx, &mut rbml_w); - stats.native_lib_bytes = rbml_w.writer.tell().unwrap() - i; + stats.native_lib_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode the plugin registrar function - i = rbml_w.writer.tell().unwrap(); + i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); encode_plugin_registrar_fn(&ecx, &mut rbml_w); - stats.plugin_registrar_fn_bytes = rbml_w.writer.tell().unwrap() - i; + stats.plugin_registrar_fn_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode codemap - i = rbml_w.writer.tell().unwrap(); + i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); encode_codemap(&ecx, &mut rbml_w); - stats.codemap_bytes = rbml_w.writer.tell().unwrap() - i; + stats.codemap_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode macro definitions - i = rbml_w.writer.tell().unwrap(); + i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); encode_macro_defs(&mut rbml_w, krate); - stats.macro_defs_bytes = rbml_w.writer.tell().unwrap() - i; + stats.macro_defs_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode the def IDs of impls, for coherence checking. - i = rbml_w.writer.tell().unwrap(); + i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); encode_impls(&ecx, krate, &mut rbml_w); - stats.impl_bytes = rbml_w.writer.tell().unwrap() - i; + stats.impl_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode miscellaneous info. - i = rbml_w.writer.tell().unwrap(); + i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); encode_misc_info(&ecx, krate, &mut rbml_w); encode_reachable_extern_fns(&ecx, &mut rbml_w); - stats.misc_bytes = rbml_w.writer.tell().unwrap() - i; + stats.misc_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode and index the items. rbml_w.start_tag(tag_items); - i = rbml_w.writer.tell().unwrap(); + i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); let items_index = encode_info_for_items(&ecx, &mut rbml_w, krate); - stats.item_bytes = rbml_w.writer.tell().unwrap() - i; + stats.item_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; - i = rbml_w.writer.tell().unwrap(); + i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); encode_index(&mut rbml_w, items_index, write_i64); - stats.index_bytes = rbml_w.writer.tell().unwrap() - i; + stats.index_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; rbml_w.end_tag(); encode_struct_field_attrs(&mut rbml_w, krate); - stats.total_bytes = rbml_w.writer.tell().unwrap(); + stats.total_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); if tcx.sess.meta_stats() { for e in rbml_w.writer.get_ref() { @@ -2117,12 +2127,12 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter, // Get the encoded string for a type pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> String { - let mut wr = SeekableMemWriter::new(); + let mut wr = Cursor::new(Vec::new()); tyencode::enc_ty(&mut Encoder::new(&mut wr), &tyencode::ctxt { diag: tcx.sess.diagnostic(), ds: def_to_string, tcx: tcx, abbrevs: &RefCell::new(FnvHashMap()) }, t); - String::from_utf8(wr.unwrap()).unwrap() + String::from_utf8(wr.into_inner()).unwrap() } diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 86f1605b8bf..b0fa0e757fe 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -14,6 +14,7 @@ #![allow(non_camel_case_types)] use std::cell::RefCell; +use std::io::prelude::*; use middle::region; use middle::subst; diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index fb5b934c2cd..ed1d876d836 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -38,10 +38,11 @@ use syntax::parse::token; use syntax::ptr::P; use syntax; -use std::old_io::Seek; +use std::cell::Cell; +use std::io::SeekFrom; +use std::io::prelude::*; use std::num::FromPrimitive; use std::rc::Rc; -use std::cell::Cell; use rbml::reader; use rbml::writer::Encoder; @@ -50,7 +51,7 @@ use serialize; use serialize::{Decodable, Decoder, DecoderHelpers, Encodable}; use serialize::{EncoderHelpers}; -#[cfg(test)] use rbml::io::SeekableMemWriter; +#[cfg(test)] use std::io::Cursor; #[cfg(test)] use syntax::parse; #[cfg(test)] use syntax::print::pprust; @@ -85,7 +86,7 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext, }; debug!("> Encoding inlined item: {} ({:?})", ecx.tcx.map.path_to_string(id), - rbml_w.writer.tell()); + rbml_w.writer.seek(SeekFrom::Current(0))); // Folding could be avoided with a smarter encoder. let ii = simplify_ast(ii); @@ -99,7 +100,7 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext, debug!("< Encoded inlined fn: {} ({:?})", ecx.tcx.map.path_to_string(id), - rbml_w.writer.tell()); + rbml_w.writer.seek(SeekFrom::Current(0))); } impl<'a, 'b, 'c, 'tcx> ast_map::FoldOps for &'a DecodeContext<'b, 'c, 'tcx> { @@ -1974,7 +1975,7 @@ fn mk_ctxt() -> parse::ParseSess { #[cfg(test)] fn roundtrip(in_item: Option<P<ast::Item>>) { let in_item = in_item.unwrap(); - let mut wr = SeekableMemWriter::new(); + let mut wr = Cursor::new(Vec::new()); encode_item_ast(&mut Encoder::new(&mut wr), &*in_item); let rbml_doc = rbml::Doc::new(wr.get_ref()); let out_item = decode_item_ast(rbml_doc); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 892452ccc1c..932c9c61ef1 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -118,9 +118,11 @@ use middle::ty::ClosureTyper; use lint; use util::nodemap::NodeMap; -use std::{fmt, old_io, usize}; -use std::rc::Rc; +use std::{fmt, usize}; +use std::io::prelude::*; +use std::io; use std::iter::repeat; +use std::rc::Rc; use syntax::ast::{self, NodeId, Expr}; use syntax::codemap::{BytePos, original_sp, Span}; use syntax::parse::token::{self, special_idents}; @@ -680,10 +682,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } fn write_vars<F>(&self, - wr: &mut old_io::Writer, + wr: &mut Write, ln: LiveNode, mut test: F) - -> old_io::IoResult<()> where + -> io::Result<()> where F: FnMut(usize) -> LiveNode, { let node_base_idx = self.idx(ln, Variable(0)); @@ -727,7 +729,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn ln_str(&self, ln: LiveNode) -> String { let mut wr = Vec::new(); { - let wr = &mut wr as &mut old_io::Writer; + let wr = &mut wr as &mut Write; write!(wr, "[ln({:?}) of kind {:?} reads", ln.get(), self.ir.lnk(ln)); self.write_vars(wr, ln, |idx| self.users[idx].reader); write!(wr, " writes"); diff --git a/src/librustc_back/fs.rs b/src/librustc_back/fs.rs index 20335bc8c09..6a6502800f6 100644 --- a/src/librustc_back/fs.rs +++ b/src/librustc_back/fs.rs @@ -9,11 +9,8 @@ // except according to those terms. use std::io; -use std::old_io::fs; -use std::old_io; -#[allow(deprecated)] -use std::old_path; -use std::os; +#[allow(deprecated)] use std::old_path; +#[allow(deprecated)] use std::old_io; use std::path::{Path, PathBuf}; /// Returns an absolute path in the filesystem that `path` points to. The @@ -31,6 +28,8 @@ pub fn realpath(original: &Path) -> io::Result<PathBuf> { #[allow(deprecated)] fn old_realpath(original: &old_path::Path) -> old_io::IoResult<old_path::Path> { + use std::old_io::fs; + use std::os; const MAX_LINKS_FOLLOWED: usize = 256; let original = try!(os::getcwd()).join(original); diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index cdea84e4a37..e0261606ef1 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -29,7 +29,6 @@ #![feature(collections)] #![feature(core)] #![feature(int_uint)] -#![feature(old_io)] #![feature(libc)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] @@ -38,6 +37,7 @@ #![feature(staged_api)] #![feature(exit_status)] #![feature(io)] +#![feature(set_panic)] extern crate arena; extern crate flate; @@ -74,10 +74,11 @@ use rustc::util::common::time; use std::cmp::Ordering::Equal; use std::env; +use std::io::{self, Read, Write}; use std::iter::repeat; -use std::old_io::{self, stdio}; use std::path::PathBuf; -use std::sync::mpsc::channel; +use std::str; +use std::sync::{Arc, Mutex}; use std::thread; use rustc::session::early_error; @@ -171,8 +172,8 @@ fn make_input(free_matches: &[String]) -> Option<(Input, Option<PathBuf>)> { if free_matches.len() == 1 { let ifile = &free_matches[0][..]; if ifile == "-" { - let contents = old_io::stdin().read_to_end().unwrap(); - let src = String::from_utf8(contents).unwrap(); + let mut src = String::new(); + io::stdin().read_to_string(&mut src).unwrap(); Some((Input::Str(src), None)) } else { Some((Input::File(PathBuf::new(ifile)), Some(PathBuf::new(ifile)))) @@ -794,9 +795,16 @@ fn parse_crate_attrs(sess: &Session, input: &Input) -> pub fn monitor<F:FnOnce()+Send+'static>(f: F) { const STACK_SIZE: uint = 8 * 1024 * 1024; // 8MB - let (tx, rx) = channel(); - let w = old_io::ChanWriter::new(tx); - let mut r = old_io::ChanReader::new(rx); + struct Sink(Arc<Mutex<Vec<u8>>>); + impl Write for Sink { + fn write(&mut self, data: &[u8]) -> io::Result<usize> { + Write::write(&mut *self.0.lock().unwrap(), data) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } + } + + let data = Arc::new(Mutex::new(Vec::new())); + let err = Sink(data.clone()); let mut cfg = thread::Builder::new().name("rustc".to_string()); @@ -806,7 +814,7 @@ pub fn monitor<F:FnOnce()+Send+'static>(f: F) { cfg = cfg.stack_size(STACK_SIZE); } - match cfg.spawn(move || { stdio::set_stderr(box w); f() }).unwrap().join() { + match cfg.spawn(move || { io::set_panic(box err); f() }).unwrap().join() { Ok(()) => { /* fallthrough */ } Err(value) => { // Thread panicked without emitting a fatal diagnostic @@ -833,22 +841,13 @@ pub fn monitor<F:FnOnce()+Send+'static>(f: F) { emitter.emit(None, ¬e[..], None, diagnostic::Note) } - match r.read_to_string() { - Ok(s) => println!("{}", s), - Err(e) => { - emitter.emit(None, - &format!("failed to read internal \ - stderr: {}", e), - None, - diagnostic::Error) - } - } + println!("{}", str::from_utf8(&data.lock().unwrap()).unwrap()); } // Panic so the process returns a failure code, but don't pollute the // output with some unnecessary panic messages, we've already // printed everything that we needed to. - old_io::stdio::set_stderr(box old_io::util::NullWriter); + io::set_panic(box io::sink()); panic!(); } } diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index ffb2a05e437..9e693a64ef0 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -40,7 +40,6 @@ use graphviz as dot; use std::fs::File; use std::io::{self, Write}; -use std::old_io; use std::option; use std::path::PathBuf; use std::str::FromStr; @@ -615,7 +614,7 @@ pub fn pretty_print_input(sess: Session, }); let code = blocks::Code::from_node(node); - let out: &mut Writer = &mut out; + let out: &mut Write = &mut out; match code { Some(code) => { let variants = gather_flowgraph_variants(&sess); @@ -654,11 +653,11 @@ pub fn pretty_print_input(sess: Session, } } -fn print_flowgraph<W:old_io::Writer>(variants: Vec<borrowck_dot::Variant>, - analysis: ty::CrateAnalysis, - code: blocks::Code, - mode: PpFlowGraphMode, - mut out: W) -> io::Result<()> { +fn print_flowgraph<W: Write>(variants: Vec<borrowck_dot::Variant>, + analysis: ty::CrateAnalysis, + code: blocks::Code, + mode: PpFlowGraphMode, + mut out: W) -> io::Result<()> { let ty_cx = &analysis.ty_cx; let cfg = match code { blocks::BlockCode(block) => cfg::CFG::new(ty_cx, &*block), @@ -698,7 +697,7 @@ fn print_flowgraph<W:old_io::Writer>(variants: Vec<borrowck_dot::Variant>, } } - fn expand_err_details(r: old_io::IoResult<()>) -> io::Result<()> { + fn expand_err_details(r: io::Result<()>) -> io::Result<()> { r.map_err(|ioerr| { io::Error::new(io::ErrorKind::Other, "graphviz::render failed", Some(ioerr.to_string())) diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 66dd49f241f..efc81da560b 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -38,7 +38,6 @@ #![feature(unsafe_destructor)] #![feature(staged_api)] #![feature(unicode)] -#![feature(io)] #![feature(path_ext)] #![feature(fs)] #![feature(hash)] diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index 6cfe7a33dd4..c2b6c940cae 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -11,7 +11,6 @@ use std::fs::File; use std::io::prelude::*; use std::io; -use std::old_io; use std::path::{PathBuf, Path}; use std::str; @@ -51,12 +50,12 @@ macro_rules! load_or_return { let input = PathBuf::new($input); match ::externalfiles::load_string(&input) { Err(e) => { - let _ = writeln!(&mut old_io::stderr(), + let _ = writeln!(&mut io::stderr(), "error reading `{}`: {}", input.display(), e); return $cant_read; } Ok(None) => { - let _ = writeln!(&mut old_io::stderr(), + let _ = writeln!(&mut io::stderr(), "error reading `{}`: not UTF-8", input.display()); return $not_utf8; } diff --git a/src/librustdoc/flock.rs b/src/librustdoc/flock.rs index 51c58861b4b..8c85eaff23c 100644 --- a/src/librustdoc/flock.rs +++ b/src/librustdoc/flock.rs @@ -23,8 +23,8 @@ mod imp { use std::ffi::{AsOsStr, CString}; use std::os::unix::prelude::*; use std::path::Path; + use std::io; use libc; - use std::os as stdos; #[cfg(target_os = "linux")] mod os { @@ -121,8 +121,8 @@ mod imp { libc::open(buf.as_ptr(), libc::O_RDWR | libc::O_CREAT, libc::S_IRWXU) }; - assert!(fd > 0, "failed to open lockfile: [{}] {}", - stdos::errno(), stdos::last_os_error()); + assert!(fd > 0, "failed to open lockfile: {}", + io::Error::last_os_error()); let flock = os::flock { l_start: 0, l_len: 0, @@ -135,10 +135,9 @@ mod imp { libc::fcntl(fd, os::F_SETLKW, &flock) }; if ret == -1 { - let errno = stdos::errno(); + let err = io::Error::last_os_error(); unsafe { libc::close(fd); } - panic!("could not lock `{}`: [{}] {}", p.display(), - errno, stdos::error_string(errno)) + panic!("could not lock `{}`: {}", p.display(), err); } Lock { fd: fd } } @@ -166,9 +165,9 @@ mod imp { mod imp { use libc; use std::ffi::AsOsStr; + use std::io; use std::mem; use std::os::windows::prelude::*; - use std::os; use std::path::Path; use std::ptr; @@ -210,8 +209,7 @@ mod imp { ptr::null_mut()) }; if handle == libc::INVALID_HANDLE_VALUE { - panic!("create file error: [{}] {}", - os::errno(), os::last_os_error()); + panic!("create file error: {}", io::Error::last_os_error()); } let mut overlapped: libc::OVERLAPPED = unsafe { mem::zeroed() }; let ret = unsafe { @@ -219,10 +217,9 @@ mod imp { &mut overlapped) }; if ret == 0 { - let errno = os::errno(); + let err = io::Error::last_os_error(); unsafe { libc::CloseHandle(handle); } - panic!("could not lock `{}`: [{}] {}", p.display(), - errno, os::error_string(errno)); + panic!("could not lock `{}`: {}", p.display(), err); } Lock { handle: handle } } diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index b88e5065b4f..d19ccabed47 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -15,7 +15,8 @@ use html::escape::Escape; -use std::old_io; +use std::io; +use std::io::prelude::*; use syntax::parse::lexer; use syntax::parse::token; use syntax::parse; @@ -46,7 +47,7 @@ pub fn highlight(src: &str, class: Option<&str>, id: Option<&str>) -> String { /// source. fn doit(sess: &parse::ParseSess, mut lexer: lexer::StringReader, class: Option<&str>, id: Option<&str>, - out: &mut Writer) -> old_io::IoResult<()> { + out: &mut Write) -> io::Result<()> { use syntax::parse::lexer::Reader; try!(write!(out, "<pre ")); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 246004751c5..152b6f5c80a 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -26,9 +26,8 @@ #![feature(core)] #![feature(exit_status)] #![feature(int_uint)] -#![feature(old_io)] +#![feature(set_panic)] #![feature(libc)] -#![feature(os)] #![feature(old_path)] #![feature(rustc_private)] #![feature(staged_api)] @@ -465,7 +464,7 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche fn json_input(input: &str) -> Result<Output, String> { let mut bytes = Vec::new(); match File::open(input).and_then(|mut f| f.read_to_end(&mut bytes)) { - Ok(()) => {} + Ok(_) => {} Err(e) => return Err(format!("couldn't open {}: {}", input, e)), }; match json::from_reader(&mut &bytes[..]) { diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 7d635c8b232..09b4915222b 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -9,8 +9,8 @@ // except according to those terms. use std::fs::File; -use std::io::Write; -use std::old_io; +use std::io; +use std::io::prelude::*; use std::path::{PathBuf, Path}; use core; @@ -64,7 +64,7 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches, let mut out = match File::create(&output) { Err(e) => { - let _ = writeln!(&mut old_io::stderr(), + let _ = writeln!(&mut io::stderr(), "error opening `{}` for writing: {}", output.display(), e); return 4; @@ -74,7 +74,7 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches, let (metadata, text) = extract_leading_metadata(&input_str); if metadata.len() == 0 { - let _ = writeln!(&mut old_io::stderr(), + let _ = writeln!(&mut io::stderr(), "invalid markdown file: expecting initial line with `% ...TITLE...`"); return 5; } @@ -129,7 +129,7 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches, match err { Err(e) => { - let _ = writeln!(&mut old_io::stderr(), + let _ = writeln!(&mut io::stderr(), "error writing to `{}`: {}", output.display(), e); 6 diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index e7312d6548e..e2f8a6f82c6 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -13,13 +13,12 @@ use std::collections::{HashSet, HashMap}; use std::dynamic_lib::DynamicLibrary; use std::env; use std::ffi::OsString; -use std::old_io; +use std::io::prelude::*; use std::io; use std::path::PathBuf; use std::process::Command; use std::str; -use std::sync::mpsc::channel; -use std::thread; +use std::sync::{Arc, Mutex}; use std::thunk::Thunk; use testing; @@ -140,30 +139,29 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths, // an explicit handle into rustc to collect output messages, but we also // want to catch the error message that rustc prints when it fails. // - // We take our task-local stderr (likely set by the test runner), and move - // it into another task. This helper task then acts as a sink for both the - // stderr of this task and stderr of rustc itself, copying all the info onto - // the stderr channel we originally started with. + // We take our task-local stderr (likely set by the test runner) and replace + // it with a sink that is also passed to rustc itself. When this function + // returns the output of the sink is copied onto the output of our own task. // // The basic idea is to not use a default_handler() for rustc, and then also // not print things by default to the actual stderr. - let (tx, rx) = channel(); - let w1 = old_io::ChanWriter::new(tx); - let w2 = w1.clone(); - let old = old_io::stdio::set_stderr(box w1); - thread::spawn(move || { - let mut p = old_io::ChanReader::new(rx); - let mut err = match old { - Some(old) => { - // Chop off the `Send` bound. - let old: Box<Writer> = old; - old - } - None => box old_io::stderr() as Box<Writer>, - }; - old_io::util::copy(&mut p, &mut err).unwrap(); - }); - let emitter = diagnostic::EmitterWriter::new(box w2, None); + struct Sink(Arc<Mutex<Vec<u8>>>); + impl Write for Sink { + fn write(&mut self, data: &[u8]) -> io::Result<usize> { + Write::write(&mut *self.0.lock().unwrap(), data) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } + } + struct Bomb(Arc<Mutex<Vec<u8>>>, Box<Write+Send>); + impl Drop for Bomb { + fn drop(&mut self) { + let _ = self.1.write_all(&self.0.lock().unwrap()); + } + } + let data = Arc::new(Mutex::new(Vec::new())); + let emitter = diagnostic::EmitterWriter::new(box Sink(data.clone()), None); + let old = io::set_panic(box Sink(data.clone())); + let _bomb = Bomb(data, old.unwrap_or(box io::stdout())); // Compile the code let codemap = CodeMap::new(); diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 6fc56522c6a..d0ef89e811b 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -199,15 +199,17 @@ use self::DecoderError::*; use self::ParserState::*; use self::InternalStackElement::*; -use std; use std::collections::{HashMap, BTreeMap}; -use std::{char, f64, fmt, old_io, num, str}; +use std::io::prelude::*; +use std::io; use std::mem::{swap}; -use std::num::{Float, Int}; use std::num::FpCategory as Fp; +use std::num::{Float, Int}; +use std::ops::Index; use std::str::FromStr; use std::string; -use std::ops::Index; +use std::{char, f64, fmt, num, str}; +use std; use unicode::str as unicode_str; use unicode::str::Utf16Item; @@ -256,11 +258,11 @@ pub enum ErrorCode { NotUtf8, } -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, PartialEq, Debug)] pub enum ParserError { /// msg, line, col SyntaxError(ErrorCode, uint, uint), - IoError(old_io::IoErrorKind, &'static str), + IoError(io::ErrorKind, String), } // Builder and Parser have the same errors. @@ -331,8 +333,8 @@ impl fmt::Display for ErrorCode { } } -fn io_error_to_error(io: old_io::IoError) -> ParserError { - IoError(io.kind, io.desc) +fn io_error_to_error(io: io::Error) -> ParserError { + IoError(io.kind(), io.to_string()) } impl fmt::Display for ParserError { @@ -1982,7 +1984,7 @@ impl<T: Iterator<Item=char>> Builder<T> { self.bump(); match self.token { None => {} - Some(Error(e)) => { return Err(e); } + Some(Error(ref e)) => { return Err(e.clone()); } ref tok => { panic!("unexpected token {:?}", tok.clone()); } } result @@ -2004,7 +2006,7 @@ impl<T: Iterator<Item=char>> Builder<T> { swap(s, &mut temp); Ok(Json::String(temp)) } - Some(Error(e)) => Err(e), + Some(Error(ref e)) => Err(e.clone()), Some(ArrayStart) => self.build_array(), Some(ObjectStart) => self.build_object(), Some(ObjectEnd) => self.parser.error(InvalidSyntax), @@ -2037,7 +2039,7 @@ impl<T: Iterator<Item=char>> Builder<T> { loop { match self.token { Some(ObjectEnd) => { return Ok(Json::Object(values)); } - Some(Error(e)) => { return Err(e); } + Some(Error(ref e)) => { return Err(e.clone()); } None => { break; } _ => {} } @@ -2056,8 +2058,9 @@ impl<T: Iterator<Item=char>> Builder<T> { } /// Decodes a json value from an `&mut old_io::Reader` -pub fn from_reader(rdr: &mut old_io::Reader) -> Result<Json, BuilderError> { - let contents = match rdr.read_to_end() { +pub fn from_reader(rdr: &mut Read) -> Result<Json, BuilderError> { + let mut contents = Vec::new(); + match rdr.read_to_end(&mut contents) { Ok(c) => c, Err(e) => return Err(io_error_to_error(e)) }; diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 8d58ba99e13..49e44a6d455 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -31,7 +31,7 @@ Core encoding and decoding interfaces. #![feature(collections)] #![feature(core)] #![feature(int_uint)] -#![feature(old_io)] +#![feature(io)] #![feature(old_path)] #![feature(rustc_private)] #![feature(staged_api)] diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 44564ebf53d..677894ba6e4 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -17,6 +17,7 @@ use io; use iter::IteratorExt; use libc; use mem; +#[allow(deprecated)] use old_io; use ops::Deref; use option::Option::{self, Some, None}; @@ -298,6 +299,7 @@ impl FromError<NulError> for io::Error { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl FromError<NulError> for old_io::IoError { fn from_error(_: NulError) -> old_io::IoError { old_io::IoError { diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 3603f127504..03416eb86a0 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -16,8 +16,7 @@ use prelude::v1::*; use io::prelude::*; use cmp; -use error::Error as StdError; -use error::FromError; +use error::{self, FromError}; use fmt; use io::{self, Cursor, DEFAULT_BUF_SIZE, Error, ErrorKind}; use ptr; @@ -28,6 +27,7 @@ use ptr; /// For example, every call to `read` on `TcpStream` results in a system call. /// A `BufReader` performs large, infrequent reads on the underlying `Read` /// and maintains an in-memory buffer of the results. +#[stable(feature = "rust1", since = "1.0.0")] pub struct BufReader<R> { inner: R, buf: Cursor<Vec<u8>>, @@ -35,11 +35,13 @@ pub struct BufReader<R> { impl<R: Read> BufReader<R> { /// Creates a new `BufReader` with a default buffer capacity + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: R) -> BufReader<R> { BufReader::with_capacity(DEFAULT_BUF_SIZE, inner) } /// Creates a new `BufReader` with the specified buffer capacity + #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacity(cap: usize, inner: R) -> BufReader<R> { BufReader { inner: inner, @@ -48,6 +50,7 @@ impl<R: Read> BufReader<R> { } /// Gets a reference to the underlying reader. + #[stable(feature = "rust1", since = "1.0.0")] pub fn get_ref(&self) -> &R { &self.inner } /// Gets a mutable reference to the underlying reader. @@ -55,14 +58,17 @@ impl<R: Read> BufReader<R> { /// # Warning /// /// It is inadvisable to directly read from the underlying reader. + #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut R { &mut self.inner } /// Unwraps this `BufReader`, returning the underlying reader. /// /// Note that any leftover data in the internal buffer is lost. + #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> R { self.inner } } +#[stable(feature = "rust1", since = "1.0.0")] impl<R: Read> Read for BufReader<R> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { // If we don't have any buffered data and we're doing a massive read @@ -77,6 +83,7 @@ impl<R: Read> Read for BufReader<R> { } } +#[stable(feature = "rust1", since = "1.0.0")] impl<R: Read> BufRead for BufReader<R> { fn fill_buf(&mut self) -> io::Result<&[u8]> { // If we've reached the end of our internal buffer then we need to fetch @@ -112,6 +119,7 @@ impl<R> fmt::Debug for BufReader<R> where R: fmt::Debug { /// underlying `Write` in large, infrequent batches. /// /// This writer will be flushed when it is dropped. +#[stable(feature = "rust1", since = "1.0.0")] pub struct BufWriter<W> { inner: Option<W>, buf: Vec<u8>, @@ -120,15 +128,18 @@ pub struct BufWriter<W> { /// An error returned by `into_inner` which indicates whether a flush error /// happened or not. #[derive(Debug)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct IntoInnerError<W>(W, Error); impl<W: Write> BufWriter<W> { /// Creates a new `BufWriter` with a default buffer capacity + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: W) -> BufWriter<W> { BufWriter::with_capacity(DEFAULT_BUF_SIZE, inner) } /// Creates a new `BufWriter` with the specified buffer capacity + #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacity(cap: usize, inner: W) -> BufWriter<W> { BufWriter { inner: Some(inner), @@ -148,6 +159,7 @@ impl<W: Write> BufWriter<W> { break; } Ok(n) => written += n, + Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} Err(e) => { ret = Err(e); break } } @@ -165,6 +177,7 @@ impl<W: Write> BufWriter<W> { } /// Gets a reference to the underlying writer. + #[stable(feature = "rust1", since = "1.0.0")] pub fn get_ref(&self) -> &W { self.inner.as_ref().unwrap() } /// Gets a mutable reference to the underlying write. @@ -172,11 +185,13 @@ impl<W: Write> BufWriter<W> { /// # Warning /// /// It is inadvisable to directly read from the underlying writer. + #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut W { self.inner.as_mut().unwrap() } /// Unwraps this `BufWriter`, returning the underlying writer. /// /// The buffer is flushed before returning the writer. + #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> { match self.flush_buf() { Err(e) => Err(IntoInnerError(self, e)), @@ -185,6 +200,7 @@ impl<W: Write> BufWriter<W> { } } +#[stable(feature = "rust1", since = "1.0.0")] impl<W: Write> Write for BufWriter<W> { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { if self.buf.len() + buf.len() > self.buf.capacity() { @@ -224,23 +240,30 @@ impl<W> IntoInnerError<W> { /// Returns the error which caused the call to `into_inner` to fail. /// /// This error was returned when attempting to flush the internal buffer. + #[stable(feature = "rust1", since = "1.0.0")] pub fn error(&self) -> &Error { &self.1 } /// Returns the underlying `BufWriter` instance which generated the error. /// /// The returned object can be used to retry a flush or re-inspect the /// buffer. + #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> W { self.0 } } +#[stable(feature = "rust1", since = "1.0.0")] impl<W> FromError<IntoInnerError<W>> for Error { fn from_error(iie: IntoInnerError<W>) -> Error { iie.1 } } -impl<W> StdError for IntoInnerError<W> { - fn description(&self) -> &str { self.error().description() } +#[stable(feature = "rust1", since = "1.0.0")] +impl<W> error::Error for IntoInnerError<W> { + fn description(&self) -> &str { + error::Error::description(self.error()) + } } +#[stable(feature = "rust1", since = "1.0.0")] impl<W> fmt::Display for IntoInnerError<W> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.error().fmt(f) @@ -251,26 +274,41 @@ impl<W> fmt::Display for IntoInnerError<W> { /// (`0x0a`, `'\n'`) is detected. /// /// This writer will be flushed when it is dropped. +#[stable(feature = "rust1", since = "1.0.0")] pub struct LineWriter<W> { inner: BufWriter<W>, } impl<W: Write> LineWriter<W> { /// Creates a new `LineWriter` + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: W) -> LineWriter<W> { // Lines typically aren't that long, don't use a giant buffer - LineWriter { inner: BufWriter::with_capacity(1024, inner) } + LineWriter::with_capacity(1024, inner) + } + + /// Creates a new `LineWriter` with a specified capacity for the internal + /// buffer. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn with_capacity(cap: usize, inner: W) -> LineWriter<W> { + LineWriter { inner: BufWriter::with_capacity(cap, inner) } } /// Gets a reference to the underlying writer. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get_ref(&self) -> &W { self.inner.get_ref() } + + /// Gets a mutable reference to the underlying writer. /// - /// This type does not expose the ability to get a mutable reference to the - /// underlying reader because that could possibly corrupt the buffer. - pub fn get_ref<'a>(&'a self) -> &'a W { self.inner.get_ref() } + /// Caution must be taken when calling methods on the mutable reference + /// returned as extra writes could corrupt the output stream. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() } /// Unwraps this `LineWriter`, returning the underlying writer. /// /// The internal buffer is flushed before returning the writer. + #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> Result<W, IntoInnerError<LineWriter<W>>> { self.inner.into_inner().map_err(|IntoInnerError(buf, e)| { IntoInnerError(LineWriter { inner: buf }, e) @@ -278,6 +316,7 @@ impl<W: Write> LineWriter<W> { } } +#[stable(feature = "rust1", since = "1.0.0")] impl<W: Write> Write for LineWriter<W> { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { match buf.rposition_elem(&b'\n') { @@ -320,12 +359,13 @@ impl<W: Read> Read for InternalBufWriter<W> { /// Wraps a Stream and buffers input and output to and from it. /// -/// It can be excessively inefficient to work directly with a `Stream`. For +/// It can be excessively inefficient to work directly with a `Read+Write`. For /// example, every call to `read` or `write` on `TcpStream` results in a system /// call. A `BufStream` keeps in memory buffers of data, making large, -/// infrequent calls to `read` and `write` on the underlying `Stream`. +/// infrequent calls to `read` and `write` on the underlying `Read+Write`. /// /// The output half will be flushed when this stream is dropped. +#[stable(feature = "rust1", since = "1.0.0")] pub struct BufStream<S> { inner: BufReader<InternalBufWriter<S>> } @@ -333,6 +373,7 @@ pub struct BufStream<S> { impl<S: Read + Write> BufStream<S> { /// Creates a new buffered stream with explicitly listed capacities for the /// reader/writer buffer. + #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacities(reader_cap: usize, writer_cap: usize, inner: S) -> BufStream<S> { let writer = BufWriter::with_capacity(writer_cap, inner); @@ -343,11 +384,13 @@ impl<S: Read + Write> BufStream<S> { /// Creates a new buffered stream with the default reader/writer buffer /// capacities. + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: S) -> BufStream<S> { BufStream::with_capacities(DEFAULT_BUF_SIZE, DEFAULT_BUF_SIZE, inner) } /// Gets a reference to the underlying stream. + #[stable(feature = "rust1", since = "1.0.0")] pub fn get_ref(&self) -> &S { let InternalBufWriter(ref w) = self.inner.inner; w.get_ref() @@ -359,6 +402,7 @@ impl<S: Read + Write> BufStream<S> { /// /// It is inadvisable to read directly from or write directly to the /// underlying stream. + #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut S { let InternalBufWriter(ref mut w) = self.inner.inner; w.get_mut() @@ -368,6 +412,7 @@ impl<S: Read + Write> BufStream<S> { /// /// The internal buffer is flushed before returning the stream. Any leftover /// data in the read buffer is lost. + #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> Result<S, IntoInnerError<BufStream<S>>> { let BufReader { inner: InternalBufWriter(w), buf } = self.inner; w.into_inner().map_err(|IntoInnerError(w, e)| { @@ -378,17 +423,20 @@ impl<S: Read + Write> BufStream<S> { } } +#[stable(feature = "rust1", since = "1.0.0")] impl<S: Read + Write> BufRead for BufStream<S> { fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() } fn consume(&mut self, amt: uint) { self.inner.consume(amt) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<S: Read + Write> Read for BufStream<S> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.inner.read(buf) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<S: Read + Write> Write for BufStream<S> { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.inner.inner.get_mut().write(buf) diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index 9f3cd8c8b15..530c6728107 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -10,7 +10,7 @@ use boxed::Box; use clone::Clone; -use error::Error as StdError; +use error; use fmt; use option::Option::{self, Some, None}; use result; @@ -22,6 +22,7 @@ use sys; /// /// This typedef is generally used to avoid writing out `io::Error` directly and /// is otherwise a direct mapping to `std::result::Result`. +#[stable(feature = "rust1", since = "1.0.0")] pub type Result<T> = result::Result<T, Error>; /// The error type for I/O operations of the `Read`, `Write`, `Seek`, and @@ -31,6 +32,7 @@ pub type Result<T> = result::Result<T, Error>; /// `Error` can be created with crafted error messages and a particular value of /// `ErrorKind`. #[derive(PartialEq, Eq, Clone, Debug)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct Error { repr: Repr, } @@ -50,6 +52,10 @@ struct Custom { /// A list specifying general categories of I/O error. #[derive(Copy, PartialEq, Eq, Clone, Debug)] +#[unstable(feature = "io", + reason = "the interaction between OS error codes and how they map to \ + these names (as well as the names themselves) has not \ + been thoroughly thought out")] pub enum ErrorKind { /// The file was not found. FileNotFound, @@ -96,6 +102,9 @@ pub enum ErrorKind { impl Error { /// Creates a new custom error from a specified kind/description/detail. + #[unstable(feature = "io", reason = "the exact makeup of an Error may + change to include `Box<Error>` for \ + example")] pub fn new(kind: ErrorKind, description: &'static str, detail: Option<String>) -> Error { @@ -113,16 +122,20 @@ impl Error { /// This function reads the value of `errno` for the target platform (e.g. /// `GetLastError` on Windows) and will return a corresponding instance of /// `Error` for the error code. + #[stable(feature = "rust1", since = "1.0.0")] pub fn last_os_error() -> Error { Error::from_os_error(sys::os::errno() as i32) } /// Creates a new instance of an `Error` from a particular OS error code. + #[unstable(feature = "io", + reason = "unclear whether this function is necessary")] pub fn from_os_error(code: i32) -> Error { Error { repr: Repr::Os(code) } } /// Return the corresponding `ErrorKind` for this error. + #[stable(feature = "rust1", since = "1.0.0")] pub fn kind(&self) -> ErrorKind { match self.repr { Repr::Os(code) => sys::decode_error_kind(code), @@ -131,6 +144,9 @@ impl Error { } /// Returns a short description for this error message + #[unstable(feature = "io")] + #[deprecated(since = "1.0.0", reason = "use the Error trait's description \ + method instead")] pub fn description(&self) -> &str { match self.repr { Repr::Os(..) => "os error", @@ -139,6 +155,8 @@ impl Error { } /// Returns a detailed error message for this error (if one is available) + #[unstable(feature = "io")] + #[deprecated(since = "1.0.0", reason = "use the to_string() method instead")] pub fn detail(&self) -> Option<String> { match self.repr { Repr::Os(code) => Some(sys::os::error_string(code)), @@ -147,6 +165,7 @@ impl Error { } } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for Error { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match self.repr { @@ -173,7 +192,8 @@ impl fmt::Display for Error { } } -impl StdError for Error { +#[stable(feature = "rust1", since = "1.0.0")] +impl error::Error for Error { fn description(&self) -> &str { match self.repr { Repr::Os(..) => "os error", diff --git a/src/libstd/io/impls.rs b/src/libstd/io/impls.rs index c968415d3ef..16298240acf 100644 --- a/src/libstd/io/impls.rs +++ b/src/libstd/io/impls.rs @@ -27,10 +27,10 @@ impl<'a, R: Read + ?Sized> Read for &'a mut R { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { (**self).read(buf) } - fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<()> { + fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { (**self).read_to_end(buf) } - fn read_to_string(&mut self, buf: &mut String) -> io::Result<()> { + fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { (**self).read_to_string(buf) } } @@ -53,10 +53,10 @@ impl<'a, S: Seek + ?Sized> Seek for &'a mut S { impl<'a, B: BufRead + ?Sized> BufRead for &'a mut B { fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() } fn consume(&mut self, amt: usize) { (**self).consume(amt) } - fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<()> { + fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> { (**self).read_until(byte, buf) } - fn read_line(&mut self, buf: &mut String) -> io::Result<()> { + fn read_line(&mut self, buf: &mut String) -> io::Result<usize> { (**self).read_line(buf) } } @@ -66,10 +66,10 @@ impl<R: Read + ?Sized> Read for Box<R> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { (**self).read(buf) } - fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<()> { + fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { (**self).read_to_end(buf) } - fn read_to_string(&mut self, buf: &mut String) -> io::Result<()> { + fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { (**self).read_to_string(buf) } } @@ -92,10 +92,10 @@ impl<S: Seek + ?Sized> Seek for Box<S> { impl<B: BufRead + ?Sized> BufRead for Box<B> { fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() } fn consume(&mut self, amt: usize) { (**self).consume(amt) } - fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<()> { + fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> { (**self).read_until(byte, buf) } - fn read_line(&mut self, buf: &mut String) -> io::Result<()> { + fn read_line(&mut self, buf: &mut String) -> io::Result<usize> { (**self).read_line(buf) } } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 9137068076b..3fddaaad807 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -14,13 +14,11 @@ //! > development. At this time it is still recommended to use the `old_io` //! > module while the details of this module shake out. -#![unstable(feature = "io", - reason = "this new I/O module is still under active development and \ - APIs are subject to tweaks fairly regularly")] +#![stable(feature = "rust1", since = "1.0.0")] use cmp; use unicode::str as core_str; -use error::Error as StdError; +use error as std_error; use fmt; use iter::Iterator; use marker::Sized; @@ -41,6 +39,8 @@ pub use self::error::{Result, Error, ErrorKind}; pub use self::util::{copy, sink, Sink, empty, Empty, repeat, Repeat}; pub use self::stdio::{stdin, stdout, stderr, Stdin, Stdout, Stderr}; pub use self::stdio::{StdoutLock, StderrLock, StdinLock}; +#[doc(no_inline, hidden)] +pub use self::stdio::set_panic; #[macro_use] mod lazy; @@ -111,8 +111,8 @@ fn with_end_to_cap<F>(v: &mut Vec<u8>, f: F) -> Result<usize> // 2. We're passing a raw buffer to the function `f`, and it is expected that // the function only *appends* bytes to the buffer. We'll get undefined // behavior if existing bytes are overwritten to have non-UTF-8 data. -fn append_to_string<F>(buf: &mut String, f: F) -> Result<()> - where F: FnOnce(&mut Vec<u8>) -> Result<()> +fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize> + where F: FnOnce(&mut Vec<u8>) -> Result<usize> { struct Guard<'a> { s: &'a mut Vec<u8>, len: usize } #[unsafe_destructor] @@ -126,7 +126,7 @@ fn append_to_string<F>(buf: &mut String, f: F) -> Result<()> let mut g = Guard { len: buf.len(), s: buf.as_mut_vec() }; let ret = f(g.s); if str::from_utf8(&g.s[g.len..]).is_err() { - ret.and_then(|()| { + ret.and_then(|_| { Err(Error::new(ErrorKind::InvalidInput, "stream did not contain valid UTF-8", None)) }) @@ -137,14 +137,15 @@ fn append_to_string<F>(buf: &mut String, f: F) -> Result<()> } } -fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<()> { +fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> { + let mut read = 0; loop { if buf.capacity() == buf.len() { buf.reserve(DEFAULT_BUF_SIZE); } match with_end_to_cap(buf, |b| r.read(b)) { - Ok(0) => return Ok(()), - Ok(_) => {} + Ok(0) => return Ok(read), + Ok(n) => read += n, Err(ref e) if e.kind() == ErrorKind::Interrupted => {} Err(e) => return Err(e), } @@ -159,6 +160,7 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<()> { /// Readers are intended to be composable with one another. Many objects /// throughout the I/O and related libraries take and provide types which /// implement the `Read` trait. +#[stable(feature = "rust1", since = "1.0.0")] pub trait Read { /// Pull some bytes from this source into the specified buffer, returning /// how many bytes were read. @@ -187,6 +189,7 @@ pub trait Read { /// If this function encounters any form of I/O or other error, an error /// variant will be returned. If an error is returned then it must be /// guaranteed that no bytes were read. + #[stable(feature = "rust1", since = "1.0.0")] fn read(&mut self, buf: &mut [u8]) -> Result<usize>; /// Read all bytes until EOF in this source, placing them into `buf`. @@ -198,7 +201,8 @@ pub trait Read { /// 2. Returns an error which is not of the kind `ErrorKind::Interrupted`. /// /// Until one of these conditions is met the function will continuously - /// invoke `read` to append more data to `buf`. + /// invoke `read` to append more data to `buf`. If successful, this function + /// will return the total number of bytes read. /// /// # Errors /// @@ -209,19 +213,24 @@ pub trait Read { /// If any other read error is encountered then this function immediately /// returns. Any bytes which have already been read will be appended to /// `buf`. - fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<()> { + #[stable(feature = "rust1", since = "1.0.0")] + fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> { read_to_end(self, buf) } /// Read all bytes until EOF in this source, placing them into `buf`. /// + /// If successful, this function returns the number of bytes which were read + /// and appended to `buf`. + /// /// # Errors /// /// If the data in this stream is *not* valid UTF-8 then an error is /// returned and `buf` is unchanged. /// /// See `read_to_end` for other error semantics. - fn read_to_string(&mut self, buf: &mut String) -> Result<()> { + #[stable(feature = "rust1", since = "1.0.0")] + fn read_to_string(&mut self, buf: &mut String) -> Result<usize> { // Note that we do *not* call `.read_to_end()` here. We are passing // `&mut Vec<u8>` (the raw contents of `buf`) into the `read_to_end` // method to fill it up. An arbitrary implementation could overwrite the @@ -233,18 +242,13 @@ pub trait Read { // know is guaranteed to only read data into the end of the buffer. append_to_string(buf, |b| read_to_end(self, b)) } -} -/// Extension methods for all instances of `Read`, typically imported through -/// `std::io::prelude::*`. -#[unstable(feature = "io", reason = "may merge into the Read trait")] -pub trait ReadExt: Read + Sized { /// Create a "by reference" adaptor for this instance of `Read`. /// /// The returned adaptor also implements `Read` and will simply borrow this /// current reader. #[stable(feature = "rust1", since = "1.0.0")] - fn by_ref(&mut self) -> &mut Self { self } + fn by_ref(&mut self) -> &mut Self where Self: Sized { self } /// Transform this `Read` instance to an `Iterator` over its bytes. /// @@ -253,7 +257,7 @@ pub trait ReadExt: Read + Sized { /// `Err` otherwise for I/O errors. EOF is mapped to returning `None` from /// this iterator. #[stable(feature = "rust1", since = "1.0.0")] - fn bytes(self) -> Bytes<Self> { + fn bytes(self) -> Bytes<Self> where Self: Sized { Bytes { inner: self } } @@ -270,7 +274,7 @@ pub trait ReadExt: Read + Sized { #[unstable(feature = "io", reason = "the semantics of a partial read/write \ of where errors happen is currently \ unclear and may change")] - fn chars(self) -> Chars<Self> { + fn chars(self) -> Chars<Self> where Self: Sized { Chars { inner: self } } @@ -280,7 +284,7 @@ pub trait ReadExt: Read + Sized { /// until EOF is encountered. Afterwards the output is equivalent to the /// output of `next`. #[stable(feature = "rust1", since = "1.0.0")] - fn chain<R: Read>(self, next: R) -> Chain<Self, R> { + fn chain<R: Read>(self, next: R) -> Chain<Self, R> where Self: Sized { Chain { first: self, second: next, done_first: false } } @@ -291,7 +295,7 @@ pub trait ReadExt: Read + Sized { /// read errors will not count towards the number of bytes read and future /// calls to `read` may succeed. #[stable(feature = "rust1", since = "1.0.0")] - fn take(self, limit: u64) -> Take<Self> { + fn take(self, limit: u64) -> Take<Self> where Self: Sized { Take { inner: self, limit: limit } } @@ -304,13 +308,11 @@ pub trait ReadExt: Read + Sized { #[unstable(feature = "io", reason = "the semantics of a partial read/write \ of where errors happen is currently \ unclear and may change")] - fn tee<W: Write>(self, out: W) -> Tee<Self, W> { + fn tee<W: Write>(self, out: W) -> Tee<Self, W> where Self: Sized { Tee { reader: self, writer: out } } } -impl<T: Read> ReadExt for T {} - /// A trait for objects which are byte-oriented sinks. /// /// The `write` method will attempt to write some data into the object, @@ -322,6 +324,7 @@ impl<T: Read> ReadExt for T {} /// Writers are intended to be composable with one another. Many objects /// throughout the I/O and related libraries take and provide types which /// implement the `Write` trait. +#[stable(feature = "rust1", since = "1.0.0")] pub trait Write { /// Write a buffer into this object, returning how many bytes were written. /// @@ -347,6 +350,7 @@ pub trait Write { /// /// It is **not** considered an error if the entire buffer could not be /// written to this writer. + #[stable(feature = "rust1", since = "1.0.0")] fn write(&mut self, buf: &[u8]) -> Result<usize>; /// Flush this output stream, ensuring that all intermediately buffered @@ -356,6 +360,7 @@ pub trait Write { /// /// It is considered an error if not all bytes could be written due to /// I/O errors or EOF being reached. + #[unstable(feature = "io", reason = "waiting for RFC 950")] fn flush(&mut self) -> Result<()>; /// Attempts to write an entire buffer into this write. @@ -368,6 +373,7 @@ pub trait Write { /// # Errors /// /// This function will return the first error that `write` returns. + #[stable(feature = "rust1", since = "1.0.0")] fn write_all(&mut self, mut buf: &[u8]) -> Result<()> { while buf.len() > 0 { match self.write(buf) { @@ -396,6 +402,7 @@ pub trait Write { /// # Errors /// /// This function will return any I/O error reported while formatting. + #[stable(feature = "rust1", since = "1.0.0")] fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()> { // Create a shim which translates a Write to a fmt::Write and saves // off I/O errors. instead of discarding them @@ -422,18 +429,13 @@ pub trait Write { Err(..) => output.error } } -} -/// Extension methods for all instances of `Write`, typically imported through -/// `std::io::prelude::*`. -#[unstable(feature = "io", reason = "may merge into the Read trait")] -pub trait WriteExt: Write + Sized { /// Create a "by reference" adaptor for this instance of `Write`. /// /// The returned adaptor also implements `Write` and will simply borrow this /// current writer. #[stable(feature = "rust1", since = "1.0.0")] - fn by_ref(&mut self) -> &mut Self { self } + fn by_ref(&mut self) -> &mut Self where Self: Sized { self } /// Creates a new writer which will write all data to both this writer and /// another writer. @@ -446,19 +448,21 @@ pub trait WriteExt: Write + Sized { #[unstable(feature = "io", reason = "the semantics of a partial read/write \ of where errors happen is currently \ unclear and may change")] - fn broadcast<W: Write>(self, other: W) -> Broadcast<Self, W> { + fn broadcast<W: Write>(self, other: W) -> Broadcast<Self, W> + where Self: Sized + { Broadcast { first: self, second: other } } } -#[stable(feature = "rust1", since = "1.0.0")] -impl<T: Write> WriteExt for T {} - /// An object implementing `Seek` internally has some form of cursor which can /// be moved within a stream of bytes. /// /// The stream typically has a fixed size, allowing seeking relative to either /// end or the current offset. +#[unstable(feature = "io", reason = "the central `seek` method may be split \ + into multiple methods instead of taking \ + an enum as an argument")] pub trait Seek { /// Seek to an offset, in bytes, in a stream /// @@ -479,6 +483,7 @@ pub trait Seek { /// Enumeration of possible methods to seek within an I/O object. #[derive(Copy, PartialEq, Eq, Clone, Debug)] +#[unstable(feature = "io", reason = "awaiting the stability of Seek")] pub enum SeekFrom { /// Set the offset to the provided number of bytes. Start(u64), @@ -499,7 +504,8 @@ pub enum SeekFrom { } fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) - -> Result<()> { + -> Result<usize> { + let mut read = 0; loop { let (done, used) = { let available = match r.fill_buf() { @@ -519,8 +525,9 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) } }; r.consume(used); + read += used; if done || used == 0 { - return Ok(()); + return Ok(read); } } } @@ -530,6 +537,7 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) /// /// This type extends the `Read` trait with a few methods that are not /// possible to reasonably implement with purely a read interface. +#[stable(feature = "rust1", since = "1.0.0")] pub trait BufRead: Read { /// Fills the internal buffer of this object, returning the buffer contents. /// @@ -546,10 +554,16 @@ pub trait BufRead: Read { /// /// This function will return an I/O error if the underlying reader was /// read, but returned an error. + #[stable(feature = "rust1", since = "1.0.0")] fn fill_buf(&mut self) -> Result<&[u8]>; /// Tells this buffer that `amt` bytes have been consumed from the buffer, /// so they should no longer be returned in calls to `read`. + /// + /// This function does not perform any I/O, it simply informs this object + /// that some amount of its buffer, returned from `fill_buf`, has been + /// consumed and should no longer be returned. + #[stable(feature = "rust1", since = "1.0.0")] fn consume(&mut self, amt: usize); /// Read all bytes until the delimiter `byte` is reached. @@ -560,7 +574,8 @@ pub trait BufRead: Read { /// `buf`. /// /// If this buffered reader is currently at EOF, then this function will not - /// place any more bytes into `buf` and will return `Ok(())`. + /// place any more bytes into `buf` and will return `Ok(n)` where `n` is the + /// number of bytes which were read. /// /// # Errors /// @@ -569,7 +584,8 @@ pub trait BufRead: Read { /// /// If an I/O error is encountered then all bytes read so far will be /// present in `buf` and its length will have been adjusted appropriately. - fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> Result<()> { + #[stable(feature = "rust1", since = "1.0.0")] + fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> Result<usize> { read_until(self, byte, buf) } @@ -581,7 +597,8 @@ pub trait BufRead: Read { /// found) will be appended to `buf`. /// /// If this reader is currently at EOF then this function will not modify - /// `buf` and will return `Ok(())`. + /// `buf` and will return `Ok(n)` where `n` is the number of bytes which + /// were read. /// /// # Errors /// @@ -589,17 +606,14 @@ pub trait BufRead: Read { /// return an error if the read bytes are not valid UTF-8. If an I/O error /// is encountered then `buf` may contain some bytes already read in the /// event that all data read so far was valid UTF-8. - fn read_line(&mut self, buf: &mut String) -> Result<()> { + #[stable(feature = "rust1", since = "1.0.0")] + fn read_line(&mut self, buf: &mut String) -> Result<usize> { // Note that we are not calling the `.read_until` method here, but // rather our hardcoded implementation. For more details as to why, see // the comments in `read_to_end`. append_to_string(buf, |b| read_until(self, b'\n', b)) } -} -/// Extension methods for all instances of `BufRead`, typically imported through -/// `std::io::prelude::*`. -pub trait BufReadExt: BufRead + Sized { /// Returns an iterator over the contents of this reader split on the byte /// `byte`. /// @@ -611,7 +625,7 @@ pub trait BufReadExt: BufRead + Sized { /// yielded an error. #[unstable(feature = "io", reason = "may be renamed to not conflict with \ SliceExt::split")] - fn split(self, byte: u8) -> Split<Self> { + fn split(self, byte: u8) -> Split<Self> where Self: Sized { Split { buf: self, delim: byte } } @@ -624,22 +638,21 @@ pub trait BufReadExt: BufRead + Sized { /// This function will yield errors whenever `read_string` would have also /// yielded an error. #[stable(feature = "rust1", since = "1.0.0")] - fn lines(self) -> Lines<Self> { + fn lines(self) -> Lines<Self> where Self: Sized { Lines { buf: self } } } -#[stable(feature = "rust1", since = "1.0.0")] -impl<T: BufRead> BufReadExt for T {} - /// A `Write` adaptor which will write data to multiple locations. /// /// For more information, see `WriteExt::broadcast`. +#[unstable(feature = "io", reason = "awaiting stability of WriteExt::broadcast")] pub struct Broadcast<T, U> { first: T, second: U, } +#[unstable(feature = "io", reason = "awaiting stability of WriteExt::broadcast")] impl<T: Write, U: Write> Write for Broadcast<T, U> { fn write(&mut self, data: &[u8]) -> Result<usize> { let n = try!(self.first.write(data)); @@ -732,11 +745,13 @@ impl<T: BufRead> BufRead for Take<T> { /// An adaptor which will emit all read data to a specified writer as well. /// /// For more information see `ReadExt::tee` +#[unstable(feature = "io", reason = "awaiting stability of ReadExt::tee")] pub struct Tee<R, W> { reader: R, writer: W, } +#[unstable(feature = "io", reason = "awaiting stability of ReadExt::tee")] impl<R: Read, W: Write> Read for Tee<R, W> { fn read(&mut self, buf: &mut [u8]) -> Result<usize> { let n = try!(self.reader.read(buf)); @@ -771,6 +786,7 @@ impl<R: Read> Iterator for Bytes<R> { /// A bridge from implementations of `Read` to an `Iterator` of `char`. /// /// See `ReadExt::chars` for more information. +#[unstable(feature = "io", reason = "awaiting stability of ReadExt::chars")] pub struct Chars<R> { inner: R, } @@ -778,6 +794,7 @@ pub struct Chars<R> { /// An enumeration of possible errors that can be generated from the `Chars` /// adapter. #[derive(PartialEq, Clone, Debug)] +#[unstable(feature = "io", reason = "awaiting stability of ReadExt::chars")] pub enum CharsError { /// Variant representing that the underlying stream was read successfully /// but it did not contain valid utf8 data. @@ -787,6 +804,7 @@ pub enum CharsError { Other(Error), } +#[unstable(feature = "io", reason = "awaiting stability of ReadExt::chars")] impl<R: Read> Iterator for Chars<R> { type Item = result::Result<char, CharsError>; @@ -818,14 +836,15 @@ impl<R: Read> Iterator for Chars<R> { } } -impl StdError for CharsError { +#[unstable(feature = "io", reason = "awaiting stability of ReadExt::chars")] +impl std_error::Error for CharsError { fn description(&self) -> &str { match *self { CharsError::NotUtf8 => "invalid utf8 encoding", - CharsError::Other(ref e) => e.description(), + CharsError::Other(ref e) => std_error::Error::description(e), } } - fn cause(&self) -> Option<&StdError> { + fn cause(&self) -> Option<&std_error::Error> { match *self { CharsError::NotUtf8 => None, CharsError::Other(ref e) => e.cause(), @@ -833,6 +852,7 @@ impl StdError for CharsError { } } +#[unstable(feature = "io", reason = "awaiting stability of ReadExt::chars")] impl fmt::Display for CharsError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -848,19 +868,21 @@ impl fmt::Display for CharsError { /// particular byte. /// /// See `BufReadExt::split` for more information. +#[unstable(feature = "io", reason = "awaiting stability of BufReadExt::split")] pub struct Split<B> { buf: B, delim: u8, } +#[unstable(feature = "io", reason = "awaiting stability of BufReadExt::split")] impl<B: BufRead> Iterator for Split<B> { type Item = Result<Vec<u8>>; fn next(&mut self) -> Option<Result<Vec<u8>>> { let mut buf = Vec::new(); match self.buf.read_until(self.delim, &mut buf) { - Ok(()) if buf.len() == 0 => None, - Ok(()) => { + Ok(0) => None, + Ok(_n) => { if buf[buf.len() - 1] == self.delim { buf.pop(); } @@ -887,8 +909,8 @@ impl<B: BufRead> Iterator for Lines<B> { fn next(&mut self) -> Option<Result<String>> { let mut buf = String::new(); match self.buf.read_line(&mut buf) { - Ok(()) if buf.len() == 0 => None, - Ok(()) => { + Ok(0) => None, + Ok(_n) => { if buf.ends_with("\n") { buf.pop(); } @@ -910,18 +932,18 @@ mod tests { fn read_until() { let mut buf = Cursor::new(b"12"); let mut v = Vec::new(); - assert_eq!(buf.read_until(b'3', &mut v), Ok(())); + assert_eq!(buf.read_until(b'3', &mut v), Ok(2)); assert_eq!(v, b"12"); let mut buf = Cursor::new(b"1233"); let mut v = Vec::new(); - assert_eq!(buf.read_until(b'3', &mut v), Ok(())); + assert_eq!(buf.read_until(b'3', &mut v), Ok(3)); assert_eq!(v, b"123"); v.truncate(0); - assert_eq!(buf.read_until(b'3', &mut v), Ok(())); + assert_eq!(buf.read_until(b'3', &mut v), Ok(1)); assert_eq!(v, b"3"); v.truncate(0); - assert_eq!(buf.read_until(b'3', &mut v), Ok(())); + assert_eq!(buf.read_until(b'3', &mut v), Ok(0)); assert_eq!(v, []); } @@ -943,18 +965,18 @@ mod tests { fn read_line() { let mut buf = Cursor::new(b"12"); let mut v = String::new(); - assert_eq!(buf.read_line(&mut v), Ok(())); + assert_eq!(buf.read_line(&mut v), Ok(2)); assert_eq!(v, "12"); let mut buf = Cursor::new(b"12\n\n"); let mut v = String::new(); - assert_eq!(buf.read_line(&mut v), Ok(())); + assert_eq!(buf.read_line(&mut v), Ok(3)); assert_eq!(v, "12\n"); v.truncate(0); - assert_eq!(buf.read_line(&mut v), Ok(())); + assert_eq!(buf.read_line(&mut v), Ok(1)); assert_eq!(v, "\n"); v.truncate(0); - assert_eq!(buf.read_line(&mut v), Ok(())); + assert_eq!(buf.read_line(&mut v), Ok(0)); assert_eq!(v, ""); } @@ -976,12 +998,12 @@ mod tests { fn read_to_end() { let mut c = Cursor::new(b""); let mut v = Vec::new(); - assert_eq!(c.read_to_end(&mut v), Ok(())); + assert_eq!(c.read_to_end(&mut v), Ok(0)); assert_eq!(v, []); let mut c = Cursor::new(b"1"); let mut v = Vec::new(); - assert_eq!(c.read_to_end(&mut v), Ok(())); + assert_eq!(c.read_to_end(&mut v), Ok(1)); assert_eq!(v, b"1"); } @@ -989,12 +1011,12 @@ mod tests { fn read_to_string() { let mut c = Cursor::new(b""); let mut v = String::new(); - assert_eq!(c.read_to_string(&mut v), Ok(())); + assert_eq!(c.read_to_string(&mut v), Ok(0)); assert_eq!(v, ""); let mut c = Cursor::new(b"1"); let mut v = String::new(); - assert_eq!(c.read_to_string(&mut v), Ok(())); + assert_eq!(c.read_to_string(&mut v), Ok(1)); assert_eq!(v, "1"); let mut c = Cursor::new(b"\xff"); diff --git a/src/libstd/io/prelude.rs b/src/libstd/io/prelude.rs index 637b1950985..6bf0ebd1a59 100644 --- a/src/libstd/io/prelude.rs +++ b/src/libstd/io/prelude.rs @@ -21,7 +21,9 @@ //! `Write`, `ReadExt`, and `WriteExt`. Structures and functions are not //! contained in this module. -pub use super::{Read, ReadExt, Write, WriteExt, BufRead, BufReadExt}; +#![stable(feature = "rust1", since = "1.0.0")] + +pub use super::{Read, Write, BufRead}; pub use fs::PathExt; // FIXME: pub use as `Seek` when the name isn't in the actual prelude any more diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 4027f741654..3b4e396953d 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -86,6 +86,7 @@ impl Write for StderrRaw { /// /// This handle implements the `Read` trait, but beware that concurrent reads /// of `Stdin` must be executed with care. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Stdin { inner: Arc<Mutex<BufReader<StdinRaw>>>, } @@ -94,6 +95,7 @@ pub struct Stdin { /// /// This handle implements both the `Read` and `BufRead` traits and is /// constructed via the `lock` method on `Stdin`. +#[stable(feature = "rust1", since = "1.0.0")] pub struct StdinLock<'a> { inner: MutexGuard<'a, BufReader<StdinRaw>>, } @@ -110,6 +112,7 @@ pub struct StdinLock<'a> { /// /// To avoid locking and buffering altogether, it is recommended to use the /// `stdin_raw` constructor. +#[stable(feature = "rust1", since = "1.0.0")] pub fn stdin() -> Stdin { static INSTANCE: Lazy<Mutex<BufReader<StdinRaw>>> = lazy_init!(stdin_init); return Stdin { @@ -136,30 +139,41 @@ impl Stdin { /// The lock is released when the returned lock goes out of scope. The /// returned guard also implements the `Read` and `BufRead` traits for /// accessing the underlying data. + #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StdinLock { StdinLock { inner: self.inner.lock().unwrap() } } + + /// Locks this handle and reads a line of input into the specified buffer. + /// + /// For detailed semantics of this method, see the documentation on + /// `BufRead::read_line`. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn read_line(&mut self, buf: &mut String) -> io::Result<usize> { + self.lock().read_line(buf) + } } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for Stdin { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.lock().read(buf) } - - fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<()> { + fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { self.lock().read_to_end(buf) } - - fn read_to_string(&mut self, buf: &mut String) -> io::Result<()> { + fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { self.lock().read_to_string(buf) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Read for StdinLock<'a> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.inner.read(buf) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> BufRead for StdinLock<'a> { fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() } fn consume(&mut self, n: usize) { self.inner.consume(n) } @@ -186,6 +200,7 @@ const OUT_MAX: usize = ::usize::MAX; /// Each handle shares a global buffer of data to be written to the standard /// output stream. Access is also synchronized via a lock and explicit control /// over locking is available via the `lock` method. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Stdout { // FIXME: this should be LineWriter or BufWriter depending on the state of // stdout (tty or not). Note that if this is not line buffered it @@ -197,6 +212,7 @@ pub struct Stdout { /// /// This handle implements the `Write` trait and is constructed via the `lock` /// method on `Stdout`. +#[stable(feature = "rust1", since = "1.0.0")] pub struct StdoutLock<'a> { inner: MutexGuard<'a, LineWriter<StdoutRaw>>, } @@ -211,6 +227,7 @@ pub struct StdoutLock<'a> { /// /// To avoid locking and buffering altogether, it is recommended to use the /// `stdout_raw` constructor. +#[stable(feature = "rust1", since = "1.0.0")] pub fn stdout() -> Stdout { static INSTANCE: Lazy<Mutex<LineWriter<StdoutRaw>>> = lazy_init!(stdout_init); return Stdout { @@ -228,11 +245,13 @@ impl Stdout { /// /// The lock is released when the returned lock goes out of scope. The /// returned guard also implements the `Write` trait for writing data. + #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StdoutLock { StdoutLock { inner: self.inner.lock().unwrap() } } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for Stdout { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.lock().write(buf) @@ -247,6 +266,7 @@ impl Write for Stdout { self.lock().write_fmt(fmt) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Write for StdoutLock<'a> { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.inner.write(&buf[..cmp::min(buf.len(), OUT_MAX)]) @@ -257,6 +277,7 @@ impl<'a> Write for StdoutLock<'a> { /// A handle to the standard error stream of a process. /// /// For more information, see `stderr` +#[stable(feature = "rust1", since = "1.0.0")] pub struct Stderr { inner: Arc<Mutex<StderrRaw>>, } @@ -265,6 +286,7 @@ pub struct Stderr { /// /// This handle implements the `Write` trait and is constructed via the `lock` /// method on `Stderr`. +#[stable(feature = "rust1", since = "1.0.0")] pub struct StderrLock<'a> { inner: MutexGuard<'a, StderrRaw>, } @@ -278,6 +300,7 @@ pub struct StderrLock<'a> { /// /// To avoid locking altogether, it is recommended to use the `stderr_raw` /// constructor. +#[stable(feature = "rust1", since = "1.0.0")] pub fn stderr() -> Stderr { static INSTANCE: Lazy<Mutex<StderrRaw>> = lazy_init!(stderr_init); return Stderr { @@ -295,11 +318,13 @@ impl Stderr { /// /// The lock is released when the returned lock goes out of scope. The /// returned guard also implements the `Write` trait for writing data. + #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StderrLock { StderrLock { inner: self.inner.lock().unwrap() } } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for Stderr { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.lock().write(buf) @@ -314,9 +339,33 @@ impl Write for Stderr { self.lock().write_fmt(fmt) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Write for StderrLock<'a> { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.inner.write(&buf[..cmp::min(buf.len(), OUT_MAX)]) } fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } + +/// Resets the task-local stdout handle to the specified writer +/// +/// This will replace the current task's stdout handle, returning the old +/// handle. All future calls to `print` and friends will emit their output to +/// this specified handle. +/// +/// Note that this does not need to be called for all new tasks; the default +/// output handle is to the process's stdout stream. +#[unstable(feature = "set_panic", + reason = "this function may disappear completely or be replaced \ + with a more general mechanism")] +#[doc(hidden)] +pub fn set_panic(sink: Box<Write + Send>) -> Option<Box<Write + Send>> { + use panicking::LOCAL_STDERR; + use mem; + LOCAL_STDERR.with(move |slot| { + mem::replace(&mut *slot.borrow_mut(), Some(sink)) + }).and_then(|mut s| { + let _ = s.flush(); + Some(s) + }) +} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index a05d6752073..81e2113cfdf 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -298,6 +298,7 @@ mod std { pub use sync; // used for select!() pub use error; // used for try!() pub use fmt; // used for any formatting strings + #[allow(deprecated)] pub use old_io; // used for println!() pub use option; // used for bitflags!{} pub use rt; // used for panic!() diff --git a/src/libstd/old_io/mod.rs b/src/libstd/old_io/mod.rs index f71698fa725..9d438978f42 100644 --- a/src/libstd/old_io/mod.rs +++ b/src/libstd/old_io/mod.rs @@ -242,6 +242,9 @@ #![deny(unused_must_use)] #![allow(deprecated)] // seriously this is all deprecated #![allow(unused_imports)] +#![deprecated(since = "1.0.0", + reasons = "APIs have been replaced with new I/O modules such as \ + std::{io, fs, net, process}")] pub use self::SeekStyle::*; pub use self::FileMode::*; diff --git a/src/libstd/old_io/stdio.rs b/src/libstd/old_io/stdio.rs index 70e8a4ceff0..34b4ec94a44 100644 --- a/src/libstd/old_io/stdio.rs +++ b/src/libstd/old_io/stdio.rs @@ -31,10 +31,9 @@ use boxed; use boxed::Box; use cell::RefCell; use clone::Clone; -use panicking::LOCAL_STDERR; use fmt; use old_io::{Reader, Writer, IoResult, IoError, OtherIoError, Buffer, - standard_error, EndOfFile, LineBufferedWriter, BufferedReader}; + standard_error, EndOfFile, LineBufferedWriter, BufferedReader}; use marker::{Sync, Send}; use libc; use mem; @@ -319,14 +318,10 @@ pub fn set_stdout(stdout: Box<Writer + Send>) -> Option<Box<Writer + Send>> { /// /// Note that this does not need to be called for all new tasks; the default /// output handle is to the process's stderr stream. -pub fn set_stderr(stderr: Box<Writer + Send>) -> Option<Box<Writer + Send>> { - let mut new = Some(stderr); - LOCAL_STDERR.with(|slot| { - mem::replace(&mut *slot.borrow_mut(), new.take()) - }).and_then(|mut s| { - let _ = s.flush(); - Some(s) - }) +#[unstable(feature = "old_io")] +#[deprecated(since = "1.0.0", reason = "replaced with std::io::set_panic")] +pub fn set_stderr(_stderr: Box<Writer + Send>) -> Option<Box<Writer + Send>> { + None } // Helper to access the local task's stdout handle @@ -554,19 +549,4 @@ mod tests { }); assert_eq!(r.read_to_string().unwrap(), "hello!\n"); } - - #[test] - fn capture_stderr() { - use old_io::{ChanReader, ChanWriter, Reader}; - - let (tx, rx) = channel(); - let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx)); - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. - let _t = thread::spawn(move || -> () { - set_stderr(Box::new(w)); - panic!("my special message"); - }); - let s = r.read_to_string().unwrap(); - assert!(s.contains("my special message")); - } } diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 53882c7b833..866f7caffe8 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -25,6 +25,7 @@ //! OS-ignorant code by default. #![unstable(feature = "os")] +#![deprecated(since = "1.0.0", reason = "replaced with std::env APIs")] #![allow(missing_docs)] #![allow(non_snake_case)] diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 2e05f6d974e..3e0584d9ab4 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -11,29 +11,22 @@ #![unstable(feature = "std_misc")] use prelude::v1::*; +use io::prelude::*; use any::Any; use cell::RefCell; -use old_io::IoResult; use rt::{backtrace, unwind}; -use rt::util::{Stderr, Stdio}; +use sys::stdio::Stderr; use thread; // Defined in this module instead of old_io::stdio so that the unwinding thread_local! { - pub static LOCAL_STDERR: RefCell<Option<Box<Writer + Send>>> = { + pub static LOCAL_STDERR: RefCell<Option<Box<Write + Send>>> = { RefCell::new(None) } } -impl Writer for Stdio { - fn write_all(&mut self, bytes: &[u8]) -> IoResult<()> { - let _ = self.write_bytes(bytes); - Ok(()) - } -} - -pub fn on_panic(obj: &(Any+Send), file: &'static str, line: uint) { +pub fn on_panic(obj: &(Any+Send), file: &'static str, line: usize) { let msg = match obj.downcast_ref::<&'static str>() { Some(s) => *s, None => match obj.downcast_ref::<String>() { @@ -41,7 +34,7 @@ pub fn on_panic(obj: &(Any+Send), file: &'static str, line: uint) { None => "Box<Any>", } }; - let mut err = Stderr; + let mut err = Stderr::new(); let thread = thread::current(); let name = thread.name().unwrap_or("<unnamed>"); let prev = LOCAL_STDERR.with(|s| s.borrow_mut().take()); diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index dc557403153..e72fd7b3320 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -11,16 +11,14 @@ // ignore-lexer-test FIXME #15677 use prelude::v1::*; +use io::prelude::*; -use cmp; use env; use fmt; use intrinsics; -use libc::{self, uintptr_t}; -use os; -use slice; -use str; +use libc::uintptr_t; use sync::atomic::{self, Ordering}; +use sys::stdio::Stderr; /// Dynamically inquire about whether we're running under V. /// You should usually not use this unless your test definitely @@ -62,7 +60,9 @@ pub fn min_stack() -> uint { /// Get's the number of scheduler threads requested by the environment /// either `RUST_THREADS` or `num_cpus`. +#[allow(deprecated)] pub fn default_sched_threads() -> uint { + use os; match env::var("RUST_THREADS") { Ok(nstr) => { let opt_n: Option<uint> = nstr.parse().ok(); @@ -88,76 +88,17 @@ pub fn default_sched_threads() -> uint { pub const ENFORCE_SANITY: bool = true || !cfg!(rtopt) || cfg!(rtdebug) || cfg!(rtassert); -pub struct Stdio(libc::c_int); - -#[allow(non_upper_case_globals)] -pub const Stdout: Stdio = Stdio(libc::STDOUT_FILENO); -#[allow(non_upper_case_globals)] -pub const Stderr: Stdio = Stdio(libc::STDERR_FILENO); - -impl Stdio { - pub fn write_bytes(&mut self, data: &[u8]) { - #[cfg(unix)] - type WriteLen = libc::size_t; - #[cfg(windows)] - type WriteLen = libc::c_uint; - unsafe { - let Stdio(fd) = *self; - libc::write(fd, - data.as_ptr() as *const libc::c_void, - data.len() as WriteLen); - } - } -} - -impl fmt::Write for Stdio { - fn write_str(&mut self, data: &str) -> fmt::Result { - self.write_bytes(data.as_bytes()); - Ok(()) // yes, we're lying - } -} - pub fn dumb_print(args: fmt::Arguments) { - let _ = Stderr.write_fmt(args); + let _ = write!(&mut Stderr::new(), "{}", args); } pub fn abort(args: fmt::Arguments) -> ! { - use fmt::Write; - - struct BufWriter<'a> { - buf: &'a mut [u8], - pos: uint, - } - impl<'a> fmt::Write for BufWriter<'a> { - fn write_str(&mut self, bytes: &str) -> fmt::Result { - let left = &mut self.buf[self.pos..]; - let to_write = &bytes.as_bytes()[..cmp::min(bytes.len(), left.len())]; - slice::bytes::copy_memory(left, to_write); - self.pos += to_write.len(); - Ok(()) - } - } - - // Convert the arguments into a stack-allocated string - let mut msg = [0; 512]; - let mut w = BufWriter { buf: &mut msg, pos: 0 }; - let _ = write!(&mut w, "{}", args); - let msg = str::from_utf8(&w.buf[..w.pos]).unwrap_or("aborted"); - let msg = if msg.is_empty() {"aborted"} else {msg}; - rterrln!("fatal runtime error: {}", msg); + rterrln!("fatal runtime error: {}", args); unsafe { intrinsics::abort(); } } pub unsafe fn report_overflow() { use thread; - - // See the message below for why this is not emitted to the - // ^ Where did the message below go? - // task's logger. This has the additional conundrum of the - // logger may not be initialized just yet, meaning that an FFI - // call would happen to initialized it (calling out to libuv), - // and the FFI call needs 2MB of stack when we just ran out. - rterrln!("\nthread '{}' has overflowed its stack", thread::current().name().unwrap_or("<unknown>")); } diff --git a/src/libstd/sys/common/backtrace.rs b/src/libstd/sys/common/backtrace.rs index 50a9f204799..c42a755b444 100644 --- a/src/libstd/sys/common/backtrace.rs +++ b/src/libstd/sys/common/backtrace.rs @@ -9,8 +9,9 @@ // except according to those terms. use prelude::v1::*; +use io::prelude::*; -use old_io::IoResult; +use io; #[cfg(target_pointer_width = "64")] pub const HEX_WIDTH: uint = 18; @@ -35,7 +36,7 @@ pub const HEX_WIDTH: uint = 10; // Note that this demangler isn't quite as fancy as it could be. We have lots // of other information in our symbols like hashes, version, type information, // etc. Additionally, this doesn't handle glue symbols at all. -pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { +pub fn demangle(writer: &mut Write, s: &str) -> io::Result<()> { // First validate the symbol. If it doesn't look like anything we're // expecting, we just print it literally. Note that we must handle non-rust // symbols because we could have any function in the backtrace. @@ -72,12 +73,12 @@ pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { // Alright, let's do this. if !valid { - try!(writer.write_str(s)); + try!(writer.write_all(s.as_bytes())); } else { let mut first = true; while inner.len() > 0 { if !first { - try!(writer.write_str("::")); + try!(writer.write_all(b"::")); } else { first = false; } @@ -93,11 +94,11 @@ pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { macro_rules! demangle { ($($pat:expr, => $demangled:expr),*) => ({ $(if rest.starts_with($pat) { - try!(writer.write_str($demangled)); + try!(writer.write_all($demangled)); rest = &rest[$pat.len()..]; } else)* { - try!(writer.write_str(rest)); + try!(writer.write_all(rest.as_bytes())); break; } @@ -106,29 +107,29 @@ pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { // see src/librustc/back/link.rs for these mappings demangle! ( - "$SP$", => "@", - "$BP$", => "*", - "$RF$", => "&", - "$LT$", => "<", - "$GT$", => ">", - "$LP$", => "(", - "$RP$", => ")", - "$C$", => ",", + "$SP$", => b"@", + "$BP$", => b"*", + "$RF$", => b"&", + "$LT$", => b"<", + "$GT$", => b">", + "$LP$", => b"(", + "$RP$", => b")", + "$C$", => b",", // in theory we can demangle any Unicode code point, but // for simplicity we just catch the common ones. - "$u7e$", => "~", - "$u20$", => " ", - "$u27$", => "'", - "$u5b$", => "[", - "$u5d$", => "]" + "$u7e$", => b"~", + "$u20$", => b" ", + "$u27$", => b"'", + "$u5b$", => b"[", + "$u5d$", => b"]" ) } else { let idx = match rest.find('$') { None => rest.len(), Some(i) => i, }; - try!(writer.write_str(&rest[..idx])); + try!(writer.write_all(rest[..idx].as_bytes())); rest = &rest[idx..]; } } diff --git a/src/libstd/sys/common/mod.rs b/src/libstd/sys/common/mod.rs index 9a89b290980..29c05b1e0d8 100644 --- a/src/libstd/sys/common/mod.rs +++ b/src/libstd/sys/common/mod.rs @@ -37,6 +37,7 @@ pub mod wtf8; // common error constructors +#[allow(deprecated)] pub fn eof() -> IoError { IoError { kind: old_io::EndOfFile, @@ -45,6 +46,7 @@ pub fn eof() -> IoError { } } +#[allow(deprecated)] pub fn timeout(desc: &'static str) -> IoError { IoError { kind: old_io::TimedOut, @@ -53,6 +55,7 @@ pub fn timeout(desc: &'static str) -> IoError { } } +#[allow(deprecated)] pub fn short_write(n: uint, desc: &'static str) -> IoError { IoError { kind: if n == 0 { old_io::TimedOut } else { old_io::ShortWrite(n) }, @@ -61,6 +64,7 @@ pub fn short_write(n: uint, desc: &'static str) -> IoError { } } +#[allow(deprecated)] pub fn unimpl() -> IoError { IoError { kind: old_io::IoUnavailable, @@ -70,6 +74,7 @@ pub fn unimpl() -> IoError { } // unix has nonzero values as errors +#[allow(deprecated)] pub fn mkerr_libc<T: Int>(ret: T) -> IoResult<()> { if ret != Int::zero() { Err(last_error()) diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs index 24d709e9928..3fa9f5d07aa 100644 --- a/src/libstd/sys/unix/backtrace.rs +++ b/src/libstd/sys/unix/backtrace.rs @@ -84,9 +84,10 @@ /// all unix platforms we support right now, so it at least gets the job done. use prelude::v1::*; +use io::prelude::*; use ffi::CStr; -use old_io::IoResult; +use io; use libc; use mem; use str; @@ -105,7 +106,7 @@ use sys_common::backtrace::*; /// only viable option. #[cfg(all(target_os = "ios", target_arch = "arm"))] #[inline(never)] -pub fn write(w: &mut Writer) -> IoResult<()> { +pub fn write(w: &mut Write) -> io::Result<()> { use result; extern { @@ -135,13 +136,11 @@ pub fn write(w: &mut Writer) -> IoResult<()> { #[cfg(not(all(target_os = "ios", target_arch = "arm")))] #[inline(never)] // if we know this is a function call, we can skip it when // tracing -pub fn write(w: &mut Writer) -> IoResult<()> { - use old_io::IoError; - +pub fn write(w: &mut Write) -> io::Result<()> { struct Context<'a> { idx: int, - writer: &'a mut (Writer+'a), - last_error: Option<IoError>, + writer: &'a mut (Write+'a), + last_error: Option<io::Error>, } // When using libbacktrace, we use some necessary global state, so we @@ -223,8 +222,8 @@ pub fn write(w: &mut Writer) -> IoResult<()> { } #[cfg(any(target_os = "macos", target_os = "ios"))] -fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void, - _symaddr: *mut libc::c_void) -> IoResult<()> { +fn print(w: &mut Write, idx: int, addr: *mut libc::c_void, + _symaddr: *mut libc::c_void) -> io::Result<()> { use intrinsics; #[repr(C)] struct Dl_info { @@ -249,8 +248,8 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void, } #[cfg(not(any(target_os = "macos", target_os = "ios")))] -fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void, - symaddr: *mut libc::c_void) -> IoResult<()> { +fn print(w: &mut Write, idx: int, addr: *mut libc::c_void, + symaddr: *mut libc::c_void) -> io::Result<()> { use env; use ffi::AsOsStr; use os::unix::prelude::*; @@ -442,8 +441,8 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void, } // Finally, after all that work above, we can emit a symbol. -fn output(w: &mut Writer, idx: int, addr: *mut libc::c_void, - s: Option<&[u8]>) -> IoResult<()> { +fn output(w: &mut Write, idx: int, addr: *mut libc::c_void, + s: Option<&[u8]>) -> io::Result<()> { try!(write!(w, " {:2}: {:2$?} - ", idx, addr, HEX_WIDTH)); match s.and_then(|s| str::from_utf8(s).ok()) { Some(string) => try!(demangle(w, string)), @@ -453,8 +452,8 @@ fn output(w: &mut Writer, idx: int, addr: *mut libc::c_void, } #[allow(dead_code)] -fn output_fileline(w: &mut Writer, file: &[u8], line: libc::c_int, - more: bool) -> IoResult<()> { +fn output_fileline(w: &mut Write, file: &[u8], line: libc::c_int, + more: bool) -> io::Result<()> { let file = str::from_utf8(file).ok().unwrap_or("<unknown>"); // prior line: " ##: {:2$} - func" try!(write!(w, " {:3$}at {}:{}", "", file, line, HEX_WIDTH)); diff --git a/src/libstd/sys/unix/ext.rs b/src/libstd/sys/unix/ext.rs index ca7f7c4c0ca..3dd05319194 100644 --- a/src/libstd/sys/unix/ext.rs +++ b/src/libstd/sys/unix/ext.rs @@ -43,7 +43,7 @@ use sys::os_str::Buf; use sys_common::{AsInner, AsInnerMut, IntoInner, FromInner}; use libc::{self, gid_t, uid_t}; -use old_io; +#[allow(deprecated)] use old_io; /// Raw file descriptors. pub type Fd = libc::c_int; @@ -67,6 +67,7 @@ impl AsRawFd for fs::File { } } +#[allow(deprecated)] impl AsRawFd for old_io::pipe::PipeStream { fn as_raw_fd(&self) -> Fd { self.as_inner().fd() diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index f23619955e2..c839ce65298 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -9,6 +9,7 @@ // except according to those terms. //! Blocking posix-based file I/O +#![allow(deprecated)] #![allow(deprecated)] // this module itself is essentially deprecated diff --git a/src/libstd/sys/unix/helper_signal.rs b/src/libstd/sys/unix/helper_signal.rs index ed9bd0a239f..ff29dea254f 100644 --- a/src/libstd/sys/unix/helper_signal.rs +++ b/src/libstd/sys/unix/helper_signal.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(deprecated)] + use libc; use os; diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 865ea987279..a8cee74828d 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -60,10 +60,12 @@ pub type wrlen = libc::size_t; pub type msglen_t = libc::size_t; pub unsafe fn close_sock(sock: sock_t) { let _ = libc::close(sock); } +#[allow(deprecated)] pub fn last_error() -> IoError { decode_error_detailed(os::errno() as i32) } +#[allow(deprecated)] pub fn last_net_error() -> IoError { last_error() } @@ -72,6 +74,7 @@ extern "system" { fn gai_strerror(errcode: libc::c_int) -> *const libc::c_char; } +#[allow(deprecated)] pub fn last_gai_error(s: libc::c_int) -> IoError { let mut err = decode_error(s); @@ -83,6 +86,7 @@ pub fn last_gai_error(s: libc::c_int) -> IoError { } /// Convert an `errno` value into a high-level error variant and description. +#[allow(deprecated)] pub fn decode_error(errno: i32) -> IoError { // FIXME: this should probably be a bit more descriptive... let (kind, desc) = match errno { @@ -119,12 +123,14 @@ pub fn decode_error(errno: i32) -> IoError { IoError { kind: kind, desc: desc, detail: None } } +#[allow(deprecated)] pub fn decode_error_detailed(errno: i32) -> IoError { let mut err = decode_error(errno); err.detail = Some(os::error_string(errno)); err } +#[allow(deprecated)] pub fn decode_error_kind(errno: i32) -> ErrorKind { match errno as libc::c_int { libc::ECONNREFUSED => ErrorKind::ConnectionRefused, @@ -155,6 +161,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { } #[inline] +#[allow(deprecated)] pub fn retry<T, F> (mut f: F) -> T where T: SignedInt, F: FnMut() -> T, @@ -194,11 +201,13 @@ pub fn ms_to_timeval(ms: u64) -> libc::timeval { } } +#[allow(deprecated)] pub fn wouldblock() -> bool { let err = os::errno(); err == libc::EWOULDBLOCK as i32 || err == libc::EAGAIN as i32 } +#[allow(deprecated)] pub fn set_nonblocking(fd: sock_t, nb: bool) { let set = nb as libc::c_int; mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) })).unwrap(); diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 3266da5eb31..d332556d188 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -22,7 +22,7 @@ use io; use iter; use libc::{self, c_int, c_char, c_void}; use mem; -use old_io::{IoError, IoResult}; +#[allow(deprecated)] use old_io::{IoError, IoResult}; use ptr; use path::{self, PathBuf}; use slice; @@ -398,7 +398,7 @@ pub fn env() -> Env { let mut environ = *environ(); if environ as usize == 0 { panic!("os::env() failure getting env string from OS: {}", - IoError::last_error()); + io::Error::last_os_error()); } let mut result = Vec::new(); while *environ != ptr::null() { @@ -434,7 +434,7 @@ pub fn setenv(k: &OsStr, v: &OsStr) { let k = k.to_cstring().unwrap(); let v = v.to_cstring().unwrap(); if libc::funcs::posix01::unistd::setenv(k.as_ptr(), v.as_ptr(), 1) != 0 { - panic!("failed setenv: {}", IoError::last_error()); + panic!("failed setenv: {}", io::Error::last_os_error()); } } } @@ -443,11 +443,12 @@ pub fn unsetenv(n: &OsStr) { unsafe { let nbuf = n.to_cstring().unwrap(); if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 { - panic!("failed unsetenv: {}", IoError::last_error()); + panic!("failed unsetenv: {}", io::Error::last_os_error()); } } } +#[allow(deprecated)] pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> { let mut fds = [0; 2]; if libc::pipe(fds.as_mut_ptr()) == 0 { diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index 9cddfca69cb..daa981720f6 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(deprecated)] + use prelude::v1::*; use ffi::CString; diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs index 2f9610fa5b5..5f5101e96d7 100644 --- a/src/libstd/sys/unix/stdio.rs +++ b/src/libstd/sys/unix/stdio.rs @@ -50,3 +50,13 @@ impl Stderr { return ret; } } + +// FIXME: right now this raw stderr handle is used in a few places because +// std::io::stderr_raw isn't exposed, but once that's exposed this impl +// should go away +impl io::Write for Stderr { + fn write(&mut self, data: &[u8]) -> io::Result<usize> { + Stderr::write(self, data) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} diff --git a/src/libstd/sys/unix/timer.rs b/src/libstd/sys/unix/timer.rs index ce9748ede85..ef0274fdda9 100644 --- a/src/libstd/sys/unix/timer.rs +++ b/src/libstd/sys/unix/timer.rs @@ -46,6 +46,8 @@ //! //! Note that all time units in this file are in *milliseconds*. +#![allow(deprecated)] + use prelude::v1::*; use self::Req::*; diff --git a/src/libstd/sys/unix/tty.rs b/src/libstd/sys/unix/tty.rs index 1d74b36a625..f607f7c6a2f 100644 --- a/src/libstd/sys/unix/tty.rs +++ b/src/libstd/sys/unix/tty.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(deprecated)] + use prelude::v1::*; use sys::fs::FileDesc; diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs index b464ba70911..8638099ca69 100644 --- a/src/libstd/sys/windows/backtrace.rs +++ b/src/libstd/sys/windows/backtrace.rs @@ -28,9 +28,10 @@ use prelude::v1::*; use dynamic_lib::DynamicLibrary; +use io; +use io::prelude::*; use ffi::CStr; use intrinsics; -use old_io::IoResult; use libc; use mem; use ptr; @@ -292,7 +293,7 @@ impl Drop for Cleanup { fn drop(&mut self) { (self.SymCleanup)(self.handle); } } -pub fn write(w: &mut Writer) -> IoResult<()> { +pub fn write(w: &mut Write) -> io::Result<()> { // According to windows documentation, all dbghelp functions are // single-threaded. static LOCK: StaticMutex = MUTEX_INIT; diff --git a/src/libstd/sys/windows/condvar.rs b/src/libstd/sys/windows/condvar.rs index 071637e3a93..67552255fdb 100644 --- a/src/libstd/sys/windows/condvar.rs +++ b/src/libstd/sys/windows/condvar.rs @@ -12,7 +12,7 @@ use prelude::v1::*; use cell::UnsafeCell; use libc::{self, DWORD}; -use os; +use sys::os; use sys::mutex::{self, Mutex}; use sys::sync as ffi; use time::Duration; @@ -46,7 +46,7 @@ impl Condvar { 0); if r == 0 { const ERROR_TIMEOUT: DWORD = 0x5B4; - debug_assert_eq!(os::errno() as uint, ERROR_TIMEOUT as uint); + debug_assert_eq!(os::errno() as usize, ERROR_TIMEOUT as usize); false } else { true diff --git a/src/libstd/sys/windows/ext.rs b/src/libstd/sys/windows/ext.rs index 1d63da813c9..dc820a4ce45 100644 --- a/src/libstd/sys/windows/ext.rs +++ b/src/libstd/sys/windows/ext.rs @@ -25,6 +25,7 @@ use net; use sys::os_str::Buf; use sys_common::{AsInner, FromInner, AsInnerMut}; +#[allow(deprecated)] use old_io; /// Raw HANDLEs. @@ -52,6 +53,7 @@ impl AsRawHandle for fs::File { } } +#[allow(deprecated)] impl AsRawHandle for old_io::pipe::PipeStream { fn as_raw_handle(&self) -> Handle { self.as_inner().handle() diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 46085826e60..6b0f6a78c85 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -64,6 +64,7 @@ pub type msglen_t = libc::c_int; pub unsafe fn close_sock(sock: sock_t) { let _ = libc::closesocket(sock); } // windows has zero values as errors +#[allow(deprecated)] fn mkerr_winbool(ret: libc::c_int) -> IoResult<()> { if ret == 0 { Err(last_error()) @@ -72,6 +73,7 @@ fn mkerr_winbool(ret: libc::c_int) -> IoResult<()> { } } +#[allow(deprecated)] pub fn last_error() -> IoError { let errno = os::errno() as i32; let mut err = decode_error(errno); @@ -79,6 +81,7 @@ pub fn last_error() -> IoError { err } +#[allow(deprecated)] pub fn last_net_error() -> IoError { let errno = unsafe { c::WSAGetLastError() as i32 }; let mut err = decode_error(errno); @@ -86,11 +89,13 @@ pub fn last_net_error() -> IoError { err } +#[allow(deprecated)] pub fn last_gai_error(_errno: i32) -> IoError { last_net_error() } /// Convert an `errno` value into a high-level error variant and description. +#[allow(deprecated)] pub fn decode_error(errno: i32) -> IoError { let (kind, desc) = match errno { libc::EOF => (old_io::EndOfFile, "end of file"), @@ -134,6 +139,7 @@ pub fn decode_error(errno: i32) -> IoError { IoError { kind: kind, desc: desc, detail: None } } +#[allow(deprecated)] pub fn decode_error_detailed(errno: i32) -> IoError { let mut err = decode_error(errno); err.detail = Some(os::error_string(errno)); @@ -178,11 +184,13 @@ pub fn ms_to_timeval(ms: u64) -> libc::timeval { } } +#[allow(deprecated)] pub fn wouldblock() -> bool { let err = os::errno(); err == libc::WSAEWOULDBLOCK as i32 } +#[allow(deprecated)] pub fn set_nonblocking(fd: sock_t, nb: bool) { let mut set = nb as libc::c_ulong; if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) } != 0 { @@ -205,6 +213,7 @@ pub fn init_net() { } } +#[allow(deprecated)] pub fn to_utf16(s: Option<&str>) -> IoResult<Vec<u16>> { match s { Some(s) => Ok(to_utf16_os(OsStr::from_str(s))), @@ -283,6 +292,7 @@ fn fill_utf16_buf_base<F1, F2, T>(mut f1: F1, f2: F2) -> Result<T, ()> } } +#[allow(deprecated)] fn fill_utf16_buf<F1, F2, T>(f1: F1, f2: F2) -> IoResult<T> where F1: FnMut(*mut u16, libc::DWORD) -> libc::DWORD, F2: FnOnce(&[u16]) -> T diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index 89cf8a08a68..ecd538abfb4 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -22,6 +22,7 @@ use io; use libc::types::os::arch::extra::LPWCH; use libc::{self, c_int, c_void}; use mem; +#[allow(deprecated)] use old_io::{IoError, IoResult}; use ops::Range; use path::{self, PathBuf}; @@ -134,7 +135,7 @@ pub fn env() -> Env { let ch = GetEnvironmentStringsW(); if ch as usize == 0 { panic!("failure getting env string from OS: {}", - IoError::last_error()); + io::Error::last_os_error()); } Env { base: ch, cur: ch } } @@ -269,7 +270,7 @@ pub fn setenv(k: &OsStr, v: &OsStr) { unsafe { if libc::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr()) == 0 { - panic!("failed to set env: {}", IoError::last_error()); + panic!("failed to set env: {}", io::Error::last_os_error()); } } } @@ -278,7 +279,7 @@ pub fn unsetenv(n: &OsStr) { let v = super::to_utf16_os(n); unsafe { if libc::SetEnvironmentVariableW(v.as_ptr(), ptr::null()) == 0 { - panic!("failed to unset env: {}", IoError::last_error()); + panic!("failed to unset env: {}", io::Error::last_os_error()); } } } @@ -333,6 +334,7 @@ pub fn page_size() -> usize { } } +#[allow(deprecated)] pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> { // Windows pipes work subtly differently than unix pipes, and their // inheritance has to be handled in a different way that I do not diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs index 1f228b7d32e..2b03e9e7431 100644 --- a/src/libstd/sys/windows/pipe.rs +++ b/src/libstd/sys/windows/pipe.rs @@ -84,6 +84,8 @@ //! the test suite passing (the suite is in libstd), and that's good enough for //! me! +#![allow(deprecated)] + use prelude::v1::*; use libc; diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index 72ce8b7c6e3..d1bff0e135d 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -135,6 +135,16 @@ impl Stderr { } } +// FIXME: right now this raw stderr handle is used in a few places because +// std::io::stderr_raw isn't exposed, but once that's exposed this impl +// should go away +impl io::Write for Stderr { + fn write(&mut self, data: &[u8]) -> io::Result<usize> { + Stderr::write(self, data) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} + impl NoClose { fn new(handle: libc::HANDLE) -> NoClose { NoClose(Some(Handle::new(handle))) diff --git a/src/libstd/sys/windows/timer.rs b/src/libstd/sys/windows/timer.rs index a23a90a9cf8..91a7f694181 100644 --- a/src/libstd/sys/windows/timer.rs +++ b/src/libstd/sys/windows/timer.rs @@ -20,6 +20,8 @@ //! Other than that, the implementation is pretty straightforward in terms of //! the other two implementations of timers with nothing *that* new showing up. +#![allow(deprecated)] + use prelude::v1::*; use self::Req::*; diff --git a/src/libstd/sys/windows/tty.rs b/src/libstd/sys/windows/tty.rs index 37dce423a68..f542cb2323e 100644 --- a/src/libstd/sys/windows/tty.rs +++ b/src/libstd/sys/windows/tty.rs @@ -25,6 +25,8 @@ //! wrapper that performs encoding/decoding, this implementation should switch //! to working in raw UTF-16, with such a wrapper around it. +#![allow(deprecated)] + use prelude::v1::*; use old_io::{self, IoError, IoResult, MemReader}; diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs index 5c5f9f75fd9..adc3b77407a 100644 --- a/src/libstd/thread.rs +++ b/src/libstd/thread.rs @@ -148,7 +148,6 @@ use cell::UnsafeCell; use fmt; use io; use marker::PhantomData; -use old_io::stdio; use rt::{self, unwind}; use sync::{Mutex, Condvar, Arc}; use thunk::Thunk; @@ -165,10 +164,6 @@ pub struct Builder { name: Option<String>, // The size of the stack for the spawned thread stack_size: Option<usize>, - // Thread-local stdout - stdout: Option<Box<Writer + Send + 'static>>, - // Thread-local stderr - stderr: Option<Box<Writer + Send + 'static>>, } impl Builder { @@ -179,8 +174,6 @@ impl Builder { Builder { name: None, stack_size: None, - stdout: None, - stderr: None, } } @@ -202,16 +195,22 @@ impl Builder { /// Redirect thread-local stdout. #[unstable(feature = "std_misc", reason = "Will likely go away after proc removal")] - pub fn stdout(mut self, stdout: Box<Writer + Send + 'static>) -> Builder { - self.stdout = Some(stdout); + #[deprecated(since = "1.0.0", + reason = "the old I/O module is deprecated and this function \ + will be removed with no replacement")] + #[allow(deprecated)] + pub fn stdout(self, _stdout: Box<Writer + Send + 'static>) -> Builder { self } /// Redirect thread-local stderr. #[unstable(feature = "std_misc", reason = "Will likely go away after proc removal")] - pub fn stderr(mut self, stderr: Box<Writer + Send + 'static>) -> Builder { - self.stderr = Some(stderr); + #[deprecated(since = "1.0.0", + reason = "the old I/O module is deprecated and this function \ + will be removed with no replacement")] + #[allow(deprecated)] + pub fn stderr(self, _stderr: Box<Writer + Send + 'static>) -> Builder { self } @@ -259,7 +258,7 @@ impl Builder { } fn spawn_inner<T: Send>(self, f: Thunk<(), T>) -> io::Result<JoinInner<T>> { - let Builder { name, stack_size, stdout, stderr } = self; + let Builder { name, stack_size } = self; let stack_size = stack_size.unwrap_or(rt::min_stack()); @@ -290,16 +289,6 @@ impl Builder { } let mut output = None; - let f: Thunk<(), T> = if stdout.is_some() || stderr.is_some() { - Thunk::new(move || { - let _ = stdout.map(stdio::set_stdout); - let _ = stderr.map(stdio::set_stderr); - f.invoke(()) - }) - } else { - f - }; - let try_result = { let ptr = &mut output; @@ -916,20 +905,6 @@ mod test { } #[test] - fn test_stdout() { - let (tx, rx) = channel(); - let mut reader = ChanReader::new(rx); - let stdout = ChanWriter::new(tx); - - Builder::new().stdout(box stdout as Box<Writer + Send>).scoped(move|| { - print!("Hello, world!"); - }).unwrap().join(); - - let output = reader.read_to_string().unwrap(); - assert_eq!(output, "Hello, world!".to_string()); - } - - #[test] fn test_park_timeout_unpark_before() { for _ in 0..10 { thread::current().unpark(); diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index e094cbcac53..32857769acf 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -19,10 +19,11 @@ use diagnostics; use std::cell::{RefCell, Cell}; use std::fmt; -use std::old_io; -use std::string::String; +use std::io::prelude::*; +use std::io; use term::WriterWrapper; use term; +use libc; /// maximum number of lines we will print for each error; arbitrary. const MAX_LINES: usize = 6; @@ -271,7 +272,7 @@ impl Level { fn print_maybe_styled(w: &mut EmitterWriter, msg: &str, - color: term::attr::Attr) -> old_io::IoResult<()> { + color: term::attr::Attr) -> io::Result<()> { match w.dst { Terminal(ref mut t) => { try!(t.attr(color)); @@ -289,23 +290,21 @@ fn print_maybe_styled(w: &mut EmitterWriter, // to be miscolored. We assume this is rare enough that we don't // have to worry about it. if msg.ends_with("\n") { - try!(t.write_str(&msg[..msg.len()-1])); + try!(t.write_all(msg[..msg.len()-1].as_bytes())); try!(t.reset()); - try!(t.write_str("\n")); + try!(t.write_all(b"\n")); } else { - try!(t.write_str(msg)); + try!(t.write_all(msg.as_bytes())); try!(t.reset()); } Ok(()) } - Raw(ref mut w) => { - w.write_str(msg) - } + Raw(ref mut w) => w.write_all(msg.as_bytes()), } } fn print_diagnostic(dst: &mut EmitterWriter, topic: &str, lvl: Level, - msg: &str, code: Option<&str>) -> old_io::IoResult<()> { + msg: &str, code: Option<&str>) -> io::Result<()> { if !topic.is_empty() { try!(write!(&mut dst.dst, "{} ", topic)); } @@ -324,7 +323,7 @@ fn print_diagnostic(dst: &mut EmitterWriter, topic: &str, lvl: Level, } None => () } - try!(dst.dst.write_char('\n')); + try!(write!(&mut dst.dst, "\n")); Ok(()) } @@ -335,18 +334,18 @@ pub struct EmitterWriter { enum Destination { Terminal(Box<term::Terminal<WriterWrapper> + Send>), - Raw(Box<Writer + Send>), + Raw(Box<Write + Send>), } impl EmitterWriter { pub fn stderr(color_config: ColorConfig, registry: Option<diagnostics::registry::Registry>) -> EmitterWriter { - let stderr = old_io::stderr(); + let stderr = io::stderr(); let use_color = match color_config { Always => true, Never => false, - Auto => stderr.get_ref().isatty() + Auto => stderr_isatty(), }; if use_color { @@ -360,17 +359,42 @@ impl EmitterWriter { } } - pub fn new(dst: Box<Writer + Send>, + pub fn new(dst: Box<Write + Send>, registry: Option<diagnostics::registry::Registry>) -> EmitterWriter { EmitterWriter { dst: Raw(dst), registry: registry } } } -impl Writer for Destination { - fn write_all(&mut self, bytes: &[u8]) -> old_io::IoResult<()> { +#[cfg(unix)] +fn stderr_isatty() -> bool { + unsafe { libc::isatty(libc::STDERR_FILENO) != 0 } +} +#[cfg(windows)] +fn stderr_isatty() -> bool { + const STD_ERROR_HANDLE: libc::DWORD = -12; + extern "system" { + fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE; + fn GetConsoleMode(hConsoleHandle: libc::HANDLE, + lpMode: libc::LPDWORD) -> libc::BOOL; + } + unsafe { + let handle = GetStdHandle(STD_ERROR_HANDLE); + let mut out = 0; + GetConsoleMode(handle, &mut out) != 0 + } +} + +impl Write for Destination { + fn write(&mut self, bytes: &[u8]) -> io::Result<usize> { + match *self { + Terminal(ref mut t) => t.write(bytes), + Raw(ref mut w) => w.write(bytes), + } + } + fn flush(&mut self) -> io::Result<()> { match *self { - Terminal(ref mut t) => t.write_all(bytes), - Raw(ref mut w) => w.write_all(bytes), + Terminal(ref mut t) => t.flush(), + Raw(ref mut w) => w.flush(), } } } @@ -403,7 +427,7 @@ impl Emitter for EmitterWriter { } fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan, - msg: &str, code: Option<&str>, lvl: Level, custom: bool) -> old_io::IoResult<()> { + msg: &str, code: Option<&str>, lvl: Level, custom: bool) -> io::Result<()> { let sp = rsp.span(); // We cannot check equality directly with COMMAND_LINE_SP @@ -451,7 +475,7 @@ fn highlight_lines(err: &mut EmitterWriter, cm: &codemap::CodeMap, sp: Span, lvl: Level, - lines: codemap::FileLines) -> old_io::IoResult<()> { + lines: codemap::FileLines) -> io::Result<()> { let fm = &*lines.file; let mut elided = false; @@ -560,7 +584,7 @@ fn custom_highlight_lines(w: &mut EmitterWriter, sp: Span, lvl: Level, lines: codemap::FileLines) - -> old_io::IoResult<()> { + -> io::Result<()> { let fm = &*lines.file; let lines = &lines.lines[..]; @@ -617,8 +641,8 @@ fn custom_highlight_lines(w: &mut EmitterWriter, fn print_macro_backtrace(w: &mut EmitterWriter, cm: &codemap::CodeMap, sp: Span) - -> old_io::IoResult<()> { - let cs = try!(cm.with_expn_info(sp.expn_id, |expn_info| -> old_io::IoResult<_> { + -> io::Result<()> { + let cs = try!(cm.with_expn_info(sp.expn_id, |expn_info| -> io::Result<_> { match expn_info { Some(ei) => { let ss = ei.callee.span.map_or(String::new(), diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 90f0dc30c75..f60ac8f3f33 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -30,7 +30,6 @@ #![feature(collections)] #![feature(core)] #![feature(int_uint)] -#![feature(old_io)] #![feature(libc)] #![feature(old_path)] #![feature(quote, unsafe_destructor)] diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index f5781e0587d..d9887c28e5c 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1470,11 +1470,11 @@ mod test { use diagnostic; use parse::token; use parse::token::{str_to_ident}; - use std::old_io::util; + use std::io; fn mk_sh() -> diagnostic::SpanHandler { // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. - let emitter = diagnostic::EmitterWriter::new(Box::new(util::NullWriter), None); + let emitter = diagnostic::EmitterWriter::new(Box::new(io::sink()), None); let handler = diagnostic::mk_handler(true, Box::new(emitter)); diagnostic::mk_span_handler(handler, CodeMap::new()) } diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index be467c1f1fb..36225fad221 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -21,6 +21,8 @@ //! ```no_run //! extern crate term; //! +//! use std::io::prelude::*; +//! //! fn main() { //! let mut t = term::stdout().unwrap(); //! @@ -56,7 +58,6 @@ #![feature(collections)] #![feature(int_uint)] #![feature(io)] -#![feature(old_io)] #![feature(rustc_private)] #![feature(staged_api)] #![feature(std_misc)] @@ -69,27 +70,28 @@ pub use terminfo::TerminfoTerminal; #[cfg(windows)] pub use win::WinConsole; -use std::old_io::IoResult; +use std::io::prelude::*; +use std::io; pub mod terminfo; #[cfg(windows)] mod win; -/// A hack to work around the fact that `Box<Writer + Send>` does not -/// currently implement `Writer`. +/// A hack to work around the fact that `Box<Write + Send>` does not +/// currently implement `Write`. pub struct WriterWrapper { - wrapped: Box<Writer + Send>, + wrapped: Box<Write + Send>, } -impl Writer for WriterWrapper { +impl Write for WriterWrapper { #[inline] - fn write_all(&mut self, buf: &[u8]) -> IoResult<()> { - self.wrapped.write_all(buf) + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.wrapped.write(buf) } #[inline] - fn flush(&mut self) -> IoResult<()> { + fn flush(&mut self) -> io::Result<()> { self.wrapped.flush() } } @@ -99,7 +101,7 @@ impl Writer for WriterWrapper { /// opened. pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> { TerminfoTerminal::new(WriterWrapper { - wrapped: box std::old_io::stdout() as Box<Writer + Send>, + wrapped: box std::io::stdout() as Box<Write + Send>, }) } @@ -108,14 +110,14 @@ pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> { /// opened. pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> { let ti = TerminfoTerminal::new(WriterWrapper { - wrapped: box std::old_io::stdout() as Box<Writer + Send>, + wrapped: box std::io::stdout() as Box<Write + Send>, }); match ti { Some(t) => Some(t), None => { WinConsole::new(WriterWrapper { - wrapped: box std::old_io::stdout() as Box<Writer + Send>, + wrapped: box std::io::stdout() as Box<Write + Send>, }) } } @@ -126,7 +128,7 @@ pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> { /// opened. pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send>> { TerminfoTerminal::new(WriterWrapper { - wrapped: box std::old_io::stderr() as Box<Writer + Send>, + wrapped: box std::io::stderr() as Box<Write + Send>, }) } @@ -135,14 +137,14 @@ pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send>> { /// opened. pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send>> { let ti = TerminfoTerminal::new(WriterWrapper { - wrapped: box std::old_io::stderr() as Box<Writer + Send>, + wrapped: box std::io::stderr() as Box<Write + Send>, }); match ti { Some(t) => Some(t), None => { WinConsole::new(WriterWrapper { - wrapped: box std::old_io::stderr() as Box<Writer + Send>, + wrapped: box std::io::stderr() as Box<Write + Send>, }) } } @@ -209,7 +211,7 @@ pub mod attr { /// A terminal with similar capabilities to an ANSI Terminal /// (foreground/background colors etc). -pub trait Terminal<T: Writer>: Writer { +pub trait Terminal<T: Write>: Write { /// Sets the foreground color to the given color. /// /// If the color is a bright color, but the terminal only supports 8 colors, @@ -217,7 +219,7 @@ pub trait Terminal<T: Writer>: Writer { /// /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)` /// if there was an I/O error. - fn fg(&mut self, color: color::Color) -> IoResult<bool>; + fn fg(&mut self, color: color::Color) -> io::Result<bool>; /// Sets the background color to the given color. /// @@ -226,19 +228,19 @@ pub trait Terminal<T: Writer>: Writer { /// /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)` /// if there was an I/O error. - fn bg(&mut self, color: color::Color) -> IoResult<bool>; + fn bg(&mut self, color: color::Color) -> io::Result<bool>; /// Sets the given terminal attribute, if supported. Returns `Ok(true)` /// if the attribute was supported, `Ok(false)` otherwise, and `Err(e)` if /// there was an I/O error. - fn attr(&mut self, attr: attr::Attr) -> IoResult<bool>; + fn attr(&mut self, attr: attr::Attr) -> io::Result<bool>; /// Returns whether the given terminal attribute is supported. fn supports_attr(&self, attr: attr::Attr) -> bool; /// Resets all terminal attributes and color to the default. /// Returns `Ok()`. - fn reset(&mut self) -> IoResult<()>; + fn reset(&mut self) -> io::Result<()>; /// Gets an immutable reference to the stream inside fn get_ref<'a>(&'a self) -> &'a T; @@ -248,7 +250,7 @@ pub trait Terminal<T: Writer>: Writer { } /// A terminal which can be unwrapped. -pub trait UnwrappableTerminal<T: Writer>: Terminal<T> { +pub trait UnwrappableTerminal<T: Write>: Terminal<T> { /// Returns the contained stream, destroying the `Terminal` fn unwrap(self) -> T; } diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs index be1c623c859..3c269cc485d 100644 --- a/src/libterm/terminfo/mod.rs +++ b/src/libterm/terminfo/mod.rs @@ -11,8 +11,9 @@ //! Terminfo database interface. use std::collections::HashMap; -use std::old_io::IoResult; use std::env; +use std::io::prelude::*; +use std::io; use attr; use color; @@ -72,8 +73,8 @@ pub struct TerminfoTerminal<T> { ti: Box<TermInfo> } -impl<T: Writer+Send+'static> Terminal<T> for TerminfoTerminal<T> { - fn fg(&mut self, color: color::Color) -> IoResult<bool> { +impl<T: Write+Send+'static> Terminal<T> for TerminfoTerminal<T> { + fn fg(&mut self, color: color::Color) -> io::Result<bool> { let color = self.dim_if_necessary(color); if self.num_colors > color { let s = expand(self.ti @@ -90,7 +91,7 @@ impl<T: Writer+Send+'static> Terminal<T> for TerminfoTerminal<T> { Ok(false) } - fn bg(&mut self, color: color::Color) -> IoResult<bool> { + fn bg(&mut self, color: color::Color) -> io::Result<bool> { let color = self.dim_if_necessary(color); if self.num_colors > color { let s = expand(self.ti @@ -107,7 +108,7 @@ impl<T: Writer+Send+'static> Terminal<T> for TerminfoTerminal<T> { Ok(false) } - fn attr(&mut self, attr: attr::Attr) -> IoResult<bool> { + fn attr(&mut self, attr: attr::Attr) -> io::Result<bool> { match attr { attr::ForegroundColor(c) => self.fg(c), attr::BackgroundColor(c) => self.bg(c), @@ -140,7 +141,7 @@ impl<T: Writer+Send+'static> Terminal<T> for TerminfoTerminal<T> { } } - fn reset(&mut self) -> IoResult<()> { + fn reset(&mut self) -> io::Result<()> { let mut cap = self.ti.strings.get("sgr0"); if cap.is_none() { // are there any terminals that have color/attrs and not sgr0? @@ -164,11 +165,11 @@ impl<T: Writer+Send+'static> Terminal<T> for TerminfoTerminal<T> { fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.out } } -impl<T: Writer+Send+'static> UnwrappableTerminal<T> for TerminfoTerminal<T> { +impl<T: Write+Send+'static> UnwrappableTerminal<T> for TerminfoTerminal<T> { fn unwrap(self) -> T { self.out } } -impl<T: Writer+Send+'static> TerminfoTerminal<T> { +impl<T: Write+Send+'static> TerminfoTerminal<T> { /// Returns `None` whenever the terminal cannot be created for some /// reason. pub fn new(out: T) -> Option<Box<Terminal<T>+Send+'static>> { @@ -220,12 +221,12 @@ impl<T: Writer+Send+'static> TerminfoTerminal<T> { } -impl<T: Writer> Writer for TerminfoTerminal<T> { - fn write_all(&mut self, buf: &[u8]) -> IoResult<()> { - self.out.write_all(buf) +impl<T: Write> Write for TerminfoTerminal<T> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.out.write(buf) } - fn flush(&mut self) -> IoResult<()> { + fn flush(&mut self) -> io::Result<()> { self.out.flush() } } diff --git a/src/libterm/win.rs b/src/libterm/win.rs index e93b956dc7c..e29e0e27394 100644 --- a/src/libterm/win.rs +++ b/src/libterm/win.rs @@ -14,7 +14,8 @@ extern crate libc; -use std::old_io::IoResult; +use std::io; +use std::io::prelude::*; use attr; use color; @@ -86,7 +87,7 @@ fn bits_to_color(bits: u16) -> color::Color { color | (bits & 0x8) // copy the hi-intensity bit } -impl<T: Writer+Send+'static> WinConsole<T> { +impl<T: Write+Send+'static> WinConsole<T> { fn apply(&mut self) { let _unused = self.buf.flush(); let mut accum: libc::WORD = 0; @@ -129,32 +130,32 @@ impl<T: Writer+Send+'static> WinConsole<T> { } } -impl<T: Writer> Writer for WinConsole<T> { - fn write_all(&mut self, buf: &[u8]) -> IoResult<()> { - self.buf.write_all(buf) +impl<T: Write> Write for WinConsole<T> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.buf.write(buf) } - fn flush(&mut self) -> IoResult<()> { + fn flush(&mut self) -> io::Result<()> { self.buf.flush() } } -impl<T: Writer+Send+'static> Terminal<T> for WinConsole<T> { - fn fg(&mut self, color: color::Color) -> IoResult<bool> { +impl<T: Write+Send+'static> Terminal<T> for WinConsole<T> { + fn fg(&mut self, color: color::Color) -> io::Result<bool> { self.foreground = color; self.apply(); Ok(true) } - fn bg(&mut self, color: color::Color) -> IoResult<bool> { + fn bg(&mut self, color: color::Color) -> io::Result<bool> { self.background = color; self.apply(); Ok(true) } - fn attr(&mut self, attr: attr::Attr) -> IoResult<bool> { + fn attr(&mut self, attr: attr::Attr) -> io::Result<bool> { match attr { attr::ForegroundColor(f) => { self.foreground = f; @@ -179,7 +180,7 @@ impl<T: Writer+Send+'static> Terminal<T> for WinConsole<T> { } } - fn reset(&mut self) -> IoResult<()> { + fn reset(&mut self) -> io::Result<()> { self.foreground = self.def_foreground; self.background = self.def_background; self.apply(); @@ -192,6 +193,6 @@ impl<T: Writer+Send+'static> Terminal<T> for WinConsole<T> { fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.buf } } -impl<T: Writer+Send+'static> UnwrappableTerminal<T> for WinConsole<T> { +impl<T: Write+Send+'static> UnwrappableTerminal<T> for WinConsole<T> { fn unwrap(self) -> T { self.buf } } diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 80d5ab5baf3..ca8a60553ab 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -44,11 +44,14 @@ #![feature(staged_api)] #![feature(std_misc)] #![feature(io)] +#![feature(libc)] +#![feature(set_panic)] extern crate getopts; extern crate serialize; extern crate "serialize" as rustc_serialize; extern crate term; +extern crate libc; pub use self::TestFn::*; pub use self::ColorConfig::*; @@ -70,14 +73,13 @@ use std::collections::BTreeMap; use std::env; use std::fmt; use std::fs::File; -use std::io::{self, Write}; +use std::io::prelude::*; +use std::io; use std::iter::repeat; use std::num::{Float, Int}; -use std::old_io::stdio::StdWriter; -use std::old_io::{ChanReader, ChanWriter}; -use std::old_io; use std::path::{PathBuf}; use std::sync::mpsc::{channel, Sender}; +use std::sync::{Arc, Mutex}; use std::thread; use std::thunk::{Thunk, Invoke}; use std::time::Duration; @@ -452,23 +454,15 @@ struct ConsoleTestState<T> { max_name_len: uint, // number of columns to fill when aligning names } -fn new2old(new: io::Error) -> old_io::IoError { - old_io::IoError { - kind: old_io::OtherIoError, - desc: "other error", - detail: Some(new.to_string()), - } -} - -impl<T: Writer> ConsoleTestState<T> { +impl<T: Write> ConsoleTestState<T> { pub fn new(opts: &TestOpts, - _: Option<T>) -> old_io::IoResult<ConsoleTestState<StdWriter>> { + _: Option<T>) -> io::Result<ConsoleTestState<io::Stdout>> { let log_out = match opts.logfile { - Some(ref path) => Some(try!(File::create(path).map_err(new2old))), + Some(ref path) => Some(try!(File::create(path))), None => None }; let out = match term::stdout() { - None => Raw(old_io::stdio::stdout_raw()), + None => Raw(io::stdout()), Some(t) => Pretty(t) }; @@ -487,29 +481,29 @@ impl<T: Writer> ConsoleTestState<T> { }) } - pub fn write_ok(&mut self) -> old_io::IoResult<()> { + pub fn write_ok(&mut self) -> io::Result<()> { self.write_pretty("ok", term::color::GREEN) } - pub fn write_failed(&mut self) -> old_io::IoResult<()> { + pub fn write_failed(&mut self) -> io::Result<()> { self.write_pretty("FAILED", term::color::RED) } - pub fn write_ignored(&mut self) -> old_io::IoResult<()> { + pub fn write_ignored(&mut self) -> io::Result<()> { self.write_pretty("ignored", term::color::YELLOW) } - pub fn write_metric(&mut self) -> old_io::IoResult<()> { + pub fn write_metric(&mut self) -> io::Result<()> { self.write_pretty("metric", term::color::CYAN) } - pub fn write_bench(&mut self) -> old_io::IoResult<()> { + pub fn write_bench(&mut self) -> io::Result<()> { self.write_pretty("bench", term::color::CYAN) } pub fn write_pretty(&mut self, word: &str, - color: term::color::Color) -> old_io::IoResult<()> { + color: term::color::Color) -> io::Result<()> { match self.out { Pretty(ref mut term) => { if self.use_color { @@ -528,7 +522,7 @@ impl<T: Writer> ConsoleTestState<T> { } } - pub fn write_plain(&mut self, s: &str) -> old_io::IoResult<()> { + pub fn write_plain(&mut self, s: &str) -> io::Result<()> { match self.out { Pretty(ref mut term) => { try!(term.write_all(s.as_bytes())); @@ -541,19 +535,19 @@ impl<T: Writer> ConsoleTestState<T> { } } - pub fn write_run_start(&mut self, len: uint) -> old_io::IoResult<()> { + pub fn write_run_start(&mut self, len: uint) -> io::Result<()> { self.total = len; let noun = if len != 1 { "tests" } else { "test" }; self.write_plain(&format!("\nrunning {} {}\n", len, noun)) } pub fn write_test_start(&mut self, test: &TestDesc, - align: NamePadding) -> old_io::IoResult<()> { + align: NamePadding) -> io::Result<()> { let name = test.padded_name(self.max_name_len, align); self.write_plain(&format!("test {} ... ", name)) } - pub fn write_result(&mut self, result: &TestResult) -> old_io::IoResult<()> { + pub fn write_result(&mut self, result: &TestResult) -> io::Result<()> { try!(match *result { TrOk => self.write_ok(), TrFailed => self.write_failed(), @@ -590,7 +584,7 @@ impl<T: Writer> ConsoleTestState<T> { } } - pub fn write_failures(&mut self) -> old_io::IoResult<()> { + pub fn write_failures(&mut self) -> io::Result<()> { try!(self.write_plain("\nfailures:\n")); let mut failures = Vec::new(); let mut fail_out = String::new(); @@ -616,7 +610,7 @@ impl<T: Writer> ConsoleTestState<T> { Ok(()) } - pub fn write_run_finish(&mut self) -> old_io::IoResult<bool> { + pub fn write_run_finish(&mut self) -> io::Result<bool> { assert!(self.passed + self.failed + self.ignored + self.measured == self.total); let success = self.failed == 0; @@ -652,15 +646,15 @@ pub fn fmt_bench_samples(bs: &BenchSamples) -> String { } // A simple console test runner -pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn> ) -> old_io::IoResult<bool> { +pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn> ) -> io::Result<bool> { - fn callback<T: Writer>(event: &TestEvent, - st: &mut ConsoleTestState<T>) -> old_io::IoResult<()> { + fn callback<T: Write>(event: &TestEvent, + st: &mut ConsoleTestState<T>) -> io::Result<()> { match (*event).clone() { TeFiltered(ref filtered_tests) => st.write_run_start(filtered_tests.len()), TeWait(ref test, padding) => st.write_test_start(test, padding), TeResult(test, result, stdout) => { - try!(st.write_log(&test, &result).map_err(new2old)); + try!(st.write_log(&test, &result)); try!(st.write_result(&result)); match result { TrOk => st.passed += 1, @@ -694,7 +688,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn> ) -> old_io: } } - let mut st = try!(ConsoleTestState::new(opts, None::<StdWriter>)); + let mut st = try!(ConsoleTestState::new(opts, None::<io::Stdout>)); fn len_if_padded(t: &TestDescAndFn) -> uint { match t.testfn.padding() { PadNone => 0, @@ -753,12 +747,31 @@ fn should_sort_failures_before_printing_them() { fn use_color(opts: &TestOpts) -> bool { match opts.color { - AutoColor => get_concurrency() == 1 && old_io::stdout().get_ref().isatty(), + AutoColor => get_concurrency() == 1 && stdout_isatty(), AlwaysColor => true, NeverColor => false, } } +#[cfg(unix)] +fn stdout_isatty() -> bool { + unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } +} +#[cfg(windows)] +fn stdout_isatty() -> bool { + const STD_OUTPUT_HANDLE: libc::DWORD = -11; + extern "system" { + fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE; + fn GetConsoleMode(hConsoleHandle: libc::HANDLE, + lpMode: libc::LPDWORD) -> libc::BOOL; + } + unsafe { + let handle = GetStdHandle(STD_OUTPUT_HANDLE); + let mut out = 0; + GetConsoleMode(handle, &mut out) != 0 + } +} + #[derive(Clone)] enum TestEvent { TeFiltered(Vec<TestDesc> ), @@ -771,8 +784,8 @@ pub type MonitorMsg = (TestDesc, TestResult, Vec<u8> ); fn run_tests<F>(opts: &TestOpts, tests: Vec<TestDescAndFn> , - mut callback: F) -> old_io::IoResult<()> where - F: FnMut(TestEvent) -> old_io::IoResult<()>, + mut callback: F) -> io::Result<()> where + F: FnMut(TestEvent) -> io::Result<()>, { let filtered_tests = filter_tests(opts, tests); let filtered_descs = filtered_tests.iter() @@ -896,29 +909,41 @@ pub fn run_test(opts: &TestOpts, return; } + #[allow(deprecated)] // set_stdout fn run_test_inner(desc: TestDesc, monitor_ch: Sender<MonitorMsg>, nocapture: bool, testfn: Thunk<'static>) { + struct Sink(Arc<Mutex<Vec<u8>>>); + impl Write for Sink { + fn write(&mut self, data: &[u8]) -> io::Result<usize> { + Write::write(&mut *self.0.lock().unwrap(), data) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } + } + impl Writer for Sink { + fn write_all(&mut self, data: &[u8]) -> std::old_io::IoResult<()> { + Writer::write_all(&mut *self.0.lock().unwrap(), data) + } + } + thread::spawn(move || { - let (tx, rx) = channel(); - let mut reader = ChanReader::new(rx); - let stdout = ChanWriter::new(tx.clone()); - let stderr = ChanWriter::new(tx); - let mut cfg = thread::Builder::new().name(match desc.name { + let data = Arc::new(Mutex::new(Vec::new())); + let data2 = data.clone(); + let cfg = thread::Builder::new().name(match desc.name { DynTestName(ref name) => name.clone().to_string(), StaticTestName(name) => name.to_string(), }); - if nocapture { - drop((stdout, stderr)); - } else { - cfg = cfg.stdout(box stdout as Box<Writer + Send>); - cfg = cfg.stderr(box stderr as Box<Writer + Send>); - } - let result_guard = cfg.spawn(move || { testfn.invoke(()) }).unwrap(); - let stdout = reader.read_to_end().unwrap().into_iter().collect(); + let result_guard = cfg.spawn(move || { + if !nocapture { + std::old_io::stdio::set_stdout(box Sink(data2.clone())); + io::set_panic(box Sink(data2)); + } + testfn.invoke(()) + }).unwrap(); let test_result = calc_result(&desc, result_guard.join()); + let stdout = data.lock().unwrap().to_vec(); monitor_ch.send((desc.clone(), test_result, stdout)).unwrap(); }); } diff --git a/src/rustbook/main.rs b/src/rustbook/main.rs index dadea634bf0..84d510294ef 100644 --- a/src/rustbook/main.rs +++ b/src/rustbook/main.rs @@ -12,8 +12,6 @@ #![feature(core)] #![feature(exit_status)] -#![feature(io)] -#![feature(old_io)] #![feature(rustdoc)] #![feature(rustc_private)] diff --git a/src/rustbook/term.rs b/src/rustbook/term.rs index 06595cb0455..060297beb75 100644 --- a/src/rustbook/term.rs +++ b/src/rustbook/term.rs @@ -12,22 +12,23 @@ //! verbosity support. For now, just a wrapper around stdout/stderr. use std::env; -use std::old_io::stdio; +use std::io; +use std::io::prelude::*; pub struct Term { - err: Box<Writer + 'static> + err: Box<Write + 'static> } impl Term { pub fn new() -> Term { Term { - err: Box::new(stdio::stderr()) + err: Box::new(io::stderr()) } } pub fn err(&mut self, msg: &str) { // swallow any errors - let _ = self.err.write_line(msg); + let _ = writeln!(&mut self.err, "{}", msg); env::set_exit_status(101); } } diff --git a/src/test/run-pass/issue-11881.rs b/src/test/run-pass/issue-11881.rs index 10d694957f5..bc907787c7c 100644 --- a/src/test/run-pass/issue-11881.rs +++ b/src/test/run-pass/issue-11881.rs @@ -13,16 +13,15 @@ extern crate rbml; extern crate serialize; -use std::old_io; +use std::io::Cursor; +use std::io::prelude::*; use std::fmt; -use std::old_io::{IoResult, SeekStyle}; use std::slice; use serialize::{Encodable, Encoder}; use serialize::json; use rbml::writer; -use rbml::io::SeekableMemWriter; #[derive(Encodable)] struct Foo { @@ -40,17 +39,17 @@ enum WireProtocol { // ... } -fn encode_json<T: Encodable>(val: &T, wr: &mut SeekableMemWriter) { +fn encode_json<T: Encodable>(val: &T, wr: &mut Cursor<Vec<u8>>) { write!(wr, "{}", json::as_json(val)); } -fn encode_rbml<T: Encodable>(val: &T, wr: &mut SeekableMemWriter) { +fn encode_rbml<T: Encodable>(val: &T, wr: &mut Cursor<Vec<u8>>) { let mut encoder = writer::Encoder::new(wr); val.encode(&mut encoder); } pub fn main() { let target = Foo{baz: false,}; - let mut wr = SeekableMemWriter::new(); + let mut wr = Cursor::new(Vec::new()); let proto = WireProtocol::JSON; match proto { WireProtocol::JSON => encode_json(&target, &mut wr), diff --git a/src/test/run-pass/task-stderr.rs b/src/test/run-pass/task-stderr.rs index 1c263b19dd1..3131cda1dbc 100644 --- a/src/test/run-pass/task-stderr.rs +++ b/src/test/run-pass/task-stderr.rs @@ -11,21 +11,30 @@ #![allow(unknown_features)] #![feature(box_syntax)] -use std::sync::mpsc::channel; -use std::old_io::{ChanReader, ChanWriter}; +use std::io::prelude::*; +use std::io; +use std::str; +use std::sync::{Arc, Mutex}; use std::thread; -fn main() { - let (tx, rx) = channel(); - let mut reader = ChanReader::new(rx); - let stderr = ChanWriter::new(tx); +struct Sink(Arc<Mutex<Vec<u8>>>); +impl Write for Sink { + fn write(&mut self, data: &[u8]) -> io::Result<usize> { + Write::write(&mut *self.0.lock().unwrap(), data) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} - let res = thread::Builder::new().stderr(box stderr as Box<Writer + Send>) - .spawn(move|| -> () { +fn main() { + let data = Arc::new(Mutex::new(Vec::new())); + let sink = Sink(data.clone()); + let res = thread::Builder::new().spawn(move|| -> () { + io::set_panic(Box::new(sink)); panic!("Hello, world!") }).unwrap().join(); assert!(res.is_err()); - let output = reader.read_to_string().unwrap(); + let output = data.lock().unwrap(); + let output = str::from_utf8(&output).unwrap(); assert!(output.contains("Hello, world!")); } |
