Major clean-up of std::io

Use ifaces instead of objs, stop wrapping everything in two (or three)
layers of no-value-added indirection, and remove some of the more
pointless/outdated idioms from the code.
This commit is contained in:
Marijn Haverbeke 2012-01-11 15:15:54 +01:00
parent 807592e99f
commit 34d7f05292
31 changed files with 309 additions and 416 deletions

View file

@ -10,6 +10,7 @@ import rustc::util::filesearch::get_cargo_root;
import std::fs;
import std::generic_os;
import std::io;
import io::writer_util;
import std::json;
import option;
import option::{none, some};

View file

@ -1,5 +1,4 @@
// -*- rust -*-
import metadata::{creader, cstore};
import syntax::parse::{parser};
@ -13,6 +12,7 @@ import back::link;
import core::{option, str, int, result};
import result::{ok, err};
import std::{fs, io, getopts};
import io::reader_util;
import option::{some, none};
import getopts::{optopt, optmulti, optflag, optflagopt, opt_present};
import back::{x86, x86_64};
@ -84,7 +84,7 @@ fn parse_input(sess: session::session, cfg: ast::crate_cfg, input: str) ->
fn parse_input_src(sess: session::session, cfg: ast::crate_cfg, infile: str)
-> {crate: @ast::crate, src: str} {
let srcbytes = if infile != "-" {
let src_stream = if infile != "-" {
alt io::file_reader(infile) {
result::ok(reader) { reader }
result::err(e) {
@ -93,7 +93,8 @@ fn parse_input_src(sess: session::session, cfg: ast::crate_cfg, infile: str)
}
} else {
io::stdin()
}.read_whole_stream();
};
let srcbytes = src_stream.read_whole_stream();
let src = str::unsafe_from_bytes(srcbytes);
let crate =
parser::parse_crate_from_source_str(infile, src, cfg,

View file

@ -5,6 +5,7 @@ use rustc;
import core::{option, str, vec, result};
import result::{ok, err};
import std::{io, getopts};
import io::writer_util;
import option::{some, none};
import getopts::{opt_present};
import rustc::driver::driver::*;

View file

@ -7,8 +7,8 @@ import front::attr;
import syntax::visit;
import syntax::codemap::span;
import util::{filesearch};
import core::{either, vec, str, option};
import std::{io, fs};
import io::writer_util;
import option::{none, some};
import std::map::{hashmap, new_int_hash};
import syntax::print::pprust;

View file

@ -1,6 +1,7 @@
// Decoding metadata from a single crate's metadata
import std::{ebml, io};
import io::writer_util;
import syntax::{ast, ast_util};
import front::attr;
import middle::ty;

View file

@ -1,7 +1,7 @@
// Metadata encoding
import core::{vec, str, uint};
import std::{io, ebml, map};
import io::writer_util;
import syntax::ast::*;
import syntax::ast_util;
import syntax::ast_util::local_def;
@ -191,7 +191,7 @@ fn encode_type_param_bounds(ebml_w: ebml::writer, ecx: @encode_ctxt,
for param in params {
ebml::start_tag(ebml_w, tag_items_data_item_ty_param_bounds);
let bs = ecx.ccx.tcx.ty_param_bounds.get(param.id);
tyencode::enc_bounds(io::new_writer(ebml_w.writer), ty_str_ctxt, bs);
tyencode::enc_bounds(ebml_w.writer, ty_str_ctxt, bs);
ebml::end_tag(ebml_w);
}
}
@ -207,7 +207,7 @@ fn write_type(ecx: @encode_ctxt, ebml_w: ebml::writer, typ: ty::t) {
@{ds: def_to_str,
tcx: ecx.ccx.tcx,
abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
tyencode::enc_ty(io::new_writer(ebml_w.writer), ty_str_ctxt, typ);
tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
}
fn encode_type(ecx: @encode_ctxt, ebml_w: ebml::writer, typ: ty::t) {
@ -522,7 +522,7 @@ fn create_index<T: copy>(index: [entry<T>], hash_fn: fn(T) -> uint) ->
fn encode_index<T>(ebml_w: ebml::writer, buckets: [@[entry<T>]],
write_fn: fn(io::writer, T)) {
let writer = io::new_writer(ebml_w.writer);
let writer = ebml_w.writer;
ebml::start_tag(ebml_w, tag_index);
let bucket_locs: [uint] = [];
ebml::start_tag(ebml_w, tag_index_buckets);
@ -702,8 +702,8 @@ fn encode_metadata(cx: @crate_ctxt, crate: @crate) -> str {
let abbrevs = ty::new_ty_hash();
let ecx = @{ccx: cx, type_abbrevs: abbrevs};
let string_w = io::string_writer();
let buf_w = string_w.get_writer().get_buf_writer();
let buf = io::mk_mem_buffer();
let buf_w = io::mem_buffer_writer(buf);
let ebml_w = ebml::create_writer(buf_w);
encode_hash(ebml_w, cx.link_meta.extras_hash);
@ -714,32 +714,31 @@ fn encode_metadata(cx: @crate_ctxt, crate: @crate) -> str {
encode_crate_deps(ebml_w, cx.sess.get_cstore());
// Encode and index the paths.
ebml::start_tag(ebml_w, tag_paths);
let paths_index = encode_item_paths(ebml_w, ecx, crate);
let paths_buckets = create_index(paths_index, hash_path);
encode_index(ebml_w, paths_buckets, write_str);
ebml::end_tag(ebml_w);
// Encode and index the items.
// Encode and index the items.
ebml::start_tag(ebml_w, tag_items);
let items_index = encode_info_for_items(ecx, ebml_w, crate.node.module);
let items_buckets = create_index(items_index, hash_node_id);
encode_index(ebml_w, items_buckets, write_int);
ebml::end_tag(ebml_w);
// Pad this, since something (LLVM, presumably) is cutting off the
// remaining % 4 bytes.
buf_w.write([0u8, 0u8, 0u8, 0u8]);
ret string_w.get_str();
io::mem_buffer_str(buf)
}
// Get the encoded string for a type
fn encoded_ty(tcx: ty::ctxt, t: ty::t) -> str {
let cx = @{ds: def_to_str, tcx: tcx, abbrevs: tyencode::ac_no_abbrevs};
let sw = io::string_writer();
tyencode::enc_ty(sw.get_writer(), cx, t);
ret sw.get_str();
let buf = io::mk_mem_buffer();
tyencode::enc_ty(io::mem_buffer_writer(buf), cx, t);
ret io::mem_buffer_str(buf);
}

View file

@ -1,7 +1,7 @@
// Type encoding
import core::{int, uint};
import std::io;
import io::writer_util;
import std::map::hashmap;
import option::{some, none};
import syntax::ast::*;
@ -37,25 +37,24 @@ fn cx_uses_abbrevs(cx: @ctxt) -> bool {
fn enc_ty(w: io::writer, cx: @ctxt, t: ty::t) {
alt cx.abbrevs {
ac_no_abbrevs. {
let result_str: @str;
alt cx.tcx.short_names_cache.find(t) {
some(s) { result_str = s; }
let result_str = alt cx.tcx.short_names_cache.find(t) {
some(s) { *s }
none. {
let sw = io::string_writer();
enc_sty(sw.get_writer(), cx, ty::struct(cx.tcx, t));
result_str = @sw.get_str();
cx.tcx.short_names_cache.insert(t, result_str);
let buf = io::mk_mem_buffer();
enc_sty(io::mem_buffer_writer(buf), cx, ty::struct(cx.tcx, t));
cx.tcx.short_names_cache.insert(t, @io::mem_buffer_str(buf));
io::mem_buffer_str(buf)
}
}
w.write_str(*result_str);
};
w.write_str(result_str);
}
ac_use_abbrevs(abbrevs) {
alt abbrevs.find(t) {
some(a) { w.write_str(*a.s); ret; }
none. {
let pos = w.get_buf_writer().tell();
let pos = w.tell();
enc_sty(w, cx, ty::struct(cx.tcx, t));
let end = w.get_buf_writer().tell();
let end = w.tell();
let len = end - pos;
fn estimate_sz(u: uint) -> uint {
let n = u;

View file

@ -1,5 +1,6 @@
import core::{vec, uint, str, option, result};
import std::{term, io};
import io::writer_util;
import option::{some, none};
type filename = str;
@ -126,11 +127,11 @@ fn print_diagnostic(topic: str, t: diagnostictype, msg: str) {
io::stdout().write_str(#fmt["%s ", topic]);
}
if term::color_supported() {
term::fg(io::stdout().get_buf_writer(), diagnosticcolor(t));
term::fg(io::stdout(), diagnosticcolor(t));
}
io::stdout().write_str(#fmt["%s:", diagnosticstr(t)]);
if term::color_supported() {
term::reset(io::stdout().get_buf_writer());
term::reset(io::stdout());
}
io::stdout().write_str(#fmt[" %s\n", msg]);
}

View file

@ -1,6 +1,6 @@
import option;
import base::*;
import syntax::ast;
import std::io::writer_util;
fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, arg: @ast::expr,
_body: option::t<str>) -> @ast::expr {

View file

@ -1,6 +1,7 @@
import core::{vec, str, option, either};
import std::io;
import io::reader_util;
import option::{some, none};
import util::interner;
import util::interner::intern;

View file

@ -1,6 +1,7 @@
import core::{vec, str};
import std::io;
import io::writer_util;
/*
* This pretty-printer is a direct reimplementation of Philip Karlton's

View file

@ -93,25 +93,23 @@ fn path_to_str(&&p: @ast::path) -> str {
fn fun_to_str(decl: ast::fn_decl, name: ast::ident,
params: [ast::ty_param]) -> str {
let writer = io::string_writer();
let s = rust_printer(writer.get_writer());
let buffer = io::mk_mem_buffer();
let s = rust_printer(io::mem_buffer_writer(buffer));
print_fn(s, decl, name, params);
eof(s.s);
ret writer.get_str();
io::mem_buffer_str(buffer)
}
fn block_to_str(blk: ast::blk) -> str {
let writer = io::string_writer();
let s = rust_printer(writer.get_writer());
let buffer = io::mk_mem_buffer();
let s = rust_printer(io::mem_buffer_writer(buffer));
// containing cbox, will be closed by print-block at }
cbox(s, indent_unit);
// head-ibox, will be closed by print-block after {
ibox(s, 0u);
print_block(s, blk);
eof(s.s);
ret writer.get_str();
io::mem_buffer_str(buffer)
}
fn meta_item_to_str(mi: ast::meta_item) -> str {
@ -1597,11 +1595,11 @@ fn escape_str(st: str, to_escape: char) -> str {
}
fn to_str<T>(t: T, f: fn@(ps, T)) -> str {
let writer = io::string_writer();
let s = rust_printer(writer.get_writer());
let buffer = io::mk_mem_buffer();
let s = rust_printer(io::mem_buffer_writer(buffer));
f(s, t);
eof(s.s);
ret writer.get_str();
io::mem_buffer_str(buffer)
}
fn next_comment(s: ps) -> option::t<lexer::cmnt> {

View file

@ -1,6 +1,5 @@
import option;
import str;
import std::io;
import io::reader_util;
import std::fs;
import common::config;

View file

@ -1,6 +1,7 @@
import option;
import str;
import std::io;
import io::reader_util;
import std::fs;
import common::config;

View file

@ -4,16 +4,12 @@
// child process. Because of that we have to use a complicated scheme with a
// dedicated server for spawning processes.
import core::comm;
import core::option;
import task;
import std::generic_os::setenv;
import std::generic_os::getenv;
import vec;
import std::os;
import std::run;
import std::io;
import str;
import io::writer_util;
import comm::chan;
import comm::port;
import comm::send;
@ -75,7 +71,7 @@ fn run(handle: handle, lib_path: str, prog: str, args: [str],
fn writeclose(fd: fd_t, s: option::t<str>) {
if option::is_some(s) {
let writer = io::new_writer(io::fd_buf_writer(fd, option::none));
let writer = io::fd_writer(fd, false);
writer.write_str(option::get(s));
}
@ -85,7 +81,7 @@ fn writeclose(fd: fd_t, s: option::t<str>) {
fn readclose(fd: fd_t) -> str {
// Copied from run::program_output
let file = os::fd_FILE(fd);
let reader = io::new_reader(io::FILE_buf_reader(file, option::none));
let reader = io::FILE_reader(file, false);
let buf = "";
while !reader.eof() {
let bytes = reader.read_bytes(4096u);

View file

@ -1,10 +1,7 @@
import std::io;
import str;
import option;
import io::writer_util;
import std::fs;
import std::os;
import vec;
import result;
import common::mode_run_pass;
import common::mode_run_fail;

View file

@ -36,5 +36,5 @@ fn path_div() -> str { ";" }
fn logv(config: config, s: str) {
log(debug, s);
if config.verbose { io::stdout().write_line(s); }
if config.verbose { io::println(s); }
}

View file

@ -1,4 +1,5 @@
import std::{fs, io};
import io::writer_util;
import rustc::syntax::{ast, ast_util, fold, visit, codemap};
import rustc::syntax::parse::parser;
@ -212,12 +213,12 @@ fn under(n: uint, it: block(uint)) {
while i < n { it(i); i += 1u; }
}
fn devnull() -> io::writer { std::io::string_writer().get_writer() }
fn devnull() -> io::writer { io::mem_buffer_writer(io::mk_mem_buffer()) }
fn as_str(f: fn@(io::writer)) -> str {
let w = std::io::string_writer();
f(w.get_writer());
ret w.get_str();
let buf = io::mk_mem_buffer();
f(io::mem_buffer_writer(buf));
io::mem_buffer_str(buf)
}
fn check_variants_of_ast(crate: ast::crate, codemap: codemap::codemap,

View file

@ -153,22 +153,21 @@ Function: to_mut
Produces a mutable vector from an immutable vector.
*/
fn to_mut<T: copy>(v: [T]) -> [mutable T] {
let vres = [mutable];
for t: T in v { vres += [mutable t]; }
ret vres;
fn to_mut<T>(+v: [T]) -> [mutable T] unsafe {
let r = ::unsafe::reinterpret_cast(v);
::unsafe::leak(v);
r
}
// Same comment as from_mut
/*
Function: from_mut
Produces an immutable vector from a mutable vector.
*/
fn from_mut<T: copy>(v: [mutable T]) -> [T] {
let vres = [];
for t: T in v { vres += [t]; }
ret vres;
fn from_mut<T>(+v: [mutable T]) -> [T] unsafe {
let r = ::unsafe::reinterpret_cast(v);
::unsafe::leak(v);
r
}
// Accessors

View file

@ -116,9 +116,9 @@ fn doc_as_uint(d: doc) -> uint {
// ebml writing
type writer = {writer: io::buf_writer, mutable size_positions: [uint]};
type writer = {writer: io::writer, mutable size_positions: [uint]};
fn write_sized_vint(w: io::buf_writer, n: uint, size: uint) {
fn write_sized_vint(w: io::writer, n: uint, size: uint) {
let buf: [u8];
alt size {
1u { buf = [0x80u8 | (n as u8)]; }
@ -138,7 +138,7 @@ fn write_sized_vint(w: io::buf_writer, n: uint, size: uint) {
w.write(buf);
}
fn write_vint(w: io::buf_writer, n: uint) {
fn write_vint(w: io::writer, n: uint) {
if n < 0x7fu { write_sized_vint(w, n, 1u); ret; }
if n < 0x4000u { write_sized_vint(w, n, 2u); ret; }
if n < 0x200000u { write_sized_vint(w, n, 3u); ret; }
@ -147,7 +147,7 @@ fn write_vint(w: io::buf_writer, n: uint) {
fail;
}
fn create_writer(w: io::buf_writer) -> writer {
fn create_writer(w: io::writer) -> writer {
let size_positions: [uint] = [];
ret {writer: w, mutable size_positions: size_positions};
}

View file

@ -4,8 +4,6 @@ Module: io
Basic input/output
*/
import core::option;
import core::result;
import core::ctypes::fd_t;
import core::ctypes::c_int;
@ -22,86 +20,20 @@ native mod rustrt {
tag seek_style { seek_set; seek_end; seek_cur; }
// The raw underlying reader class. All readers must implement this.
type buf_reader =
// FIXME: Seekable really should be orthogonal. We will need
// inheritance.
obj {
fn read(uint) -> [u8];
fn read_byte() -> int;
fn unread_byte(int);
fn eof() -> bool;
fn seek(int, seek_style);
fn tell() -> uint;
// Needed on readers in case one needs to flush metadata
// changes (atime)
fn fsync(level: fsync::level) -> int;
};
// Convenience methods for reading.
type reader =
// FIXME: This should inherit from buf_reader.
// FIXME: eventually u64
obj {
fn get_buf_reader() -> buf_reader;
fn read_byte() -> int;
fn unread_byte(int);
fn read_bytes(uint) -> [u8];
fn read_char() -> char;
fn read_chars(uint) -> [char];
fn eof() -> bool;
fn read_line() -> str;
fn read_c_str() -> str;
fn read_le_uint(uint) -> uint;
fn read_le_int(uint) -> int;
fn read_be_uint(uint) -> uint;
fn read_whole_stream() -> [u8];
fn seek(int, seek_style);
fn tell() -> uint;
};
fn convert_whence(whence: seek_style) -> i32 {
ret alt whence {
seek_set. { 0i32 }
seek_cur. { 1i32 }
seek_end. { 2i32 }
};
// The raw underlying reader iface. All readers must implement this.
iface reader {
// FIXME: Seekable really should be orthogonal.
fn read_bytes(uint) -> [u8];
fn read_byte() -> int;
fn unread_byte(int);
fn eof() -> bool;
fn seek(int, seek_style);
fn tell() -> uint;
}
resource FILE_res(f: os::libc::FILE) {
os::libc::fclose(f);
}
// Generic utility functions defined on readers
obj FILE_buf_reader(f: os::libc::FILE, res: option::t<@FILE_res>) {
fn read(len: uint) -> [u8] unsafe {
let buf = [];
vec::reserve::<u8>(buf, len);
let read =
os::libc::fread(vec::unsafe::to_ptr::<u8>(buf), 1u, len, f);
vec::unsafe::set_len::<u8>(buf, read);
ret buf;
}
fn read_byte() -> int { ret os::libc::fgetc(f) as int; }
fn unread_byte(byte: int) { os::libc::ungetc(byte as i32, f); }
fn eof() -> bool { ret os::libc::feof(f) != 0i32; }
fn seek(offset: int, whence: seek_style) {
assert (os::libc::fseek(f, offset, convert_whence(whence)) == 0i32);
}
fn tell() -> uint { ret os::libc::ftell(f) as uint; }
fn fsync(level: fsync::level) -> int {
ret os::fsync_fd(os::libc::fileno(f), level) as int;
}
}
// FIXME: Convert this into pseudomethods on buf_reader.
obj new_reader(rdr: buf_reader) {
fn get_buf_reader() -> buf_reader { ret rdr; }
fn read_byte() -> int { ret rdr.read_byte(); }
fn unread_byte(byte: int) { ret rdr.unread_byte(byte); }
fn read_bytes(len: uint) -> [u8] { ret rdr.read(len); }
impl reader_util for reader {
fn read_chars(n: uint) -> [char] {
// returns the (consumed offset, n_req), appends characters to &chars
fn chars_from_buf(buf: [u8], &chars: [char]) -> (uint, uint) {
@ -158,8 +90,9 @@ obj new_reader(rdr: buf_reader) {
buf = vec::slice(buf, offset, vec::len(buf));
}
}
ret chars;
chars
}
fn read_char() -> char {
let c = self.read_chars(1u);
if vec::len(c) == 0u {
@ -168,75 +101,116 @@ obj new_reader(rdr: buf_reader) {
assert(vec::len(c) == 1u);
ret c[0];
}
fn eof() -> bool { ret rdr.eof(); }
fn read_line() -> str {
let buf: [u8] = [];
// No break yet in rustc
let go_on = true;
while go_on {
let ch = rdr.read_byte();
if ch == -1 || ch == 10 {
go_on = false;
} else { buf += [ch as u8]; }
while true {
let ch = self.read_byte();
if ch == -1 || ch == 10 { break; }
buf += [ch as u8];
}
ret str::unsafe_from_bytes(buf);
str::unsafe_from_bytes(buf)
}
fn read_c_str() -> str {
let buf: [u8] = [];
let go_on = true;
while go_on {
let ch = rdr.read_byte();
if ch < 1 { go_on = false; } else { buf += [ch as u8]; }
while true {
let ch = self.read_byte();
if ch < 1 { break; } else { buf += [ch as u8]; }
}
ret str::unsafe_from_bytes(buf);
str::unsafe_from_bytes(buf)
}
// FIXME deal with eof?
fn read_le_uint(size: uint) -> uint {
let val = 0u;
let pos = 0u;
let i = size;
let val = 0u, pos = 0u, i = size;
while i > 0u {
val += (rdr.read_byte() as uint) << pos;
val += (self.read_byte() as uint) << pos;
pos += 8u;
i -= 1u;
}
ret val;
val
}
fn read_le_int(size: uint) -> int {
let val = 0u, pos = 0u, i = size;
while i > 0u {
val += (rdr.read_byte() as uint) << pos;
val += (self.read_byte() as uint) << pos;
pos += 8u;
i -= 1u;
}
ret val as int;
val as int
}
// FIXME deal with eof?
fn read_be_uint(sz: uint) -> uint {
let val = 0u, i = sz;
fn read_be_uint(size: uint) -> uint {
let val = 0u, i = size;
while i > 0u {
i -= 1u;
val += (rdr.read_byte() as uint) << i * 8u;
val += (self.read_byte() as uint) << i * 8u;
}
ret val;
val
}
fn read_whole_stream() -> [u8] {
let buf: [u8] = [];
while !rdr.eof() { buf += rdr.read(2048u); }
ret buf;
while !self.eof() { buf += self.read_bytes(2048u); }
buf
}
fn seek(offset: int, whence: seek_style) { ret rdr.seek(offset, whence); }
fn tell() -> uint { ret rdr.tell(); }
}
fn stdin() -> reader {
ret new_reader(FILE_buf_reader(rustrt::rust_get_stdin(), option::none));
// Reader implementations
fn convert_whence(whence: seek_style) -> i32 {
ret alt whence {
seek_set. { 0i32 }
seek_cur. { 1i32 }
seek_end. { 2i32 }
};
}
impl of reader for os::libc::FILE {
fn read_bytes(len: uint) -> [u8] unsafe {
let buf = [];
vec::reserve(buf, len);
let read = os::libc::fread(vec::unsafe::to_ptr(buf), 1u, len, self);
vec::unsafe::set_len(buf, read);
ret buf;
}
fn read_byte() -> int { ret os::libc::fgetc(self) as int; }
fn unread_byte(byte: int) { os::libc::ungetc(byte as i32, self); }
fn eof() -> bool { ret os::libc::feof(self) != 0i32; }
fn seek(offset: int, whence: seek_style) {
assert os::libc::fseek(self, offset, convert_whence(whence)) == 0i32;
}
fn tell() -> uint { ret os::libc::ftell(self) as uint; }
}
// A forwarding impl of reader that also holds on to a resource for the
// duration of its lifetime.
// FIXME there really should be a better way to do this
impl <T: reader, C> of reader for {base: T, cleanup: C} {
fn read_bytes(len: uint) -> [u8] { self.base.read_bytes(len) }
fn read_byte() -> int { self.base.read_byte() }
fn unread_byte(byte: int) { self.base.unread_byte(byte); }
fn eof() -> bool { self.base.eof() }
fn seek(off: int, whence: seek_style) { self.base.seek(off, whence) }
fn tell() -> uint { self.base.tell() }
}
resource FILE_res(f: os::libc::FILE) { os::libc::fclose(f); }
fn FILE_reader(f: os::libc::FILE, cleanup: bool) -> reader {
if cleanup {
{base: f, cleanup: FILE_res(f)} as reader
} else {
f as reader
}
}
// FIXME: this should either be an iface-less impl, a set of top-level
// functions that take a reader, or a set of default methods on reader
// (which can then be called reader)
fn stdin() -> reader { rustrt::rust_get_stdin() as reader }
fn file_reader(path: str) -> result::t<reader, str> {
let f = str::as_buf(path, {|pathbuf|
str::as_buf("r", {|modebuf|
@ -245,7 +219,7 @@ fn file_reader(path: str) -> result::t<reader, str> {
});
ret if f as uint == 0u { result::err("error opening " + path) }
else {
result::ok(new_reader(FILE_buf_reader(f, option::some(@FILE_res(f)))))
result::ok(FILE_reader(f, true))
}
}
@ -253,90 +227,91 @@ fn file_reader(path: str) -> result::t<reader, str> {
// Byte buffer readers
// TODO: const u8, but this fails with rustboot.
type byte_buf = @{buf: [u8], mutable pos: uint};
type byte_buf = {buf: [u8], mutable pos: uint};
obj byte_buf_reader(bbuf: byte_buf) {
fn read(len: uint) -> [u8] {
let rest = vec::len::<u8>(bbuf.buf) - bbuf.pos;
impl of reader for byte_buf {
fn read_bytes(len: uint) -> [u8] {
let rest = vec::len(self.buf) - self.pos;
let to_read = len;
if rest < to_read { to_read = rest; }
let range = vec::slice::<u8>(bbuf.buf, bbuf.pos, bbuf.pos + to_read);
bbuf.pos += to_read;
let range = vec::slice(self.buf, self.pos, self.pos + to_read);
self.pos += to_read;
ret range;
}
fn read_byte() -> int {
if bbuf.pos == vec::len::<u8>(bbuf.buf) { ret -1; }
let b = bbuf.buf[bbuf.pos];
bbuf.pos += 1u;
if self.pos == vec::len(self.buf) { ret -1; }
let b = self.buf[self.pos];
self.pos += 1u;
ret b as int;
}
fn unread_byte(_byte: int) { #error("TODO: unread_byte"); fail; }
fn eof() -> bool { ret bbuf.pos == vec::len::<u8>(bbuf.buf); }
fn eof() -> bool { self.pos == vec::len(self.buf) }
fn seek(offset: int, whence: seek_style) {
let pos = bbuf.pos;
let len = vec::len::<u8>(bbuf.buf);
bbuf.pos = seek_in_buf(offset, pos, len, whence);
let pos = self.pos;
let len = vec::len(self.buf);
self.pos = seek_in_buf(offset, pos, len, whence);
}
fn tell() -> uint { ret bbuf.pos; }
fn fsync(_level: fsync::level) -> int { ret 0; }
}
fn new_byte_buf_reader(buf: [u8]) -> buf_reader {
ret byte_buf_reader(@{buf: buf, mutable pos: 0u});
fn tell() -> uint { self.pos }
}
fn bytes_reader(bytes: [u8]) -> reader {
ret new_reader(new_byte_buf_reader(bytes));
{buf: bytes, mutable pos: 0u} as reader
}
fn string_reader(s: str) -> reader {
ret new_reader(new_byte_buf_reader(str::bytes(s)));
bytes_reader(str::bytes(s))
}
// Writing
tag fileflag { append; create; truncate; none; }
type buf_writer =
// FIXME: Seekable really should be orthogonal. We will need
// inheritance.
// FIXME: eventually u64
// FIXME: Seekable really should be orthogonal.
// FIXME: eventually u64
iface writer {
fn write([const u8]);
fn seek(int, seek_style);
fn tell() -> uint;
fn flush() -> int;
}
obj {
fn write([const u8]);
fn seek(int, seek_style);
fn tell() -> uint;
fn flush() -> int;
fn fsync(level: fsync::level) -> int;
};
impl <T: writer, C> of writer for {base: T, cleanup: C} {
fn write(bs: [const u8]) { self.base.write(bs); }
fn seek(off: int, style: seek_style) { self.base.seek(off, style); }
fn tell() -> uint { self.base.tell() }
fn flush() -> int { self.base.flush() }
}
obj FILE_writer(f: os::libc::FILE, res: option::t<@FILE_res>) {
impl of writer for os::libc::FILE {
fn write(v: [const u8]) unsafe {
let len = vec::len::<u8>(v);
let vbuf = vec::unsafe::to_ptr::<u8>(v);
let nout = os::libc::fwrite(vbuf, len, 1u, f);
let len = vec::len(v);
let vbuf = vec::unsafe::to_ptr(v);
let nout = os::libc::fwrite(vbuf, len, 1u, self);
if nout < 1u { #error("error dumping buffer"); }
}
fn seek(offset: int, whence: seek_style) {
assert (os::libc::fseek(f, offset, convert_whence(whence)) == 0i32);
assert os::libc::fseek(self, offset, convert_whence(whence)) == 0i32;
}
fn tell() -> uint { ret os::libc::ftell(f) as uint; }
fn flush() -> int { ret os::libc::fflush(f) as int; }
fn fsync(level: fsync::level) -> int {
ret os::fsync_fd(os::libc::fileno(f), level) as int;
fn tell() -> uint { os::libc::ftell(self) as uint }
fn flush() -> int { os::libc::fflush(self) as int }
}
fn FILE_writer(f: os::libc::FILE, cleanup: bool) -> writer {
if cleanup {
{base: f, cleanup: FILE_res(f)} as writer
} else {
f as writer
}
}
resource fd_res(fd: fd_t) { os::libc::close(fd); }
obj fd_buf_writer(fd: fd_t, res: option::t<@fd_res>) {
impl of writer for fd_t {
fn write(v: [const u8]) unsafe {
let len = vec::len::<u8>(v);
let len = vec::len(v);
let count = 0u;
let vbuf;
while count < len {
vbuf = ptr::offset(vec::unsafe::to_ptr::<u8>(v), count);
let nout = os::libc::write(fd, vbuf, len);
vbuf = ptr::offset(vec::unsafe::to_ptr(v), count);
let nout = os::libc::write(self, vbuf, len);
if nout < 0 {
#error("error dumping buffer");
log(error, sys::last_os_error());
@ -353,16 +328,21 @@ obj fd_buf_writer(fd: fd_t, res: option::t<@fd_res>) {
#error("need 64-bit native calls for tell, sorry");
fail;
}
fn flush() -> int { 0 }
}
fn flush() -> int { ret 0; }
resource fd_res(fd: fd_t) { os::libc::close(fd); }
fn fsync(level: fsync::level) -> int {
ret os::fsync_fd(fd, level) as int;
fn fd_writer(fd: fd_t, cleanup: bool) -> writer {
if cleanup {
{base: fd, cleanup: fd_res(fd)} as writer
} else {
fd as writer
}
}
fn file_buf_writer(path: str,
flags: [fileflag]) -> result::t<buf_writer, str> {
fn mk_file_writer(path: str, flags: [fileflag])
-> result::t<writer, str> {
let fflags: i32 =
os::libc_constants::O_WRONLY | os::libc_constants::O_BINARY;
for f: fileflag in flags {
@ -373,37 +353,19 @@ fn file_buf_writer(path: str,
none. { }
}
}
let fd =
str::as_buf(path,
{|pathbuf|
os::libc::open(pathbuf, fflags,
os::libc_constants::S_IRUSR |
os::libc_constants::S_IWUSR)
});
ret if fd < 0i32 {
let fd = str::as_buf(path, {|pathbuf|
os::libc::open(pathbuf, fflags, os::libc_constants::S_IRUSR |
os::libc_constants::S_IWUSR)
});
if fd < 0i32 {
// FIXME don't log this! put it in the returned error string
log(error, sys::last_os_error());
result::err("error opening " + path)
} else {
result::ok(fd_buf_writer(fd, option::some(@fd_res(fd))))
result::ok(fd_writer(fd, true))
}
}
type writer =
// write_str will continue to do utf-8 output only. an alternative
// function will be provided for general encoded string output
obj {
fn get_buf_writer() -> buf_writer;
fn write_str(str);
fn write_line(str);
fn write_char(char);
fn write_int(int);
fn write_uint(uint);
fn write_bytes([const u8]);
fn write_le_uint(uint, uint);
fn write_le_int(int, uint);
fn write_be_uint(uint, uint);
};
fn uint_to_le_bytes(n: uint, size: uint) -> [u8] {
let bytes: [u8] = [], i = size, n = n;
while i > 0u { bytes += [n & 255u as u8]; n >>= 8u; i -= 1u; }
@ -417,130 +379,89 @@ fn uint_to_be_bytes(n: uint, size: uint) -> [u8] {
ret bytes;
}
obj new_writer(out: buf_writer) {
fn get_buf_writer() -> buf_writer { ret out; }
fn write_str(s: str) { out.write(str::bytes(s)); }
fn write_line(s: str) {
out.write(str::bytes(s));
out.write(str::bytes("\n"));
}
impl writer_util for writer {
fn write_char(ch: char) {
// FIXME needlessly consy
out.write(str::bytes(str::from_char(ch)));
if ch as uint < 128u {
self.write([ch as u8]);
} else {
self.write(str::bytes(str::from_char(ch)));
}
}
fn write_int(n: int) { out.write(str::bytes(int::to_str(n, 10u))); }
fn write_uint(n: uint) { out.write(str::bytes(uint::to_str(n, 10u))); }
fn write_bytes(bytes: [const u8]) { out.write(bytes); }
fn write_str(s: str) { self.write(str::bytes(s)); }
fn write_line(s: str) { self.write(str::bytes(s + "\n")); }
fn write_int(n: int) { self.write(str::bytes(int::to_str(n, 10u))); }
fn write_uint(n: uint) { self.write(str::bytes(uint::to_str(n, 10u))); }
fn write_le_uint(n: uint, size: uint) {
out.write(uint_to_le_bytes(n, size));
self.write(uint_to_le_bytes(n, size));
}
fn write_le_int(n: int, size: uint) {
out.write(uint_to_le_bytes(n as uint, size));
self.write(uint_to_le_bytes(n as uint, size));
}
fn write_be_uint(n: uint, size: uint) {
out.write(uint_to_be_bytes(n, size));
self.write(uint_to_be_bytes(n, size));
}
}
fn file_writer(path: str, flags: [fileflag]) -> result::t<writer, str> {
result::chain(file_buf_writer(path, flags), { |w|
result::ok(new_writer(w))
})
result::chain(mk_file_writer(path, flags), { |w| result::ok(w)})
}
// FIXME: fileflags
fn buffered_file_buf_writer(path: str) -> result::t<buf_writer, str> {
let f =
str::as_buf(path,
{|pathbuf|
str::as_buf("w",
{|modebuf|
os::libc::fopen(pathbuf, modebuf)
})
});
fn buffered_file_writer(path: str) -> result::t<writer, str> {
let f = str::as_buf(path, {|pathbuf|
str::as_buf("w", {|modebuf| os::libc::fopen(pathbuf, modebuf) })
});
ret if f as uint == 0u { result::err("error opening " + path) }
else { result::ok(FILE_writer(f, option::some(@FILE_res(f)))) }
else { result::ok(FILE_writer(f, true)) }
}
// FIXME it would be great if this could be a const
// Problem seems to be that new_writer is not pure
fn stdout() -> writer { ret new_writer(fd_buf_writer(1i32, option::none)); }
fn stderr() -> writer { ret new_writer(fd_buf_writer(2i32, option::none)); }
fn stdout() -> writer { fd_writer(1i32, false) }
fn stderr() -> writer { fd_writer(2i32, false) }
fn print(s: str) { stdout().write_str(s); }
fn println(s: str) { stdout().write_str(s + "\n"); }
fn println(s: str) { stdout().write_line(s); }
type bytes_writer =
obj {
fn get_writer() -> writer;
fn get_bytes() -> [mutable u8];
};
type mem_buffer = @{mutable buf: [mutable u8],
mutable pos: uint};
type str_writer =
obj {
fn get_writer() -> writer;
fn get_str() -> str;
};
type mutable_byte_buf = @{mutable buf: [mutable u8], mutable pos: uint};
obj byte_buf_writer(buf: mutable_byte_buf) {
impl of writer for mem_buffer {
fn write(v: [const u8]) {
// Fast path.
if buf.pos == vec::len(buf.buf) {
for b: u8 in v { buf.buf += [mutable b]; }
buf.pos += vec::len::<u8>(v);
if self.pos == vec::len(self.buf) {
for b: u8 in v { self.buf += [mutable b]; }
self.pos += vec::len(v);
ret;
}
// FIXME: Optimize: These should be unique pointers.
let vlen = vec::len::<u8>(v);
let vlen = vec::len(v);
let vpos = 0u;
while vpos < vlen {
let b = v[vpos];
if buf.pos == vec::len(buf.buf) {
buf.buf += [mutable b];
} else { buf.buf[buf.pos] = b; }
buf.pos += 1u;
if self.pos == vec::len(self.buf) {
self.buf += [mutable b];
} else { self.buf[self.pos] = b; }
self.pos += 1u;
vpos += 1u;
}
}
fn seek(offset: int, whence: seek_style) {
let pos = buf.pos;
let len = vec::len(buf.buf);
buf.pos = seek_in_buf(offset, pos, len, whence);
let pos = self.pos;
let len = vec::len(self.buf);
self.pos = seek_in_buf(offset, pos, len, whence);
}
fn tell() -> uint { ret buf.pos; }
fn flush() -> int { ret 0; }
fn fsync(_level: fsync::level) -> int { ret 0; }
fn tell() -> uint { self.pos }
fn flush() -> int { 0 }
}
fn bytes_writer() -> bytes_writer {
// FIXME: yikes, this is bad. Needs fixing of mutable syntax.
let b: [mutable u8] = [mutable 0u8];
vec::pop(b);
let buf = @{mutable buf: b, mutable pos: 0u};
obj byte_buf_writer_wrap(wr: writer, buf: mutable_byte_buf) {
fn get_writer() -> writer { ret wr; }
fn get_bytes() -> [mutable u8] { ret buf.buf; }
}
ret byte_buf_writer_wrap(new_writer(byte_buf_writer(buf)), buf);
fn mk_mem_buffer() -> mem_buffer {
@{mutable buf: [mutable], mutable pos: 0u}
}
fn string_writer() -> str_writer {
let writer = bytes_writer();
obj str_writer_wrap(wr: bytes_writer) {
fn get_writer() -> writer { wr.get_writer() }
fn get_str() -> str { str::unsafe_from_bytes(wr.get_bytes()) }
}
str_writer_wrap(writer)
}
fn mem_buffer_writer(b: mem_buffer) -> writer { b as writer }
fn mem_buffer_buf(b: mem_buffer) -> [u8] { vec::from_mut(b.buf) }
fn mem_buffer_str(b: mem_buffer) -> str { str::unsafe_from_bytes(b.buf) }
// Utility functions
fn seek_in_buf(offset: int, pos: uint, len: uint, whence: seek_style) ->
@ -562,9 +483,9 @@ fn read_whole_file_str(file: str) -> result::t<str, str> {
})
}
// FIXME implement this in a low-level way. Going through the abstractions is
// pointless.
fn read_whole_file(file: str) -> result::t<[u8], str> {
// FIXME: There's a lot of copying here
result::chain(file_reader(file), { |rdr|
result::ok(rdr.read_whole_stream())
})
@ -591,8 +512,8 @@ mod fsync {
// Resource of artifacts that need to fsync on destruction
resource res<t>(arg: arg<t>) {
alt arg.opt_level {
option::none::<level>. { }
option::some::<level>(level) {
option::none. { }
option::some(level) {
// fail hard if not succesful
assert(arg.fsync_fn(arg.val, level) != -1);
}
@ -629,7 +550,7 @@ mod fsync {
}
// Type of objects that may want to fsync
type t = obj { fn fsync(l: level) -> int; };
iface t { fn fsync(l: level) -> int; }
// Call o.fsync after executing blk
fn obj_sync(&&o: t, opt_level: option::t<level>, blk: block(&&res<t>)) {

View file

@ -197,15 +197,9 @@ fn start_program(prog: str, args: [str]) -> program {
impl of program for prog_res {
fn get_id() -> pid_t { ret self.pid; }
fn input() -> io::writer {
ret io::new_writer(io::fd_buf_writer(self.in_fd, none));
}
fn output() -> io::reader {
ret io::new_reader(io::FILE_buf_reader(self.out_file, none));
}
fn err() -> io::reader {
ret io::new_reader(io::FILE_buf_reader(self.err_file, none));
}
fn input() -> io::writer { io::fd_writer(self.in_fd, false) }
fn output() -> io::reader { io::FILE_reader(self.out_file, false) }
fn err() -> io::reader { io::FILE_reader(self.err_file, false) }
fn close_input() { close_repr_input(*self); }
fn finish() -> int { finish_repr(*self) }
fn destroy() { destroy_repr(*self); }

View file

@ -45,14 +45,14 @@ const color_bright_cyan: u8 = 14u8;
/* Const: color_bright_white */
const color_bright_white: u8 = 15u8;
fn esc(writer: io::buf_writer) { writer.write([0x1bu8, '[' as u8]); }
fn esc(writer: io::writer) { writer.write([0x1bu8, '[' as u8]); }
/*
Function: reset
Reset the foreground and background colors to default
*/
fn reset(writer: io::buf_writer) {
fn reset(writer: io::writer) {
esc(writer);
writer.write(['0' as u8, 'm' as u8]);
}
@ -76,7 +76,7 @@ fn color_supported() -> bool {
};
}
fn set_color(writer: io::buf_writer, first_char: u8, color: u8) {
fn set_color(writer: io::writer, first_char: u8, color: u8) {
assert (color < 16u8);
esc(writer);
let color = color;
@ -89,7 +89,7 @@ Function: fg
Set the foreground color
*/
fn fg(writer: io::buf_writer, color: u8) {
fn fg(writer: io::writer, color: u8) {
ret set_color(writer, '3' as u8, color);
}
@ -98,7 +98,7 @@ Function: fg
Set the background color
*/
fn bg(writer: io::buf_writer, color: u8) {
fn bg(writer: io::writer, color: u8) {
ret set_color(writer, '4' as u8, color);
}

View file

@ -3,13 +3,7 @@
// simplest interface possible for representing and running tests
// while providing a base that other test frameworks may build off of.
import core::comm;
import core::task;
import task::task;
import core::option;
import core::either;
import core::vec;
import core::result::{ok, err};
import result::{ok, err};
export test_name;
export test_fn;
@ -36,6 +30,12 @@ native mod rustrt {
fn sched_threads() -> uint;
}
// FIXME Kludge to work around issue #1494 . Simply import io::writer_util
// when that is fixed.
impl writer_util for io::writer {
fn write_str(s: str) { self.write(str::bytes(s)); }
fn write_line(s: str) { self.write(str::bytes(s + "\n")); }
}
// The name of a test. By convention this follows the rules for rust
// paths; i.e. it should be a series of identifiers seperated by double
@ -101,7 +101,7 @@ fn parse_opts(args: [str]) : vec::is_not_empty(args) -> opt_res {
tag test_result { tr_ok; tr_failed; tr_ignored; }
type joinable = (task, comm::port<task::task_notification>);
type joinable = (task::task, comm::port<task::task_notification>);
// To get isolation and concurrency tests have to be run in their own tasks.
// In cases where test functions are closures it is not ok to just dump them
@ -203,11 +203,11 @@ fn run_tests_console_<T: copy>(opts: test_opts, tests: [test_desc<T>],
fn write_pretty(out: io::writer, word: str, color: u8, use_color: bool) {
if use_color && term::color_supported() {
term::fg(out.get_buf_writer(), color);
term::fg(out, color);
}
out.write_str(word);
if use_color && term::color_supported() {
term::reset(out.get_buf_writer());
term::reset(out);
}
}
}

View file

@ -13,6 +13,7 @@ import rustc::syntax::parse::parser;
import rustc::syntax::print::pprust;
import rustc::syntax::visit;
import std::io;
import io::writer_util;
import std::map;
type rustdoc = {

View file

@ -12,16 +12,9 @@
use std;
import vec;
import uint;
import std::time;
import str;
import std::{time, io, getopts};
import io::writer_util;
import int::range;
import std::io;
import std::getopts;
import task;
import u64;
import comm;
import comm::port;
import comm::chan;
import comm::send;

View file

@ -1,11 +1,7 @@
use std;
import std::io;
import str;
import uint;
import u8;
import vec;
import std::bitv;
import std::{io, bitv};
import io::{writer_util, reader_util};
// Computes a single solution to a given 9x9 sudoku
//

View file

@ -11,20 +11,11 @@
use std;
import option = option::t;
import option::some;
import option::none;
import str;
import std::map;
import vec;
import std::io;
import option::{some, none};
import std::{map, io, time};
import io::reader_util;
import std::time;
import u64;
import result;
import task;
import task::joinable_task;
import comm;
import comm::chan;
import comm::port;
import comm::recv;
@ -210,7 +201,6 @@ fn read_word(r: io::reader) -> option<str> {
while !r.eof() {
let c = r.read_char();
if is_word_char(c) {
w += str::from_char(c);
} else { if w != "" { ret some(w); } }

View file

@ -3,6 +3,7 @@ import core::*;
// -*- rust -*-
use std;
import std::io;
import io::{writer_util, reader_util};
import str;
import result;
@ -82,8 +83,8 @@ fn file_reader_not_exist() {
}
#[test]
fn file_buf_writer_bad_name() {
alt io::file_buf_writer("?/?", []) {
fn file_writer_bad_name() {
alt io::file_writer("?/?", []) {
result::err(e) {
assert e == "error opening ?/?";
}
@ -92,8 +93,8 @@ fn file_buf_writer_bad_name() {
}
#[test]
fn buffered_file_buf_writer_bad_name() {
alt io::buffered_file_buf_writer("?/?") {
fn buffered_file_writer_bad_name() {
alt io::buffered_file_writer("?/?") {
result::err(e) {
assert e == "error opening ?/?";
}

View file

@ -44,7 +44,7 @@ fn test() {
}
}
// Regression test for #705
// Regression test for #750
#[test]
fn test_simple() {
let names = [mutable 2, 1, 3];

View file

@ -4,6 +4,7 @@ use std;
import std::run;
import std::os;
import std::io;
import io::writer_util;
import option;
import str;
import ctypes::fd_t;
@ -41,7 +42,7 @@ fn test_pipes() {
fn writeclose(fd: fd_t, s: str) {
#error("writeclose %d, %s", fd as int, s);
let writer = io::new_writer(io::fd_buf_writer(fd, option::none));
let writer = io::fd_writer(fd, false);
writer.write_str(s);
os::close(fd);
@ -50,7 +51,7 @@ fn test_pipes() {
fn readclose(fd: fd_t) -> str {
// Copied from run::program_output
let file = os::fd_FILE(fd);
let reader = io::new_reader(io::FILE_buf_reader(file, option::none));
let reader = io::FILE_reader(file, false);
let buf = "";
while !reader.eof() {
let bytes = reader.read_bytes(4096u);