use std::str;
+macro_rules! if_ok( ($e:expr) => (
+ match $e { Ok(e) => e, Err(e) => { self.last_error = Err(e); return } }
+) )
+
// Simple Extensible Binary Markup Language (ebml) reader and writer on a
// cursor model. See the specification here:
// http://www.matroska.org/technical/specs/rfc/index.html
// ebml writing
pub struct Encoder<'a> {
- // FIXME(#5665): this should take a trait object
+ // FIXME(#5665): this should take a trait object. Note that if you
+ // delete this comment you should consider removing the
+ // unwrap()'s below of the results of the calls to
+ // write(). We're guaranteed that writing into a MemWriter
+ // won't fail, but this is not true for all I/O streams in
+ // general.
writer: &'a mut MemWriter,
priv size_positions: ~[uint],
+ last_error: io::IoResult<()>,
}
fn write_sized_vuint(w: &mut MemWriter, n: uint, size: uint) {
4u => w.write(&[0x10u8 | ((n >> 24_u) as u8), (n >> 16_u) as u8,
(n >> 8_u) as u8, n as u8]),
_ => fail!("vint to write too big: {}", n)
- };
+ }.unwrap()
}
fn write_vuint(w: &mut MemWriter, n: uint) {
let size_positions: ~[uint] = ~[];
Encoder {
writer: w,
- size_positions: size_positions
+ size_positions: size_positions,
+ last_error: Ok(()),
}
}
Encoder {
writer: cast::transmute_copy(&self.writer),
size_positions: self.size_positions.clone(),
+ last_error: Ok(()),
}
}
write_vuint(self.writer, tag_id);
// Write a placeholder four-byte size.
- self.size_positions.push(self.writer.tell() as uint);
+ self.size_positions.push(if_ok!(self.writer.tell()) as uint);
let zeroes: &[u8] = &[0u8, 0u8, 0u8, 0u8];
- self.writer.write(zeroes);
+ if_ok!(self.writer.write(zeroes));
}
pub fn end_tag(&mut self) {
let last_size_pos = self.size_positions.pop().unwrap();
- let cur_pos = self.writer.tell();
- self.writer.seek(last_size_pos as i64, io::SeekSet);
+ let cur_pos = if_ok!(self.writer.tell());
+ if_ok!(self.writer.seek(last_size_pos as i64, io::SeekSet));
let size = (cur_pos as uint - last_size_pos - 4);
write_sized_vuint(self.writer, size, 4u);
- self.writer.seek(cur_pos as i64, io::SeekSet);
+ if_ok!(self.writer.seek(cur_pos as i64, io::SeekSet));
debug!("End tag (size = {})", size);
}
pub fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) {
write_vuint(self.writer, tag_id);
write_vuint(self.writer, b.len());
- self.writer.write(b);
+ self.writer.write(b).unwrap();
}
pub fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) {
pub fn wr_bytes(&mut self, b: &[u8]) {
debug!("Write {} bytes", b.len());
- self.writer.write(b);
+ self.writer.write(b).unwrap();
}
pub fn wr_str(&mut self, s: &str) {
debug!("Write str: {}", s);
- self.writer.write(s.as_bytes());
+ self.writer.write(s.as_bytes()).unwrap();
}
}
use serialize;
use treemap::TreeMap;
+macro_rules! if_ok( ($e:expr) => (
+ match $e { Ok(e) => e, Err(e) => { self.error = Err(e); return } }
+) )
+
/// Represents a json value
#[deriving(Clone, Eq)]
pub enum Json {
priv msg: ~str,
}
+fn io_error_to_error(io: io::IoError) -> Error {
+ Error {
+ line: 0,
+ col: 0,
+ msg: format!("io error: {}", io)
+ }
+}
+
fn escape_str(s: &str) -> ~str {
let mut escaped = ~"\"";
for c in s.chars() {
/// A structure for implementing serialization to JSON.
pub struct Encoder<'a> {
priv wr: &'a mut io::Writer,
+ priv error: io::IoResult<()>,
}
impl<'a> Encoder<'a> {
/// Creates a new JSON encoder whose output will be written to the writer
/// specified.
pub fn new<'a>(wr: &'a mut io::Writer) -> Encoder<'a> {
- Encoder { wr: wr }
+ Encoder { wr: wr, error: Ok(()) }
}
/// Encode the specified struct into a json [u8]
}
impl<'a> serialize::Encoder for Encoder<'a> {
- fn emit_nil(&mut self) { write!(self.wr, "null") }
+ fn emit_nil(&mut self) { if_ok!(write!(self.wr, "null")) }
fn emit_uint(&mut self, v: uint) { self.emit_f64(v as f64); }
fn emit_u64(&mut self, v: u64) { self.emit_f64(v as f64); }
fn emit_bool(&mut self, v: bool) {
if v {
- write!(self.wr, "true");
+ if_ok!(write!(self.wr, "true"));
} else {
- write!(self.wr, "false");
+ if_ok!(write!(self.wr, "false"));
}
}
fn emit_f64(&mut self, v: f64) {
- write!(self.wr, "{}", f64::to_str_digits(v, 6u))
+ if_ok!(write!(self.wr, "{}", f64::to_str_digits(v, 6u)))
}
fn emit_f32(&mut self, v: f32) { self.emit_f64(v as f64); }
fn emit_char(&mut self, v: char) { self.emit_str(str::from_char(v)) }
fn emit_str(&mut self, v: &str) {
- write!(self.wr, "{}", escape_str(v))
+ if_ok!(write!(self.wr, "{}", escape_str(v)))
}
fn emit_enum(&mut self, _name: &str, f: |&mut Encoder<'a>|) { f(self) }
// Bunny => "Bunny"
// Kangaroo(34,"William") => {"variant": "Kangaroo", "fields": [34,"William"]}
if cnt == 0 {
- write!(self.wr, "{}", escape_str(name));
+ if_ok!(write!(self.wr, "{}", escape_str(name)));
} else {
- write!(self.wr, "\\{\"variant\":");
- write!(self.wr, "{}", escape_str(name));
- write!(self.wr, ",\"fields\":[");
+ if_ok!(write!(self.wr, "\\{\"variant\":"));
+ if_ok!(write!(self.wr, "{}", escape_str(name)));
+ if_ok!(write!(self.wr, ",\"fields\":["));
f(self);
- write!(self.wr, "]\\}");
+ if_ok!(write!(self.wr, "]\\}"));
}
}
fn emit_enum_variant_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
if idx != 0 {
- write!(self.wr, ",");
+ if_ok!(write!(self.wr, ","));
}
f(self);
}
}
fn emit_struct(&mut self, _: &str, _: uint, f: |&mut Encoder<'a>|) {
- write!(self.wr, r"\{");
+ if_ok!(write!(self.wr, r"\{"));
f(self);
- write!(self.wr, r"\}");
+ if_ok!(write!(self.wr, r"\}"));
}
fn emit_struct_field(&mut self,
name: &str,
idx: uint,
f: |&mut Encoder<'a>|) {
- if idx != 0 { write!(self.wr, ",") }
- write!(self.wr, "{}:", escape_str(name));
+ if idx != 0 { if_ok!(write!(self.wr, ",")) }
+ if_ok!(write!(self.wr, "{}:", escape_str(name)));
f(self);
}
fn emit_option_some(&mut self, f: |&mut Encoder<'a>|) { f(self); }
fn emit_seq(&mut self, _len: uint, f: |&mut Encoder<'a>|) {
- write!(self.wr, "[");
+ if_ok!(write!(self.wr, "["));
f(self);
- write!(self.wr, "]");
+ if_ok!(write!(self.wr, "]"));
}
fn emit_seq_elt(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
if idx != 0 {
- write!(self.wr, ",");
+ if_ok!(write!(self.wr, ","));
}
f(self)
}
fn emit_map(&mut self, _len: uint, f: |&mut Encoder<'a>|) {
- write!(self.wr, r"\{");
+ if_ok!(write!(self.wr, r"\{"));
f(self);
- write!(self.wr, r"\}");
+ if_ok!(write!(self.wr, r"\}"));
}
fn emit_map_elt_key(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
- if idx != 0 { write!(self.wr, ",") }
+ if idx != 0 { if_ok!(write!(self.wr, ",")) }
f(self)
}
fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
- write!(self.wr, ":");
+ if_ok!(write!(self.wr, ":"));
f(self)
}
}
pub struct PrettyEncoder<'a> {
priv wr: &'a mut io::Writer,
priv indent: uint,
+ priv error: io::IoResult<()>,
}
impl<'a> PrettyEncoder<'a> {
PrettyEncoder {
wr: wr,
indent: 0,
+ error: Ok(())
}
}
}
impl<'a> serialize::Encoder for PrettyEncoder<'a> {
- fn emit_nil(&mut self) { write!(self.wr, "null") }
+ fn emit_nil(&mut self) { if_ok!(write!(self.wr, "null")); }
fn emit_uint(&mut self, v: uint) { self.emit_f64(v as f64); }
fn emit_u64(&mut self, v: u64) { self.emit_f64(v as f64); }
fn emit_bool(&mut self, v: bool) {
if v {
- write!(self.wr, "true");
+ if_ok!(write!(self.wr, "true"));
} else {
- write!(self.wr, "false");
+ if_ok!(write!(self.wr, "false"));
}
}
fn emit_f64(&mut self, v: f64) {
- write!(self.wr, "{}", f64::to_str_digits(v, 6u))
+ if_ok!(write!(self.wr, "{}", f64::to_str_digits(v, 6u)));
}
fn emit_f32(&mut self, v: f32) { self.emit_f64(v as f64); }
fn emit_char(&mut self, v: char) { self.emit_str(str::from_char(v)) }
- fn emit_str(&mut self, v: &str) { write!(self.wr, "{}", escape_str(v)); }
+ fn emit_str(&mut self, v: &str) {
+ if_ok!(write!(self.wr, "{}", escape_str(v)));
+ }
fn emit_enum(&mut self, _name: &str, f: |&mut PrettyEncoder<'a>|) {
f(self)
cnt: uint,
f: |&mut PrettyEncoder<'a>|) {
if cnt == 0 {
- write!(self.wr, "{}", escape_str(name));
+ if_ok!(write!(self.wr, "{}", escape_str(name)));
} else {
self.indent += 2;
- write!(self.wr, "[\n{}{},\n", spaces(self.indent), escape_str(name));
+ if_ok!(write!(self.wr, "[\n{}{},\n", spaces(self.indent),
+ escape_str(name)));
f(self);
self.indent -= 2;
- write!(self.wr, "\n{}]", spaces(self.indent));
+ if_ok!(write!(self.wr, "\n{}]", spaces(self.indent)));
}
}
idx: uint,
f: |&mut PrettyEncoder<'a>|) {
if idx != 0 {
- write!(self.wr, ",\n");
+ if_ok!(write!(self.wr, ",\n"));
}
- write!(self.wr, "{}", spaces(self.indent));
+ if_ok!(write!(self.wr, "{}", spaces(self.indent)));
f(self)
}
len: uint,
f: |&mut PrettyEncoder<'a>|) {
if len == 0 {
- write!(self.wr, "\\{\\}");
+ if_ok!(write!(self.wr, "\\{\\}"));
} else {
- write!(self.wr, "\\{");
+ if_ok!(write!(self.wr, "\\{"));
self.indent += 2;
f(self);
self.indent -= 2;
- write!(self.wr, "\n{}\\}", spaces(self.indent));
+ if_ok!(write!(self.wr, "\n{}\\}", spaces(self.indent)));
}
}
idx: uint,
f: |&mut PrettyEncoder<'a>|) {
if idx == 0 {
- write!(self.wr, "\n");
+ if_ok!(write!(self.wr, "\n"));
} else {
- write!(self.wr, ",\n");
+ if_ok!(write!(self.wr, ",\n"));
}
- write!(self.wr, "{}{}: ", spaces(self.indent), escape_str(name));
+ if_ok!(write!(self.wr, "{}{}: ", spaces(self.indent), escape_str(name)));
f(self);
}
fn emit_seq(&mut self, len: uint, f: |&mut PrettyEncoder<'a>|) {
if len == 0 {
- write!(self.wr, "[]");
+ if_ok!(write!(self.wr, "[]"));
} else {
- write!(self.wr, "[");
+ if_ok!(write!(self.wr, "["));
self.indent += 2;
f(self);
self.indent -= 2;
- write!(self.wr, "\n{}]", spaces(self.indent));
+ if_ok!(write!(self.wr, "\n{}]", spaces(self.indent)));
}
}
fn emit_seq_elt(&mut self, idx: uint, f: |&mut PrettyEncoder<'a>|) {
if idx == 0 {
- write!(self.wr, "\n");
+ if_ok!(write!(self.wr, "\n"));
} else {
- write!(self.wr, ",\n");
+ if_ok!(write!(self.wr, ",\n"));
}
- write!(self.wr, "{}", spaces(self.indent));
+ if_ok!(write!(self.wr, "{}", spaces(self.indent)));
f(self)
}
fn emit_map(&mut self, len: uint, f: |&mut PrettyEncoder<'a>|) {
if len == 0 {
- write!(self.wr, "\\{\\}");
+ if_ok!(write!(self.wr, "\\{\\}"));
} else {
- write!(self.wr, "\\{");
+ if_ok!(write!(self.wr, "\\{"));
self.indent += 2;
f(self);
self.indent -= 2;
- write!(self.wr, "\n{}\\}", spaces(self.indent));
+ if_ok!(write!(self.wr, "\n{}\\}", spaces(self.indent)));
}
}
fn emit_map_elt_key(&mut self, idx: uint, f: |&mut PrettyEncoder<'a>|) {
if idx == 0 {
- write!(self.wr, "\n");
+ if_ok!(write!(self.wr, "\n"));
} else {
- write!(self.wr, ",\n");
+ if_ok!(write!(self.wr, ",\n"));
}
- write!(self.wr, "{}", spaces(self.indent));
+ if_ok!(write!(self.wr, "{}", spaces(self.indent)));
f(self);
}
fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut PrettyEncoder<'a>|) {
- write!(self.wr, ": ");
+ if_ok!(write!(self.wr, ": "));
f(self);
}
}
impl Json{
/// Encodes a json value into a io::writer. Uses a single line.
- pub fn to_writer(&self, wr: &mut io::Writer) {
+ pub fn to_writer(&self, wr: &mut io::Writer) -> io::IoResult<()> {
let mut encoder = Encoder::new(wr);
- self.encode(&mut encoder)
+ self.encode(&mut encoder);
+ encoder.error
}
/// Encodes a json value into a io::writer.
/// Pretty-prints in a more readable format.
- pub fn to_pretty_writer(&self, wr: &mut io::Writer) {
+ pub fn to_pretty_writer(&self, wr: &mut io::Writer) -> io::IoResult<()> {
let mut encoder = PrettyEncoder::new(wr);
- self.encode(&mut encoder)
+ self.encode(&mut encoder);
+ encoder.error
}
/// Encodes a json value into a string
pub fn to_pretty_str(&self) -> ~str {
let mut s = MemWriter::new();
- self.to_pretty_writer(&mut s as &mut io::Writer);
+ self.to_pretty_writer(&mut s as &mut io::Writer).unwrap();
str::from_utf8_owned(s.unwrap()).unwrap()
}
}
/// Decodes a json value from an `&mut io::Reader`
pub fn from_reader(rdr: &mut io::Reader) -> Result<Json, Error> {
- let s = str::from_utf8_owned(rdr.read_to_end()).unwrap();
+ let contents = match rdr.read_to_end() {
+ Ok(c) => c,
+ Err(e) => return Err(io_error_to_error(e))
+ };
+ let s = match str::from_utf8_owned(contents) {
+ Some(s) => s,
+ None => return Err(Error { line: 0, col: 0, msg: ~"contents not utf-8" })
+ };
let mut parser = Parser::new(s.chars());
parser.parse()
}
/// Encodes a json value into a string
fn to_str(&self) -> ~str {
let mut s = MemWriter::new();
- self.to_writer(&mut s as &mut io::Writer);
+ self.to_writer(&mut s as &mut io::Writer).unwrap();
str::from_utf8_owned(s.unwrap()).unwrap()
}
}
#[deny(non_camel_case_types)];
#[deny(missing_doc)];
+#[cfg(stage0)]
+macro_rules! if_ok (
+ ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) })
+)
+
// Utility modules
pub mod c_vec;
}
/// Render writes the min, max and quartiles of the provided `Summary` to the provided `Writer`.
-pub fn write_5_number_summary(w: &mut io::Writer, s: &Summary) {
+pub fn write_5_number_summary(w: &mut io::Writer,
+ s: &Summary) -> io::IoResult<()> {
let (q1,q2,q3) = s.quartiles;
write!(w, "(min={}, q1={}, med={}, q3={}, max={})",
s.min,
q1,
q2,
q3,
- s.max);
+ s.max)
}
/// Render a boxplot to the provided writer. The boxplot shows the min, max and quartiles of the
/// 10 | [--****#******----------] | 40
/// ~~~~
-pub fn write_boxplot(w: &mut io::Writer, s: &Summary, width_hint: uint) {
+pub fn write_boxplot(w: &mut io::Writer, s: &Summary,
+ width_hint: uint) -> io::IoResult<()> {
let (q1,q2,q3) = s.quartiles;
let range_width = width_hint - overhead_width;;
let char_step = range / (range_width as f64);
- write!(w, "{} |", lostr);
+ if_ok!(write!(w, "{} |", lostr));
let mut c = 0;
let mut v = lo;
while c < range_width && v < s.min {
- write!(w, " ");
+ if_ok!(write!(w, " "));
v += char_step;
c += 1;
}
- write!(w, "[");
+ if_ok!(write!(w, "["));
c += 1;
while c < range_width && v < q1 {
- write!(w, "-");
+ if_ok!(write!(w, "-"));
v += char_step;
c += 1;
}
while c < range_width && v < q2 {
- write!(w, "*");
+ if_ok!(write!(w, "*"));
v += char_step;
c += 1;
}
- write!(w, r"\#");
+ if_ok!(write!(w, r"\#"));
c += 1;
while c < range_width && v < q3 {
- write!(w, "*");
+ if_ok!(write!(w, "*"));
v += char_step;
c += 1;
}
while c < range_width && v < s.max {
- write!(w, "-");
+ if_ok!(write!(w, "-"));
v += char_step;
c += 1;
}
- write!(w, "]");
+ if_ok!(write!(w, "]"));
while c < range_width {
- write!(w, " ");
+ if_ok!(write!(w, " "));
v += char_step;
c += 1;
}
- write!(w, "| {}", histr);
+ if_ok!(write!(w, "| {}", histr));
+ Ok(())
}
/// Returns a HashMap with the number of occurrences of every element in the
let mut r = rand::rng();
for _ in range(0u, 1000) {
let p = tmpdir.join(r.gen_ascii_str(16) + suffix);
- match io::result(|| fs::mkdir(&p, io::UserRWX)) {
+ match fs::mkdir(&p, io::UserRWX) {
Err(..) => {}
Ok(()) => return Some(TempDir { path: Some(p) })
}
fn drop(&mut self) {
for path in self.path.iter() {
if path.exists() {
- fs::rmdir_recursive(path);
+ // FIXME: is failing the right thing to do?
+ fs::rmdir_recursive(path).unwrap();
}
}
}
Some(Err(msg)) => fail!("{}", msg),
None => return
};
- if !run_tests_console(&opts, tests) { fail!("Some tests failed"); }
+ match run_tests_console(&opts, tests) {
+ Ok(true) => {}
+ Ok(false) => fail!("Some tests failed"),
+ Err(e) => fail!("io error when running tests: {}", e),
+ }
}
// A variant optimized for invocation with a static test vector.
}
impl<T: Writer> ConsoleTestState<T> {
- pub fn new(opts: &TestOpts, _: Option<T>) -> ConsoleTestState<StdWriter> {
+ pub fn new(opts: &TestOpts,
+ _: Option<T>) -> io::IoResult<ConsoleTestState<StdWriter>> {
let log_out = match opts.logfile {
- Some(ref path) => File::create(path),
+ Some(ref path) => Some(if_ok!(File::create(path))),
None => None
};
let out = match term::Terminal::new(io::stdout()) {
Err(_) => Raw(io::stdout()),
Ok(t) => Pretty(t)
};
- ConsoleTestState {
+ Ok(ConsoleTestState {
out: out,
log_out: log_out,
use_color: use_color(),
metrics: MetricMap::new(),
failures: ~[],
max_name_len: 0u,
- }
+ })
}
- pub fn write_ok(&mut self) {
- self.write_pretty("ok", term::color::GREEN);
+ pub fn write_ok(&mut self) -> io::IoResult<()> {
+ self.write_pretty("ok", term::color::GREEN)
}
- pub fn write_failed(&mut self) {
- self.write_pretty("FAILED", term::color::RED);
+ pub fn write_failed(&mut self) -> io::IoResult<()> {
+ self.write_pretty("FAILED", term::color::RED)
}
- pub fn write_ignored(&mut self) {
- self.write_pretty("ignored", term::color::YELLOW);
+ pub fn write_ignored(&mut self) -> io::IoResult<()> {
+ self.write_pretty("ignored", term::color::YELLOW)
}
- pub fn write_metric(&mut self) {
- self.write_pretty("metric", term::color::CYAN);
+ pub fn write_metric(&mut self) -> io::IoResult<()> {
+ self.write_pretty("metric", term::color::CYAN)
}
- pub fn write_bench(&mut self) {
- self.write_pretty("bench", term::color::CYAN);
+ pub fn write_bench(&mut self) -> io::IoResult<()> {
+ self.write_pretty("bench", term::color::CYAN)
}
- pub fn write_added(&mut self) {
- self.write_pretty("added", term::color::GREEN);
+ pub fn write_added(&mut self) -> io::IoResult<()> {
+ self.write_pretty("added", term::color::GREEN)
}
- pub fn write_improved(&mut self) {
- self.write_pretty("improved", term::color::GREEN);
+ pub fn write_improved(&mut self) -> io::IoResult<()> {
+ self.write_pretty("improved", term::color::GREEN)
}
- pub fn write_removed(&mut self) {
- self.write_pretty("removed", term::color::YELLOW);
+ pub fn write_removed(&mut self) -> io::IoResult<()> {
+ self.write_pretty("removed", term::color::YELLOW)
}
- pub fn write_regressed(&mut self) {
- self.write_pretty("regressed", term::color::RED);
+ pub fn write_regressed(&mut self) -> io::IoResult<()> {
+ self.write_pretty("regressed", term::color::RED)
}
pub fn write_pretty(&mut self,
word: &str,
- color: term::color::Color) {
+ color: term::color::Color) -> io::IoResult<()> {
match self.out {
Pretty(ref mut term) => {
if self.use_color {
- term.fg(color);
+ if_ok!(term.fg(color));
}
- term.write(word.as_bytes());
+ if_ok!(term.write(word.as_bytes()));
if self.use_color {
- term.reset();
+ if_ok!(term.reset());
}
+ Ok(())
}
Raw(ref mut stdout) => stdout.write(word.as_bytes())
}
}
- pub fn write_plain(&mut self, s: &str) {
+ pub fn write_plain(&mut self, s: &str) -> io::IoResult<()> {
match self.out {
Pretty(ref mut term) => term.write(s.as_bytes()),
Raw(ref mut stdout) => stdout.write(s.as_bytes())
}
}
- pub fn write_run_start(&mut self, len: uint) {
+ pub fn write_run_start(&mut self, len: uint) -> io::IoResult<()> {
self.total = len;
let noun = if len != 1 { &"tests" } else { &"test" };
- self.write_plain(format!("\nrunning {} {}\n", len, noun));
+ self.write_plain(format!("\nrunning {} {}\n", len, noun))
}
- pub fn write_test_start(&mut self, test: &TestDesc, align: NamePadding) {
+ pub fn write_test_start(&mut self, test: &TestDesc,
+ align: NamePadding) -> io::IoResult<()> {
let name = test.padded_name(self.max_name_len, align);
- self.write_plain(format!("test {} ... ", name));
+ self.write_plain(format!("test {} ... ", name))
}
- pub fn write_result(&mut self, result: &TestResult) {
- match *result {
+ pub fn write_result(&mut self, result: &TestResult) -> io::IoResult<()> {
+ if_ok!(match *result {
TrOk => self.write_ok(),
TrFailed => self.write_failed(),
TrIgnored => self.write_ignored(),
TrMetrics(ref mm) => {
- self.write_metric();
- self.write_plain(format!(": {}", fmt_metrics(mm)));
+ if_ok!(self.write_metric());
+ self.write_plain(format!(": {}", fmt_metrics(mm)))
}
TrBench(ref bs) => {
- self.write_bench();
- self.write_plain(format!(": {}", fmt_bench_samples(bs)));
+ if_ok!(self.write_bench());
+ self.write_plain(format!(": {}", fmt_bench_samples(bs)))
}
- }
- self.write_plain("\n");
+ });
+ self.write_plain("\n")
}
- pub fn write_log(&mut self, test: &TestDesc, result: &TestResult) {
+ pub fn write_log(&mut self, test: &TestDesc,
+ result: &TestResult) -> io::IoResult<()> {
match self.log_out {
- None => (),
+ None => Ok(()),
Some(ref mut o) => {
let s = format!("{} {}\n", match *result {
TrOk => ~"ok",
TrMetrics(ref mm) => fmt_metrics(mm),
TrBench(ref bs) => fmt_bench_samples(bs)
}, test.name.to_str());
- o.write(s.as_bytes());
+ o.write(s.as_bytes())
}
}
}
- pub fn write_failures(&mut self) {
- self.write_plain("\nfailures:\n");
+ pub fn write_failures(&mut self) -> io::IoResult<()> {
+ if_ok!(self.write_plain("\nfailures:\n"));
let mut failures = ~[];
for f in self.failures.iter() {
failures.push(f.name.to_str());
}
failures.sort();
for name in failures.iter() {
- self.write_plain(format!(" {}\n", name.to_str()));
+ if_ok!(self.write_plain(format!(" {}\n", name.to_str())));
}
+ Ok(())
}
- pub fn write_metric_diff(&mut self, diff: &MetricDiff) {
+ pub fn write_metric_diff(&mut self, diff: &MetricDiff) -> io::IoResult<()> {
let mut noise = 0;
let mut improved = 0;
let mut regressed = 0;
LikelyNoise => noise += 1,
MetricAdded => {
added += 1;
- self.write_added();
- self.write_plain(format!(": {}\n", *k));
+ if_ok!(self.write_added());
+ if_ok!(self.write_plain(format!(": {}\n", *k)));
}
MetricRemoved => {
removed += 1;
- self.write_removed();
- self.write_plain(format!(": {}\n", *k));
+ if_ok!(self.write_removed());
+ if_ok!(self.write_plain(format!(": {}\n", *k)));
}
Improvement(pct) => {
improved += 1;
- self.write_plain(format!(": {}", *k));
- self.write_improved();
- self.write_plain(format!(" by {:.2f}%\n", pct as f64));
+ if_ok!(self.write_plain(format!(": {}", *k)));
+ if_ok!(self.write_improved());
+ if_ok!(self.write_plain(format!(" by {:.2f}%\n", pct as f64)));
}
Regression(pct) => {
regressed += 1;
- self.write_plain(format!(": {}", *k));
- self.write_regressed();
- self.write_plain(format!(" by {:.2f}%\n", pct as f64));
+ if_ok!(self.write_plain(format!(": {}", *k)));
+ if_ok!(self.write_regressed());
+ if_ok!(self.write_plain(format!(" by {:.2f}%\n", pct as f64)));
}
}
}
- self.write_plain(format!("result of ratchet: {} matrics added, {} removed, \
- {} improved, {} regressed, {} noise\n",
- added, removed, improved, regressed, noise));
+ if_ok!(self.write_plain(format!("result of ratchet: {} matrics added, \
+ {} removed, {} improved, {} regressed, \
+ {} noise\n",
+ added, removed, improved, regressed,
+ noise)));
if regressed == 0 {
- self.write_plain("updated ratchet file\n");
+ if_ok!(self.write_plain("updated ratchet file\n"));
} else {
- self.write_plain("left ratchet file untouched\n");
+ if_ok!(self.write_plain("left ratchet file untouched\n"));
}
+ Ok(())
}
pub fn write_run_finish(&mut self,
ratchet_metrics: &Option<Path>,
- ratchet_pct: Option<f64>) -> bool {
+ ratchet_pct: Option<f64>) -> io::IoResult<bool> {
assert!(self.passed + self.failed + self.ignored + self.measured == self.total);
let ratchet_success = match *ratchet_metrics {
None => true,
Some(ref pth) => {
- self.write_plain(format!("\nusing metrics ratcher: {}\n", pth.display()));
+ if_ok!(self.write_plain(format!("\nusing metrics ratcher: {}\n",
+ pth.display())));
match ratchet_pct {
None => (),
Some(pct) =>
- self.write_plain(format!("with noise-tolerance forced to: {}%\n",
- pct))
+ if_ok!(self.write_plain(format!("with noise-tolerance \
+ forced to: {}%\n",
+ pct)))
}
let (diff, ok) = self.metrics.ratchet(pth, ratchet_pct);
- self.write_metric_diff(&diff);
+ if_ok!(self.write_metric_diff(&diff));
ok
}
};
let test_success = self.failed == 0u;
if !test_success {
- self.write_failures();
+ if_ok!(self.write_failures());
}
let success = ratchet_success && test_success;
- self.write_plain("\ntest result: ");
+ if_ok!(self.write_plain("\ntest result: "));
if success {
// There's no parallelism at this point so it's safe to use color
- self.write_ok();
+ if_ok!(self.write_ok());
} else {
- self.write_failed();
+ if_ok!(self.write_failed());
}
let s = format!(". {} passed; {} failed; {} ignored; {} measured\n\n",
self.passed, self.failed, self.ignored, self.measured);
- self.write_plain(s);
- return success;
+ if_ok!(self.write_plain(s));
+ return Ok(success);
}
}
// A simple console test runner
pub fn run_tests_console(opts: &TestOpts,
- tests: ~[TestDescAndFn]) -> bool {
- fn callback<T: Writer>(event: &TestEvent, st: &mut ConsoleTestState<T>) {
+ tests: ~[TestDescAndFn]) -> io::IoResult<bool> {
+ fn callback<T: Writer>(event: &TestEvent,
+ st: &mut ConsoleTestState<T>) -> io::IoResult<()> {
debug!("callback(event={:?})", event);
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) => {
- st.write_log(&test, &result);
- st.write_result(&result);
+ if_ok!(st.write_log(&test, &result));
+ if_ok!(st.write_result(&result));
match result {
TrOk => st.passed += 1,
TrIgnored => st.ignored += 1,
st.failures.push(test);
}
}
+ Ok(())
}
}
}
- let mut st = ConsoleTestState::new(opts, None::<StdWriter>);
+ let mut st = if_ok!(ConsoleTestState::new(opts, None::<StdWriter>));
fn len_if_padded(t: &TestDescAndFn) -> uint {
match t.testfn.padding() {
PadNone => 0u,
},
None => {}
}
- run_tests(opts, tests, |x| callback(&x, &mut st));
+ if_ok!(run_tests(opts, tests, |x| callback(&x, &mut st)));
match opts.save_metrics {
None => (),
Some(ref pth) => {
- st.metrics.save(pth);
- st.write_plain(format!("\nmetrics saved to: {}", pth.display()));
+ if_ok!(st.metrics.save(pth));
+ if_ok!(st.write_plain(format!("\nmetrics saved to: {}",
+ pth.display())));
}
}
return st.write_run_finish(&opts.ratchet_metrics, opts.ratchet_noise_percent);
fn run_tests(opts: &TestOpts,
tests: ~[TestDescAndFn],
- callback: |e: TestEvent|) {
+ callback: |e: TestEvent| -> io::IoResult<()>) -> io::IoResult<()> {
let filtered_tests = filter_tests(opts, tests);
let filtered_descs = filtered_tests.map(|t| t.desc.clone());
- callback(TeFiltered(filtered_descs));
+ if_ok!(callback(TeFiltered(filtered_descs)));
let (filtered_tests, filtered_benchs_and_metrics) =
filtered_tests.partition(|e| {
// We are doing one test at a time so we can print the name
// of the test before we run it. Useful for debugging tests
// that hang forever.
- callback(TeWait(test.desc.clone(), test.testfn.padding()));
+ if_ok!(callback(TeWait(test.desc.clone(), test.testfn.padding())));
}
run_test(!opts.run_tests, test, ch.clone());
pending += 1;
let (desc, result) = p.recv();
if concurrency != 1 {
- callback(TeWait(desc.clone(), PadNone));
+ if_ok!(callback(TeWait(desc.clone(), PadNone)));
}
- callback(TeResult(desc, result));
+ if_ok!(callback(TeResult(desc, result)));
pending -= 1;
}
// All benchmarks run at the end, in serial.
// (this includes metric fns)
for b in filtered_benchs_and_metrics.move_iter() {
- callback(TeWait(b.desc.clone(), b.testfn.padding()));
+ if_ok!(callback(TeWait(b.desc.clone(), b.testfn.padding())));
run_test(!opts.run_benchmarks, b, ch.clone());
let (test, result) = p.recv();
- callback(TeResult(test, result));
+ if_ok!(callback(TeResult(test, result)));
}
+ Ok(())
}
fn get_concurrency() -> uint {
}
/// Load MetricDiff from a file.
+ ///
+ /// # Failure
+ ///
+ /// This function will fail if the path does not exist or the path does not
+ /// contain a valid metric map.
pub fn load(p: &Path) -> MetricMap {
assert!(p.exists());
- let mut f = File::open(p);
+ let mut f = File::open(p).unwrap();
let value = json::from_reader(&mut f as &mut io::Reader).unwrap();
let mut decoder = json::Decoder::new(value);
MetricMap(Decodable::decode(&mut decoder))
}
/// Write MetricDiff to a file.
- pub fn save(&self, p: &Path) {
- let mut file = File::create(p);
+ pub fn save(&self, p: &Path) -> io::IoResult<()> {
+ let mut file = if_ok!(File::create(p));
let MetricMap(ref map) = *self;
map.to_json().to_pretty_writer(&mut file)
}
if ok {
debug!("rewriting file '{:?}' with updated metrics", p);
- self.save(p);
+ self.save(p).unwrap();
}
return (diff, ok)
}
let mut buf = [0];
let c = match rdr.read(buf) {
- Some(..) => buf[0] as char,
- None => break
+ Ok(..) => buf[0] as char,
+ Err(..) => break
};
match c {
'%' => {
let ch = match rdr.read(buf) {
- Some(..) => buf[0] as char,
- None => break
+ Ok(..) => buf[0] as char,
+ Err(..) => break
};
match parse_type(s, pos, ch, &mut tm) {
Ok(next) => pos = next,
}
}
- if pos == len && rdr.tell() as uint == format.len() {
+ if pos == len && rdr.tell().unwrap() == format.len() as u64 {
Ok(Tm {
tm_sec: tm.tm_sec,
tm_min: tm.tm_min,
loop {
let mut b = [0];
let ch = match rdr.read(b) {
- Some(..) => b[0],
- None => break,
+ Ok(..) => b[0],
+ Err(..) => break,
};
match ch as char {
'%' => {
- rdr.read(b);
+ rdr.read(b).unwrap();
let s = parse_type(b[0] as char, tm);
buf.push_all(s.as_bytes());
}
loop {
let mut buf = [0];
let ch = match rdr.read(buf) {
- None => break,
- Some(..) => buf[0] as char,
+ Err(..) => break,
+ Ok(..) => buf[0] as char,
};
match ch {
loop {
let mut buf = [0];
let ch = match rdr.read(buf) {
- None => break,
- Some(..) => buf[0] as char
+ Err(..) => break,
+ Ok(..) => buf[0] as char
};
match ch {
'%' => {
let mut bytes = [0, 0];
match rdr.read(bytes) {
- Some(2) => {}
+ Ok(2) => {}
_ => fail!() // FIXME: malformed url?
}
let ch = uint::parse_bytes(bytes, 16u).unwrap() as u8 as char;
loop {
let mut buf = [0];
let ch = match rdr.read(buf) {
- Some(..) => buf[0] as char,
- None => break,
+ Ok(..) => buf[0] as char,
+ Err(..) => break,
};
match ch {
'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '_' | '.' | '-' => {
loop {
let mut buf = [0];
let ch = match rdr.read(buf) {
- Some(..) => buf[0] as char,
- None => break,
+ Ok(..) => buf[0] as char,
+ Err(..) => break,
};
match ch {
'&' | ';' => {
'%' => {
let mut bytes = [0, 0];
match rdr.read(bytes) {
- Some(2) => {}
+ Ok(2) => {}
_ => fail!() // FIXME: malformed?
}
uint::parse_bytes(bytes, 16u).unwrap() as u8 as char
loop {
let mut buf = [0];
let ch = match rdr.read(buf) {
- Some(..) => buf[0] as char,
- None => break,
+ Ok(..) => buf[0] as char,
+ Err(..) => break,
};
if ch == c {
// found a match, adjust markers
- index = (rdr.tell() as uint) - 1;
+ index = (rdr.tell().unwrap() as uint) - 1;
mat = 1;
break;
}
}
// FIXME #4330: This should have &mut self and should set self.db_dirty to false.
- fn save(&self) {
+ fn save(&self) -> io::IoResult<()> {
let mut f = File::create(&self.db_filename);
- self.db_cache.to_json().to_pretty_writer(&mut f);
+ self.db_cache.to_json().to_pretty_writer(&mut f)
}
fn load(&mut self) {
assert!(!self.db_dirty);
assert!(self.db_filename.exists());
- match io::result(|| File::open(&self.db_filename)) {
+ match File::open(&self.db_filename) {
Err(e) => fail!("Couldn't load workcache database {}: {}",
self.db_filename.display(),
- e.desc),
- Ok(r) => {
- let mut stream = r.unwrap();
+ e),
+ Ok(mut stream) => {
match json::from_reader(&mut stream) {
Err(e) => fail!("Couldn't parse workcache database (from file {}): {}",
self.db_filename.display(), e.to_str()),
impl Drop for Database {
fn drop(&mut self) {
if self.db_dirty {
- self.save();
+ // FIXME: is failing the right thing to do here
+ self.save().unwrap();
}
}
}
/// If the color is a bright color, but the terminal only supports 8 colors,
/// the corresponding normal color will be used instead.
///
- /// Returns true if the color was set, false otherwise.
- pub fn fg(&mut self, color: color::Color) -> bool {
+ /// Returns Ok(true) if the color was set, Ok(false) otherwise, and Err(e)
+ /// if there was an I/O error
+ pub fn fg(&mut self, color: color::Color) -> io::IoResult<bool> {
let color = self.dim_if_necessary(color);
if self.num_colors > color {
let s = expand(*self.ti.strings.find_equiv(&("setaf")).unwrap(),
[Number(color as int)], &mut Variables::new());
if s.is_ok() {
- self.out.write(s.unwrap());
- return true
+ if_ok!(self.out.write(s.unwrap()));
+ return Ok(true)
} else {
warn!("{}", s.unwrap_err());
}
}
- false
+ Ok(false)
}
/// Sets the background color to the given color.
///
/// If the color is a bright color, but the terminal only supports 8 colors,
/// the corresponding normal color will be used instead.
///
- /// Returns true if the color was set, false otherwise.
- pub fn bg(&mut self, color: color::Color) -> bool {
+ /// Returns Ok(true) if the color was set, Ok(false) otherwise, and Err(e)
+ /// if there was an I/O error
+ pub fn bg(&mut self, color: color::Color) -> io::IoResult<bool> {
let color = self.dim_if_necessary(color);
if self.num_colors > color {
let s = expand(*self.ti.strings.find_equiv(&("setab")).unwrap(),
[Number(color as int)], &mut Variables::new());
if s.is_ok() {
- self.out.write(s.unwrap());
- return true
+ if_ok!(self.out.write(s.unwrap()));
+ return Ok(true)
} else {
warn!("{}", s.unwrap_err());
}
}
- false
+ Ok(false)
}
/// Sets the given terminal attribute, if supported.
- /// Returns true if the attribute was supported, false otherwise.
- pub fn attr(&mut self, attr: attr::Attr) -> bool {
+ /// Returns Ok(true) if the attribute was supported, Ok(false) otherwise,
+ /// and Err(e) if there was an I/O error.
+ pub fn attr(&mut self, attr: attr::Attr) -> io::IoResult<bool> {
match attr {
attr::ForegroundColor(c) => self.fg(c),
attr::BackgroundColor(c) => self.bg(c),
if parm.is_some() {
let s = expand(*parm.unwrap(), [], &mut Variables::new());
if s.is_ok() {
- self.out.write(s.unwrap());
- return true
+ if_ok!(self.out.write(s.unwrap()));
+ return Ok(true)
} else {
warn!("{}", s.unwrap_err());
}
}
- false
+ Ok(false)
}
}
}
}
/// Resets all terminal attributes and color to the default.
- pub fn reset(&mut self) {
+ pub fn reset(&mut self) -> io::IoResult<()> {
let mut cap = self.ti.strings.find_equiv(&("sgr0"));
if cap.is_none() {
// are there any terminals that have color/attrs and not sgr0?
expand(*op, [], &mut Variables::new())
});
if s.is_ok() {
- self.out.write(s.unwrap());
+ return self.out.write(s.unwrap())
} else if self.num_colors > 0 {
warn!("{}", s.unwrap_err());
} else {
// but it's not worth testing all known attributes just for this.
debug!("{}", s.unwrap_err());
}
+ Ok(())
}
fn dim_if_necessary(&self, color: color::Color) -> color::Color {
}
impl<T: Writer> Writer for Terminal<T> {
- fn write(&mut self, buf: &[u8]) {
- self.out.write(buf);
+ fn write(&mut self, buf: &[u8]) -> io::IoResult<()> {
+ self.out.write(buf)
}
- fn flush(&mut self) {
- self.out.flush();
+ fn flush(&mut self) -> io::IoResult<()> {
+ self.out.flush()
}
}
/// Parse a compiled terminfo entry, using long capability names if `longnames` is true
pub fn parse(file: &mut io::Reader,
longnames: bool) -> Result<~TermInfo, ~str> {
+ macro_rules! if_ok( ($e:expr) => (
+ match $e { Ok(e) => e, Err(e) => return Err(format!("{}", e)) }
+ ) )
+
let bnames;
let snames;
let nnames;
}
// Check magic number
- let magic = file.read_le_u16();
+ let magic = if_ok!(file.read_le_u16());
if magic != 0x011A {
return Err(format!("invalid magic number: expected {:x} but found {:x}",
0x011A, magic as uint));
}
- let names_bytes = file.read_le_i16() as int;
- let bools_bytes = file.read_le_i16() as int;
- let numbers_count = file.read_le_i16() as int;
- let string_offsets_count = file.read_le_i16() as int;
- let string_table_bytes = file.read_le_i16() as int;
+ let names_bytes = if_ok!(file.read_le_i16()) as int;
+ let bools_bytes = if_ok!(file.read_le_i16()) as int;
+ let numbers_count = if_ok!(file.read_le_i16()) as int;
+ let string_offsets_count = if_ok!(file.read_le_i16()) as int;
+ let string_table_bytes = if_ok!(file.read_le_i16()) as int;
assert!(names_bytes > 0);
}
// don't read NUL
- let names_str = str::from_utf8_owned(file.read_bytes(names_bytes as uint - 1)).unwrap();
+ let bytes = if_ok!(file.read_bytes(names_bytes as uint - 1));
+ let names_str = match str::from_utf8_owned(bytes) {
+ Some(s) => s, None => return Err(~"input not utf-8"),
+ };
let term_names: ~[~str] = names_str.split('|').map(|s| s.to_owned()).collect();
- file.read_byte(); // consume NUL
+ if_ok!(file.read_byte()); // consume NUL
debug!("term names: {:?}", term_names);
let mut bools_map = HashMap::new();
if bools_bytes != 0 {
for i in range(0, bools_bytes) {
- let b = file.read_byte().unwrap();
+ let b = if_ok!(file.read_byte());
if b < 0 {
error!("EOF reading bools after {} entries", i);
return Err(~"error: expected more bools but hit EOF");
if (bools_bytes + names_bytes) % 2 == 1 {
debug!("adjusting for padding between bools and numbers");
- file.read_byte(); // compensate for padding
+ if_ok!(file.read_byte()); // compensate for padding
}
let mut numbers_map = HashMap::new();
if numbers_count != 0 {
for i in range(0, numbers_count) {
- let n = file.read_le_u16();
+ let n = if_ok!(file.read_le_u16());
if n != 0xFFFF {
debug!("{}\\#{}", nnames[i], n);
numbers_map.insert(nnames[i].to_owned(), n);
if string_offsets_count != 0 {
let mut string_offsets = vec::with_capacity(10);
for _ in range(0, string_offsets_count) {
- string_offsets.push(file.read_le_u16());
+ string_offsets.push(if_ok!(file.read_le_u16()));
}
debug!("offsets: {:?}", string_offsets);
- let string_table = file.read_bytes(string_table_bytes as uint);
+ let string_table = if_ok!(file.read_bytes(string_table_bytes as uint));
if string_table.len() != string_table_bytes as uint {
error!("EOF reading string table after {} bytes, wanted {}", string_table.len(),
match get_dbpath_for_term(term) {
Some(x) => {
match File::open(x) {
- Some(file) => Ok(file),
- None => Err(~"error opening file"),
+ Ok(file) => Ok(file),
+ Err(e) => Err(format!("error opening file: {}", e)),
}
}
None => Err(format!("could not find terminfo entry for {}", term))