diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2014-01-29 16:33:57 -0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2014-02-03 09:32:33 -0800 |
| commit | ece8a8f520697be50cbe543bebe065c5198dae4d (patch) | |
| tree | fa1bf049d3b5d781c8c56e0d0491a655ece485a2 | |
| parent | be4fc638092bf896c5c6c0672136b83b71e491ee (diff) | |
| download | rust-ece8a8f520697be50cbe543bebe065c5198dae4d.tar.gz rust-ece8a8f520697be50cbe543bebe065c5198dae4d.zip | |
std: Remove io::io_error
* All I/O now returns IoResult<T> = Result<T, IoError> * All formatting traits now return fmt::Result = IoResult<()> * The if_ok!() macro was added to libstd
35 files changed, 920 insertions, 1061 deletions
diff --git a/src/libstd/fmt/mod.rs b/src/libstd/fmt/mod.rs index a17a030f4f7..e0944dea9b2 100644 --- a/src/libstd/fmt/mod.rs +++ b/src/libstd/fmt/mod.rs @@ -501,6 +501,8 @@ use num::Signed; pub mod parse; pub mod rt; +pub type Result = io::IoResult<()>; + /// A struct to represent both where to emit formatting strings to and how they /// should be formatted. A mutable version of this is passed to all formatting /// traits. @@ -527,7 +529,7 @@ pub struct Formatter<'a> { /// compile time it is ensured that the function and the value have the correct /// types, and then this struct is used to canonicalize arguments to one type. pub struct Argument<'a> { - priv formatter: extern "Rust" fn(&util::Void, &mut Formatter), + priv formatter: extern "Rust" fn(&util::Void, &mut Formatter) -> Result, priv value: &'a util::Void, } @@ -561,50 +563,50 @@ pub struct Arguments<'a> { /// to this trait. There is not an explicit way of selecting this trait to be /// used for formatting, it is only if no other format is specified. #[allow(missing_doc)] -pub trait Show { fn fmt(&Self, &mut Formatter); } +pub trait Show { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `b` character #[allow(missing_doc)] -pub trait Bool { fn fmt(&Self, &mut Formatter); } +pub trait Bool { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `c` character #[allow(missing_doc)] -pub trait Char { fn fmt(&Self, &mut Formatter); } +pub trait Char { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `i` and `d` characters #[allow(missing_doc)] -pub trait Signed { fn fmt(&Self, &mut Formatter); } +pub trait Signed { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `u` character #[allow(missing_doc)] -pub trait Unsigned { fn fmt(&Self, &mut Formatter); } +pub trait Unsigned { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `o` character #[allow(missing_doc)] -pub trait Octal { fn fmt(&Self, &mut Formatter); } +pub trait Octal { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `b` character #[allow(missing_doc)] -pub trait Binary { fn fmt(&Self, &mut Formatter); } +pub trait Binary { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `x` character #[allow(missing_doc)] -pub trait LowerHex { fn fmt(&Self, &mut Formatter); } +pub trait LowerHex { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `X` character #[allow(missing_doc)] -pub trait UpperHex { fn fmt(&Self, &mut Formatter); } +pub trait UpperHex { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `s` character #[allow(missing_doc)] -pub trait String { fn fmt(&Self, &mut Formatter); } +pub trait String { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `?` character #[allow(missing_doc)] -pub trait Poly { fn fmt(&Self, &mut Formatter); } +pub trait Poly { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `p` character #[allow(missing_doc)] -pub trait Pointer { fn fmt(&Self, &mut Formatter); } +pub trait Pointer { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `f` character #[allow(missing_doc)] -pub trait Float { fn fmt(&Self, &mut Formatter); } +pub trait Float { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `e` character #[allow(missing_doc)] -pub trait LowerExp { fn fmt(&Self, &mut Formatter); } +pub trait LowerExp { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `E` character #[allow(missing_doc)] -pub trait UpperExp { fn fmt(&Self, &mut Formatter); } +pub trait UpperExp { fn fmt(&Self, &mut Formatter) -> Result; } // FIXME #11938 - UFCS would make us able call the above methods // directly Show::show(x, fmt). @@ -659,15 +661,15 @@ uniform_fn_call_workaround! { /// let w = &mut io::stdout() as &mut io::Writer; /// format_args!(|args| { fmt::write(w, args) }, "Hello, {}!", "world"); /// ``` -pub fn write(output: &mut io::Writer, args: &Arguments) { +pub fn write(output: &mut io::Writer, args: &Arguments) -> Result { unsafe { write_unsafe(output, args.fmt, args.args) } } /// The `writeln` function takes the same arguments as `write`, except that it /// will also write a newline (`\n`) character at the end of the format string. -pub fn writeln(output: &mut io::Writer, args: &Arguments) { - unsafe { write_unsafe(output, args.fmt, args.args) } - output.write(['\n' as u8]); +pub fn writeln(output: &mut io::Writer, args: &Arguments) -> Result { + let first = unsafe { write_unsafe(output, args.fmt, args.args) }; + first.and_then(|()| output.write(['\n' as u8])) } /// The `write_unsafe` function takes an output stream, a precompiled format @@ -692,7 +694,7 @@ pub fn writeln(output: &mut io::Writer, args: &Arguments) { /// format string. pub unsafe fn write_unsafe(output: &mut io::Writer, fmt: &[rt::Piece], - args: &[Argument]) { + args: &[Argument]) -> Result { let mut formatter = Formatter { flags: 0, width: None, @@ -704,8 +706,9 @@ pub unsafe fn write_unsafe(output: &mut io::Writer, curarg: args.iter(), }; for piece in fmt.iter() { - formatter.run(piece, None); + if_ok!(formatter.run(piece, None)); } + Ok(()) } /// The format function takes a precompiled format string and a list of @@ -752,7 +755,7 @@ pub fn format(args: &Arguments) -> ~str { /// format string. pub unsafe fn format_unsafe(fmt: &[rt::Piece], args: &[Argument]) -> ~str { let mut output = MemWriter::new(); - write_unsafe(&mut output as &mut io::Writer, fmt, args); + write_unsafe(&mut output as &mut io::Writer, fmt, args).unwrap(); return str::from_utf8_owned(output.unwrap()).unwrap(); } @@ -762,10 +765,10 @@ impl<'a> Formatter<'a> { // at runtime. This consumes all of the compile-time statics generated by // the format! syntax extension. - fn run(&mut self, piece: &rt::Piece, cur: Option<&str>) { + fn run(&mut self, piece: &rt::Piece, cur: Option<&str>) -> Result { match *piece { - rt::String(s) => { self.buf.write(s.as_bytes()); } - rt::CurrentArgument(()) => { self.buf.write(cur.unwrap().as_bytes()); } + rt::String(s) => self.buf.write(s.as_bytes()), + rt::CurrentArgument(()) => self.buf.write(cur.unwrap().as_bytes()), rt::Argument(ref arg) => { // Fill in the format parameters into the formatter self.fill = arg.format.fill; @@ -782,8 +785,8 @@ impl<'a> Formatter<'a> { // Then actually do some printing match arg.method { - None => { (value.formatter)(value.value, self); } - Some(ref method) => { self.execute(*method, value); } + None => (value.formatter)(value.value, self), + Some(ref method) => self.execute(*method, value) } } } @@ -804,7 +807,7 @@ impl<'a> Formatter<'a> { } } - fn execute(&mut self, method: &rt::Method, arg: Argument) { + fn execute(&mut self, method: &rt::Method, arg: Argument) -> Result { match *method { // Pluralization is selection upon a numeric value specified as the // parameter. @@ -847,7 +850,7 @@ impl<'a> Formatter<'a> { } } - self.runplural(value, *default); + self.runplural(value, *default) } // Select is just a matching against the string specified. @@ -860,24 +863,26 @@ impl<'a> Formatter<'a> { for s in selectors.iter() { if s.selector == value { for piece in s.result.iter() { - self.run(piece, Some(value)); + if_ok!(self.run(piece, Some(value))); } - return; + return Ok(()); } } for piece in default.iter() { - self.run(piece, Some(value)); + if_ok!(self.run(piece, Some(value))); } + Ok(()) } } } - fn runplural(&mut self, value: uint, pieces: &[rt::Piece]) { + fn runplural(&mut self, value: uint, pieces: &[rt::Piece]) -> Result { ::uint::to_str_bytes(value, 10, |buf| { let valuestr = str::from_utf8(buf).unwrap(); for piece in pieces.iter() { - self.run(piece, Some(valuestr)); + if_ok!(self.run(piece, Some(valuestr))); } + Ok(()) }) } @@ -899,7 +904,7 @@ impl<'a> Formatter<'a> { /// This function will correctly account for the flags provided as well as /// the minimum width. It will not take precision into account. pub fn pad_integral(&mut self, s: &[u8], alternate_prefix: &str, - positive: bool) { + positive: bool) -> Result { use fmt::parse::{FlagAlternate, FlagSignPlus, FlagSignAwareZeroPad}; let mut actual_len = s.len(); @@ -916,32 +921,32 @@ impl<'a> Formatter<'a> { let sign = |this: &mut Formatter| { if !signprinted { if this.flags & 1 << (FlagSignPlus as uint) != 0 && positive { - this.buf.write(['+' as u8]); + if_ok!(this.buf.write(['+' as u8])); } else if !positive { - this.buf.write(['-' as u8]); + if_ok!(this.buf.write(['-' as u8])); } if this.flags & 1 << (FlagAlternate as uint) != 0 { - this.buf.write(alternate_prefix.as_bytes()); + if_ok!(this.buf.write(alternate_prefix.as_bytes())); } signprinted = true; } + Ok(()) }; let emit = |this: &mut Formatter| { - sign(this); - this.buf.write(s); + sign(this).and_then(|()| this.buf.write(s)) }; match self.width { - None => { emit(self) } - Some(min) if actual_len >= min => { emit(self) } + None => emit(self), + Some(min) if actual_len >= min => emit(self), Some(min) => { if self.flags & 1 << (FlagSignAwareZeroPad as uint) != 0 { self.fill = '0'; - sign(self); + if_ok!(sign(self)); } self.with_padding(min - actual_len, parse::AlignRight, |me| { - emit(me); + emit(me) }) } } @@ -958,11 +963,10 @@ impl<'a> Formatter<'a> { /// is longer than this length /// /// Notably this function ignored the `flag` parameters - pub fn pad(&mut self, s: &str) { + pub fn pad(&mut self, s: &str) -> Result { // Make sure there's a fast path up front if self.width.is_none() && self.precision.is_none() { - self.buf.write(s.as_bytes()); - return + return self.buf.write(s.as_bytes()); } // The `precision` field can be interpreted as a `max-width` for the // string being formatted @@ -974,8 +978,7 @@ impl<'a> Formatter<'a> { let char_len = s.char_len(); if char_len >= max { let nchars = ::cmp::min(max, char_len); - self.buf.write(s.slice_chars(0, nchars).as_bytes()); - return + return self.buf.write(s.slice_chars(0, nchars).as_bytes()); } } None => {} @@ -985,7 +988,7 @@ impl<'a> Formatter<'a> { match self.width { // If we're under the maximum length, and there's no minimum length // requirements, then we can just emit the string - None => { self.buf.write(s.as_bytes()) } + None => self.buf.write(s.as_bytes()), // If we're under the maximum width, check if we're over the minimum // width, if so it's as easy as just emitting the string. @@ -997,7 +1000,7 @@ impl<'a> Formatter<'a> { // up the minimum width with the specified string + some alignment. Some(width) => { self.with_padding(width - s.len(), parse::AlignLeft, |me| { - me.buf.write(s.as_bytes()); + me.buf.write(s.as_bytes()) }) } } @@ -1006,29 +1009,30 @@ impl<'a> Formatter<'a> { fn with_padding(&mut self, padding: uint, default: parse::Alignment, - f: |&mut Formatter|) { + f: |&mut Formatter| -> Result) -> Result { let align = match self.align { parse::AlignUnknown => default, parse::AlignLeft | parse::AlignRight => self.align }; if align == parse::AlignLeft { - f(self); + if_ok!(f(self)); } let mut fill = [0u8, ..4]; let len = self.fill.encode_utf8(fill); for _ in range(0, padding) { - self.buf.write(fill.slice_to(len)); + if_ok!(self.buf.write(fill.slice_to(len))); } if align == parse::AlignRight { - f(self); + if_ok!(f(self)); } + Ok(()) } } /// This is a function which calls are emitted to by the compiler itself to /// create the Argument structures that are passed into the `format` function. #[doc(hidden)] #[inline] -pub fn argument<'a, T>(f: extern "Rust" fn(&T, &mut Formatter), +pub fn argument<'a, T>(f: extern "Rust" fn(&T, &mut Formatter) -> Result, t: &'a T) -> Argument<'a> { unsafe { Argument { @@ -1055,41 +1059,41 @@ pub fn argumentuint<'a>(s: &'a uint) -> Argument<'a> { // Implementations of the core formatting traits impl Bool for bool { - fn fmt(b: &bool, f: &mut Formatter) { - String::fmt(&(if *b {"true"} else {"false"}), f); + fn fmt(b: &bool, f: &mut Formatter) -> Result { + String::fmt(&(if *b {"true"} else {"false"}), f) } } impl<'a, T: str::Str> String for T { - fn fmt(s: &T, f: &mut Formatter) { - f.pad(s.as_slice()); + fn fmt(s: &T, f: &mut Formatter) -> Result { + f.pad(s.as_slice()) } } impl Char for char { - fn fmt(c: &char, f: &mut Formatter) { + fn fmt(c: &char, f: &mut Formatter) -> Result { let mut utf8 = [0u8, ..4]; let amt = c.encode_utf8(utf8); let s: &str = unsafe { cast::transmute(utf8.slice_to(amt)) }; - String::fmt(&s, f); + String::fmt(&s, f) } } macro_rules! int_base(($ty:ident, $into:ident, $base:expr, $name:ident, $prefix:expr) => { impl $name for $ty { - fn fmt(c: &$ty, f: &mut Formatter) { + fn fmt(c: &$ty, f: &mut Formatter) -> Result { ::$into::to_str_bytes(*c as $into, $base, |buf| { - f.pad_integral(buf, $prefix, true); + f.pad_integral(buf, $prefix, true) }) } } }) macro_rules! upper_hex(($ty:ident, $into:ident) => { impl UpperHex for $ty { - fn fmt(c: &$ty, f: &mut Formatter) { + fn fmt(c: &$ty, f: &mut Formatter) -> Result { ::$into::to_str_bytes(*c as $into, 16, |buf| { - upperhex(buf, f); + upperhex(buf, f) }) } } @@ -1097,7 +1101,7 @@ macro_rules! upper_hex(($ty:ident, $into:ident) => { // Not sure why, but this causes an "unresolved enum variant, struct or const" // when inlined into the above macro... #[doc(hidden)] -pub fn upperhex(buf: &[u8], f: &mut Formatter) { +pub fn upperhex(buf: &[u8], f: &mut Formatter) -> Result { let mut local = [0u8, ..16]; for i in ::iter::range(0, buf.len()) { local[i] = match buf[i] as char { @@ -1105,16 +1109,16 @@ pub fn upperhex(buf: &[u8], f: &mut Formatter) { c => c as u8, } } - f.pad_integral(local.slice_to(buf.len()), "0x", true); + f.pad_integral(local.slice_to(buf.len()), "0x", true) } macro_rules! integer(($signed:ident, $unsigned:ident) => { // Signed is special because it actuall emits the negative sign, // nothing else should do that, however. impl Signed for $signed { - fn fmt(c: &$signed, f: &mut Formatter) { + fn fmt(c: &$signed, f: &mut Formatter) -> Result { ::$unsigned::to_str_bytes(c.abs() as $unsigned, 10, |buf| { - f.pad_integral(buf, "", *c >= 0); + f.pad_integral(buf, "", *c >= 0) }) } } @@ -1138,35 +1142,35 @@ integer!(i64, u64) macro_rules! floating(($ty:ident) => { impl Float for $ty { - fn fmt(f: &$ty, fmt: &mut Formatter) { + fn fmt(f: &$ty, fmt: &mut Formatter) -> Result { // FIXME: this shouldn't perform an allocation let s = match fmt.precision { Some(i) => ::$ty::to_str_exact(f.abs(), i), None => ::$ty::to_str_digits(f.abs(), 6) }; - fmt.pad_integral(s.as_bytes(), "", *f >= 0.0); + fmt.pad_integral(s.as_bytes(), "", *f >= 0.0) } } impl LowerExp for $ty { - fn fmt(f: &$ty, fmt: &mut Formatter) { + fn fmt(f: &$ty, fmt: &mut Formatter) -> Result { // FIXME: this shouldn't perform an allocation let s = match fmt.precision { Some(i) => ::$ty::to_str_exp_exact(f.abs(), i, false), None => ::$ty::to_str_exp_digits(f.abs(), 6, false) }; - fmt.pad_integral(s.as_bytes(), "", *f >= 0.0); + fmt.pad_integral(s.as_bytes(), "", *f >= 0.0) } } impl UpperExp for $ty { - fn fmt(f: &$ty, fmt: &mut Formatter) { + fn fmt(f: &$ty, fmt: &mut Formatter) -> Result { // FIXME: this shouldn't perform an allocation let s = match fmt.precision { Some(i) => ::$ty::to_str_exp_exact(f.abs(), i, true), None => ::$ty::to_str_exp_digits(f.abs(), 6, true) }; - fmt.pad_integral(s.as_bytes(), "", *f >= 0.0); + fmt.pad_integral(s.as_bytes(), "", *f >= 0.0) } } }) @@ -1174,39 +1178,41 @@ floating!(f32) floating!(f64) impl<T> Poly for T { - fn fmt(t: &T, f: &mut Formatter) { + fn fmt(t: &T, f: &mut Formatter) -> Result { match (f.width, f.precision) { (None, None) => { - repr::write_repr(f.buf, t); + repr::write_repr(f.buf, t) } // If we have a specified width for formatting, then we have to make // this allocation of a new string _ => { let s = repr::repr_to_str(t); - f.pad(s); + f.pad(s) } } } } impl<T> Pointer for *T { - fn fmt(t: &*T, f: &mut Formatter) { + fn fmt(t: &*T, f: &mut Formatter) -> Result { f.flags |= 1 << (parse::FlagAlternate as uint); ::uint::to_str_bytes(*t as uint, 16, |buf| { - f.pad_integral(buf, "0x", true); + f.pad_integral(buf, "0x", true) }) } } impl<T> Pointer for *mut T { - fn fmt(t: &*mut T, f: &mut Formatter) { Pointer::fmt(&(*t as *T), f) } + fn fmt(t: &*mut T, f: &mut Formatter) -> Result { + Pointer::fmt(&(*t as *T), f) + } } // Implementation of Show for various core types macro_rules! delegate(($ty:ty to $other:ident) => { impl<'a> Show for $ty { - fn fmt(me: &$ty, f: &mut Formatter) { + fn fmt(me: &$ty, f: &mut Formatter) -> Result { $other::fmt(me, f) } } @@ -1229,10 +1235,10 @@ delegate!(f32 to Float) delegate!(f64 to Float) impl<T> Show for *T { - fn fmt(me: &*T, f: &mut Formatter) { Pointer::fmt(me, f) } + fn fmt(me: &*T, f: &mut Formatter) -> Result { Pointer::fmt(me, f) } } impl<T> Show for *mut T { - fn fmt(me: &*mut T, f: &mut Formatter) { Pointer::fmt(me, f) } + fn fmt(me: &*mut T, f: &mut Formatter) -> Result { Pointer::fmt(me, f) } } // If you expected tests to be here, look instead at the run-pass/ifmt.rs test, diff --git a/src/libstd/hash.rs b/src/libstd/hash.rs index 1444f9b4129..4163d1e0c96 100644 --- a/src/libstd/hash.rs +++ b/src/libstd/hash.rs @@ -27,13 +27,14 @@ #[allow(missing_doc)]; use container::Container; +use io::{Writer, IoResult}; use iter::Iterator; +use num::ToStrRadix; use option::{Some, None}; -use io::Writer; +use result::Ok; use str::OwnedStr; use to_bytes::IterBytes; use vec::ImmutableVector; -use num::ToStrRadix; // Alias `SipState` to `State`. pub use State = hash::SipState; @@ -164,7 +165,7 @@ macro_rules! compress ( impl Writer for SipState { // Methods for io::writer #[inline] - fn write(&mut self, msg: &[u8]) { + fn write(&mut self, msg: &[u8]) -> IoResult<()> { let length = msg.len(); self.length += length; @@ -180,7 +181,7 @@ impl Writer for SipState { t += 1; } self.ntail += length; - return; + return Ok(()) } let mut t = 0; @@ -222,17 +223,14 @@ impl Writer for SipState { t += 1 } self.ntail = left; - } - - fn flush(&mut self) { - // No-op + Ok(()) } } impl Streaming for SipState { #[inline] fn input(&mut self, buf: &[u8]) { - self.write(buf); + self.write(buf).unwrap(); } #[inline] diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 64e42c5480f..5e64862cbec 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -11,10 +11,11 @@ //! Buffering wrappers for I/O traits use container::Container; -use io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE}; +use io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE, IoResult}; use iter::ExactSize; use num; -use option::{Option, Some, None}; +use option::{Some, None}; +use result::{Ok, Err}; use vec::{OwnedVector, ImmutableVector, MutableVector}; use vec; @@ -86,17 +87,12 @@ impl<R: Reader> BufferedReader<R> { } impl<R: Reader> Buffer for BufferedReader<R> { - fn fill<'a>(&'a mut self) -> &'a [u8] { - if self.pos == self.cap { - match self.inner.read(self.buf) { - Some(cap) => { - self.pos = 0; - self.cap = cap; - } - None => { self.eof = true; } - } + fn fill<'a>(&'a mut self) -> IoResult<&'a [u8]> { + while self.pos == self.cap { + self.cap = if_ok!(self.inner.read(self.buf)); + self.pos = 0; } - return self.buf.slice(self.pos, self.cap); + Ok(self.buf.slice(self.pos, self.cap)) } fn consume(&mut self, amt: uint) { @@ -106,18 +102,15 @@ impl<R: Reader> Buffer for BufferedReader<R> { } impl<R: Reader> Reader for BufferedReader<R> { - fn read(&mut self, buf: &mut [u8]) -> Option<uint> { + fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { let nread = { - let available = self.fill(); + let available = if_ok!(self.fill()); let nread = num::min(available.len(), buf.len()); vec::bytes::copy_memory(buf, available.slice_to(nread)); nread }; self.pos += nread; - if nread == 0 && buf.len() != 0 && self.eof { - return None; - } - Some(nread) + Ok(nread) } } @@ -161,10 +154,13 @@ impl<W: Writer> BufferedWriter<W> { BufferedWriter::with_capacity(DEFAULT_BUF_SIZE, inner) } - fn flush_buf(&mut self) { + fn flush_buf(&mut self) -> IoResult<()> { if self.pos != 0 { - self.inner.write(self.buf.slice_to(self.pos)); + let ret = self.inner.write(self.buf.slice_to(self.pos)); self.pos = 0; + ret + } else { + Ok(()) } } @@ -178,29 +174,30 @@ impl<W: Writer> BufferedWriter<W> { /// /// The buffer is flushed before returning the writer. pub fn unwrap(mut self) -> W { - self.flush_buf(); + // FIXME: is failing the right thing to do if flushing fails? + self.flush_buf().unwrap(); self.inner } } impl<W: Writer> Writer for BufferedWriter<W> { - fn write(&mut self, buf: &[u8]) { + fn write(&mut self, buf: &[u8]) -> IoResult<()> { if self.pos + buf.len() > self.buf.len() { - self.flush_buf(); + if_ok!(self.flush_buf()); } if buf.len() > self.buf.len() { - self.inner.write(buf); + self.inner.write(buf) } else { let dst = self.buf.mut_slice_from(self.pos); vec::bytes::copy_memory(dst, buf); self.pos += buf.len(); + Ok(()) } } - fn flush(&mut self) { - self.flush_buf(); - self.inner.flush(); + fn flush(&mut self) -> IoResult<()> { + self.flush_buf().and_then(|()| self.inner.flush()) } } @@ -234,18 +231,19 @@ impl<W: Writer> LineBufferedWriter<W> { } impl<W: Writer> Writer for LineBufferedWriter<W> { - fn write(&mut self, buf: &[u8]) { + fn write(&mut self, buf: &[u8]) -> IoResult<()> { match buf.iter().rposition(|&b| b == '\n' as u8) { Some(i) => { - self.inner.write(buf.slice_to(i + 1)); - self.inner.flush(); - self.inner.write(buf.slice_from(i + 1)); + if_ok!(self.inner.write(buf.slice_to(i + 1))); + if_ok!(self.inner.flush()); + if_ok!(self.inner.write(buf.slice_from(i + 1))); + Ok(()) } None => self.inner.write(buf), } } - fn flush(&mut self) { self.inner.flush() } + fn flush(&mut self) -> IoResult<()> { self.inner.flush() } } struct InternalBufferedWriter<W>(BufferedWriter<W>); @@ -258,7 +256,9 @@ impl<W> InternalBufferedWriter<W> { } impl<W: Reader> Reader for InternalBufferedWriter<W> { - fn read(&mut self, buf: &mut [u8]) -> Option<uint> { self.get_mut_ref().inner.read(buf) } + fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { + self.get_mut_ref().inner.read(buf) + } } /// Wraps a Stream and buffers input and output to and from it @@ -326,17 +326,23 @@ impl<S: Stream> BufferedStream<S> { } impl<S: Stream> Buffer for BufferedStream<S> { - fn fill<'a>(&'a mut self) -> &'a [u8] { self.inner.fill() } + fn fill<'a>(&'a mut self) -> IoResult<&'a [u8]> { self.inner.fill() } fn consume(&mut self, amt: uint) { self.inner.consume(amt) } } impl<S: Stream> Reader for BufferedStream<S> { - fn read(&mut self, buf: &mut [u8]) -> Option<uint> { self.inner.read(buf) } + fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { + self.inner.read(buf) + } } impl<S: Stream> Writer for BufferedStream<S> { - fn write(&mut self, buf: &[u8]) { self.inner.inner.get_mut_ref().write(buf) } - fn flush(&mut self) { self.inner.inner.get_mut_ref().flush() } + fn write(&mut self, buf: &[u8]) -> IoResult<()> { + self.inner.inner.get_mut_ref().write(buf) + } + fn flush(&mut self) -> IoResult<()> { + self.inner.inner.get_mut_ref().flush() + } } #[cfg(test)] diff --git a/src/libstd/io/comm_adapters.rs b/src/libstd/io/comm_adapters.rs index 1eaa752d2a3..e86ad50d690 100644 --- a/src/libstd/io/comm_adapters.rs +++ b/src/libstd/io/comm_adapters.rs @@ -14,7 +14,7 @@ use comm::{Port, Chan}; use cmp; use io; use option::{None, Option, Some}; -use super::{Reader, Writer}; +use super::{Reader, Writer, IoResult}; use vec::{bytes, CloneableVector, MutableVector, ImmutableVector}; /// Allows reading from a port. @@ -49,7 +49,7 @@ impl PortReader { } impl Reader for PortReader { - fn read(&mut self, buf: &mut [u8]) -> Option<uint> { + fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { let mut num_read = 0; loop { match self.buf { @@ -71,10 +71,9 @@ impl Reader for PortReader { self.closed = self.buf.is_none(); } if self.closed && num_read == 0 { - io::io_error::cond.raise(io::standard_error(io::EndOfFile)); - None + Err(io::standard_error(io::EndOfFile)) } else { - Some(num_read) + Ok(num_read) } } } @@ -98,13 +97,15 @@ impl ChanWriter { } impl Writer for ChanWriter { - fn write(&mut self, buf: &[u8]) { + fn write(&mut self, buf: &[u8]) -> IoResult<()> { if !self.chan.try_send(buf.to_owned()) { - io::io_error::cond.raise(io::IoError { + Err(io::IoError { kind: io::BrokenPipe, desc: "Pipe closed", detail: None - }); + }) + } else { + Ok(()) } } } diff --git a/src/libstd/io/extensions.rs b/src/libstd/io/extensions.rs index 548dc3efe92..7e1dbcaeade 100644 --- a/src/libstd/io/extensions.rs +++ b/src/libstd/io/extensions.rs @@ -46,7 +46,7 @@ impl<'r, R: Reader> Bytes<'r, R> { impl<'r, R: Reader> Iterator<u8> for Bytes<'r, R> { #[inline] fn next(&mut self) -> Option<u8> { - self.reader.read_byte() + self.reader.read_byte().ok() } } diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs index 8904101dd05..867e0ebd6ee 100644 --- a/src/libstd/io/fs.rs +++ b/src/libstd/io/fs.rs @@ -27,21 +27,25 @@ particular bits of it, etc. # Example - use std::io::{File, fs}; +```rust +# #[allow(unused_must_use)]; +use std::io::{File, fs}; - let path = Path::new("foo.txt"); +let path = Path::new("foo.txt"); - // create the file, whether it exists or not - let mut file = File::create(&path); - file.write(bytes!("foobar")); +// create the file, whether it exists or not +let mut file = File::create(&path); +file.write(bytes!("foobar")); +# drop(file); - // open the file in read-only mode - let mut file = File::open(&path); - file.read_to_end(); +// open the file in read-only mode +let mut file = File::open(&path); +file.read_to_end(); - println!("{}", path.stat().size); - fs::symlink(&path, &Path::new("bar.txt")); - fs::unlink(&path); +println!("{}", path.stat().size); +# drop(file); +fs::unlink(&path); +``` */ @@ -50,7 +54,7 @@ use clone::Clone; use iter::Iterator; use super::{Reader, Writer, Seek}; use super::{SeekStyle, Read, Write, Open, IoError, Truncate, - FileMode, FileAccess, FileStat, io_error, FilePermission}; + FileMode, FileAccess, FileStat, IoResult, FilePermission}; use rt::rtio::{RtioFileStream, IoFactory, LocalIo}; use io; use option::{Some, None, Option}; @@ -81,22 +85,19 @@ impl File { /// /// # Example /// - /// use std::io::{File, io_error, Open, ReadWrite}; + /// ```rust + /// use std::io::{File, Open, ReadWrite}; /// - /// let p = Path::new("/some/file/path.txt"); + /// let p = Path::new("/some/file/path.txt"); /// - /// io_error::cond.trap(|_| { - /// // hoo-boy... - /// }).inside(|| { - /// let file = match File::open_mode(&p, Open, ReadWrite) { - /// Some(s) => s, - /// None => fail!("whoops! I'm sure this raised, anyways..") - /// }; - /// // do some stuff with that file + /// let file = match File::open_mode(&p, Open, ReadWrite) { + /// Ok(f) => f, + /// Err(e) => fail!("file error: {}", e), + /// }; + /// // do some stuff with that file /// - /// // the file will be closed at the end of this block - /// }) - /// // .. + /// // the file will be closed at the end of this block + /// ``` /// /// `FileMode` and `FileAccess` provide information about the permissions /// context in which a given stream is created. More information about them @@ -119,7 +120,7 @@ impl File { /// * Filesystem-level errors (full disk, etc) pub fn open_mode(path: &Path, mode: FileMode, - access: FileAccess) -> Option<File> { + access: FileAccess) -> IoResult<File> { LocalIo::maybe_raise(|io| { io.fs_open(&path.to_c_str(), mode, access).map(|fd| { File { @@ -139,10 +140,12 @@ impl File { /// /// # Example /// - /// use std::io::File; + /// ```rust + /// use std::io::File; /// - /// let contents = File::open(&Path::new("foo.txt")).read_to_end(); - pub fn open(path: &Path) -> Option<File> { + /// let contents = File::open(&Path::new("foo.txt")).read_to_end(); + /// ``` + pub fn open(path: &Path) -> IoResult<File> { File::open_mode(path, Open, Read) } @@ -154,11 +157,16 @@ impl File { /// /// # Example /// - /// use std::io::File; + /// ```rust + /// # #[allow(unused_must_use)]; + /// use std::io::File; /// - /// let mut f = File::create(&Path::new("foo.txt")); - /// f.write(bytes!("This is a sample file")); - pub fn create(path: &Path) -> Option<File> { + /// let mut f = File::create(&Path::new("foo.txt")); + /// f.write(bytes!("This is a sample file")); + /// # drop(f); + /// # ::std::io::fs::unlnk(&Path::new("foo.txt")); + /// ``` + pub fn create(path: &Path) -> IoResult<File> { File::open_mode(path, Truncate, Write) } @@ -174,8 +182,8 @@ impl File { /// # Errors /// /// This function will raise on the `io_error` condition on failure. - pub fn fsync(&mut self) { - let _ = self.fd.fsync().map_err(|e| io_error::cond.raise(e)); + pub fn fsync(&mut self) -> IoResult<()> { + self.fd.fsync() } /// This function is similar to `fsync`, except that it may not synchronize @@ -186,8 +194,8 @@ impl File { /// # Errors /// /// This function will raise on the `io_error` condition on failure. - pub fn datasync(&mut self) { - let _ = self.fd.datasync().map_err(|e| io_error::cond.raise(e)); + pub fn datasync(&mut self) -> IoResult<()> { + self.fd.datasync() } /// Either truncates or extends the underlying file, updating the size of @@ -202,8 +210,8 @@ impl File { /// # Errors /// /// On error, this function will raise on the `io_error` condition. - pub fn truncate(&mut self, size: i64) { - let _ = self.fd.truncate(size).map_err(|e| io_error::cond.raise(e)); + pub fn truncate(&mut self, size: i64) -> IoResult<()> { + self.fd.truncate(size) } /// Tests whether this stream has reached EOF. @@ -219,12 +227,13 @@ impl File { /// /// # Example /// -/// use std::io::fs; +/// ```rust +/// # #[allow(unused_must_use)]; +/// use std::io::fs; /// -/// let p = Path::new("/some/file/path.txt"); -/// fs::unlink(&p); -/// // if we made it here without failing, then the -/// // unlink operation was successful +/// let p = Path::new("/some/file/path.txt"); +/// fs::unlink(&p); +/// ``` /// /// Note that, just because an unlink call was successful, it is not /// guaranteed that a file is immediately deleted (e.g. depending on @@ -235,8 +244,8 @@ impl File { /// This function will raise an `io_error` condition if the path points to a /// directory, the user lacks permissions to remove the file, or if some /// other filesystem-level error occurs. -pub fn unlink(path: &Path) { - LocalIo::maybe_raise(|io| io.fs_unlink(&path.to_c_str())); +pub fn unlink(path: &Path) -> IoResult<()> { + LocalIo::maybe_raise(|io| io.fs_unlink(&path.to_c_str())) } /// Given a path, query the file system to get information about a file, @@ -249,48 +258,26 @@ pub fn unlink(path: &Path) { /// /// # Example /// -/// use std::io; -/// use std::io::fs; +/// ```rust +/// use std::io; +/// use std::io::fs; /// -/// let p = Path::new("/some/file/path.txt"); -/// match io::result(|| fs::stat(&p)) { -/// Ok(stat) => { /* ... */ } -/// Err(e) => { /* handle error */ } -/// } +/// let p = Path::new("/some/file/path.txt"); +/// match fs::stat(&p) { +/// Ok(stat) => { /* ... */ } +/// Err(e) => { /* handle error */ } +/// } +/// ``` /// /// # Errors /// /// This call will raise an `io_error` condition if the user lacks the /// requisite permissions to perform a `stat` call on the given path or if /// there is no entry in the filesystem at the provided path. -pub fn stat(path: &Path) -> FileStat { +pub fn stat(path: &Path) -> IoResult<FileStat> { LocalIo::maybe_raise(|io| { io.fs_stat(&path.to_c_str()) - }).unwrap_or_else(dummystat) -} - -fn dummystat() -> FileStat { - FileStat { - path: Path::new(""), - size: 0, - kind: io::TypeFile, - perm: 0, - created: 0, - modified: 0, - accessed: 0, - unstable: io::UnstableFileStat { - device: 0, - inode: 0, - rdev: 0, - nlink: 0, - uid: 0, - gid: 0, - blksize: 0, - blocks: 0, - flags: 0, - gen: 0, - } - } + }) } /// Perform the same operation as the `stat` function, except that this @@ -301,28 +288,30 @@ fn dummystat() -> FileStat { /// # Errors /// /// See `stat` -pub fn lstat(path: &Path) -> FileStat { +pub fn lstat(path: &Path) -> IoResult<FileStat> { LocalIo::maybe_raise(|io| { io.fs_lstat(&path.to_c_str()) - }).unwrap_or_else(dummystat) + }) } /// Rename a file or directory to a new name. /// /// # Example /// -/// use std::io::fs; +/// ```rust +/// # #[allow(unused_must_use)]; +/// use std::io::fs; /// -/// fs::rename(&Path::new("foo"), &Path::new("bar")); -/// // Oh boy, nothing was raised! +/// fs::rename(&Path::new("foo"), &Path::new("bar")); +/// ``` /// /// # Errors /// /// Will raise an `io_error` condition if the provided `path` doesn't exist, /// the process lacks permissions to view the contents, or if some other /// intermittent I/O error occurs. -pub fn rename(from: &Path, to: &Path) { - LocalIo::maybe_raise(|io| io.fs_rename(&from.to_c_str(), &to.to_c_str())); +pub fn rename(from: &Path, to: &Path) -> IoResult<()> { + LocalIo::maybe_raise(|io| io.fs_rename(&from.to_c_str(), &to.to_c_str())) } /// Copies the contents of one file to another. This function will also @@ -333,10 +322,12 @@ pub fn rename(from: &Path, to: &Path) { /// /// # Example /// -/// use std::io::fs; +/// ```rust +/// # #[allow(unused_must_use)]; +/// use std::io::fs; /// -/// fs::copy(&Path::new("foo.txt"), &Path::new("bar.txt")); -/// // Oh boy, nothing was raised! +/// fs::copy(&Path::new("foo.txt"), &Path::new("bar.txt")); +/// ``` /// /// # Errors /// @@ -351,27 +342,29 @@ pub fn rename(from: &Path, to: &Path) { /// Note that this copy is not atomic in that once the destination is /// ensured to not exist, there is nothing preventing the destination from /// being created and then destroyed by this operation. -pub fn copy(from: &Path, to: &Path) { +pub fn copy(from: &Path, to: &Path) -> IoResult<()> { if !from.is_file() { - return io_error::cond.raise(IoError { + return Err(IoError { kind: io::MismatchedFileTypeForOperation, desc: "the source path is not an existing file", detail: None, - }); + }) } - let mut reader = match File::open(from) { Some(f) => f, None => return }; - let mut writer = match File::create(to) { Some(f) => f, None => return }; + let mut reader = if_ok!(File::open(from)); + let mut writer = if_ok!(File::create(to)); let mut buf = [0, ..io::DEFAULT_BUF_SIZE]; loop { - match reader.read(buf) { - Some(amt) => writer.write(buf.slice_to(amt)), - None => break - } + let amt = match reader.read(buf) { + Ok(n) => n, + Err(ref e) if e.kind == io::EndOfFile => { break } + Err(e) => return Err(e) + }; + if_ok!(writer.write(buf.slice_to(amt))); } - chmod(to, from.stat().perm) + chmod(to, if_ok!(from.stat()).perm) } /// Changes the permission mode bits found on a file or a directory. This @@ -379,21 +372,24 @@ pub fn copy(from: &Path, to: &Path) { /// /// # Example /// -/// use std::io; -/// use std::io::fs; +/// ```rust +/// # #[allow(unused_must_use)] +/// use std::io; +/// use std::io::fs; /// -/// fs::chmod(&Path::new("file.txt"), io::UserFile); -/// fs::chmod(&Path::new("file.txt"), io::UserRead | io::UserWrite); -/// fs::chmod(&Path::new("dir"), io::UserDir); -/// fs::chmod(&Path::new("file.exe"), io::UserExec); +/// fs::chmod(&Path::new("file.txt"), io::UserFile); +/// fs::chmod(&Path::new("file.txt"), io::UserRead | io::UserWrite); +/// fs::chmod(&Path::new("dir"), io::UserDir); +/// fs::chmod(&Path::new("file.exe"), io::UserExec); +/// ``` /// /// # Errors /// /// If this function encounters an I/O error, it will raise on the `io_error` /// condition. Some possible error situations are not having the permission to /// change the attributes of a file or the file not existing. -pub fn chmod(path: &Path, mode: io::FilePermission) { - LocalIo::maybe_raise(|io| io.fs_chmod(&path.to_c_str(), mode)); +pub fn chmod(path: &Path, mode: io::FilePermission) -> IoResult<()> { + LocalIo::maybe_raise(|io| io.fs_chmod(&path.to_c_str(), mode)) } /// Change the user and group owners of a file at the specified path. @@ -401,8 +397,8 @@ pub fn chmod(path: &Path, mode: io::FilePermission) { /// # Errors /// /// This function will raise on the `io_error` condition on failure. -pub fn chown(path: &Path, uid: int, gid: int) { - LocalIo::maybe_raise(|io| io.fs_chown(&path.to_c_str(), uid, gid)); +pub fn chown(path: &Path, uid: int, gid: int) -> IoResult<()> { + LocalIo::maybe_raise(|io| io.fs_chown(&path.to_c_str(), uid, gid)) } /// Creates a new hard link on the filesystem. The `dst` path will be a @@ -412,8 +408,8 @@ pub fn chown(path: &Path, uid: int, gid: int) { /// # Errors /// /// This function will raise on the `io_error` condition on failure. -pub fn link(src: &Path, dst: &Path) { - LocalIo::maybe_raise(|io| io.fs_link(&src.to_c_str(), &dst.to_c_str())); +pub fn link(src: &Path, dst: &Path) -> IoResult<()> { + LocalIo::maybe_raise(|io| io.fs_link(&src.to_c_str(), &dst.to_c_str())) } /// Creates a new symbolic link on the filesystem. The `dst` path will be a @@ -422,8 +418,8 @@ pub fn link(src: &Path, dst: &Path) { /// # Errors /// /// This function will raise on the `io_error` condition on failure. -pub fn symlink(src: &Path, dst: &Path) { - LocalIo::maybe_raise(|io| io.fs_symlink(&src.to_c_str(), &dst.to_c_str())); +pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> { + LocalIo::maybe_raise(|io| io.fs_symlink(&src.to_c_str(), &dst.to_c_str())) } /// Reads a symlink, returning the file that the symlink points to. @@ -433,7 +429,7 @@ pub fn symlink(src: &Path, dst: &Path) { /// This function will raise on the `io_error` condition on failure. Failure /// conditions include reading a file that does not exist or reading a file /// which is not a symlink. -pub fn readlink(path: &Path) -> Option<Path> { +pub fn readlink(path: &Path) -> IoResult<Path> { LocalIo::maybe_raise(|io| io.fs_readlink(&path.to_c_str())) } @@ -441,75 +437,81 @@ pub fn readlink(path: &Path) -> Option<Path> { /// /// # Example /// -/// use std::libc::S_IRWXU; -/// use std::io::fs; +/// ```rust +/// # #[allow(unused_must_use)]; +/// use std::io; +/// use std::io::fs; /// -/// let p = Path::new("/some/dir"); -/// fs::mkdir(&p, S_IRWXU as int); -/// // If we got here, our directory exists! Hooray! +/// let p = Path::new("/some/dir"); +/// fs::mkdir(&p, io::UserRWX); +/// ``` /// /// # Errors /// /// This call will raise an `io_error` condition if the user lacks permissions /// to make a new directory at the provided path, or if the directory already /// exists. -pub fn mkdir(path: &Path, mode: FilePermission) { - LocalIo::maybe_raise(|io| io.fs_mkdir(&path.to_c_str(), mode)); +pub fn mkdir(path: &Path, mode: FilePermission) -> IoResult<()> { + LocalIo::maybe_raise(|io| io.fs_mkdir(&path.to_c_str(), mode)) } /// Remove an existing, empty directory /// /// # Example /// -/// use std::io::fs; +/// ```rust +/// # #[allow(unused_must_use)]; +/// use std::io::fs; /// -/// let p = Path::new("/some/dir"); -/// fs::rmdir(&p); -/// // good riddance, you mean ol' directory +/// let p = Path::new("/some/dir"); +/// fs::rmdir(&p); +/// ``` /// /// # Errors /// /// This call will raise an `io_error` condition if the user lacks permissions /// to remove the directory at the provided path, or if the directory isn't /// empty. -pub fn rmdir(path: &Path) { - LocalIo::maybe_raise(|io| io.fs_rmdir(&path.to_c_str())); +pub fn rmdir(path: &Path) -> IoResult<()> { + LocalIo::maybe_raise(|io| io.fs_rmdir(&path.to_c_str())) } /// Retrieve a vector containing all entries within a provided directory /// /// # Example /// -/// use std::io::fs; +/// ```rust +/// use std::io::fs; /// -/// // one possible implementation of fs::walk_dir only visiting files -/// fn visit_dirs(dir: &Path, cb: |&Path|) { -/// if dir.is_dir() { -/// let contents = fs::readdir(dir).unwrap(); -/// for entry in contents.iter() { -/// if entry.is_dir() { visit_dirs(entry, cb); } -/// else { cb(entry); } -/// } +/// // one possible implementation of fs::walk_dir only visiting files +/// fn visit_dirs(dir: &Path, cb: |&Path|) { +/// if dir.is_dir() { +/// let contents = fs::readdir(dir).unwrap(); +/// for entry in contents.iter() { +/// if entry.is_dir() { visit_dirs(entry, cb); } +/// else { cb(entry); } /// } -/// else { fail!("nope"); } /// } +/// else { fail!("nope"); } +/// } +/// ``` /// /// # Errors /// /// Will raise an `io_error` condition if the provided `from` doesn't exist, /// the process lacks permissions to view the contents or if the `path` points /// at a non-directory file -pub fn readdir(path: &Path) -> ~[Path] { +pub fn readdir(path: &Path) -> IoResult<~[Path]> { LocalIo::maybe_raise(|io| { io.fs_readdir(&path.to_c_str(), 0) - }).unwrap_or_else(|| ~[]) + }) } /// Returns an iterator which will recursively walk the directory structure /// rooted at `path`. The path given will not be iterated over, and this will /// perform iteration in a top-down order. -pub fn walk_dir(path: &Path) -> Directories { - Directories { stack: readdir(path) } +pub fn walk_dir(path: &Path) -> IoResult<Directories> { + Ok(Directories { stack: if_ok!(readdir(path)) }) } /// An iterator which walks over a directory @@ -522,7 +524,10 @@ impl Iterator<Path> for Directories { match self.stack.shift() { Some(path) => { if path.is_dir() { - self.stack.push_all_move(readdir(&path)); + match readdir(&path) { + Ok(dirs) => { self.stack.push_all_move(dirs); } + Err(..) => {} + } } Some(path) } @@ -539,14 +544,14 @@ impl Iterator<Path> for Directories { /// This function will raise on the `io_error` condition if an error /// happens, see `fs::mkdir` for more information about error conditions /// and performance. -pub fn mkdir_recursive(path: &Path, mode: FilePermission) { +pub fn mkdir_recursive(path: &Path, mode: FilePermission) -> IoResult<()> { // tjc: if directory exists but with different permissions, // should we return false? if path.is_dir() { - return + return Ok(()) } if path.filename().is_some() { - mkdir_recursive(&path.dir_path(), mode); + if_ok!(mkdir_recursive(&path.dir_path(), mode)); } mkdir(path, mode) } @@ -559,17 +564,17 @@ pub fn mkdir_recursive(path: &Path, mode: FilePermission) { /// This function will raise on the `io_error` condition if an error /// happens. See `file::unlink` and `fs::readdir` for possible error /// conditions. -pub fn rmdir_recursive(path: &Path) { - let children = readdir(path); +pub fn rmdir_recursive(path: &Path) -> IoResult<()> { + let children = if_ok!(readdir(path)); for child in children.iter() { if child.is_dir() { - rmdir_recursive(child); + if_ok!(rmdir_recursive(child)); } else { - unlink(child); + if_ok!(unlink(child)); } } // Directory should now be empty - rmdir(path); + rmdir(path) } /// Changes the timestamps for a file's last modification and access time. @@ -582,64 +587,42 @@ pub fn rmdir_recursive(path: &Path) { /// This function will raise on the `io_error` condition if an error /// happens. // FIXME(#10301) these arguments should not be u64 -pub fn change_file_times(path: &Path, atime: u64, mtime: u64) { - LocalIo::maybe_raise(|io| io.fs_utime(&path.to_c_str(), atime, mtime)); +pub fn change_file_times(path: &Path, atime: u64, mtime: u64) -> IoResult<()> { + LocalIo::maybe_raise(|io| io.fs_utime(&path.to_c_str(), atime, mtime)) } impl Reader for File { - fn read(&mut self, buf: &mut [u8]) -> Option<uint> { + fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { match self.fd.read(buf) { Ok(read) => { self.last_nread = read; match read { - 0 => None, - _ => Some(read as uint) + 0 => Err(io::standard_error(io::EndOfFile)), + _ => Ok(read as uint) } }, - Err(ioerr) => { - // EOF is indicated by returning None - if ioerr.kind != io::EndOfFile { - io_error::cond.raise(ioerr); - } - return None; - } + Err(e) => Err(e), } } } impl Writer for File { - fn write(&mut self, buf: &[u8]) { - match self.fd.write(buf) { - Ok(()) => (), - Err(ioerr) => { - io_error::cond.raise(ioerr); - } - } - } + fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.fd.write(buf) } } impl Seek for File { - fn tell(&self) -> u64 { - let res = self.fd.tell(); - match res { - Ok(cursor) => cursor, - Err(ioerr) => { - io_error::cond.raise(ioerr); - return -1; - } - } + fn tell(&self) -> IoResult<u64> { + self.fd.tell() } - fn seek(&mut self, pos: i64, style: SeekStyle) { + fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> { match self.fd.seek(pos, style) { Ok(_) => { // successful seek resets EOF indicator self.last_nread = -1; - () - }, - Err(ioerr) => { - io_error::cond.raise(ioerr); + Ok(()) } + Err(e) => Err(e), } } } @@ -650,7 +633,7 @@ impl path::Path { /// Consult the `file::stat` documentation for more info. /// /// This call preserves identical runtime/error semantics with `file::stat`. - pub fn stat(&self) -> FileStat { stat(self) } + pub fn stat(&self) -> IoResult<FileStat> { stat(self) } /// Boolean value indicator whether the underlying file exists on the local /// filesystem. This will return true if the path points to either a @@ -660,7 +643,7 @@ impl path::Path { /// /// Will not raise a condition pub fn exists(&self) -> bool { - io::result(|| self.stat()).is_ok() + self.stat().is_ok() } /// Whether the underlying implementation (be it a file path, or something @@ -672,7 +655,7 @@ impl path::Path { /// /// Will not raise a condition pub fn is_file(&self) -> bool { - match io::result(|| self.stat()) { + match self.stat() { Ok(s) => s.kind == io::TypeFile, Err(..) => false } @@ -687,7 +670,7 @@ impl path::Path { /// /// Will not raise a condition pub fn is_dir(&self) -> bool { - match io::result(|| self.stat()) { + match self.stat() { Ok(s) => s.kind == io::TypeDirectory, Err(..) => false } diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs index c185951feca..f3535df5c5e 100644 --- a/src/libstd/io/mem.rs +++ b/src/libstd/io/mem.rs @@ -13,9 +13,10 @@ use cmp::max; use cmp::min; use container::Container; -use option::{Option, Some, None}; -use super::{Reader, Writer, Seek, Buffer, IoError, SeekStyle, io_error, - OtherIoError}; +use option::None; +use result::{Err, Ok}; +use io; +use io::{Reader, Writer, Seek, Buffer, IoError, SeekStyle, IoResult}; use vec; use vec::{Vector, ImmutableVector, MutableVector, OwnedCloneableVector}; @@ -59,7 +60,7 @@ impl MemWriter { } impl Writer for MemWriter { - fn write(&mut self, buf: &[u8]) { + fn write(&mut self, buf: &[u8]) -> IoResult<()> { // Make sure the internal buffer is as least as big as where we // currently are let difference = self.pos as i64 - self.buf.len() as i64; @@ -86,14 +87,15 @@ impl Writer for MemWriter { // Bump us forward self.pos += buf.len(); + Ok(()) } } // FIXME(#10432) impl Seek for MemWriter { - fn tell(&self) -> u64 { self.pos as u64 } + fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) } - fn seek(&mut self, pos: i64, style: SeekStyle) { + fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> { // compute offset as signed and clamp to prevent overflow let offset = match style { SeekSet => { 0 } @@ -102,6 +104,7 @@ impl Seek for MemWriter { } as i64; self.pos = max(0, offset+pos) as uint; + Ok(()) } } @@ -148,8 +151,8 @@ impl MemReader { } impl Reader for MemReader { - fn read(&mut self, buf: &mut [u8]) -> Option<uint> { - if self.eof() { return None } + fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { + if self.eof() { return Err(io::standard_error(io::EndOfFile)) } let write_len = min(buf.len(), self.buf.len() - self.pos); { @@ -161,17 +164,19 @@ impl Reader for MemReader { self.pos += write_len; assert!(self.pos <= self.buf.len()); - return Some(write_len); + return Ok(write_len); } } impl Seek for MemReader { - fn tell(&self) -> u64 { self.pos as u64 } - fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } + fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) } + fn seek(&mut self, _pos: i64, _style: SeekStyle) -> IoResult<()> { fail!() } } impl Buffer for MemReader { - fn fill<'a>(&'a mut self) -> &'a [u8] { self.buf.slice_from(self.pos) } + fn fill<'a>(&'a mut self) -> IoResult<&'a [u8]> { + Ok(self.buf.slice_from(self.pos)) + } fn consume(&mut self, amt: uint) { self.pos += amt; } } @@ -207,28 +212,28 @@ impl<'a> BufWriter<'a> { } impl<'a> Writer for BufWriter<'a> { - fn write(&mut self, buf: &[u8]) { + fn write(&mut self, buf: &[u8]) -> IoResult<()> { // raises a condition if the entire write does not fit in the buffer let max_size = self.buf.len(); if self.pos >= max_size || (self.pos + buf.len()) > max_size { - io_error::cond.raise(IoError { - kind: OtherIoError, + return Err(IoError { + kind: io::OtherIoError, desc: "Trying to write past end of buffer", detail: None - }); - return; + }) } vec::bytes::copy_memory(self.buf.mut_slice_from(self.pos), buf); self.pos += buf.len(); + Ok(()) } } // FIXME(#10432) impl<'a> Seek for BufWriter<'a> { - fn tell(&self) -> u64 { self.pos as u64 } + fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) } - fn seek(&mut self, pos: i64, style: SeekStyle) { + fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> { // compute offset as signed and clamp to prevent overflow let offset = match style { SeekSet => { 0 } @@ -237,6 +242,7 @@ impl<'a> Seek for BufWriter<'a> { } as i64; self.pos = max(0, offset+pos) as uint; + Ok(()) } } @@ -274,8 +280,8 @@ impl<'a> BufReader<'a> { } impl<'a> Reader for BufReader<'a> { - fn read(&mut self, buf: &mut [u8]) -> Option<uint> { - if self.eof() { return None } + fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { + if self.eof() { return Err(io::standard_error(io::EndOfFile)) } let write_len = min(buf.len(), self.buf.len() - self.pos); { @@ -287,18 +293,19 @@ impl<'a> Reader for BufReader<'a> { self.pos += write_len; assert!(self.pos <= self.buf.len()); - return Some(write_len); + return Ok(write_len); } } impl<'a> Seek for BufReader<'a> { - fn tell(&self) -> u64 { self.pos as u64 } - - fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } + fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) } + fn seek(&mut self, _pos: i64, _style: SeekStyle) -> IoResult<()> { fail!() } } impl<'a> Buffer for BufReader<'a> { - fn fill<'a>(&'a mut self) -> &'a [u8] { self.buf.slice_from(self.pos) } + fn fill<'a>(&'a mut self) -> IoResult<&'a [u8]> { + Ok(self.buf.slice_from(self.pos)) + } fn consume(&mut self, amt: uint) { self.pos += amt; } } @@ -388,7 +395,7 @@ mod test { let mut called = false; io_error::cond.trap(|err| { - assert_eq!(err.kind, OtherIoError); + assert_eq!(err.kind, io::OtherIoError); called = true; }).inside(|| { writer.write([0, 0]); diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 69f0cf96ffc..1cf137279c4 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -290,15 +290,15 @@ Out of scope use cast; use char::Char; -use condition::Guard; use container::Container; +use fmt; use int; use iter::Iterator; use option::{Option, Some, None}; use path::Path; use result::{Ok, Err, Result}; -use str; use str::{StrSlice, OwnedStr}; +use str; use to_str::ToStr; use uint; use unstable::finally::Finally; @@ -347,8 +347,8 @@ mod mem; /// Non-blocking access to stdin, stdout, stderr pub mod stdio; -/// Implementations for Option -mod option; +/// Implementations for Result +mod result; /// Extension traits pub mod extensions; @@ -373,17 +373,30 @@ mod comm_adapters; // https://groups.google.com/forum/#!topic/libuv/oQO1HJAIDdA static DEFAULT_BUF_SIZE: uint = 1024 * 64; +pub type IoResult<T> = Result<T, IoError>; + /// The type passed to I/O condition handlers to indicate error /// /// # FIXME /// /// Is something like this sufficient? It's kind of archaic +#[deriving(Eq, Clone)] pub struct IoError { kind: IoErrorKind, desc: &'static str, detail: Option<~str> } +impl fmt::Default for IoError { + fn fmt(err: &IoError, fmt: &mut fmt::Formatter) -> fmt::Result { + if_ok!(fmt.buf.write_str(err.desc)); + match err.detail { + Some(ref s) => write!(fmt.buf, " ({})", *s), + None => Ok(()) + } + } +} + // FIXME: #8242 implementing manually because deriving doesn't work for some reason impl ToStr for IoError { fn to_str(&self) -> ~str { @@ -398,9 +411,8 @@ impl ToStr for IoError { } } -#[deriving(Eq)] +#[deriving(Eq, Clone)] pub enum IoErrorKind { - PreviousIoError, OtherIoError, EndOfFile, FileNotFound, @@ -424,7 +436,6 @@ pub enum IoErrorKind { impl ToStr for IoErrorKind { fn to_str(&self) -> ~str { match *self { - PreviousIoError => ~"PreviousIoError", OtherIoError => ~"OtherIoError", EndOfFile => ~"EndOfFile", FileNotFound => ~"FileNotFound", @@ -446,38 +457,6 @@ impl ToStr for IoErrorKind { } } -// FIXME: Can't put doc comments on macros -// Raised by `I/O` operations on error. -condition! { - pub io_error: IoError -> (); -} - -/// Helper for wrapper calls where you want to -/// ignore any io_errors that might be raised -pub fn ignore_io_error() -> Guard<'static,IoError,()> { - io_error::cond.trap(|_| { - // just swallow the error.. downstream users - // who can make a decision based on a None result - // won't care - }).guard() -} - -/// Helper for catching an I/O error and wrapping it in a Result object. The -/// return result will be the last I/O error that happened or the result of the -/// closure if no error occurred. -pub fn result<T>(cb: || -> T) -> Result<T, IoError> { - let mut err = None; - let ret = io_error::cond.trap(|e| { - if err.is_none() { - err = Some(e); - } - }).inside(cb); - match err { - Some(e) => Err(e), - None => Ok(ret), - } -} - pub trait Reader { // Only two methods which need to get implemented for this trait @@ -504,7 +483,7 @@ pub trait Reader { /// Will people often need to slice their vectors to call this /// and will that be annoying? /// Is it actually possible for 0 bytes to be read successfully? - fn read(&mut self, buf: &mut [u8]) -> Option<uint>; + fn read(&mut self, buf: &mut [u8]) -> IoResult<uint>; // Convenient helper methods based on the above methods @@ -514,16 +493,17 @@ pub trait Reader { /// /// Raises the same conditions as the `read` method. Returns /// `None` if the condition is handled. - fn read_byte(&mut self) -> Option<u8> { + fn read_byte(&mut self) -> IoResult<u8> { let mut buf = [0]; - match self.read(buf) { - Some(0) => { - debug!("read 0 bytes. trying again"); - self.read_byte() + loop { + match self.read(buf) { + Ok(0) => { + debug!("read 0 bytes. trying again"); + } + Ok(1) => return Ok(buf[0]), + Ok(_) => unreachable!(), + Err(e) => return Err(e) } - Some(1) => Some(buf[0]), - Some(_) => unreachable!(), - None => None } } @@ -537,30 +517,26 @@ pub trait Reader { /// Raises the same conditions as `read`. Additionally raises `io_error` /// on EOF. If `io_error` is handled then `push_bytes` may push less /// than the requested number of bytes. - fn push_bytes(&mut self, buf: &mut ~[u8], len: uint) { - unsafe { - let start_len = buf.len(); - let mut total_read = 0; - - buf.reserve_additional(len); - buf.set_len(start_len + len); - - (|| { - while total_read < len { - let len = buf.len(); - let slice = buf.mut_slice(start_len + total_read, len); - match self.read(slice) { - Some(nread) => { - total_read += nread; - } - None => { - io_error::cond.raise(standard_error(EndOfFile)); - break; - } + fn push_bytes(&mut self, buf: &mut ~[u8], len: uint) -> IoResult<()> { + let start_len = buf.len(); + let mut total_read = 0; + + buf.reserve_additional(len); + unsafe { buf.set_len(start_len + len); } + + (|| { + while total_read < len { + let len = buf.len(); + let slice = buf.mut_slice(start_len + total_read, len); + match self.read(slice) { + Ok(nread) => { + total_read += nread; } + Err(e) => return Err(e) } - }).finally(|| buf.set_len(start_len + total_read)) - } + } + Ok(()) + }).finally(|| unsafe { buf.set_len(start_len + total_read) }) } /// Reads `len` bytes and gives you back a new vector of length `len` @@ -570,10 +546,10 @@ pub trait Reader { /// Raises the same conditions as `read`. Additionally raises `io_error` /// on EOF. If `io_error` is handled then the returned vector may /// contain less than the requested number of bytes. - fn read_bytes(&mut self, len: uint) -> ~[u8] { + fn read_bytes(&mut self, len: uint) -> IoResult<~[u8]> { let mut buf = vec::with_capacity(len); - self.push_bytes(&mut buf, len); - return buf; + if_ok!(self.push_bytes(&mut buf, len)); + return Ok(buf); } /// Reads all remaining bytes from the stream. @@ -582,21 +558,16 @@ pub trait Reader { /// /// Raises the same conditions as the `read` method except for /// `EndOfFile` which is swallowed. - fn read_to_end(&mut self) -> ~[u8] { + fn read_to_end(&mut self) -> IoResult<~[u8]> { let mut buf = vec::with_capacity(DEFAULT_BUF_SIZE); - let mut keep_reading = true; - io_error::cond.trap(|e| { - if e.kind == EndOfFile { - keep_reading = false; - } else { - io_error::cond.raise(e) + loop { + match self.push_bytes(&mut buf, DEFAULT_BUF_SIZE) { + Ok(()) => {} + Err(ref e) if e.kind == EndOfFile => break, + Err(e) => return Err(e) } - }).inside(|| { - while keep_reading { - self.push_bytes(&mut buf, DEFAULT_BUF_SIZE) - } - }); - return buf; + } + return Ok(buf); } /// Reads all of the remaining bytes of this stream, interpreting them as a @@ -606,14 +577,13 @@ pub trait Reader { /// /// This function will raise all the same conditions as the `read` method, /// along with raising a condition if the input is not valid UTF-8. - fn read_to_str(&mut self) -> ~str { - match str::from_utf8_owned(self.read_to_end()) { - Some(s) => s, - None => { - io_error::cond.raise(standard_error(InvalidInput)); - ~"" + fn read_to_str(&mut self) -> IoResult<~str> { + self.read_to_end().and_then(|s| { + match str::from_utf8_owned(s) { + Some(s) => Ok(s), + None => Err(standard_error(InvalidInput)), } - } + }) } /// Create an iterator that reads a single byte on @@ -633,225 +603,219 @@ pub trait Reader { /// Reads `n` little-endian unsigned integer bytes. /// /// `n` must be between 1 and 8, inclusive. - fn read_le_uint_n(&mut self, nbytes: uint) -> u64 { + fn read_le_uint_n(&mut self, nbytes: uint) -> IoResult<u64> { assert!(nbytes > 0 && nbytes <= 8); let mut val = 0u64; let mut pos = 0; let mut i = nbytes; while i > 0 { - val += (self.read_u8() as u64) << pos; + val += (if_ok!(self.read_u8()) as u64) << pos; pos += 8; i -= 1; } - val + Ok(val) } /// Reads `n` little-endian signed integer bytes. /// /// `n` must be between 1 and 8, inclusive. - fn read_le_int_n(&mut self, nbytes: uint) -> i64 { - extend_sign(self.read_le_uint_n(nbytes), nbytes) + fn read_le_int_n(&mut self, nbytes: uint) -> IoResult<i64> { + self.read_le_uint_n(nbytes).map(|i| extend_sign(i, nbytes)) } /// Reads `n` big-endian unsigned integer bytes. /// /// `n` must be between 1 and 8, inclusive. - fn read_be_uint_n(&mut self, nbytes: uint) -> u64 { + fn read_be_uint_n(&mut self, nbytes: uint) -> IoResult<u64> { assert!(nbytes > 0 && nbytes <= 8); let mut val = 0u64; let mut i = nbytes; while i > 0 { i -= 1; - val += (self.read_u8() as u64) << i * 8; + val += (if_ok!(self.read_u8()) as u64) << i * 8; } - val + Ok(val) } /// Reads `n` big-endian signed integer bytes. /// /// `n` must be between 1 and 8, inclusive. - fn read_be_int_n(&mut self, nbytes: uint) -> i64 { - extend_sign(self.read_be_uint_n(nbytes), nbytes) + fn read_be_int_n(&mut self, nbytes: uint) -> IoResult<i64> { + self.read_be_uint_n(nbytes).map(|i| extend_sign(i, nbytes)) } /// Reads a little-endian unsigned integer. /// /// The number of bytes returned is system-dependant. - fn read_le_uint(&mut self) -> uint { - self.read_le_uint_n(uint::BYTES) as uint + fn read_le_uint(&mut self) -> IoResult<uint> { + self.read_le_uint_n(uint::BYTES).map(|i| i as uint) } /// Reads a little-endian integer. /// /// The number of bytes returned is system-dependant. - fn read_le_int(&mut self) -> int { - self.read_le_int_n(int::BYTES) as int + fn read_le_int(&mut self) -> IoResult<int> { + self.read_le_int_n(int::BYTES).map(|i| i as int) } /// Reads a big-endian unsigned integer. /// /// The number of bytes returned is system-dependant. - fn read_be_uint(&mut self) -> uint { - self.read_be_uint_n(uint::BYTES) as uint + fn read_be_uint(&mut self) -> IoResult<uint> { + self.read_be_uint_n(uint::BYTES).map(|i| i as uint) } /// Reads a big-endian integer. /// /// The number of bytes returned is system-dependant. - fn read_be_int(&mut self) -> int { - self.read_be_int_n(int::BYTES) as int + fn read_be_int(&mut self) -> IoResult<int> { + self.read_be_int_n(int::BYTES).map(|i| i as int) } /// Reads a big-endian `u64`. /// /// `u64`s are 8 bytes long. - fn read_be_u64(&mut self) -> u64 { + fn read_be_u64(&mut self) -> IoResult<u64> { self.read_be_uint_n(8) } /// Reads a big-endian `u32`. /// /// `u32`s are 4 bytes long. - fn read_be_u32(&mut self) -> u32 { - self.read_be_uint_n(4) as u32 + fn read_be_u32(&mut self) -> IoResult<u32> { + self.read_be_uint_n(4).map(|i| i as u32) } /// Reads a big-endian `u16`. /// /// `u16`s are 2 bytes long. - fn read_be_u16(&mut self) -> u16 { - self.read_be_uint_n(2) as u16 + fn read_be_u16(&mut self) -> IoResult<u16> { + self.read_be_uint_n(2).map(|i| i as u16) } /// Reads a big-endian `i64`. /// /// `i64`s are 8 bytes long. - fn read_be_i64(&mut self) -> i64 { + fn read_be_i64(&mut self) -> IoResult<i64> { self.read_be_int_n(8) } /// Reads a big-endian `i32`. /// /// `i32`s are 4 bytes long. - fn read_be_i32(&mut self) -> i32 { - self.read_be_int_n(4) as i32 + fn read_be_i32(&mut self) -> IoResult<i32> { + self.read_be_int_n(4).map(|i| i as i32) } /// Reads a big-endian `i16`. /// /// `i16`s are 2 bytes long. - fn read_be_i16(&mut self) -> i16 { - self.read_be_int_n(2) as i16 + fn read_be_i16(&mut self) -> IoResult<i16> { + self.read_be_int_n(2).map(|i| i as i16) } /// Reads a big-endian `f64`. /// /// `f64`s are 8 byte, IEEE754 double-precision floating point numbers. - fn read_be_f64(&mut self) -> f64 { - unsafe { - cast::transmute::<u64, f64>(self.read_be_u64()) - } + fn read_be_f64(&mut self) -> IoResult<f64> { + self.read_be_u64().map(|i| unsafe { + cast::transmute::<u64, f64>(i) + }) } /// Reads a big-endian `f32`. /// /// `f32`s are 4 byte, IEEE754 single-precision floating point numbers. - fn read_be_f32(&mut self) -> f32 { - unsafe { - cast::transmute::<u32, f32>(self.read_be_u32()) - } + fn read_be_f32(&mut self) -> IoResult<f32> { + self.read_be_u32().map(|i| unsafe { + cast::transmute::<u32, f32>(i) + }) } /// Reads a little-endian `u64`. /// /// `u64`s are 8 bytes long. - fn read_le_u64(&mut self) -> u64 { + fn read_le_u64(&mut self) -> IoResult<u64> { self.read_le_uint_n(8) } /// Reads a little-endian `u32`. /// /// `u32`s are 4 bytes long. - fn read_le_u32(&mut self) -> u32 { - self.read_le_uint_n(4) as u32 + fn read_le_u32(&mut self) -> IoResult<u32> { + self.read_le_uint_n(4).map(|i| i as u32) } /// Reads a little-endian `u16`. /// /// `u16`s are 2 bytes long. - fn read_le_u16(&mut self) -> u16 { - self.read_le_uint_n(2) as u16 + fn read_le_u16(&mut self) -> IoResult<u16> { + self.read_le_uint_n(2).map(|i| i as u16) } /// Reads a little-endian `i64`. /// /// `i64`s are 8 bytes long. - fn read_le_i64(&mut self) -> i64 { + fn read_le_i64(&mut self) -> IoResult<i64> { self.read_le_int_n(8) } /// Reads a little-endian `i32`. /// /// `i32`s are 4 bytes long. - fn read_le_i32(&mut self) -> i32 { - self.read_le_int_n(4) as i32 + fn read_le_i32(&mut self) -> IoResult<i32> { + self.read_le_int_n(4).map(|i| i as i32) } /// Reads a little-endian `i16`. /// /// `i16`s are 2 bytes long. - fn read_le_i16(&mut self) -> i16 { - self.read_le_int_n(2) as i16 + fn read_le_i16(&mut self) -> IoResult<i16> { + self.read_le_int_n(2).map(|i| i as i16) } /// Reads a little-endian `f64`. /// /// `f64`s are 8 byte, IEEE754 double-precision floating point numbers. - fn read_le_f64(&mut self) -> f64 { - unsafe { - cast::transmute::<u64, f64>(self.read_le_u64()) - } + fn read_le_f64(&mut self) -> IoResult<f64> { + self.read_le_u64().map(|i| unsafe { + cast::transmute::<u64, f64>(i) + }) } /// Reads a little-endian `f32`. /// /// `f32`s are 4 byte, IEEE754 single-precision floating point numbers. - fn read_le_f32(&mut self) -> f32 { - unsafe { - cast::transmute::<u32, f32>(self.read_le_u32()) - } + fn read_le_f32(&mut self) -> IoResult<f32> { + self.read_le_u32().map(|i| unsafe { + cast::transmute::<u32, f32>(i) + }) } /// Read a u8. /// /// `u8`s are 1 byte. - fn read_u8(&mut self) -> u8 { - match self.read_byte() { - Some(b) => b, - None => 0 - } + fn read_u8(&mut self) -> IoResult<u8> { + self.read_byte() } /// Read an i8. /// /// `i8`s are 1 byte. - fn read_i8(&mut self) -> i8 { - match self.read_byte() { - Some(b) => b as i8, - None => 0 - } + fn read_i8(&mut self) -> IoResult<i8> { + self.read_byte().map(|i| i as i8) } } impl Reader for ~Reader { - fn read(&mut self, buf: &mut [u8]) -> Option<uint> { self.read(buf) } + fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { self.read(buf) } } impl<'a> Reader for &'a mut Reader { - fn read(&mut self, buf: &mut [u8]) -> Option<uint> { self.read(buf) } + fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { self.read(buf) } } fn extend_sign(val: u64, nbytes: uint) -> i64 { @@ -865,14 +829,14 @@ pub trait Writer { /// # Failure /// /// Raises the `io_error` condition on error - fn write(&mut self, buf: &[u8]); + fn write(&mut self, buf: &[u8]) -> IoResult<()>; /// Flush this output stream, ensuring that all intermediately buffered /// contents reach their destination. /// /// This is by default a no-op and implementers of the `Writer` trait should /// decide whether their stream needs to be buffered or not. - fn flush(&mut self) {} + fn flush(&mut self) -> IoResult<()> { Ok(()) } /// Write a rust string into this sink. /// @@ -880,8 +844,8 @@ pub trait Writer { /// If other encodings are desired, it is recommended to compose this stream /// with another performing the conversion, or to use `write` with a /// converted byte-array instead. - fn write_str(&mut self, s: &str) { - self.write(s.as_bytes()); + fn write_str(&mut self, s: &str) -> IoResult<()> { + self.write(s.as_bytes()) } /// Writes a string into this sink, and then writes a literal newline (`\n`) @@ -891,125 +855,124 @@ pub trait Writer { /// /// If other encodings or line ending flavors are desired, it is recommended /// that the `write` method is used specifically instead. - fn write_line(&mut self, s: &str) { - self.write_str(s); - self.write(['\n' as u8]); + fn write_line(&mut self, s: &str) -> IoResult<()> { + self.write_str(s).and_then(|()| self.write(['\n' as u8])) } /// Write a single char, encoded as UTF-8. - fn write_char(&mut self, c: char) { + fn write_char(&mut self, c: char) -> IoResult<()> { let mut buf = [0u8, ..4]; let n = c.encode_utf8(buf.as_mut_slice()); - self.write(buf.slice_to(n)); + self.write(buf.slice_to(n)) } /// Write the result of passing n through `int::to_str_bytes`. - fn write_int(&mut self, n: int) { + fn write_int(&mut self, n: int) -> IoResult<()> { int::to_str_bytes(n, 10u, |bytes| self.write(bytes)) } /// Write the result of passing n through `uint::to_str_bytes`. - fn write_uint(&mut self, n: uint) { + fn write_uint(&mut self, n: uint) -> IoResult<()> { uint::to_str_bytes(n, 10u, |bytes| self.write(bytes)) } /// Write a little-endian uint (number of bytes depends on system). - fn write_le_uint(&mut self, n: uint) { + fn write_le_uint(&mut self, n: uint) -> IoResult<()> { extensions::u64_to_le_bytes(n as u64, uint::BYTES, |v| self.write(v)) } /// Write a little-endian int (number of bytes depends on system). - fn write_le_int(&mut self, n: int) { + fn write_le_int(&mut self, n: int) -> IoResult<()> { extensions::u64_to_le_bytes(n as u64, int::BYTES, |v| self.write(v)) } /// Write a big-endian uint (number of bytes depends on system). - fn write_be_uint(&mut self, n: uint) { + fn write_be_uint(&mut self, n: uint) -> IoResult<()> { extensions::u64_to_be_bytes(n as u64, uint::BYTES, |v| self.write(v)) } /// Write a big-endian int (number of bytes depends on system). - fn write_be_int(&mut self, n: int) { + fn write_be_int(&mut self, n: int) -> IoResult<()> { extensions::u64_to_be_bytes(n as u64, int::BYTES, |v| self.write(v)) } /// Write a big-endian u64 (8 bytes). - fn write_be_u64(&mut self, n: u64) { + fn write_be_u64(&mut self, n: u64) -> IoResult<()> { extensions::u64_to_be_bytes(n, 8u, |v| self.write(v)) } /// Write a big-endian u32 (4 bytes). - fn write_be_u32(&mut self, n: u32) { + fn write_be_u32(&mut self, n: u32) -> IoResult<()> { extensions::u64_to_be_bytes(n as u64, 4u, |v| self.write(v)) } /// Write a big-endian u16 (2 bytes). - fn write_be_u16(&mut self, n: u16) { + fn write_be_u16(&mut self, n: u16) -> IoResult<()> { extensions::u64_to_be_bytes(n as u64, 2u, |v| self.write(v)) } /// Write a big-endian i64 (8 bytes). - fn write_be_i64(&mut self, n: i64) { + fn write_be_i64(&mut self, n: i64) -> IoResult<()> { extensions::u64_to_be_bytes(n as u64, 8u, |v| self.write(v)) } /// Write a big-endian i32 (4 bytes). - fn write_be_i32(&mut self, n: i32) { + fn write_be_i32(&mut self, n: i32) -> IoResult<()> { extensions::u64_to_be_bytes(n as u64, 4u, |v| self.write(v)) } /// Write a big-endian i16 (2 bytes). - fn write_be_i16(&mut self, n: i16) { + fn write_be_i16(&mut self, n: i16) -> IoResult<()> { extensions::u64_to_be_bytes(n as u64, 2u, |v| self.write(v)) } /// Write a big-endian IEEE754 double-precision floating-point (8 bytes). - fn write_be_f64(&mut self, f: f64) { + fn write_be_f64(&mut self, f: f64) -> IoResult<()> { unsafe { self.write_be_u64(cast::transmute(f)) } } /// Write a big-endian IEEE754 single-precision floating-point (4 bytes). - fn write_be_f32(&mut self, f: f32) { + fn write_be_f32(&mut self, f: f32) -> IoResult<()> { unsafe { self.write_be_u32(cast::transmute(f)) } } /// Write a little-endian u64 (8 bytes). - fn write_le_u64(&mut self, n: u64) { + fn write_le_u64(&mut self, n: u64) -> IoResult<()> { extensions::u64_to_le_bytes(n, 8u, |v| self.write(v)) } /// Write a little-endian u32 (4 bytes). - fn write_le_u32(&mut self, n: u32) { + fn write_le_u32(&mut self, n: u32) -> IoResult<()> { extensions::u64_to_le_bytes(n as u64, 4u, |v| self.write(v)) } /// Write a little-endian u16 (2 bytes). - fn write_le_u16(&mut self, n: u16) { + fn write_le_u16(&mut self, n: u16) -> IoResult<()> { extensions::u64_to_le_bytes(n as u64, 2u, |v| self.write(v)) } /// Write a little-endian i64 (8 bytes). - fn write_le_i64(&mut self, n: i64) { + fn write_le_i64(&mut self, n: i64) -> IoResult<()> { extensions::u64_to_le_bytes(n as u64, 8u, |v| self.write(v)) } /// Write a little-endian i32 (4 bytes). - fn write_le_i32(&mut self, n: i32) { + fn write_le_i32(&mut self, n: i32) -> IoResult<()> { extensions::u64_to_le_bytes(n as u64, 4u, |v| self.write(v)) } /// Write a little-endian i16 (2 bytes). - fn write_le_i16(&mut self, n: i16) { + fn write_le_i16(&mut self, n: i16) -> IoResult<()> { extensions::u64_to_le_bytes(n as u64, 2u, |v| self.write(v)) } /// Write a little-endian IEEE754 double-precision floating-point /// (8 bytes). - fn write_le_f64(&mut self, f: f64) { + fn write_le_f64(&mut self, f: f64) -> IoResult<()> { unsafe { self.write_le_u64(cast::transmute(f)) } @@ -1017,31 +980,31 @@ pub trait Writer { /// Write a little-endian IEEE754 single-precision floating-point /// (4 bytes). - fn write_le_f32(&mut self, f: f32) { + fn write_le_f32(&mut self, f: f32) -> IoResult<()> { unsafe { self.write_le_u32(cast::transmute(f)) } } /// Write a u8 (1 byte). - fn write_u8(&mut self, n: u8) { + fn write_u8(&mut self, n: u8) -> IoResult<()> { self.write([n]) } /// Write a i8 (1 byte). - fn write_i8(&mut self, n: i8) { + fn write_i8(&mut self, n: i8) -> IoResult<()> { self.write([n as u8]) } } impl Writer for ~Writer { - fn write(&mut self, buf: &[u8]) { self.write(buf) } - fn flush(&mut self) { self.flush() } + fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.write(buf) } + fn flush(&mut self) -> IoResult<()> { self.flush() } } impl<'a> Writer for &'a mut Writer { - fn write(&mut self, buf: &[u8]) { self.write(buf) } - fn flush(&mut self) { self.flush() } + fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.write(buf) } + fn flush(&mut self) -> IoResult<()> { self.flush() } } pub trait Stream: Reader + Writer { } @@ -1068,7 +1031,7 @@ pub struct Lines<'r, T> { impl<'r, T: Buffer> Iterator<~str> for Lines<'r, T> { fn next(&mut self) -> Option<~str> { - self.buffer.read_line() + self.buffer.read_line().ok() } } @@ -1089,7 +1052,7 @@ pub trait Buffer: Reader { /// /// This function will raise on the `io_error` condition if a read error is /// encountered. - fn fill<'a>(&'a mut self) -> &'a [u8]; + fn fill<'a>(&'a mut self) -> IoResult<&'a [u8]>; /// Tells this buffer that `amt` bytes have been consumed from the buffer, /// so they should no longer be returned in calls to `fill` or `read`. @@ -1116,7 +1079,7 @@ pub trait Buffer: Reader { /// `EndOfFile` which is swallowed) if a read error is encountered. /// The task will also fail if sequence of bytes leading up to /// the newline character are not valid UTF-8. - fn read_line(&mut self) -> Option<~str> { + fn read_line(&mut self) -> IoResult<~str> { self.read_until('\n' as u8).map(|line| str::from_utf8_owned(line).unwrap()) } @@ -1140,39 +1103,32 @@ pub trait Buffer: Reader { /// /// This function will raise on the `io_error` condition if a read error is /// encountered, except that `EndOfFile` is swallowed. - fn read_until(&mut self, byte: u8) -> Option<~[u8]> { + fn read_until(&mut self, byte: u8) -> IoResult<~[u8]> { let mut res = ~[]; - io_error::cond.trap(|e| { - if e.kind != EndOfFile { - io_error::cond.raise(e); - } - }).inside(|| { - let mut used; - loop { - { - let available = self.fill(); - match available.iter().position(|&b| b == byte) { - Some(i) => { - res.push_all(available.slice_to(i + 1)); - used = i + 1; - break - } - None => { - res.push_all(available); - used = available.len(); - } + let mut used; + loop { + { + let available = if_ok!(self.fill()); + match available.iter().position(|&b| b == byte) { + Some(i) => { + res.push_all(available.slice_to(i + 1)); + used = i + 1; + break + } + None => { + res.push_all(available); + used = available.len(); } } - if used == 0 { - break - } - self.consume(used); + } + if used == 0 { + break } self.consume(used); - }); - return if res.len() == 0 {None} else {Some(res)}; - + } + self.consume(used); + Ok(res) } /// Reads the next utf8-encoded character from the underlying stream. @@ -1184,27 +1140,26 @@ pub trait Buffer: Reader { /// /// This function will raise on the `io_error` condition if a read error is /// encountered. - fn read_char(&mut self) -> Option<char> { + fn read_char(&mut self) -> IoResult<char> { let width = { - let available = self.fill(); - if available.len() == 0 { return None } // read error + let available = if_ok!(self.fill()); str::utf8_char_width(available[0]) }; - if width == 0 { return None } // not uf8 + if width == 0 { return Err(standard_error(InvalidInput)) } // not uf8 let mut buf = [0, ..4]; { let mut start = 0; loop { - match self.read(buf.mut_slice(start, width)) { - Some(n) if n == width - start => break, - Some(n) if n < width - start => { start += n; } - Some(..) | None => return None // read error + match if_ok!(self.read(buf.mut_slice(start, width))) { + n if n == width - start => break, + n if n < width - start => { start += n; } + _ => return Err(standard_error(InvalidInput)), } } } match str::from_utf8(buf.slice_to(width)) { - Some(s) => Some(s.char_at(0)), - None => None + Some(s) => Ok(s.char_at(0)), + None => Err(standard_error(InvalidInput)) } } } @@ -1222,7 +1177,7 @@ pub enum SeekStyle { /// * Are `u64` and `i64` the right choices? pub trait Seek { /// Return position of file cursor in the stream - fn tell(&self) -> u64; + fn tell(&self) -> IoResult<u64>; /// Seek to an offset in a stream /// @@ -1231,7 +1186,7 @@ pub trait Seek { /// # FIXME /// /// * What is the behavior when seeking past the end of a stream? - fn seek(&mut self, pos: i64, style: SeekStyle); + fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()>; } /// A listener is a value that can consume itself to start listening for connections. @@ -1243,7 +1198,7 @@ pub trait Listener<T, A: Acceptor<T>> { /// /// Raises `io_error` condition. If the condition is handled, /// then `listen` returns `None`. - fn listen(self) -> Option<A>; + fn listen(self) -> IoResult<A>; } /// An acceptor is a value that presents incoming connections @@ -1253,7 +1208,7 @@ pub trait Acceptor<T> { /// # Failure /// Raise `io_error` condition. If the condition is handled, /// then `accept` returns `None`. - fn accept(&mut self) -> Option<T>; + fn accept(&mut self) -> IoResult<T>; /// Create an iterator over incoming connection attempts fn incoming<'r>(&'r mut self) -> IncomingConnections<'r, Self> { @@ -1272,15 +1227,14 @@ pub struct IncomingConnections<'a, A> { priv inc: &'a mut A, } -impl<'a, T, A: Acceptor<T>> Iterator<Option<T>> for IncomingConnections<'a, A> { - fn next(&mut self) -> Option<Option<T>> { +impl<'a, T, A: Acceptor<T>> Iterator<IoResult<T>> for IncomingConnections<'a, A> { + fn next(&mut self) -> Option<IoResult<T>> { Some(self.inc.accept()) } } pub fn standard_error(kind: IoErrorKind) -> IoError { let desc = match kind { - PreviousIoError => "failing due to previous I/O error", EndOfFile => "end of file", IoUnavailable => "I/O is unavailable", InvalidInput => "invalid input", diff --git a/src/libstd/io/net/addrinfo.rs b/src/libstd/io/net/addrinfo.rs index 29bf6261a07..1f8f8beeae3 100644 --- a/src/libstd/io/net/addrinfo.rs +++ b/src/libstd/io/net/addrinfo.rs @@ -17,8 +17,9 @@ getaddrinfo() */ -use option::{Option, Some, None}; +use io::IoResult; use io::net::ip::{SocketAddr, IpAddr}; +use option::{Option, Some, None}; use rt::rtio::{IoFactory, LocalIo}; use vec::ImmutableVector; @@ -73,7 +74,7 @@ pub struct Info { /// # Failure /// /// On failure, this will raise on the `io_error` condition. -pub fn get_host_addresses(host: &str) -> Option<~[IpAddr]> { +pub fn get_host_addresses(host: &str) -> IoResult<~[IpAddr]> { lookup(Some(host), None, None).map(|a| a.map(|i| i.address.ip)) } @@ -94,7 +95,7 @@ pub fn get_host_addresses(host: &str) -> Option<~[IpAddr]> { /// FIXME: this is not public because the `Hint` structure is not ready for public /// consumption just yet. fn lookup(hostname: Option<&str>, servname: Option<&str>, hint: Option<Hint>) - -> Option<~[Info]> { + -> IoResult<~[Info]> { LocalIo::maybe_raise(|io| io.get_host_addresses(hostname, servname, hint)) } diff --git a/src/libstd/io/net/tcp.rs b/src/libstd/io/net/tcp.rs index 475e3b206f2..cc923d5b736 100644 --- a/src/libstd/io/net/tcp.rs +++ b/src/libstd/io/net/tcp.rs @@ -8,11 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use option::{Option, Some, None}; -use result::{Ok, Err}; use io::net::ip::SocketAddr; -use io::{Reader, Writer, Listener, Acceptor}; -use io::{io_error, EndOfFile}; +use io::{Reader, Writer, Listener, Acceptor, IoResult}; use rt::rtio::{IoFactory, LocalIo, RtioSocket, RtioTcpListener}; use rt::rtio::{RtioTcpAcceptor, RtioTcpStream}; @@ -25,57 +22,27 @@ impl TcpStream { TcpStream { obj: s } } - pub fn connect(addr: SocketAddr) -> Option<TcpStream> { + pub fn connect(addr: SocketAddr) -> IoResult<TcpStream> { LocalIo::maybe_raise(|io| { io.tcp_connect(addr).map(TcpStream::new) }) } - pub fn peer_name(&mut self) -> Option<SocketAddr> { - match self.obj.peer_name() { - Ok(pn) => Some(pn), - Err(ioerr) => { - debug!("failed to get peer name: {:?}", ioerr); - io_error::cond.raise(ioerr); - None - } - } + pub fn peer_name(&mut self) -> IoResult<SocketAddr> { + self.obj.peer_name() } - pub fn socket_name(&mut self) -> Option<SocketAddr> { - match self.obj.socket_name() { - Ok(sn) => Some(sn), - Err(ioerr) => { - debug!("failed to get socket name: {:?}", ioerr); - io_error::cond.raise(ioerr); - None - } - } + pub fn socket_name(&mut self) -> IoResult<SocketAddr> { + self.obj.socket_name() } } impl Reader for TcpStream { - fn read(&mut self, buf: &mut [u8]) -> Option<uint> { - match self.obj.read(buf) { - Ok(read) => Some(read), - Err(ioerr) => { - // EOF is indicated by returning None - if ioerr.kind != EndOfFile { - io_error::cond.raise(ioerr); - } - return None; - } - } - } + fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { self.obj.read(buf) } } impl Writer for TcpStream { - fn write(&mut self, buf: &[u8]) { - match self.obj.write(buf) { - Ok(_) => (), - Err(ioerr) => io_error::cond.raise(ioerr), - } - } + fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.obj.write(buf) } } pub struct TcpListener { @@ -83,33 +50,20 @@ pub struct TcpListener { } impl TcpListener { - pub fn bind(addr: SocketAddr) -> Option<TcpListener> { + pub fn bind(addr: SocketAddr) -> IoResult<TcpListener> { LocalIo::maybe_raise(|io| { io.tcp_bind(addr).map(|l| TcpListener { obj: l }) }) } - pub fn socket_name(&mut self) -> Option<SocketAddr> { - match self.obj.socket_name() { - Ok(sn) => Some(sn), - Err(ioerr) => { - debug!("failed to get socket name: {:?}", ioerr); - io_error::cond.raise(ioerr); - None - } - } + pub fn socket_name(&mut self) -> IoResult<SocketAddr> { + self.obj.socket_name() } } impl Listener<TcpStream, TcpAcceptor> for TcpListener { - fn listen(self) -> Option<TcpAcceptor> { - match self.obj.listen() { - Ok(acceptor) => Some(TcpAcceptor { obj: acceptor }), - Err(ioerr) => { - io_error::cond.raise(ioerr); - None - } - } + fn listen(self) -> IoResult<TcpAcceptor> { + self.obj.listen().map(|acceptor| TcpAcceptor { obj: acceptor }) } } @@ -118,14 +72,8 @@ pub struct TcpAcceptor { } impl Acceptor<TcpStream> for TcpAcceptor { - fn accept(&mut self) -> Option<TcpStream> { - match self.obj.accept() { - Ok(s) => Some(TcpStream::new(s)), - Err(ioerr) => { - io_error::cond.raise(ioerr); - None - } - } + fn accept(&mut self) -> IoResult<TcpStream> { + self.obj.accept().map(TcpStream::new) } } diff --git a/src/libstd/io/net/udp.rs b/src/libstd/io/net/udp.rs index 1cf30d469f7..abb6bdea75b 100644 --- a/src/libstd/io/net/udp.rs +++ b/src/libstd/io/net/udp.rs @@ -8,11 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use option::{Option, Some, None}; use result::{Ok, Err}; use io::net::ip::SocketAddr; -use io::{Reader, Writer}; -use io::{io_error, EndOfFile}; +use io::{Reader, Writer, IoResult}; use rt::rtio::{RtioSocket, RtioUdpSocket, IoFactory, LocalIo}; pub struct UdpSocket { @@ -20,45 +18,26 @@ pub struct UdpSocket { } impl UdpSocket { - pub fn bind(addr: SocketAddr) -> Option<UdpSocket> { + pub fn bind(addr: SocketAddr) -> IoResult<UdpSocket> { LocalIo::maybe_raise(|io| { io.udp_bind(addr).map(|s| UdpSocket { obj: s }) }) } - pub fn recvfrom(&mut self, buf: &mut [u8]) -> Option<(uint, SocketAddr)> { - match self.obj.recvfrom(buf) { - Ok((nread, src)) => Some((nread, src)), - Err(ioerr) => { - // EOF is indicated by returning None - if ioerr.kind != EndOfFile { - io_error::cond.raise(ioerr); - } - None - } - } + pub fn recvfrom(&mut self, buf: &mut [u8]) -> IoResult<(uint, SocketAddr)> { + self.obj.recvfrom(buf) } - pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) { - match self.obj.sendto(buf, dst) { - Ok(_) => (), - Err(ioerr) => io_error::cond.raise(ioerr), - } + pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> { + self.obj.sendto(buf, dst) } pub fn connect(self, other: SocketAddr) -> UdpStream { UdpStream { socket: self, connectedTo: other } } - pub fn socket_name(&mut self) -> Option<SocketAddr> { - match self.obj.socket_name() { - Ok(sn) => Some(sn), - Err(ioerr) => { - debug!("failed to get socket name: {:?}", ioerr); - io_error::cond.raise(ioerr); - None - } - } + pub fn socket_name(&mut self) -> IoResult<SocketAddr> { + self.obj.socket_name() } } @@ -76,21 +55,21 @@ impl UdpStream { } impl Reader for UdpStream { - fn read(&mut self, buf: &mut [u8]) -> Option<uint> { + fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { let peer = self.connectedTo; self.as_socket(|sock| { match sock.recvfrom(buf) { - Some((_nread, src)) if src != peer => Some(0), - Some((nread, _src)) => Some(nread), - None => None, + Ok((_nread, src)) if src != peer => Ok(0), + Ok((nread, _src)) => Ok(nread), + Err(e) => Err(e), } }) } } impl Writer for UdpStream { - fn write(&mut self, buf: &[u8]) { - self.as_socket(|sock| sock.sendto(buf, self.connectedTo)); + fn write(&mut self, buf: &[u8]) -> IoResult<()> { + self.as_socket(|sock| sock.sendto(buf, self.connectedTo)) } } diff --git a/src/libstd/io/net/unix.rs b/src/libstd/io/net/unix.rs index d470e9bfda1..b8b396b24fd 100644 --- a/src/libstd/io/net/unix.rs +++ b/src/libstd/io/net/unix.rs @@ -28,7 +28,7 @@ use c_str::ToCStr; use rt::rtio::{IoFactory, LocalIo, RtioUnixListener}; use rt::rtio::{RtioUnixAcceptor, RtioPipe}; use io::pipe::PipeStream; -use io::{io_error, Listener, Acceptor, Reader, Writer}; +use io::{Listener, Acceptor, Reader, Writer, IoResult}; /// A stream which communicates over a named pipe. pub struct UnixStream { @@ -52,13 +52,15 @@ impl UnixStream { /// /// # Example /// - /// use std::io::net::unix::UnixStream; + /// ```rust + /// # #[allow(unused_must_use)]; + /// use std::io::net::unix::UnixStream; /// - /// let server = Path("path/to/my/socket"); - /// let mut stream = UnixStream::connect(&server); - /// stream.write([1, 2, 3]); - /// - pub fn connect<P: ToCStr>(path: &P) -> Option<UnixStream> { + /// let server = Path::new("path/to/my/socket"); + /// let mut stream = UnixStream::connect(&server); + /// stream.write([1, 2, 3]); + /// ``` + pub fn connect<P: ToCStr>(path: &P) -> IoResult<UnixStream> { LocalIo::maybe_raise(|io| { io.unix_connect(&path.to_c_str()).map(UnixStream::new) }) @@ -66,11 +68,11 @@ impl UnixStream { } impl Reader for UnixStream { - fn read(&mut self, buf: &mut [u8]) -> Option<uint> { self.obj.read(buf) } + fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { self.obj.read(buf) } } impl Writer for UnixStream { - fn write(&mut self, buf: &[u8]) { self.obj.write(buf) } + fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.obj.write(buf) } } pub struct UnixListener { @@ -91,16 +93,18 @@ impl UnixListener { /// /// # Example /// - /// use std::io::net::unix::UnixListener; - /// - /// let server = Path("path/to/my/socket"); - /// let mut stream = UnixListener::bind(&server); - /// for client in stream.incoming() { - /// let mut client = client; - /// client.write([1, 2, 3, 4]); - /// } + /// ``` + /// use std::io::net::unix::UnixListener; + /// use std::io::Listener; /// - pub fn bind<P: ToCStr>(path: &P) -> Option<UnixListener> { + /// let server = Path::new("path/to/my/socket"); + /// let mut stream = UnixListener::bind(&server); + /// for client in stream.incoming() { + /// let mut client = client; + /// client.write([1, 2, 3, 4]); + /// } + /// ``` + pub fn bind<P: ToCStr>(path: &P) -> IoResult<UnixListener> { LocalIo::maybe_raise(|io| { io.unix_bind(&path.to_c_str()).map(|s| UnixListener { obj: s }) }) @@ -108,14 +112,8 @@ impl UnixListener { } impl Listener<UnixStream, UnixAcceptor> for UnixListener { - fn listen(self) -> Option<UnixAcceptor> { - match self.obj.listen() { - Ok(acceptor) => Some(UnixAcceptor { obj: acceptor }), - Err(ioerr) => { - io_error::cond.raise(ioerr); - None - } - } + fn listen(self) -> IoResult<UnixAcceptor> { + self.obj.listen().map(|obj| UnixAcceptor { obj: obj }) } } @@ -124,14 +122,8 @@ pub struct UnixAcceptor { } impl Acceptor<UnixStream> for UnixAcceptor { - fn accept(&mut self) -> Option<UnixStream> { - match self.obj.accept() { - Ok(s) => Some(UnixStream::new(s)), - Err(ioerr) => { - io_error::cond.raise(ioerr); - None - } - } + fn accept(&mut self) -> IoResult<UnixStream> { + self.obj.accept().map(UnixStream::new) } } diff --git a/src/libstd/io/pipe.rs b/src/libstd/io/pipe.rs index 9919d333f41..34d8bf96aa2 100644 --- a/src/libstd/io/pipe.rs +++ b/src/libstd/io/pipe.rs @@ -14,7 +14,7 @@ //! enough so that pipes can be created to child processes. use prelude::*; -use io::{io_error, EndOfFile}; +use io::IoResult; use libc; use rt::rtio::{RtioPipe, LocalIo}; @@ -42,7 +42,7 @@ impl PipeStream { /// /// If the pipe cannot be created, an error will be raised on the /// `io_error` condition. - pub fn open(fd: libc::c_int) -> Option<PipeStream> { + pub fn open(fd: libc::c_int) -> IoResult<PipeStream> { LocalIo::maybe_raise(|io| { io.pipe_open(fd).map(|obj| PipeStream { obj: obj }) }) @@ -54,29 +54,11 @@ impl PipeStream { } impl Reader for PipeStream { - fn read(&mut self, buf: &mut [u8]) -> Option<uint> { - match self.obj.read(buf) { - Ok(read) => Some(read), - Err(ioerr) => { - // EOF is indicated by returning None - if ioerr.kind != EndOfFile { - io_error::cond.raise(ioerr); - } - return None; - } - } - } + fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { self.obj.read(buf) } } impl Writer for PipeStream { - fn write(&mut self, buf: &[u8]) { - match self.obj.write(buf) { - Ok(_) => (), - Err(ioerr) => { - io_error::cond.raise(ioerr); - } - } - } + fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.obj.write(buf) } } #[cfg(test)] diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs index 6a10f24916f..62f6b3c3029 100644 --- a/src/libstd/io/process.rs +++ b/src/libstd/io/process.rs @@ -14,7 +14,7 @@ use prelude::*; use libc; use io; -use io::io_error; +use io::IoResult; use rt::rtio::{RtioProcess, IoFactory, LocalIo}; use fmt; @@ -93,7 +93,7 @@ pub enum ProcessExit { impl fmt::Show for ProcessExit { /// Format a ProcessExit enum, to nicely present the information. - fn fmt(obj: &ProcessExit, f: &mut fmt::Formatter) { + fn fmt(obj: &ProcessExit, f: &mut fmt::Formatter) -> fmt::Result { match *obj { ExitStatus(code) => write!(f.buf, "exit code: {}", code), ExitSignal(code) => write!(f.buf, "signal: {}", code), @@ -118,7 +118,7 @@ impl ProcessExit { impl Process { /// Creates a new pipe initialized, but not bound to any particular /// source/destination - pub fn new(config: ProcessConfig) -> Option<Process> { + pub fn new(config: ProcessConfig) -> IoResult<Process> { let mut config = Some(config); LocalIo::maybe_raise(|io| { io.spawn(config.take_unwrap()).map(|(p, io)| { @@ -142,13 +142,8 @@ impl Process { /// function. /// /// If the signal delivery fails, then the `io_error` condition is raised on - pub fn signal(&mut self, signal: int) { - match self.handle.kill(signal) { - Ok(()) => {} - Err(err) => { - io_error::cond.raise(err) - } - } + pub fn signal(&mut self, signal: int) -> IoResult<()> { + self.handle.kill(signal) } /// Wait for the child to exit completely, returning the status that it diff --git a/src/libstd/io/option.rs b/src/libstd/io/result.rs index e2eec652d9d..6eed4d146ba 100644 --- a/src/libstd/io/option.rs +++ b/src/libstd/io/result.rs @@ -14,80 +14,64 @@ //! These implementations allow e.g. `Option<File>` to be used //! as a `Reader` without unwrapping the option first. -use option::*; -use super::{Reader, Writer, Listener, Acceptor, Seek, SeekStyle}; -use super::{standard_error, PreviousIoError, io_error, IoError}; +use clone::Clone; +use result::{Ok, Err}; +use super::{Reader, Writer, Listener, Acceptor, Seek, SeekStyle, IoResult}; -fn prev_io_error() -> IoError { - standard_error(PreviousIoError) -} - -impl<W: Writer> Writer for Option<W> { - fn write(&mut self, buf: &[u8]) { +impl<W: Writer> Writer for IoResult<W> { + fn write(&mut self, buf: &[u8]) -> IoResult<()> { match *self { - Some(ref mut writer) => writer.write(buf), - None => io_error::cond.raise(prev_io_error()) + Ok(ref mut writer) => writer.write(buf), + Err(ref e) => Err((*e).clone()) } } - fn flush(&mut self) { + fn flush(&mut self) -> IoResult<()> { match *self { - Some(ref mut writer) => writer.flush(), - None => io_error::cond.raise(prev_io_error()) + Ok(ref mut writer) => writer.flush(), + Err(ref e) => Err(e.clone()), } } } -impl<R: Reader> Reader for Option<R> { - fn read(&mut self, buf: &mut [u8]) -> Option<uint> { +impl<R: Reader> Reader for IoResult<R> { + fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { match *self { - Some(ref mut reader) => reader.read(buf), - None => { - io_error::cond.raise(prev_io_error()); - None - } + Ok(ref mut reader) => reader.read(buf), + Err(ref e) => Err(e.clone()), } } } -impl<S: Seek> Seek for Option<S> { - fn tell(&self) -> u64 { +impl<S: Seek> Seek for IoResult<S> { + fn tell(&self) -> IoResult<u64> { match *self { - Some(ref seeker) => seeker.tell(), - None => { - io_error::cond.raise(prev_io_error()); - 0 - } + Ok(ref seeker) => seeker.tell(), + Err(ref e) => Err(e.clone()), } } - fn seek(&mut self, pos: i64, style: SeekStyle) { + fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> { match *self { - Some(ref mut seeker) => seeker.seek(pos, style), - None => io_error::cond.raise(prev_io_error()) + Ok(ref mut seeker) => seeker.seek(pos, style), + Err(ref e) => Err(e.clone()) } } } -impl<T, A: Acceptor<T>, L: Listener<T, A>> Listener<T, A> for Option<L> { - fn listen(self) -> Option<A> { +impl<T, A: Acceptor<T>, L: Listener<T, A>> Listener<T, A> for IoResult<L> { + fn listen(self) -> IoResult<A> { match self { - Some(listener) => listener.listen(), - None => { - io_error::cond.raise(prev_io_error()); - None - } + Ok(listener) => listener.listen(), + Err(e) => Err(e), } } } -impl<T, A: Acceptor<T>> Acceptor<T> for Option<A> { - fn accept(&mut self) -> Option<T> { +impl<T, A: Acceptor<T>> Acceptor<T> for IoResult<A> { + fn accept(&mut self) -> IoResult<T> { match *self { - Some(ref mut acceptor) => acceptor.accept(), - None => { - io_error::cond.raise(prev_io_error()); - None - } + Ok(ref mut acceptor) => acceptor.accept(), + Err(ref e) => Err(e.clone()), } } } diff --git a/src/libstd/io/signal.rs b/src/libstd/io/signal.rs index 5575e289b59..aaec1aba4b8 100644 --- a/src/libstd/io/signal.rs +++ b/src/libstd/io/signal.rs @@ -20,10 +20,11 @@ definitions for a number of signals. */ use clone::Clone; +use result::{Ok, Err}; use comm::{Port, SharedChan}; use container::{Map, MutableMap}; use hashmap; -use option::{Some, None}; +use io; use rt::rtio::{IoFactory, LocalIo, RtioSignal}; #[repr(int)] @@ -117,18 +118,18 @@ impl Listener { /// If this function fails to register a signal handler, then an error will /// be raised on the `io_error` condition and the function will return /// false. - pub fn register(&mut self, signum: Signum) -> bool { + pub fn register(&mut self, signum: Signum) -> io::IoResult<()> { if self.handles.contains_key(&signum) { - return true; // self is already listening to signum, so succeed + return Ok(()); // self is already listening to signum, so succeed } match LocalIo::maybe_raise(|io| { io.signal(signum, self.chan.clone()) }) { - Some(handle) => { + Ok(handle) => { self.handles.insert(signum, handle); - true + Ok(()) } - None => false + Err(e) => Err(e) } } diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index d9fa2a4fc33..bdf013233c0 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -28,7 +28,7 @@ out.write(bytes!("Hello, world!")); use container::Container; use fmt; -use io::{Reader, Writer, io_error, IoError, OtherIoError, +use io::{Reader, Writer, IoResult, IoError, OtherIoError, standard_error, EndOfFile, LineBufferedWriter}; use libc; use option::{Option, Some, None}; @@ -114,7 +114,8 @@ fn reset_helper(w: ~Writer, match f(t.get(), w) { Some(mut w) => { drop(t); - w.flush(); + // FIXME: is failing right here? + w.flush().unwrap(); Some(w) } None => None @@ -155,9 +156,9 @@ pub fn set_stderr(stderr: ~Writer) -> Option<~Writer> { // // io1 aliases io2 // }) // }) -fn with_task_stdout(f: |&mut Writer|) { +fn with_task_stdout(f: |&mut Writer| -> IoResult<()> ) { let task: Option<~Task> = Local::try_take(); - match task { + let result = match task { Some(mut task) => { // Printing may run arbitrary code, so ensure that the task is in // TLS to allow all std services. Note that this means a print while @@ -169,7 +170,7 @@ fn with_task_stdout(f: |&mut Writer|) { if my_stdout.is_none() { my_stdout = Some(~LineBufferedWriter::new(stdout()) as ~Writer); } - f(*my_stdout.get_mut_ref()); + let ret = f(*my_stdout.get_mut_ref()); // Note that we need to be careful when putting the stdout handle // back into the task. If the handle was set to `Some` while @@ -184,22 +185,29 @@ fn with_task_stdout(f: |&mut Writer|) { let prev = util::replace(&mut t.get().stdout, my_stdout); drop(t); drop(prev); + ret } None => { struct Stdout; impl Writer for Stdout { - fn write(&mut self, data: &[u8]) { + fn write(&mut self, data: &[u8]) -> IoResult<()> { unsafe { libc::write(libc::STDOUT_FILENO, data.as_ptr() as *libc::c_void, data.len() as libc::size_t); } + Ok(()) // just ignore the results } } let mut io = Stdout; - f(&mut io as &mut Writer); + f(&mut io as &mut Writer) } + }; + + match result { + Ok(()) => {} + Err(e) => fail!("failed printing to stdout: {}", e), } } @@ -226,8 +234,7 @@ pub fn print(s: &str) { /// `\n` character is printed to the console after the string. pub fn println(s: &str) { with_task_stdout(|io| { - io.write(s.as_bytes()); - io.write(['\n' as u8]); + io.write(s.as_bytes()).and_then(|()| io.write(['\n' as u8])) }) } @@ -249,7 +256,7 @@ pub struct StdReader { } impl Reader for StdReader { - fn read(&mut self, buf: &mut [u8]) -> Option<uint> { + fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { let ret = match self.inner { TTY(ref mut tty) => tty.read(buf), File(ref mut file) => file.read(buf).map(|i| i as uint), @@ -260,15 +267,8 @@ impl Reader for StdReader { // return an actual EOF error, but apparently for stdin it's a // little different. Hence, here we convert a 0 length read to an // end-of-file indicator so the caller knows to stop reading. - Ok(0) => { - io_error::cond.raise(standard_error(EndOfFile)); - None - } - Ok(amt) => Some(amt), - Err(e) => { - io_error::cond.raise(e); - None - } + Ok(0) => { Err(standard_error(EndOfFile)) } + ret @ Ok(..) | ret @ Err(..) => ret, } } } @@ -289,24 +289,15 @@ impl StdWriter { /// /// This function will raise on the `io_error` condition if an error /// happens. - pub fn winsize(&mut self) -> Option<(int, int)> { + pub fn winsize(&mut self) -> IoResult<(int, int)> { match self.inner { - TTY(ref mut tty) => { - match tty.get_winsize() { - Ok(p) => Some(p), - Err(e) => { - io_error::cond.raise(e); - None - } - } - } + TTY(ref mut tty) => tty.get_winsize(), File(..) => { - io_error::cond.raise(IoError { + Err(IoError { kind: OtherIoError, desc: "stream is not a tty", detail: None, - }); - None + }) } } } @@ -318,20 +309,15 @@ impl StdWriter { /// /// This function will raise on the `io_error` condition if an error /// happens. - pub fn set_raw(&mut self, raw: bool) { + pub fn set_raw(&mut self, raw: bool) -> IoResult<()> { match self.inner { - TTY(ref mut tty) => { - match tty.set_raw(raw) { - Ok(()) => {}, - Err(e) => io_error::cond.raise(e), - } - } + TTY(ref mut tty) => tty.set_raw(raw), File(..) => { - io_error::cond.raise(IoError { + Err(IoError { kind: OtherIoError, desc: "stream is not a tty", detail: None, - }); + }) } } } @@ -346,14 +332,10 @@ impl StdWriter { } impl Writer for StdWriter { - fn write(&mut self, buf: &[u8]) { - let ret = match self.inner { + fn write(&mut self, buf: &[u8]) -> IoResult<()> { + match self.inner { TTY(ref mut tty) => tty.write(buf), File(ref mut file) => file.write(buf), - }; - match ret { - Ok(()) => {} - Err(e) => io_error::cond.raise(e) } } } diff --git a/src/libstd/io/timer.rs b/src/libstd/io/timer.rs index 24eaf6adf3f..692aaa7afd0 100644 --- a/src/libstd/io/timer.rs +++ b/src/libstd/io/timer.rs @@ -39,8 +39,8 @@ loop { */ use comm::Port; -use option::Option; use rt::rtio::{IoFactory, LocalIo, RtioTimer}; +use io::IoResult; pub struct Timer { priv obj: ~RtioTimer @@ -48,7 +48,8 @@ pub struct Timer { /// Sleep the current task for `msecs` milliseconds. pub fn sleep(msecs: u64) { - let mut timer = Timer::new().expect("timer::sleep: could not create a Timer"); + let timer = Timer::new(); + let mut timer = timer.ok().expect("timer::sleep: could not create a Timer"); timer.sleep(msecs) } @@ -57,7 +58,7 @@ impl Timer { /// Creates a new timer which can be used to put the current task to sleep /// for a number of milliseconds, or to possibly create channels which will /// get notified after an amount of time has passed. - pub fn new() -> Option<Timer> { + pub fn new() -> IoResult<Timer> { LocalIo::maybe_raise(|io| io.timer_init().map(|t| Timer { obj: t })) } diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index a1794d24fc9..2c7f64ba747 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -7,8 +7,10 @@ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. + use prelude::*; use cmp; +use io; use vec::bytes::MutableByteVector; /// Wraps a `Reader`, limiting the number of bytes that can be read from it. @@ -25,9 +27,9 @@ impl<'a, R: Reader> LimitReader<'a, R> { } impl<'a, R: Reader> Reader for LimitReader<'a, R> { - fn read(&mut self, buf: &mut [u8]) -> Option<uint> { + fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> { if self.limit == 0 { - return None; + return Err(io::standard_error(io::EndOfFile)); } let len = cmp::min(self.limit, buf.len()); @@ -43,7 +45,7 @@ pub struct NullWriter; impl Writer for NullWriter { #[inline] - fn write(&mut self, _buf: &[u8]) { } + fn write(&mut self, _buf: &[u8]) -> io::IoResult<()> { Ok(()) } } /// A `Reader` which returns an infinite stream of 0 bytes, like /dev/zero. @@ -51,9 +53,9 @@ pub struct ZeroReader; impl Reader for ZeroReader { #[inline] - fn read(&mut self, buf: &mut [u8]) -> Option<uint> { + fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> { buf.set_memory(0); - Some(buf.len()) + Ok(buf.len()) } } @@ -62,8 +64,8 @@ pub struct NullReader; impl Reader for NullReader { #[inline] - fn read(&mut self, _buf: &mut [u8]) -> Option<uint> { - None + fn read(&mut self, _buf: &mut [u8]) -> io::IoResult<uint> { + Err(io::standard_error(io::EndOfFile)) } } @@ -81,17 +83,21 @@ impl MultiWriter { impl Writer for MultiWriter { #[inline] - fn write(&mut self, buf: &[u8]) { + fn write(&mut self, buf: &[u8]) -> io::IoResult<()> { + let mut ret = Ok(()); for writer in self.writers.mut_iter() { - writer.write(buf); + ret = ret.and(writer.write(buf)); } + return ret; } #[inline] - fn flush(&mut self) { + fn flush(&mut self) -> io::IoResult<()> { + let mut ret = Ok(()); for writer in self.writers.mut_iter() { - writer.flush(); + ret = ret.and(writer.flush()); } + return ret; } } @@ -111,20 +117,25 @@ impl<R: Reader, I: Iterator<R>> ChainedReader<I, R> { } impl<R: Reader, I: Iterator<R>> Reader for ChainedReader<I, R> { - fn read(&mut self, buf: &mut [u8]) -> Option<uint> { + fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> { loop { - match self.cur_reader { + let err = match self.cur_reader { Some(ref mut r) => { match r.read(buf) { - Some(len) => return Some(len), - None => {} + Ok(len) => return Ok(len), + Err(ref e) if e.kind == io::EndOfFile => None, + Err(e) => Some(e), } } None => break + }; + self.cur_reader = self.readers.next(); + match err { + Some(e) => return Err(e), + None => {} } - self.cur_reader = self.readers.next() } - None + Err(io::standard_error(io::EndOfFile)) } } @@ -150,22 +161,23 @@ impl<R: Reader, W: Writer> TeeReader<R, W> { } impl<R: Reader, W: Writer> Reader for TeeReader<R, W> { - fn read(&mut self, buf: &mut [u8]) -> Option<uint> { - self.reader.read(buf).map(|len| { - self.writer.write(buf.slice_to(len)); - len + fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> { + self.reader.read(buf).and_then(|len| { + self.writer.write(buf.slice_to(len)).map(|()| len) }) } } /// Copies all data from a `Reader` to a `Writer`. -pub fn copy<R: Reader, W: Writer>(r: &mut R, w: &mut W) { +pub fn copy<R: Reader, W: Writer>(r: &mut R, w: &mut W) -> io::IoResult<()> { let mut buf = [0, ..super::DEFAULT_BUF_SIZE]; loop { - match r.read(buf) { - Some(len) => w.write(buf.slice_to(len)), - None => break - } + let len = match r.read(buf) { + Ok(len) => len, + Err(ref e) if e.kind == io::EndOfFile => return Ok(()), + Err(e) => return Err(e), + }; + if_ok!(w.write(buf.slice_to(len))); } } diff --git a/src/libstd/logging.rs b/src/libstd/logging.rs index 636d3ffd90a..c5e66ffc7be 100644 --- a/src/libstd/logging.rs +++ b/src/libstd/logging.rs @@ -102,6 +102,7 @@ use io::Writer; use ops::Drop; use option::{Some, None, Option}; use prelude::drop; +use result::{Ok, Err}; use rt::local::Local; use rt::task::Task; use util; @@ -131,13 +132,19 @@ struct DefaultLogger { impl Logger for DefaultLogger { // by default, just ignore the level fn log(&mut self, _level: u32, args: &fmt::Arguments) { - fmt::writeln(&mut self.handle, args); + match fmt::writeln(&mut self.handle, args) { + Err(e) => fail!("failed to log: {}", e), + Ok(()) => {} + } } } impl Drop for DefaultLogger { fn drop(&mut self) { - self.handle.flush(); + match self.handle.flush() { + Err(e) => fail!("failed to flush a logger: {}", e), + Ok(()) => {} + } } } diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 4032b63790b..b31ae92d742 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -197,3 +197,8 @@ macro_rules! local_data_key ( pub static $name: ::std::local_data::Key<$ty> = &::std::local_data::Key; ) ) + +#[macro_export] +macro_rules! if_ok ( + ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) }) +) diff --git a/src/libstd/option.rs b/src/libstd/option.rs index 83cedd92a3f..19478e3dbb3 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -382,7 +382,7 @@ impl<T: Default> Option<T> { impl<T: fmt::Show> fmt::Show for Option<T> { #[inline] - fn fmt(s: &Option<T>, f: &mut fmt::Formatter) { + fn fmt(s: &Option<T>, f: &mut fmt::Formatter) -> fmt::Result { match *s { Some(ref t) => write!(f.buf, "Some({})", *t), None => write!(f.buf, "None") diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 0ea1c7510a1..1afada0a45a 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -929,7 +929,7 @@ pub enum MapError { } impl fmt::Show for MapError { - fn fmt(val: &MapError, out: &mut fmt::Formatter) { + fn fmt(val: &MapError, out: &mut fmt::Formatter) -> fmt::Result { let str = match *val { ErrFdNotAvail => "fd not available for reading or writing", ErrInvalidFd => "Invalid fd", @@ -944,23 +944,19 @@ impl fmt::Show for MapError { ErrAlreadyExists => "File mapping for specified file already exists", ErrZeroLength => "Zero-length mapping not allowed", ErrUnknown(code) => { - write!(out.buf, "Unknown error = {}", code); - return + return write!(out.buf, "Unknown error = {}", code) }, ErrVirtualAlloc(code) => { - write!(out.buf, "VirtualAlloc failure = {}", code); - return + return write!(out.buf, "VirtualAlloc failure = {}", code) }, ErrCreateFileMappingW(code) => { - format!("CreateFileMappingW failure = {}", code); - return + return write!(out.buf, "CreateFileMappingW failure = {}", code) }, ErrMapViewOfFile(code) => { - write!(out.buf, "MapViewOfFile failure = {}", code); - return + return write!(out.buf, "MapViewOfFile failure = {}", code) } }; - write!(out.buf, "{}", str); + write!(out.buf, "{}", str) } } diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs index 86f96a1075b..190cf5745f4 100644 --- a/src/libstd/path/mod.rs +++ b/src/libstd/path/mod.rs @@ -533,7 +533,7 @@ pub struct Display<'a, P> { } impl<'a, P: GenericPath> fmt::Show for Display<'a, P> { - fn fmt(d: &Display<P>, f: &mut fmt::Formatter) { + fn fmt(d: &Display<P>, f: &mut fmt::Formatter) -> fmt::Display { d.with_str(|s| f.pad(s)) } } diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index c359d79d275..e9068c6b0c8 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -62,7 +62,7 @@ impl OSRng { pub fn new() -> OSRng { use path::Path; let reader = File::open(&Path::new("/dev/urandom")); - let reader = reader.expect("Error opening /dev/urandom"); + let reader = reader.ok().expect("Error opening /dev/urandom"); let reader_rng = ReaderRng::new(reader); OSRng { inner: reader_rng } diff --git a/src/libstd/rand/reader.rs b/src/libstd/rand/reader.rs index e19fbd9aaf8..621d70970f0 100644 --- a/src/libstd/rand/reader.rs +++ b/src/libstd/rand/reader.rs @@ -11,7 +11,7 @@ //! A wrapper around any Reader to treat it as an RNG. use container::Container; -use option::{Some, None}; +use result::{Ok, Err}; use io::Reader; use rand::Rng; @@ -49,26 +49,26 @@ impl<R: Reader> Rng for ReaderRng<R> { // platform just involves blitting the bytes into the memory // of the u32, similarly for BE on BE; avoiding byteswapping. if cfg!(target_endian="little") { - self.reader.read_le_u32() + self.reader.read_le_u32().unwrap() } else { - self.reader.read_be_u32() + self.reader.read_be_u32().unwrap() } } fn next_u64(&mut self) -> u64 { // see above for explanation. if cfg!(target_endian="little") { - self.reader.read_le_u64() + self.reader.read_le_u64().unwrap() } else { - self.reader.read_be_u64() + self.reader.read_be_u64().unwrap() } } fn fill_bytes(&mut self, v: &mut [u8]) { if v.len() == 0 { return } match self.reader.read(v) { - Some(n) if n == v.len() => return, - Some(n) => fail!("ReaderRng.fill_bytes could not fill buffer: \ - read {} out of {} bytes.", n, v.len()), - None => fail!("ReaderRng.fill_bytes reached eof.") + Ok(n) if n == v.len() => return, + Ok(n) => fail!("ReaderRng.fill_bytes could not fill buffer: \ + read {} out of {} bytes.", n, v.len()), + Err(e) => fail!("ReaderRng.fill_bytes error: {}", e) } } } diff --git a/src/libstd/reflect.rs b/src/libstd/reflect.rs index d6b4d3f5656..44ee5de7ac3 100644 --- a/src/libstd/reflect.rs +++ b/src/libstd/reflect.rs @@ -66,6 +66,8 @@ impl<V:TyVisitor + MovePtr> MovePtrAdaptor<V> { pub fn bump_past<T>(&mut self) { self.bump(mem::size_of::<T>()); } + + pub fn unwrap(self) -> V { self.inner } } /// Abstract type-directed pointer-movement using the MovePtr trait diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs index 41ddf027787..f71649602b2 100644 --- a/src/libstd/repr.rs +++ b/src/libstd/repr.rs @@ -21,48 +21,57 @@ use char; use container::Container; use io; use iter::Iterator; -use option::{Some, None}; +use option::{Some, None, Option}; use ptr; use reflect; use reflect::{MovePtr, align}; +use result::{Ok, Err}; use str::StrSlice; use to_str::ToStr; use vec::OwnedVector; use unstable::intrinsics::{Disr, Opaque, TyDesc, TyVisitor, get_tydesc, visit_tydesc}; use unstable::raw; +macro_rules! if_ok( ($me:expr, $e:expr) => ( + match $e { + Ok(()) => {}, + Err(e) => { $me.last_err = Some(e); return false; } + } +) ) + /// Representations trait Repr { - fn write_repr(&self, writer: &mut io::Writer); + fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()>; } impl Repr for () { - fn write_repr(&self, writer: &mut io::Writer) { - writer.write("()".as_bytes()); + fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()> { + writer.write("()".as_bytes()) } } impl Repr for bool { - fn write_repr(&self, writer: &mut io::Writer) { + fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()> { let s = if *self { "true" } else { "false" }; writer.write(s.as_bytes()) } } impl Repr for int { - fn write_repr(&self, writer: &mut io::Writer) { + fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()> { ::int::to_str_bytes(*self, 10u, |bits| { - writer.write(bits); + writer.write(bits) }) } } macro_rules! int_repr(($ty:ident, $suffix:expr) => (impl Repr for $ty { - fn write_repr(&self, writer: &mut io::Writer) { + fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()> { ::$ty::to_str_bytes(*self, 10u, |bits| { - writer.write(bits); - writer.write(bytes!($suffix)); + writer.write(bits).and_then(|()| { + writer.write(bytes!($suffix)) + }) }) } })) @@ -78,10 +87,11 @@ int_repr!(u32, "u32") int_repr!(u64, "u64") macro_rules! num_repr(($ty:ident, $suffix:expr) => (impl Repr for $ty { - fn write_repr(&self, writer: &mut io::Writer) { + fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()> { let s = self.to_str(); - writer.write(s.as_bytes()); - writer.write(bytes!($suffix)); + writer.write(s.as_bytes()).and_then(|()| { + writer.write(bytes!($suffix)) + }) } })) @@ -100,7 +110,8 @@ pub struct ReprVisitor<'a> { priv ptr: *u8, priv ptr_stk: ~[*u8], priv var_stk: ~[VariantState], - priv writer: &'a mut io::Writer + priv writer: &'a mut io::Writer, + priv last_err: Option<io::IoError>, } pub fn ReprVisitor<'a>(ptr: *u8, @@ -110,6 +121,7 @@ pub fn ReprVisitor<'a>(ptr: *u8, ptr_stk: ~[], var_stk: ~[], writer: writer, + last_err: None, } } @@ -130,11 +142,10 @@ impl<'a> ReprVisitor<'a> { // Various helpers for the TyVisitor impl #[inline] - pub fn get<T>(&mut self, f: |&mut ReprVisitor, &T|) -> bool { + pub fn get<T>(&mut self, f: |&mut ReprVisitor, &T| -> bool) -> bool { unsafe { - f(self, transmute::<*u8,&T>(self.ptr)); + f(self, transmute::<*u8,&T>(self.ptr)) } - true } #[inline] @@ -152,43 +163,53 @@ impl<'a> ReprVisitor<'a> { ptr_stk: ~[], var_stk: ~[], writer: ::cast::transmute_copy(&self.writer), + last_err: None, }; let mut v = reflect::MovePtrAdaptor(u); // Obviously this should not be a thing, but blame #8401 for now visit_tydesc(inner, &mut v as &mut TyVisitor); - true + match v.unwrap().last_err { + Some(e) => { + self.last_err = Some(e); + false + } + None => true, + } } } #[inline] pub fn write<T:Repr>(&mut self) -> bool { self.get(|this, v:&T| { - v.write_repr(unsafe { ::cast::transmute_copy(&this.writer) }); + if_ok!(this, v.write_repr(this.writer)); + true }) } - pub fn write_escaped_slice(&mut self, slice: &str) { - self.writer.write(['"' as u8]); + pub fn write_escaped_slice(&mut self, slice: &str) -> bool { + if_ok!(self, self.writer.write(['"' as u8])); for ch in slice.chars() { - self.write_escaped_char(ch, true); + if !self.write_escaped_char(ch, true) { return false } } - self.writer.write(['"' as u8]); + if_ok!(self, self.writer.write(['"' as u8])); + true } - pub fn write_mut_qualifier(&mut self, mtbl: uint) { + pub fn write_mut_qualifier(&mut self, mtbl: uint) -> bool { if mtbl == 0 { - self.writer.write("mut ".as_bytes()); + if_ok!(self, self.writer.write("mut ".as_bytes())); } else if mtbl == 1 { // skip, this is ast::m_imm } else { fail!("invalid mutability value"); } + true } pub fn write_vec_range(&mut self, ptr: *(), len: uint, inner: *TyDesc) -> bool { let mut p = ptr as *u8; let (sz, al) = unsafe { ((*inner).size, (*inner).align) }; - self.writer.write(['[' as u8]); + if_ok!(self, self.writer.write(['[' as u8])); let mut first = true; let mut left = len; // unit structs have 0 size, and don't loop forever. @@ -197,13 +218,13 @@ impl<'a> ReprVisitor<'a> { if first { first = false; } else { - self.writer.write(", ".as_bytes()); + if_ok!(self, self.writer.write(", ".as_bytes())); } self.visit_ptr_inner(p as *u8, inner); p = align(unsafe { ptr::offset(p, sz as int) as uint }, al) as *u8; left -= dec; } - self.writer.write([']' as u8]); + if_ok!(self, self.writer.write([']' as u8])); true } @@ -211,8 +232,8 @@ impl<'a> ReprVisitor<'a> { self.write_vec_range(ptr::to_unsafe_ptr(&v.data), v.fill, inner) } - fn write_escaped_char(&mut self, ch: char, is_str: bool) { - match ch { + fn write_escaped_char(&mut self, ch: char, is_str: bool) -> bool { + if_ok!(self, match ch { '\t' => self.writer.write("\\t".as_bytes()), '\r' => self.writer.write("\\r".as_bytes()), '\n' => self.writer.write("\\n".as_bytes()), @@ -234,16 +255,18 @@ impl<'a> ReprVisitor<'a> { '\x20'..'\x7e' => self.writer.write([ch as u8]), _ => { char::escape_unicode(ch, |c| { - self.writer.write([c as u8]); - }) + let _ = self.writer.write([c as u8]); + }); + Ok(()) } - } + }); + return true; } } impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_bot(&mut self) -> bool { - self.writer.write("!".as_bytes()); + if_ok!(self, self.writer.write("!".as_bytes())); true } fn visit_nil(&mut self) -> bool { self.write::<()>() } @@ -265,9 +288,10 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_char(&mut self) -> bool { self.get::<char>(|this, &ch| { - this.writer.write(['\'' as u8]); - this.write_escaped_char(ch, false); - this.writer.write(['\'' as u8]); + if_ok!(this, this.writer.write(['\'' as u8])); + if !this.write_escaped_char(ch, false) { return false } + if_ok!(this, this.writer.write(['\'' as u8])); + true }) } @@ -277,8 +301,8 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_estr_uniq(&mut self) -> bool { self.get::<~str>(|this, s| { - this.writer.write(['~' as u8]); - this.write_escaped_slice(*s); + if_ok!(this, this.writer.write(['~' as u8])); + this.write_escaped_slice(*s) }) } @@ -291,34 +315,35 @@ impl<'a> TyVisitor for ReprVisitor<'a> { _align: uint) -> bool { fail!(); } fn visit_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool { - self.writer.write(['@' as u8]); + if_ok!(self, self.writer.write(['@' as u8])); self.write_mut_qualifier(mtbl); self.get::<&raw::Box<()>>(|this, b| { let p = ptr::to_unsafe_ptr(&b.data) as *u8; - this.visit_ptr_inner(p, inner); + this.visit_ptr_inner(p, inner) }) } fn visit_uniq(&mut self, _mtbl: uint, inner: *TyDesc) -> bool { - self.writer.write(['~' as u8]); + if_ok!(self, self.writer.write(['~' as u8])); self.get::<*u8>(|this, b| { - this.visit_ptr_inner(*b, inner); + this.visit_ptr_inner(*b, inner) }) } fn visit_ptr(&mut self, mtbl: uint, _inner: *TyDesc) -> bool { self.get::<*u8>(|this, p| { - write!(this.writer, "({} as *", *p); + if_ok!(this, write!(this.writer, "({} as *", *p)); this.write_mut_qualifier(mtbl); - this.writer.write("())".as_bytes()); + if_ok!(this, this.writer.write("())".as_bytes())); + true }) } fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool { - self.writer.write(['&' as u8]); + if_ok!(self, self.writer.write(['&' as u8])); self.write_mut_qualifier(mtbl); self.get::<*u8>(|this, p| { - this.visit_ptr_inner(*p, inner); + this.visit_ptr_inner(*p, inner) }) } @@ -327,33 +352,33 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_unboxed_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.get::<raw::Vec<()>>(|this, b| { - this.write_unboxed_vec_repr(mtbl, b, inner); + this.write_unboxed_vec_repr(mtbl, b, inner) }) } fn visit_evec_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.get::<&raw::Box<raw::Vec<()>>>(|this, b| { - this.writer.write(['@' as u8]); + if_ok!(this, this.writer.write(['@' as u8])); this.write_mut_qualifier(mtbl); - this.write_unboxed_vec_repr(mtbl, &b.data, inner); + this.write_unboxed_vec_repr(mtbl, &b.data, inner) }) } fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.get::<&raw::Vec<()>>(|this, b| { - this.writer.write(['~' as u8]); - this.write_unboxed_vec_repr(mtbl, *b, inner); + if_ok!(this, this.writer.write(['~' as u8])); + this.write_unboxed_vec_repr(mtbl, *b, inner) }) } fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.get::<raw::Slice<()>>(|this, s| { - this.writer.write(['&' as u8]); + if_ok!(this, this.writer.write(['&' as u8])); this.write_mut_qualifier(mtbl); let size = unsafe { if (*inner).size == 0 { 1 } else { (*inner).size } }; - this.write_vec_range(s.data, s.len * size, inner); + this.write_vec_range(s.data, s.len * size, inner) }) } @@ -361,42 +386,42 @@ impl<'a> TyVisitor for ReprVisitor<'a> { _: uint, inner: *TyDesc) -> bool { let assumed_size = if sz == 0 { n } else { sz }; self.get::<()>(|this, b| { - this.write_vec_range(ptr::to_unsafe_ptr(b), assumed_size, inner); + this.write_vec_range(ptr::to_unsafe_ptr(b), assumed_size, inner) }) } fn visit_enter_rec(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { - self.writer.write(['{' as u8]); + if_ok!(self, self.writer.write(['{' as u8])); true } fn visit_rec_field(&mut self, i: uint, name: &str, mtbl: uint, inner: *TyDesc) -> bool { if i != 0 { - self.writer.write(", ".as_bytes()); + if_ok!(self, self.writer.write(", ".as_bytes())); } self.write_mut_qualifier(mtbl); - self.writer.write(name.as_bytes()); - self.writer.write(": ".as_bytes()); + if_ok!(self, self.writer.write(name.as_bytes())); + if_ok!(self, self.writer.write(": ".as_bytes())); self.visit_inner(inner); true } fn visit_leave_rec(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { - self.writer.write(['}' as u8]); + if_ok!(self, self.writer.write(['}' as u8])); true } fn visit_enter_class(&mut self, name: &str, named_fields: bool, n_fields: uint, _sz: uint, _align: uint) -> bool { - self.writer.write(name.as_bytes()); + if_ok!(self, self.writer.write(name.as_bytes())); if n_fields != 0 { if named_fields { - self.writer.write(['{' as u8]); + if_ok!(self, self.writer.write(['{' as u8])); } else { - self.writer.write(['(' as u8]); + if_ok!(self, self.writer.write(['(' as u8])); } } true @@ -405,11 +430,11 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_class_field(&mut self, i: uint, name: &str, named: bool, _mtbl: uint, inner: *TyDesc) -> bool { if i != 0 { - self.writer.write(", ".as_bytes()); + if_ok!(self, self.writer.write(", ".as_bytes())); } if named { - self.writer.write(name.as_bytes()); - self.writer.write(": ".as_bytes()); + if_ok!(self, self.writer.write(name.as_bytes())); + if_ok!(self, self.writer.write(": ".as_bytes())); } self.visit_inner(inner); true @@ -419,9 +444,9 @@ impl<'a> TyVisitor for ReprVisitor<'a> { _sz: uint, _align: uint) -> bool { if n_fields != 0 { if named_fields { - self.writer.write(['}' as u8]); + if_ok!(self, self.writer.write(['}' as u8])); } else { - self.writer.write([')' as u8]); + if_ok!(self, self.writer.write([')' as u8])); } } true @@ -429,13 +454,13 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_enter_tup(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { - self.writer.write(['(' as u8]); + if_ok!(self, self.writer.write(['(' as u8])); true } fn visit_tup_field(&mut self, i: uint, inner: *TyDesc) -> bool { if i != 0 { - self.writer.write(", ".as_bytes()); + if_ok!(self, self.writer.write(", ".as_bytes())); } self.visit_inner(inner); true @@ -444,9 +469,9 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_leave_tup(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { if _n_fields == 1 { - self.writer.write([',' as u8]); + if_ok!(self, self.writer.write([',' as u8])); } - self.writer.write([')' as u8]); + if_ok!(self, self.writer.write([')' as u8])); true } @@ -482,9 +507,9 @@ impl<'a> TyVisitor for ReprVisitor<'a> { } if write { - self.writer.write(name.as_bytes()); + if_ok!(self, self.writer.write(name.as_bytes())); if n_fields > 0 { - self.writer.write(['(' as u8]); + if_ok!(self, self.writer.write(['(' as u8])); } } true @@ -498,7 +523,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> { match self.var_stk[self.var_stk.len() - 1] { Matched => { if i != 0 { - self.writer.write(", ".as_bytes()); + if_ok!(self, self.writer.write(", ".as_bytes())); } if ! self.visit_inner(inner) { return false; @@ -516,7 +541,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> { match self.var_stk[self.var_stk.len() - 1] { Matched => { if n_fields > 0 { - self.writer.write([')' as u8]); + if_ok!(self, self.writer.write([')' as u8])); } } _ => () @@ -538,28 +563,29 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_enter_fn(&mut self, _purity: uint, _proto: uint, _n_inputs: uint, _retstyle: uint) -> bool { - self.writer.write("fn(".as_bytes()); + if_ok!(self, self.writer.write("fn(".as_bytes())); true } fn visit_fn_input(&mut self, i: uint, _mode: uint, inner: *TyDesc) -> bool { if i != 0 { - self.writer.write(", ".as_bytes()); + if_ok!(self, self.writer.write(", ".as_bytes())); } let name = unsafe { (*inner).name }; - self.writer.write(name.as_bytes()); + if_ok!(self, self.writer.write(name.as_bytes())); true } - fn visit_fn_output(&mut self, _retstyle: uint, variadic: bool, inner: *TyDesc) -> bool { + fn visit_fn_output(&mut self, _retstyle: uint, variadic: bool, + inner: *TyDesc) -> bool { if variadic { - self.writer.write(", ...".as_bytes()); + if_ok!(self, self.writer.write(", ...".as_bytes())); } - self.writer.write(")".as_bytes()); + if_ok!(self, self.writer.write(")".as_bytes())); let name = unsafe { (*inner).name }; if name != "()" { - self.writer.write(" -> ".as_bytes()); - self.writer.write(name.as_bytes()); + if_ok!(self, self.writer.write(" -> ".as_bytes())); + if_ok!(self, self.writer.write(name.as_bytes())); } true } @@ -569,7 +595,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_trait(&mut self, name: &str) -> bool { - self.writer.write(name.as_bytes()); + if_ok!(self, self.writer.write(name.as_bytes())); true } @@ -582,13 +608,17 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_closure_ptr(&mut self, _ck: uint) -> bool { true } } -pub fn write_repr<T>(writer: &mut io::Writer, object: &T) { +pub fn write_repr<T>(writer: &mut io::Writer, object: &T) -> io::IoResult<()> { unsafe { let ptr = ptr::to_unsafe_ptr(object) as *u8; let tydesc = get_tydesc::<T>(); let u = ReprVisitor(ptr, writer); let mut v = reflect::MovePtrAdaptor(u); visit_tydesc(tydesc, &mut v as &mut TyVisitor); + match v.unwrap().last_err { + Some(e) => Err(e), + None => Ok(()), + } } } @@ -597,7 +627,7 @@ pub fn repr_to_str<T>(t: &T) -> ~str { use io; let mut result = io::MemWriter::new(); - write_repr(&mut result as &mut io::Writer, t); + write_repr(&mut result as &mut io::Writer, t).unwrap(); str::from_utf8_owned(result.unwrap()).unwrap() } @@ -615,7 +645,7 @@ fn test_repr() { fn exact_test<T>(t: &T, e:&str) { let mut m = io::MemWriter::new(); - write_repr(&mut m as &mut io::Writer, t); + write_repr(&mut m as &mut io::Writer, t).unwrap(); let s = str::from_utf8_owned(m.unwrap()).unwrap(); assert_eq!(s.as_slice(), e); } diff --git a/src/libstd/result.rs b/src/libstd/result.rs index cc8fdeaccfe..846bba7533f 100644 --- a/src/libstd/result.rs +++ b/src/libstd/result.rs @@ -208,7 +208,7 @@ impl<T, E> Result<T, E> { impl<T: fmt::Show, E: fmt::Show> fmt::Show for Result<T, E> { #[inline] - fn fmt(s: &Result<T, E>, f: &mut fmt::Formatter) { + fn fmt(s: &Result<T, E>, f: &mut fmt::Formatter) -> fmt::Result { match *s { Ok(ref t) => write!(f.buf, "Ok({})", *t), Err(ref e) => write!(f.buf, "Err({})", *e) diff --git a/src/libstd/rt/rtio.rs b/src/libstd/rt/rtio.rs index 455a84b4ce3..35b1e21df06 100644 --- a/src/libstd/rt/rtio.rs +++ b/src/libstd/rt/rtio.rs @@ -16,13 +16,13 @@ use libc; use ops::Drop; use option::{Option, Some, None}; use path::Path; -use result::{Result, Ok, Err}; +use result::{Result, Err}; use rt::task::Task; use rt::local::Local; use ai = io::net::addrinfo; use io; -use io::IoError; +use io::{IoError, IoResult}; use io::net::ip::{IpAddr, SocketAddr}; use io::process::{ProcessConfig, ProcessExit}; use io::signal::Signum; @@ -116,23 +116,12 @@ impl<'a> LocalIo<'a> { return ret; } - pub fn maybe_raise<T>(f: |io: &mut IoFactory| -> Result<T, IoError>) - -> Option<T> + pub fn maybe_raise<T>(f: |io: &mut IoFactory| -> IoResult<T>) + -> IoResult<T> { match LocalIo::borrow() { - None => { - io::io_error::cond.raise(io::standard_error(io::IoUnavailable)); - None - } - Some(mut io) => { - match f(io.get()) { - Ok(t) => Some(t), - Err(ioerr) => { - io::io_error::cond.raise(ioerr); - None - } - } - } + None => Err(io::standard_error(io::IoUnavailable)), + Some(mut io) => f(io.get()), } } diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index 7c43e64f17b..515eb93001a 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -119,6 +119,7 @@ impl Task { // Run the task main function, then do some cleanup. f.finally(|| { + #[allow(unused_must_use)] fn close_outputs() { let mut task = Local::borrow(None::<Task>); let logger = task.get().logger.take(); @@ -126,8 +127,8 @@ impl Task { let stdout = task.get().stdout.take(); drop(task); drop(logger); // loggers are responsible for flushing - match stdout { Some(mut w) => w.flush(), None => {} } - match stderr { Some(mut w) => w.flush(), None => {} } + match stdout { Some(mut w) => { w.flush(); }, None => {} } + match stderr { Some(mut w) => { w.flush(); }, None => {} } } // First, flush/destroy the user stdout/logger because these diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs index 4d2dcb6c51c..9aece13b84c 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind.rs @@ -464,9 +464,10 @@ fn begin_unwind_inner(msg: ~Any, file: &'static str, line: uint) -> ! { match task.stderr.take() { Some(mut stderr) => { Local::put(task); - format_args!(|args| ::fmt::writeln(stderr, args), - "task '{}' failed at '{}', {}:{}", - n, msg_s, file, line); + // FIXME: what to do when the task printing fails? + let _err = format_args!(|args| ::fmt::writeln(stderr, args), + "task '{}' failed at '{}', {}:{}", + n, msg_s, file, line); task = Local::take(); match util::replace(&mut task.stderr, Some(stderr)) { diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index 9c17c624987..69e240f30bc 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -11,10 +11,12 @@ use container::Container; use fmt; use from_str::FromStr; +use io::IoResult; use iter::Iterator; use libc; use option::{Some, None, Option}; use os; +use result::Ok; use str::StrSlice; use unstable::running_on_valgrind; use vec::ImmutableVector; @@ -73,16 +75,17 @@ pub fn dumb_println(args: &fmt::Arguments) { struct Stderr; impl io::Writer for Stderr { - fn write(&mut self, data: &[u8]) { + fn write(&mut self, data: &[u8]) -> IoResult<()> { unsafe { libc::write(libc::STDERR_FILENO, data.as_ptr() as *libc::c_void, data.len() as libc::size_t); } + Ok(()) // yes, we're lying } } let mut w = Stderr; - fmt::writeln(&mut w as &mut io::Writer, args); + let _ = fmt::writeln(&mut w as &mut io::Writer, args); } pub fn abort(msg: &str) -> ! { diff --git a/src/libstd/run.rs b/src/libstd/run.rs index ef2374f6095..fe4693a079f 100644 --- a/src/libstd/run.rs +++ b/src/libstd/run.rs @@ -119,7 +119,8 @@ impl Process { * * options - Options to configure the environment of the process, * the working directory and the standard IO streams. */ - pub fn new(prog: &str, args: &[~str], options: ProcessOptions) -> Option<Process> { + pub fn new(prog: &str, args: &[~str], + options: ProcessOptions) -> io::IoResult<Process> { let ProcessOptions { env, dir, in_fd, out_fd, err_fd } = options; let env = env.as_ref().map(|a| a.as_slice()); let cwd = dir.as_ref().map(|a| a.as_str().unwrap()); @@ -138,10 +139,7 @@ impl Process { cwd: cwd, io: rtio, }; - match process::Process::new(rtconfig) { - Some(inner) => Some(Process { inner: inner }), - None => None - } + process::Process::new(rtconfig).map(|p| Process { inner: p }) } /// Returns the unique id of the process @@ -224,19 +222,17 @@ impl Process { let ch_clone = ch.clone(); spawn(proc() { - let _guard = io::ignore_io_error(); let mut error = error; match error { Some(ref mut e) => ch.send((2, e.read_to_end())), - None => ch.send((2, ~[])) + None => ch.send((2, Ok(~[]))) } }); spawn(proc() { - let _guard = io::ignore_io_error(); let mut output = output; match output { Some(ref mut e) => ch_clone.send((1, e.read_to_end())), - None => ch_clone.send((1, ~[])) + None => ch_clone.send((1, Ok(~[]))) } }); @@ -251,8 +247,8 @@ impl Process { }; return ProcessOutput {status: status, - output: outs, - error: errs}; + output: outs.ok().unwrap_or(~[]), + error: errs.ok().unwrap_or(~[]) }; } /** @@ -263,7 +259,8 @@ impl Process { * TerminateProcess(..) will be called. */ pub fn destroy(&mut self) { - self.inner.signal(io::process::PleaseExitSignal); + // This should never fail because we own the process + self.inner.signal(io::process::PleaseExitSignal).unwrap(); self.finish(); } @@ -275,8 +272,10 @@ impl Process { * TerminateProcess(..) will be called. */ pub fn force_destroy(&mut self) { - self.inner.signal(io::process::MustDieSignal); + // This should never fail because we own the process + self.inner.signal(io::process::MustDieSignal).unwrap(); self.finish(); + } } @@ -293,18 +292,14 @@ impl Process { * * The process's exit code, or None if the child process could not be started */ -pub fn process_status(prog: &str, args: &[~str]) -> Option<ProcessExit> { - let mut opt_prog = Process::new(prog, args, ProcessOptions { +pub fn process_status(prog: &str, args: &[~str]) -> io::IoResult<ProcessExit> { + Process::new(prog, args, ProcessOptions { env: None, dir: None, in_fd: Some(unsafe { libc::dup(libc::STDIN_FILENO) }), out_fd: Some(unsafe { libc::dup(libc::STDOUT_FILENO) }), err_fd: Some(unsafe { libc::dup(libc::STDERR_FILENO) }) - }); - match opt_prog { - Some(ref mut prog) => Some(prog.finish()), - None => None - } + }).map(|mut p| p.finish()) } /** @@ -320,12 +315,10 @@ pub fn process_status(prog: &str, args: &[~str]) -> Option<ProcessExit> { * The process's stdout/stderr output and exit code, or None if the child process could not be * started. */ -pub fn process_output(prog: &str, args: &[~str]) -> Option<ProcessOutput> { - let mut opt_prog = Process::new(prog, args, ProcessOptions::new()); - match opt_prog { - Some(ref mut prog) => Some(prog.finish_with_output()), - None => None - } +pub fn process_output(prog: &str, args: &[~str]) -> io::IoResult<ProcessOutput> { + Process::new(prog, args, ProcessOptions::new()).map(|mut p| { + p.finish_with_output() + }) } #[cfg(test)] diff --git a/src/libstd/to_bytes.rs b/src/libstd/to_bytes.rs index 4c545de73b4..c8bd1907c5c 100644 --- a/src/libstd/to_bytes.rs +++ b/src/libstd/to_bytes.rs @@ -349,7 +349,7 @@ impl<A:IterBytes> ToBytes for A { let mut m = ::io::MemWriter::new(); self.iter_bytes(lsb0, |bytes| { - m.write(bytes); + m.write(bytes).unwrap(); true }); m.unwrap() |
