Auto merge of #23292 - alexcrichton:stabilize-io, r=aturon
The new `std::io` module has had some time to bake now, and this commit stabilizes its functionality. There are still portions of the module which remain unstable, and below contains a summart of the actions taken. This commit also deprecates the entire contents of the `old_io` module in a blanket fashion. All APIs should now have a reasonable replacement in the new I/O modules. Stable APIs: * `std::io` (the name) * `std::io::prelude` (the name) * `Read` * `Read::read` * `Read::{read_to_end, read_to_string}` after being modified to return a `usize` for the number of bytes read. * `ReadExt` * `Write` * `Write::write` * `Write::{write_all, write_fmt}` * `WriteExt` * `BufRead` * `BufRead::{fill_buf, consume}` * `BufRead::{read_line, read_until}` after being modified to return a `usize` for the number of bytes read. * `BufReadExt` * `BufReader` * `BufReader::{new, with_capacity}` * `BufReader::{get_ref, get_mut, into_inner}` * `{Read,BufRead} for BufReader` * `BufWriter` * `BufWriter::{new, with_capacity}` * `BufWriter::{get_ref, get_mut, into_inner}` * `Write for BufWriter` * `IntoInnerError` * `IntoInnerError::{error, into_inner}` * `{Error,Display} for IntoInnerError` * `LineWriter` * `LineWriter::{new, with_capacity}` - `with_capacity` was added * `LineWriter::{get_ref, get_mut, into_inner}` - `get_mut` was added) * `Write for LineWriter` * `BufStream` * `BufStream::{new, with_capacities}` * `BufStream::{get_ref, get_mut, into_inner}` * `{BufRead,Read,Write} for BufStream` * `stdin` * `Stdin` * `Stdin::lock` * `Stdin::read_line` - added method * `StdinLock` * `Read for Stdin` * `{Read,BufRead} for StdinLock` * `stdout` * `Stdout` * `Stdout::lock` * `StdoutLock` * `Write for Stdout` * `Write for StdoutLock` * `stderr` * `Stderr` * `Stderr::lock` * `StderrLock` * `Write for Stderr` * `Write for StderrLock` * `io::Result` * `io::Error` * `io::Error::last_os_error` * `{Display, Error} for Error` Unstable APIs: (reasons can be found in the commit itself) * `Write::flush` * `Seek` * `ErrorKind` * `Error::new` * `Error::from_os_error` * `Error::kind` Deprecated APIs * `Error::description` - available via the `Error` trait * `Error::detail` - available via the `Display` implementation * `thread::Builder::{stdout, stderr}` Changes in functionality: * `old_io::stdio::set_stderr` is now a noop as the infrastructure for printing backtraces has migrated to `std::io`. [breaking-change]
This commit is contained in:
commit
3e4be02b80
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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"];
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#![feature(core)]
|
||||
#![feature(hash)]
|
||||
#![feature(int_uint)]
|
||||
#![feature(old_io)]
|
||||
#![feature(libc)]
|
||||
#![feature(old_path)]
|
||||
#![feature(quote)]
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::io::prelude::*;
|
||||
|
||||
use middle::region;
|
||||
use middle::subst;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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!();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()))
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#![feature(unsafe_destructor)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(unicode)]
|
||||
#![feature(io)]
|
||||
#![feature(path_ext)]
|
||||
#![feature(fs)]
|
||||
#![feature(hash)]
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
|
|
|
@ -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 "));
|
||||
|
|
|
@ -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[..]) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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))
|
||||
};
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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!()
|
||||
|
|
|
@ -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::*;
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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>"));
|
||||
}
|
||||
|
|
|
@ -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..];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(()) }
|
||||
}
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
//!
|
||||
//! Note that all time units in this file are in *milliseconds*.
|
||||
|
||||
#![allow(deprecated)]
|
||||
|
||||
use prelude::v1::*;
|
||||
use self::Req::*;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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::*;
|
||||
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -915,20 +904,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 {
|
||||
|
|
|
@ -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_all(bytes),
|
||||
Raw(ref mut w) => w.write_all(bytes),
|
||||
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.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(),
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#![feature(collections)]
|
||||
#![feature(core)]
|
||||
#![feature(int_uint)]
|
||||
#![feature(old_io)]
|
||||
#![feature(libc)]
|
||||
#![feature(old_path)]
|
||||
#![feature(quote, unsafe_destructor)]
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
|
||||
#![feature(core)]
|
||||
#![feature(exit_status)]
|
||||
#![feature(io)]
|
||||
#![feature(old_io)]
|
||||
#![feature(rustdoc)]
|
||||
#![feature(rustc_private)]
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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!"));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue