extra: Remove io_error usage
This commit is contained in:
parent
ece8a8f520
commit
ef00c6a278
@ -12,6 +12,10 @@
|
||||
|
||||
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
|
||||
@ -595,9 +599,15 @@ pub mod writer {
|
||||
|
||||
// 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) {
|
||||
@ -609,7 +619,7 @@ pub mod writer {
|
||||
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) {
|
||||
@ -624,7 +634,8 @@ pub mod writer {
|
||||
let size_positions: ~[uint] = ~[];
|
||||
Encoder {
|
||||
writer: w,
|
||||
size_positions: size_positions
|
||||
size_positions: size_positions,
|
||||
last_error: Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -635,6 +646,7 @@ pub mod writer {
|
||||
Encoder {
|
||||
writer: cast::transmute_copy(&self.writer),
|
||||
size_positions: self.size_positions.clone(),
|
||||
last_error: Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -645,18 +657,18 @@ pub mod writer {
|
||||
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);
|
||||
}
|
||||
@ -670,7 +682,7 @@ pub mod writer {
|
||||
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) {
|
||||
@ -723,12 +735,12 @@ pub mod writer {
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,6 +234,10 @@ use serialize::Encodable;
|
||||
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 {
|
||||
@ -260,6 +264,14 @@ pub struct Error {
|
||||
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() {
|
||||
@ -289,13 +301,14 @@ fn spaces(n: uint) -> ~str {
|
||||
/// 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]
|
||||
@ -317,7 +330,7 @@ impl<'a> Encoder<'a> {
|
||||
}
|
||||
|
||||
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); }
|
||||
@ -333,20 +346,20 @@ impl<'a> serialize::Encoder for Encoder<'a> {
|
||||
|
||||
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) }
|
||||
@ -360,19 +373,19 @@ impl<'a> serialize::Encoder for Encoder<'a> {
|
||||
// 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);
|
||||
}
|
||||
@ -393,17 +406,17 @@ impl<'a> serialize::Encoder for Encoder<'a> {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -429,31 +442,31 @@ impl<'a> serialize::Encoder for Encoder<'a> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -463,6 +476,7 @@ impl<'a> serialize::Encoder for Encoder<'a> {
|
||||
pub struct PrettyEncoder<'a> {
|
||||
priv wr: &'a mut io::Writer,
|
||||
priv indent: uint,
|
||||
priv error: io::IoResult<()>,
|
||||
}
|
||||
|
||||
impl<'a> PrettyEncoder<'a> {
|
||||
@ -471,12 +485,13 @@ 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); }
|
||||
@ -492,19 +507,21 @@ impl<'a> serialize::Encoder for PrettyEncoder<'a> {
|
||||
|
||||
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)
|
||||
@ -516,13 +533,14 @@ impl<'a> serialize::Encoder for PrettyEncoder<'a> {
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -530,9 +548,9 @@ impl<'a> serialize::Encoder for PrettyEncoder<'a> {
|
||||
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)
|
||||
}
|
||||
|
||||
@ -557,13 +575,13 @@ impl<'a> serialize::Encoder for PrettyEncoder<'a> {
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -572,11 +590,11 @@ impl<'a> serialize::Encoder for PrettyEncoder<'a> {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -605,50 +623,50 @@ impl<'a> serialize::Encoder for PrettyEncoder<'a> {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -668,22 +686,24 @@ impl<E: serialize::Encoder> serialize::Encodable<E> for Json {
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
@ -1067,7 +1087,14 @@ impl<T : Iterator<char>> Parser<T> {
|
||||
|
||||
/// 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()
|
||||
}
|
||||
@ -1540,7 +1567,7 @@ impl to_str::ToStr for Json {
|
||||
/// 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()
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,11 @@ Rust extras are part of the standard Rust distribution.
|
||||
#[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;
|
||||
|
@ -322,14 +322,15 @@ pub fn winsorize(samples: &mut [f64], pct: f64) {
|
||||
}
|
||||
|
||||
/// 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
|
||||
@ -344,7 +345,8 @@ pub fn write_5_number_summary(w: &mut io::Writer, s: &Summary) {
|
||||
/// 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;
|
||||
|
||||
@ -374,48 +376,49 @@ pub fn write_boxplot(w: &mut io::Writer, s: &Summary, width_hint: uint) {
|
||||
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
|
||||
|
@ -38,7 +38,7 @@ impl TempDir {
|
||||
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) })
|
||||
}
|
||||
@ -73,7 +73,8 @@ impl Drop for TempDir {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -163,7 +163,11 @@ pub fn test_main(args: &[~str], tests: ~[TestDescAndFn]) {
|
||||
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.
|
||||
@ -359,16 +363,17 @@ struct ConsoleTestState<T> {
|
||||
}
|
||||
|
||||
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(),
|
||||
@ -380,100 +385,103 @@ impl<T: Writer> ConsoleTestState<T> {
|
||||
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",
|
||||
@ -482,24 +490,25 @@ impl<T: Writer> ConsoleTestState<T> {
|
||||
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;
|
||||
@ -511,77 +520,82 @@ impl<T: Writer> ConsoleTestState<T> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -611,15 +625,16 @@ pub fn fmt_bench_samples(bs: &BenchSamples) -> ~str {
|
||||
|
||||
// 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,
|
||||
@ -643,10 +658,11 @@ pub fn run_tests_console(opts: &TestOpts,
|
||||
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,
|
||||
@ -661,12 +677,13 @@ pub fn run_tests_console(opts: &TestOpts,
|
||||
},
|
||||
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);
|
||||
@ -728,11 +745,11 @@ pub type MonitorMsg = (TestDesc, TestResult);
|
||||
|
||||
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| {
|
||||
@ -760,7 +777,7 @@ fn run_tests(opts: &TestOpts,
|
||||
// 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;
|
||||
@ -768,20 +785,21 @@ fn run_tests(opts: &TestOpts,
|
||||
|
||||
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 {
|
||||
@ -943,17 +961,22 @@ impl MetricMap {
|
||||
}
|
||||
|
||||
/// 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)
|
||||
}
|
||||
@ -1060,7 +1083,7 @@ impl MetricMap {
|
||||
|
||||
if ok {
|
||||
debug!("rewriting file '{:?}' with updated metrics", p);
|
||||
self.save(p);
|
||||
self.save(p).unwrap();
|
||||
}
|
||||
return (diff, ok)
|
||||
}
|
||||
|
@ -766,14 +766,14 @@ pub fn strptime(s: &str, format: &str) -> Result<Tm, ~str> {
|
||||
|
||||
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,
|
||||
@ -787,7 +787,7 @@ pub fn strptime(s: &str, format: &str) -> Result<Tm, ~str> {
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
@ -1017,12 +1017,12 @@ pub fn strftime(format: &str, tm: &Tm) -> ~str {
|
||||
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());
|
||||
}
|
||||
|
@ -102,8 +102,8 @@ fn encode_inner(s: &str, full_url: bool) -> ~str {
|
||||
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 {
|
||||
@ -166,14 +166,14 @@ fn decode_inner(s: &str, full_url: bool) -> ~str {
|
||||
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;
|
||||
@ -228,8 +228,8 @@ fn encode_plus(s: &str) -> ~str {
|
||||
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' | '_' | '.' | '-' => {
|
||||
@ -282,8 +282,8 @@ pub fn decode_form_urlencoded(s: &[u8]) -> HashMap<~str, ~[~str]> {
|
||||
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 {
|
||||
'&' | ';' => {
|
||||
@ -307,7 +307,7 @@ pub fn decode_form_urlencoded(s: &[u8]) -> HashMap<~str, ~[~str]> {
|
||||
'%' => {
|
||||
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
|
||||
@ -347,12 +347,12 @@ fn split_char_first(s: &str, c: char) -> (~str, ~str) {
|
||||
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;
|
||||
}
|
||||
|
@ -172,20 +172,19 @@ impl Database {
|
||||
}
|
||||
|
||||
// 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()),
|
||||
@ -203,7 +202,8 @@ impl Database {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -141,45 +141,48 @@ impl<T: Writer> Terminal<T> {
|
||||
/// 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),
|
||||
@ -189,13 +192,13 @@ impl<T: Writer> Terminal<T> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -214,7 +217,7 @@ impl<T: Writer> Terminal<T> {
|
||||
}
|
||||
|
||||
/// 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?
|
||||
@ -228,7 +231,7 @@ impl<T: Writer> Terminal<T> {
|
||||
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 {
|
||||
@ -236,6 +239,7 @@ impl<T: Writer> Terminal<T> {
|
||||
// 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 {
|
||||
@ -252,11 +256,11 @@ impl<T: Writer> Terminal<T> {
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
@ -162,6 +162,10 @@ pub static stringnames: &'static[&'static str] = &'static[ "cbt", "_", "cr", "cs
|
||||
/// 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;
|
||||
@ -177,17 +181,17 @@ pub fn parse(file: &mut io::Reader,
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
@ -216,18 +220,21 @@ pub fn parse(file: &mut io::Reader,
|
||||
}
|
||||
|
||||
// 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");
|
||||
@ -242,13 +249,13 @@ pub fn parse(file: &mut io::Reader,
|
||||
|
||||
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);
|
||||
@ -263,12 +270,12 @@ pub fn parse(file: &mut io::Reader,
|
||||
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(),
|
||||
|
@ -77,8 +77,8 @@ pub fn open(term: &str) -> Result<File, ~str> {
|
||||
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))
|
||||
|
Loading…
Reference in New Issue
Block a user