1
Fork 0

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
This commit is contained in:
Alex Crichton 2014-01-29 16:33:57 -08:00
parent be4fc63809
commit ece8a8f520
35 changed files with 918 additions and 1059 deletions

View file

@ -501,6 +501,8 @@ use num::Signed;
pub mod parse; pub mod parse;
pub mod rt; pub mod rt;
pub type Result = io::IoResult<()>;
/// A struct to represent both where to emit formatting strings to and how they /// 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 /// should be formatted. A mutable version of this is passed to all formatting
/// traits. /// traits.
@ -527,7 +529,7 @@ pub struct Formatter<'a> {
/// compile time it is ensured that the function and the value have the correct /// 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. /// types, and then this struct is used to canonicalize arguments to one type.
pub struct Argument<'a> { 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, 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 /// 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. /// used for formatting, it is only if no other format is specified.
#[allow(missing_doc)] #[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 /// Format trait for the `b` character
#[allow(missing_doc)] #[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 /// Format trait for the `c` character
#[allow(missing_doc)] #[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 /// Format trait for the `i` and `d` characters
#[allow(missing_doc)] #[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 /// Format trait for the `u` character
#[allow(missing_doc)] #[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 /// Format trait for the `o` character
#[allow(missing_doc)] #[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 /// Format trait for the `b` character
#[allow(missing_doc)] #[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 /// Format trait for the `x` character
#[allow(missing_doc)] #[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 /// Format trait for the `X` character
#[allow(missing_doc)] #[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 /// Format trait for the `s` character
#[allow(missing_doc)] #[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 /// Format trait for the `?` character
#[allow(missing_doc)] #[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 /// Format trait for the `p` character
#[allow(missing_doc)] #[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 /// Format trait for the `f` character
#[allow(missing_doc)] #[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 /// Format trait for the `e` character
#[allow(missing_doc)] #[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 /// Format trait for the `E` character
#[allow(missing_doc)] #[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 // FIXME #11938 - UFCS would make us able call the above methods
// directly Show::show(x, fmt). // directly Show::show(x, fmt).
@ -659,15 +661,15 @@ uniform_fn_call_workaround! {
/// let w = &mut io::stdout() as &mut io::Writer; /// let w = &mut io::stdout() as &mut io::Writer;
/// format_args!(|args| { fmt::write(w, args) }, "Hello, {}!", "world"); /// 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) } unsafe { write_unsafe(output, args.fmt, args.args) }
} }
/// The `writeln` function takes the same arguments as `write`, except that it /// 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. /// will also write a newline (`\n`) character at the end of the format string.
pub fn writeln(output: &mut io::Writer, args: &Arguments) { pub fn writeln(output: &mut io::Writer, args: &Arguments) -> Result {
unsafe { write_unsafe(output, args.fmt, args.args) } let first = unsafe { write_unsafe(output, args.fmt, args.args) };
output.write(['\n' as u8]); first.and_then(|()| output.write(['\n' as u8]))
} }
/// The `write_unsafe` function takes an output stream, a precompiled format /// 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. /// format string.
pub unsafe fn write_unsafe(output: &mut io::Writer, pub unsafe fn write_unsafe(output: &mut io::Writer,
fmt: &[rt::Piece], fmt: &[rt::Piece],
args: &[Argument]) { args: &[Argument]) -> Result {
let mut formatter = Formatter { let mut formatter = Formatter {
flags: 0, flags: 0,
width: None, width: None,
@ -704,8 +706,9 @@ pub unsafe fn write_unsafe(output: &mut io::Writer,
curarg: args.iter(), curarg: args.iter(),
}; };
for piece in fmt.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 /// The format function takes a precompiled format string and a list of
@ -752,7 +755,7 @@ pub fn format(args: &Arguments) -> ~str {
/// format string. /// format string.
pub unsafe fn format_unsafe(fmt: &[rt::Piece], args: &[Argument]) -> ~str { pub unsafe fn format_unsafe(fmt: &[rt::Piece], args: &[Argument]) -> ~str {
let mut output = MemWriter::new(); 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(); 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 // at runtime. This consumes all of the compile-time statics generated by
// the format! syntax extension. // 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 { match *piece {
rt::String(s) => { self.buf.write(s.as_bytes()); } rt::String(s) => self.buf.write(s.as_bytes()),
rt::CurrentArgument(()) => { self.buf.write(cur.unwrap().as_bytes()); } rt::CurrentArgument(()) => self.buf.write(cur.unwrap().as_bytes()),
rt::Argument(ref arg) => { rt::Argument(ref arg) => {
// Fill in the format parameters into the formatter // Fill in the format parameters into the formatter
self.fill = arg.format.fill; self.fill = arg.format.fill;
@ -782,8 +785,8 @@ impl<'a> Formatter<'a> {
// Then actually do some printing // Then actually do some printing
match arg.method { match arg.method {
None => { (value.formatter)(value.value, self); } None => (value.formatter)(value.value, self),
Some(ref method) => { self.execute(*method, value); } 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 { match *method {
// Pluralization is selection upon a numeric value specified as the // Pluralization is selection upon a numeric value specified as the
// parameter. // 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. // Select is just a matching against the string specified.
@ -860,24 +863,26 @@ impl<'a> Formatter<'a> {
for s in selectors.iter() { for s in selectors.iter() {
if s.selector == value { if s.selector == value {
for piece in s.result.iter() { 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() { 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| { ::uint::to_str_bytes(value, 10, |buf| {
let valuestr = str::from_utf8(buf).unwrap(); let valuestr = str::from_utf8(buf).unwrap();
for piece in pieces.iter() { 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 /// This function will correctly account for the flags provided as well as
/// the minimum width. It will not take precision into account. /// the minimum width. It will not take precision into account.
pub fn pad_integral(&mut self, s: &[u8], alternate_prefix: &str, pub fn pad_integral(&mut self, s: &[u8], alternate_prefix: &str,
positive: bool) { positive: bool) -> Result {
use fmt::parse::{FlagAlternate, FlagSignPlus, FlagSignAwareZeroPad}; use fmt::parse::{FlagAlternate, FlagSignPlus, FlagSignAwareZeroPad};
let mut actual_len = s.len(); let mut actual_len = s.len();
@ -916,32 +921,32 @@ impl<'a> Formatter<'a> {
let sign = |this: &mut Formatter| { let sign = |this: &mut Formatter| {
if !signprinted { if !signprinted {
if this.flags & 1 << (FlagSignPlus as uint) != 0 && positive { if this.flags & 1 << (FlagSignPlus as uint) != 0 && positive {
this.buf.write(['+' as u8]); if_ok!(this.buf.write(['+' as u8]));
} else if !positive { } else if !positive {
this.buf.write(['-' as u8]); if_ok!(this.buf.write(['-' as u8]));
} }
if this.flags & 1 << (FlagAlternate as uint) != 0 { 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; signprinted = true;
} }
Ok(())
}; };
let emit = |this: &mut Formatter| { let emit = |this: &mut Formatter| {
sign(this); sign(this).and_then(|()| this.buf.write(s))
this.buf.write(s);
}; };
match self.width { match self.width {
None => { emit(self) } None => emit(self),
Some(min) if actual_len >= min => { emit(self) } Some(min) if actual_len >= min => emit(self),
Some(min) => { Some(min) => {
if self.flags & 1 << (FlagSignAwareZeroPad as uint) != 0 { if self.flags & 1 << (FlagSignAwareZeroPad as uint) != 0 {
self.fill = '0'; self.fill = '0';
sign(self); if_ok!(sign(self));
} }
self.with_padding(min - actual_len, parse::AlignRight, |me| { 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 /// is longer than this length
/// ///
/// Notably this function ignored the `flag` parameters /// 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 // Make sure there's a fast path up front
if self.width.is_none() && self.precision.is_none() { if self.width.is_none() && self.precision.is_none() {
self.buf.write(s.as_bytes()); return self.buf.write(s.as_bytes());
return
} }
// The `precision` field can be interpreted as a `max-width` for the // The `precision` field can be interpreted as a `max-width` for the
// string being formatted // string being formatted
@ -974,8 +978,7 @@ impl<'a> Formatter<'a> {
let char_len = s.char_len(); let char_len = s.char_len();
if char_len >= max { if char_len >= max {
let nchars = ::cmp::min(max, char_len); let nchars = ::cmp::min(max, char_len);
self.buf.write(s.slice_chars(0, nchars).as_bytes()); return self.buf.write(s.slice_chars(0, nchars).as_bytes());
return
} }
} }
None => {} None => {}
@ -985,7 +988,7 @@ impl<'a> Formatter<'a> {
match self.width { match self.width {
// If we're under the maximum length, and there's no minimum length // If we're under the maximum length, and there's no minimum length
// requirements, then we can just emit the string // 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 // 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. // 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. // up the minimum width with the specified string + some alignment.
Some(width) => { Some(width) => {
self.with_padding(width - s.len(), parse::AlignLeft, |me| { 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, fn with_padding(&mut self,
padding: uint, padding: uint,
default: parse::Alignment, default: parse::Alignment,
f: |&mut Formatter|) { f: |&mut Formatter| -> Result) -> Result {
let align = match self.align { let align = match self.align {
parse::AlignUnknown => default, parse::AlignUnknown => default,
parse::AlignLeft | parse::AlignRight => self.align parse::AlignLeft | parse::AlignRight => self.align
}; };
if align == parse::AlignLeft { if align == parse::AlignLeft {
f(self); if_ok!(f(self));
} }
let mut fill = [0u8, ..4]; let mut fill = [0u8, ..4];
let len = self.fill.encode_utf8(fill); let len = self.fill.encode_utf8(fill);
for _ in range(0, padding) { 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 { 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 /// 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. /// create the Argument structures that are passed into the `format` function.
#[doc(hidden)] #[inline] #[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> { t: &'a T) -> Argument<'a> {
unsafe { unsafe {
Argument { Argument {
@ -1055,41 +1059,41 @@ pub fn argumentuint<'a>(s: &'a uint) -> Argument<'a> {
// Implementations of the core formatting traits // Implementations of the core formatting traits
impl Bool for bool { impl Bool for bool {
fn fmt(b: &bool, f: &mut Formatter) { fn fmt(b: &bool, f: &mut Formatter) -> Result {
String::fmt(&(if *b {"true"} else {"false"}), f); String::fmt(&(if *b {"true"} else {"false"}), f)
} }
} }
impl<'a, T: str::Str> String for T { impl<'a, T: str::Str> String for T {
fn fmt(s: &T, f: &mut Formatter) { fn fmt(s: &T, f: &mut Formatter) -> Result {
f.pad(s.as_slice()); f.pad(s.as_slice())
} }
} }
impl Char for char { 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 mut utf8 = [0u8, ..4];
let amt = c.encode_utf8(utf8); let amt = c.encode_utf8(utf8);
let s: &str = unsafe { cast::transmute(utf8.slice_to(amt)) }; 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, macro_rules! int_base(($ty:ident, $into:ident, $base:expr,
$name:ident, $prefix:expr) => { $name:ident, $prefix:expr) => {
impl $name for $ty { 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| { ::$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) => { macro_rules! upper_hex(($ty:ident, $into:ident) => {
impl UpperHex for $ty { 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| { ::$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" // Not sure why, but this causes an "unresolved enum variant, struct or const"
// when inlined into the above macro... // when inlined into the above macro...
#[doc(hidden)] #[doc(hidden)]
pub fn upperhex(buf: &[u8], f: &mut Formatter) { pub fn upperhex(buf: &[u8], f: &mut Formatter) -> Result {
let mut local = [0u8, ..16]; let mut local = [0u8, ..16];
for i in ::iter::range(0, buf.len()) { for i in ::iter::range(0, buf.len()) {
local[i] = match buf[i] as char { local[i] = match buf[i] as char {
@ -1105,16 +1109,16 @@ pub fn upperhex(buf: &[u8], f: &mut Formatter) {
c => c as u8, 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) => { macro_rules! integer(($signed:ident, $unsigned:ident) => {
// Signed is special because it actuall emits the negative sign, // Signed is special because it actuall emits the negative sign,
// nothing else should do that, however. // nothing else should do that, however.
impl Signed for $signed { 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| { ::$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) => { macro_rules! floating(($ty:ident) => {
impl Float for $ty { 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 // FIXME: this shouldn't perform an allocation
let s = match fmt.precision { let s = match fmt.precision {
Some(i) => ::$ty::to_str_exact(f.abs(), i), Some(i) => ::$ty::to_str_exact(f.abs(), i),
None => ::$ty::to_str_digits(f.abs(), 6) 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 { 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 // FIXME: this shouldn't perform an allocation
let s = match fmt.precision { let s = match fmt.precision {
Some(i) => ::$ty::to_str_exp_exact(f.abs(), i, false), Some(i) => ::$ty::to_str_exp_exact(f.abs(), i, false),
None => ::$ty::to_str_exp_digits(f.abs(), 6, 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 { 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 // FIXME: this shouldn't perform an allocation
let s = match fmt.precision { let s = match fmt.precision {
Some(i) => ::$ty::to_str_exp_exact(f.abs(), i, true), Some(i) => ::$ty::to_str_exp_exact(f.abs(), i, true),
None => ::$ty::to_str_exp_digits(f.abs(), 6, 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) floating!(f64)
impl<T> Poly for T { 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) { match (f.width, f.precision) {
(None, None) => { (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 // If we have a specified width for formatting, then we have to make
// this allocation of a new string // this allocation of a new string
_ => { _ => {
let s = repr::repr_to_str(t); let s = repr::repr_to_str(t);
f.pad(s); f.pad(s)
} }
} }
} }
} }
impl<T> Pointer for *T { 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); f.flags |= 1 << (parse::FlagAlternate as uint);
::uint::to_str_bytes(*t as uint, 16, |buf| { ::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 { 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 // Implementation of Show for various core types
macro_rules! delegate(($ty:ty to $other:ident) => { macro_rules! delegate(($ty:ty to $other:ident) => {
impl<'a> Show for $ty { impl<'a> Show for $ty {
fn fmt(me: &$ty, f: &mut Formatter) { fn fmt(me: &$ty, f: &mut Formatter) -> Result {
$other::fmt(me, f) $other::fmt(me, f)
} }
} }
@ -1229,10 +1235,10 @@ delegate!(f32 to Float)
delegate!(f64 to Float) delegate!(f64 to Float)
impl<T> Show for *T { 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 { 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, // If you expected tests to be here, look instead at the run-pass/ifmt.rs test,

View file

@ -27,13 +27,14 @@
#[allow(missing_doc)]; #[allow(missing_doc)];
use container::Container; use container::Container;
use io::{Writer, IoResult};
use iter::Iterator; use iter::Iterator;
use num::ToStrRadix;
use option::{Some, None}; use option::{Some, None};
use io::Writer; use result::Ok;
use str::OwnedStr; use str::OwnedStr;
use to_bytes::IterBytes; use to_bytes::IterBytes;
use vec::ImmutableVector; use vec::ImmutableVector;
use num::ToStrRadix;
// Alias `SipState` to `State`. // Alias `SipState` to `State`.
pub use State = hash::SipState; pub use State = hash::SipState;
@ -164,7 +165,7 @@ macro_rules! compress (
impl Writer for SipState { impl Writer for SipState {
// Methods for io::writer // Methods for io::writer
#[inline] #[inline]
fn write(&mut self, msg: &[u8]) { fn write(&mut self, msg: &[u8]) -> IoResult<()> {
let length = msg.len(); let length = msg.len();
self.length += length; self.length += length;
@ -180,7 +181,7 @@ impl Writer for SipState {
t += 1; t += 1;
} }
self.ntail += length; self.ntail += length;
return; return Ok(())
} }
let mut t = 0; let mut t = 0;
@ -222,17 +223,14 @@ impl Writer for SipState {
t += 1 t += 1
} }
self.ntail = left; self.ntail = left;
} Ok(())
fn flush(&mut self) {
// No-op
} }
} }
impl Streaming for SipState { impl Streaming for SipState {
#[inline] #[inline]
fn input(&mut self, buf: &[u8]) { fn input(&mut self, buf: &[u8]) {
self.write(buf); self.write(buf).unwrap();
} }
#[inline] #[inline]

View file

@ -11,10 +11,11 @@
//! Buffering wrappers for I/O traits //! Buffering wrappers for I/O traits
use container::Container; 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 iter::ExactSize;
use num; use num;
use option::{Option, Some, None}; use option::{Some, None};
use result::{Ok, Err};
use vec::{OwnedVector, ImmutableVector, MutableVector}; use vec::{OwnedVector, ImmutableVector, MutableVector};
use vec; use vec;
@ -86,17 +87,12 @@ impl<R: Reader> BufferedReader<R> {
} }
impl<R: Reader> Buffer for BufferedReader<R> { impl<R: Reader> Buffer for BufferedReader<R> {
fn fill<'a>(&'a mut self) -> &'a [u8] { fn fill<'a>(&'a mut self) -> IoResult<&'a [u8]> {
if self.pos == self.cap { while self.pos == self.cap {
match self.inner.read(self.buf) { self.cap = if_ok!(self.inner.read(self.buf));
Some(cap) => {
self.pos = 0; self.pos = 0;
self.cap = cap;
} }
None => { self.eof = true; } Ok(self.buf.slice(self.pos, self.cap))
}
}
return self.buf.slice(self.pos, self.cap);
} }
fn consume(&mut self, amt: uint) { fn consume(&mut self, amt: uint) {
@ -106,18 +102,15 @@ impl<R: Reader> Buffer for BufferedReader<R> {
} }
impl<R: Reader> Reader 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 nread = {
let available = self.fill(); let available = if_ok!(self.fill());
let nread = num::min(available.len(), buf.len()); let nread = num::min(available.len(), buf.len());
vec::bytes::copy_memory(buf, available.slice_to(nread)); vec::bytes::copy_memory(buf, available.slice_to(nread));
nread nread
}; };
self.pos += nread; self.pos += nread;
if nread == 0 && buf.len() != 0 && self.eof { Ok(nread)
return None;
}
Some(nread)
} }
} }
@ -161,10 +154,13 @@ impl<W: Writer> BufferedWriter<W> {
BufferedWriter::with_capacity(DEFAULT_BUF_SIZE, inner) BufferedWriter::with_capacity(DEFAULT_BUF_SIZE, inner)
} }
fn flush_buf(&mut self) { fn flush_buf(&mut self) -> IoResult<()> {
if self.pos != 0 { 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; self.pos = 0;
ret
} else {
Ok(())
} }
} }
@ -178,29 +174,30 @@ impl<W: Writer> BufferedWriter<W> {
/// ///
/// The buffer is flushed before returning the writer. /// The buffer is flushed before returning the writer.
pub fn unwrap(mut self) -> W { 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 self.inner
} }
} }
impl<W: Writer> Writer for BufferedWriter<W> { 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() { if self.pos + buf.len() > self.buf.len() {
self.flush_buf(); if_ok!(self.flush_buf());
} }
if buf.len() > self.buf.len() { if buf.len() > self.buf.len() {
self.inner.write(buf); self.inner.write(buf)
} else { } else {
let dst = self.buf.mut_slice_from(self.pos); let dst = self.buf.mut_slice_from(self.pos);
vec::bytes::copy_memory(dst, buf); vec::bytes::copy_memory(dst, buf);
self.pos += buf.len(); self.pos += buf.len();
Ok(())
} }
} }
fn flush(&mut self) { fn flush(&mut self) -> IoResult<()> {
self.flush_buf(); self.flush_buf().and_then(|()| self.inner.flush())
self.inner.flush();
} }
} }
@ -234,18 +231,19 @@ impl<W: Writer> LineBufferedWriter<W> {
} }
impl<W: Writer> Writer for 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) { match buf.iter().rposition(|&b| b == '\n' as u8) {
Some(i) => { Some(i) => {
self.inner.write(buf.slice_to(i + 1)); if_ok!(self.inner.write(buf.slice_to(i + 1)));
self.inner.flush(); if_ok!(self.inner.flush());
self.inner.write(buf.slice_from(i + 1)); if_ok!(self.inner.write(buf.slice_from(i + 1)));
Ok(())
} }
None => self.inner.write(buf), 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>); struct InternalBufferedWriter<W>(BufferedWriter<W>);
@ -258,7 +256,9 @@ impl<W> InternalBufferedWriter<W> {
} }
impl<W: Reader> Reader for 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 /// 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> { 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) } fn consume(&mut self, amt: uint) { self.inner.consume(amt) }
} }
impl<S: Stream> Reader for BufferedStream<S> { 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> { impl<S: Stream> Writer for BufferedStream<S> {
fn write(&mut self, buf: &[u8]) { self.inner.inner.get_mut_ref().write(buf) } fn write(&mut self, buf: &[u8]) -> IoResult<()> {
fn flush(&mut self) { self.inner.inner.get_mut_ref().flush() } self.inner.inner.get_mut_ref().write(buf)
}
fn flush(&mut self) -> IoResult<()> {
self.inner.inner.get_mut_ref().flush()
}
} }
#[cfg(test)] #[cfg(test)]

View file

@ -14,7 +14,7 @@ use comm::{Port, Chan};
use cmp; use cmp;
use io; use io;
use option::{None, Option, Some}; use option::{None, Option, Some};
use super::{Reader, Writer}; use super::{Reader, Writer, IoResult};
use vec::{bytes, CloneableVector, MutableVector, ImmutableVector}; use vec::{bytes, CloneableVector, MutableVector, ImmutableVector};
/// Allows reading from a port. /// Allows reading from a port.
@ -49,7 +49,7 @@ impl PortReader {
} }
impl Reader for 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; let mut num_read = 0;
loop { loop {
match self.buf { match self.buf {
@ -71,10 +71,9 @@ impl Reader for PortReader {
self.closed = self.buf.is_none(); self.closed = self.buf.is_none();
} }
if self.closed && num_read == 0 { if self.closed && num_read == 0 {
io::io_error::cond.raise(io::standard_error(io::EndOfFile)); Err(io::standard_error(io::EndOfFile))
None
} else { } else {
Some(num_read) Ok(num_read)
} }
} }
} }
@ -98,13 +97,15 @@ impl ChanWriter {
} }
impl Writer for 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()) { if !self.chan.try_send(buf.to_owned()) {
io::io_error::cond.raise(io::IoError { Err(io::IoError {
kind: io::BrokenPipe, kind: io::BrokenPipe,
desc: "Pipe closed", desc: "Pipe closed",
detail: None detail: None
}); })
} else {
Ok(())
} }
} }
} }

View file

@ -46,7 +46,7 @@ impl<'r, R: Reader> Bytes<'r, R> {
impl<'r, R: Reader> Iterator<u8> for Bytes<'r, R> { impl<'r, R: Reader> Iterator<u8> for Bytes<'r, R> {
#[inline] #[inline]
fn next(&mut self) -> Option<u8> { fn next(&mut self) -> Option<u8> {
self.reader.read_byte() self.reader.read_byte().ok()
} }
} }

View file

@ -27,21 +27,25 @@ particular bits of it, etc.
# Example # 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 // create the file, whether it exists or not
let mut file = File::create(&path); let mut file = File::create(&path);
file.write(bytes!("foobar")); file.write(bytes!("foobar"));
# drop(file);
// open the file in read-only mode // open the file in read-only mode
let mut file = File::open(&path); let mut file = File::open(&path);
file.read_to_end(); file.read_to_end();
println!("{}", path.stat().size); println!("{}", path.stat().size);
fs::symlink(&path, &Path::new("bar.txt")); # drop(file);
fs::unlink(&path); fs::unlink(&path);
```
*/ */
@ -50,7 +54,7 @@ use clone::Clone;
use iter::Iterator; use iter::Iterator;
use super::{Reader, Writer, Seek}; use super::{Reader, Writer, Seek};
use super::{SeekStyle, Read, Write, Open, IoError, Truncate, 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 rt::rtio::{RtioFileStream, IoFactory, LocalIo};
use io; use io;
use option::{Some, None, Option}; use option::{Some, None, Option};
@ -81,22 +85,19 @@ impl File {
/// ///
/// # Example /// # 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) { /// let file = match File::open_mode(&p, Open, ReadWrite) {
/// Some(s) => s, /// Ok(f) => f,
/// None => fail!("whoops! I'm sure this raised, anyways..") /// Err(e) => fail!("file error: {}", e),
/// }; /// };
/// // do some stuff with that file /// // 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 /// `FileMode` and `FileAccess` provide information about the permissions
/// context in which a given stream is created. More information about them /// context in which a given stream is created. More information about them
@ -119,7 +120,7 @@ impl File {
/// * Filesystem-level errors (full disk, etc) /// * Filesystem-level errors (full disk, etc)
pub fn open_mode(path: &Path, pub fn open_mode(path: &Path,
mode: FileMode, mode: FileMode,
access: FileAccess) -> Option<File> { access: FileAccess) -> IoResult<File> {
LocalIo::maybe_raise(|io| { LocalIo::maybe_raise(|io| {
io.fs_open(&path.to_c_str(), mode, access).map(|fd| { io.fs_open(&path.to_c_str(), mode, access).map(|fd| {
File { File {
@ -139,10 +140,12 @@ impl File {
/// ///
/// # Example /// # Example
/// ///
/// ```rust
/// use std::io::File; /// use std::io::File;
/// ///
/// let contents = File::open(&Path::new("foo.txt")).read_to_end(); /// let contents = File::open(&Path::new("foo.txt")).read_to_end();
pub fn open(path: &Path) -> Option<File> { /// ```
pub fn open(path: &Path) -> IoResult<File> {
File::open_mode(path, Open, Read) File::open_mode(path, Open, Read)
} }
@ -154,11 +157,16 @@ impl File {
/// ///
/// # Example /// # Example
/// ///
/// ```rust
/// # #[allow(unused_must_use)];
/// use std::io::File; /// use std::io::File;
/// ///
/// let mut f = File::create(&Path::new("foo.txt")); /// let mut f = File::create(&Path::new("foo.txt"));
/// f.write(bytes!("This is a sample file")); /// f.write(bytes!("This is a sample file"));
pub fn create(path: &Path) -> Option<File> { /// # drop(f);
/// # ::std::io::fs::unlnk(&Path::new("foo.txt"));
/// ```
pub fn create(path: &Path) -> IoResult<File> {
File::open_mode(path, Truncate, Write) File::open_mode(path, Truncate, Write)
} }
@ -174,8 +182,8 @@ impl File {
/// # Errors /// # Errors
/// ///
/// This function will raise on the `io_error` condition on failure. /// This function will raise on the `io_error` condition on failure.
pub fn fsync(&mut self) { pub fn fsync(&mut self) -> IoResult<()> {
let _ = self.fd.fsync().map_err(|e| io_error::cond.raise(e)); self.fd.fsync()
} }
/// This function is similar to `fsync`, except that it may not synchronize /// This function is similar to `fsync`, except that it may not synchronize
@ -186,8 +194,8 @@ impl File {
/// # Errors /// # Errors
/// ///
/// This function will raise on the `io_error` condition on failure. /// This function will raise on the `io_error` condition on failure.
pub fn datasync(&mut self) { pub fn datasync(&mut self) -> IoResult<()> {
let _ = self.fd.datasync().map_err(|e| io_error::cond.raise(e)); self.fd.datasync()
} }
/// Either truncates or extends the underlying file, updating the size of /// Either truncates or extends the underlying file, updating the size of
@ -202,8 +210,8 @@ impl File {
/// # Errors /// # Errors
/// ///
/// On error, this function will raise on the `io_error` condition. /// On error, this function will raise on the `io_error` condition.
pub fn truncate(&mut self, size: i64) { pub fn truncate(&mut self, size: i64) -> IoResult<()> {
let _ = self.fd.truncate(size).map_err(|e| io_error::cond.raise(e)); self.fd.truncate(size)
} }
/// Tests whether this stream has reached EOF. /// Tests whether this stream has reached EOF.
@ -219,12 +227,13 @@ impl File {
/// ///
/// # Example /// # Example
/// ///
/// ```rust
/// # #[allow(unused_must_use)];
/// use std::io::fs; /// use std::io::fs;
/// ///
/// let p = Path::new("/some/file/path.txt"); /// let p = Path::new("/some/file/path.txt");
/// fs::unlink(&p); /// fs::unlink(&p);
/// // if we made it here without failing, then the /// ```
/// // unlink operation was successful
/// ///
/// Note that, just because an unlink call was successful, it is not /// Note that, just because an unlink call was successful, it is not
/// guaranteed that a file is immediately deleted (e.g. depending on /// 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 /// 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 /// directory, the user lacks permissions to remove the file, or if some
/// other filesystem-level error occurs. /// other filesystem-level error occurs.
pub fn unlink(path: &Path) { pub fn unlink(path: &Path) -> IoResult<()> {
LocalIo::maybe_raise(|io| io.fs_unlink(&path.to_c_str())); LocalIo::maybe_raise(|io| io.fs_unlink(&path.to_c_str()))
} }
/// Given a path, query the file system to get information about a file, /// Given a path, query the file system to get information about a file,
@ -249,48 +258,26 @@ pub fn unlink(path: &Path) {
/// ///
/// # Example /// # Example
/// ///
/// ```rust
/// use std::io; /// use std::io;
/// use std::io::fs; /// use std::io::fs;
/// ///
/// let p = Path::new("/some/file/path.txt"); /// let p = Path::new("/some/file/path.txt");
/// match io::result(|| fs::stat(&p)) { /// match fs::stat(&p) {
/// Ok(stat) => { /* ... */ } /// Ok(stat) => { /* ... */ }
/// Err(e) => { /* handle error */ } /// Err(e) => { /* handle error */ }
/// } /// }
/// ```
/// ///
/// # Errors /// # Errors
/// ///
/// This call will raise an `io_error` condition if the user lacks the /// 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 /// requisite permissions to perform a `stat` call on the given path or if
/// there is no entry in the filesystem at the provided path. /// 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| { LocalIo::maybe_raise(|io| {
io.fs_stat(&path.to_c_str()) 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 /// Perform the same operation as the `stat` function, except that this
@ -301,28 +288,30 @@ fn dummystat() -> FileStat {
/// # Errors /// # Errors
/// ///
/// See `stat` /// See `stat`
pub fn lstat(path: &Path) -> FileStat { pub fn lstat(path: &Path) -> IoResult<FileStat> {
LocalIo::maybe_raise(|io| { LocalIo::maybe_raise(|io| {
io.fs_lstat(&path.to_c_str()) io.fs_lstat(&path.to_c_str())
}).unwrap_or_else(dummystat) })
} }
/// Rename a file or directory to a new name. /// Rename a file or directory to a new name.
/// ///
/// # Example /// # Example
/// ///
/// ```rust
/// # #[allow(unused_must_use)];
/// use std::io::fs; /// use std::io::fs;
/// ///
/// fs::rename(&Path::new("foo"), &Path::new("bar")); /// fs::rename(&Path::new("foo"), &Path::new("bar"));
/// // Oh boy, nothing was raised! /// ```
/// ///
/// # Errors /// # Errors
/// ///
/// Will raise an `io_error` condition if the provided `path` doesn't exist, /// 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 /// the process lacks permissions to view the contents, or if some other
/// intermittent I/O error occurs. /// intermittent I/O error occurs.
pub fn rename(from: &Path, to: &Path) { pub fn rename(from: &Path, to: &Path) -> IoResult<()> {
LocalIo::maybe_raise(|io| io.fs_rename(&from.to_c_str(), &to.to_c_str())); 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 /// Copies the contents of one file to another. This function will also
@ -333,10 +322,12 @@ pub fn rename(from: &Path, to: &Path) {
/// ///
/// # Example /// # Example
/// ///
/// ```rust
/// # #[allow(unused_must_use)];
/// use std::io::fs; /// use std::io::fs;
/// ///
/// fs::copy(&Path::new("foo.txt"), &Path::new("bar.txt")); /// fs::copy(&Path::new("foo.txt"), &Path::new("bar.txt"));
/// // Oh boy, nothing was raised! /// ```
/// ///
/// # Errors /// # 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 /// Note that this copy is not atomic in that once the destination is
/// ensured to not exist, there is nothing preventing the destination from /// ensured to not exist, there is nothing preventing the destination from
/// being created and then destroyed by this operation. /// 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() { if !from.is_file() {
return io_error::cond.raise(IoError { return Err(IoError {
kind: io::MismatchedFileTypeForOperation, kind: io::MismatchedFileTypeForOperation,
desc: "the source path is not an existing file", desc: "the source path is not an existing file",
detail: None, detail: None,
}); })
} }
let mut reader = match File::open(from) { Some(f) => f, None => return }; let mut reader = if_ok!(File::open(from));
let mut writer = match File::create(to) { Some(f) => f, None => return }; let mut writer = if_ok!(File::create(to));
let mut buf = [0, ..io::DEFAULT_BUF_SIZE]; let mut buf = [0, ..io::DEFAULT_BUF_SIZE];
loop { loop {
match reader.read(buf) { let amt = match reader.read(buf) {
Some(amt) => writer.write(buf.slice_to(amt)), Ok(n) => n,
None => break 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 /// Changes the permission mode bits found on a file or a directory. This
@ -379,6 +372,8 @@ pub fn copy(from: &Path, to: &Path) {
/// ///
/// # Example /// # Example
/// ///
/// ```rust
/// # #[allow(unused_must_use)]
/// use std::io; /// use std::io;
/// use std::io::fs; /// use std::io::fs;
/// ///
@ -386,14 +381,15 @@ pub fn copy(from: &Path, to: &Path) {
/// fs::chmod(&Path::new("file.txt"), io::UserRead | io::UserWrite); /// fs::chmod(&Path::new("file.txt"), io::UserRead | io::UserWrite);
/// fs::chmod(&Path::new("dir"), io::UserDir); /// fs::chmod(&Path::new("dir"), io::UserDir);
/// fs::chmod(&Path::new("file.exe"), io::UserExec); /// fs::chmod(&Path::new("file.exe"), io::UserExec);
/// ```
/// ///
/// # Errors /// # Errors
/// ///
/// If this function encounters an I/O error, it will raise on the `io_error` /// 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 /// condition. Some possible error situations are not having the permission to
/// change the attributes of a file or the file not existing. /// change the attributes of a file or the file not existing.
pub fn chmod(path: &Path, mode: io::FilePermission) { pub fn chmod(path: &Path, mode: io::FilePermission) -> IoResult<()> {
LocalIo::maybe_raise(|io| io.fs_chmod(&path.to_c_str(), mode)); 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. /// 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 /// # Errors
/// ///
/// This function will raise on the `io_error` condition on failure. /// This function will raise on the `io_error` condition on failure.
pub fn chown(path: &Path, uid: int, gid: int) { pub fn chown(path: &Path, uid: int, gid: int) -> IoResult<()> {
LocalIo::maybe_raise(|io| io.fs_chown(&path.to_c_str(), uid, gid)); 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 /// 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 /// # Errors
/// ///
/// This function will raise on the `io_error` condition on failure. /// This function will raise on the `io_error` condition on failure.
pub fn link(src: &Path, dst: &Path) { pub fn link(src: &Path, dst: &Path) -> IoResult<()> {
LocalIo::maybe_raise(|io| io.fs_link(&src.to_c_str(), &dst.to_c_str())); 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 /// 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 /// # Errors
/// ///
/// This function will raise on the `io_error` condition on failure. /// This function will raise on the `io_error` condition on failure.
pub fn symlink(src: &Path, dst: &Path) { pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> {
LocalIo::maybe_raise(|io| io.fs_symlink(&src.to_c_str(), &dst.to_c_str())); 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. /// 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 /// 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 /// conditions include reading a file that does not exist or reading a file
/// which is not a symlink. /// 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())) LocalIo::maybe_raise(|io| io.fs_readlink(&path.to_c_str()))
} }
@ -441,45 +437,50 @@ pub fn readlink(path: &Path) -> Option<Path> {
/// ///
/// # Example /// # Example
/// ///
/// use std::libc::S_IRWXU; /// ```rust
/// # #[allow(unused_must_use)];
/// use std::io;
/// use std::io::fs; /// use std::io::fs;
/// ///
/// let p = Path::new("/some/dir"); /// let p = Path::new("/some/dir");
/// fs::mkdir(&p, S_IRWXU as int); /// fs::mkdir(&p, io::UserRWX);
/// // If we got here, our directory exists! Hooray! /// ```
/// ///
/// # Errors /// # Errors
/// ///
/// This call will raise an `io_error` condition if the user lacks permissions /// 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 /// to make a new directory at the provided path, or if the directory already
/// exists. /// exists.
pub fn mkdir(path: &Path, mode: FilePermission) { pub fn mkdir(path: &Path, mode: FilePermission) -> IoResult<()> {
LocalIo::maybe_raise(|io| io.fs_mkdir(&path.to_c_str(), mode)); LocalIo::maybe_raise(|io| io.fs_mkdir(&path.to_c_str(), mode))
} }
/// Remove an existing, empty directory /// Remove an existing, empty directory
/// ///
/// # Example /// # Example
/// ///
/// ```rust
/// # #[allow(unused_must_use)];
/// use std::io::fs; /// use std::io::fs;
/// ///
/// let p = Path::new("/some/dir"); /// let p = Path::new("/some/dir");
/// fs::rmdir(&p); /// fs::rmdir(&p);
/// // good riddance, you mean ol' directory /// ```
/// ///
/// # Errors /// # Errors
/// ///
/// This call will raise an `io_error` condition if the user lacks permissions /// 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 /// to remove the directory at the provided path, or if the directory isn't
/// empty. /// empty.
pub fn rmdir(path: &Path) { pub fn rmdir(path: &Path) -> IoResult<()> {
LocalIo::maybe_raise(|io| io.fs_rmdir(&path.to_c_str())); LocalIo::maybe_raise(|io| io.fs_rmdir(&path.to_c_str()))
} }
/// Retrieve a vector containing all entries within a provided directory /// Retrieve a vector containing all entries within a provided directory
/// ///
/// # Example /// # Example
/// ///
/// ```rust
/// use std::io::fs; /// use std::io::fs;
/// ///
/// // one possible implementation of fs::walk_dir only visiting files /// // one possible implementation of fs::walk_dir only visiting files
@ -493,23 +494,24 @@ pub fn rmdir(path: &Path) {
/// } /// }
/// else { fail!("nope"); } /// else { fail!("nope"); }
/// } /// }
/// ```
/// ///
/// # Errors /// # Errors
/// ///
/// Will raise an `io_error` condition if the provided `from` doesn't exist, /// 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 /// the process lacks permissions to view the contents or if the `path` points
/// at a non-directory file /// at a non-directory file
pub fn readdir(path: &Path) -> ~[Path] { pub fn readdir(path: &Path) -> IoResult<~[Path]> {
LocalIo::maybe_raise(|io| { LocalIo::maybe_raise(|io| {
io.fs_readdir(&path.to_c_str(), 0) io.fs_readdir(&path.to_c_str(), 0)
}).unwrap_or_else(|| ~[]) })
} }
/// Returns an iterator which will recursively walk the directory structure /// Returns an iterator which will recursively walk the directory structure
/// rooted at `path`. The path given will not be iterated over, and this will /// rooted at `path`. The path given will not be iterated over, and this will
/// perform iteration in a top-down order. /// perform iteration in a top-down order.
pub fn walk_dir(path: &Path) -> Directories { pub fn walk_dir(path: &Path) -> IoResult<Directories> {
Directories { stack: readdir(path) } Ok(Directories { stack: if_ok!(readdir(path)) })
} }
/// An iterator which walks over a directory /// An iterator which walks over a directory
@ -522,7 +524,10 @@ impl Iterator<Path> for Directories {
match self.stack.shift() { match self.stack.shift() {
Some(path) => { Some(path) => {
if path.is_dir() { 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) Some(path)
} }
@ -539,14 +544,14 @@ impl Iterator<Path> for Directories {
/// This function will raise on the `io_error` condition if an error /// This function will raise on the `io_error` condition if an error
/// happens, see `fs::mkdir` for more information about error conditions /// happens, see `fs::mkdir` for more information about error conditions
/// and performance. /// 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, // tjc: if directory exists but with different permissions,
// should we return false? // should we return false?
if path.is_dir() { if path.is_dir() {
return return Ok(())
} }
if path.filename().is_some() { if path.filename().is_some() {
mkdir_recursive(&path.dir_path(), mode); if_ok!(mkdir_recursive(&path.dir_path(), mode));
} }
mkdir(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 /// This function will raise on the `io_error` condition if an error
/// happens. See `file::unlink` and `fs::readdir` for possible error /// happens. See `file::unlink` and `fs::readdir` for possible error
/// conditions. /// conditions.
pub fn rmdir_recursive(path: &Path) { pub fn rmdir_recursive(path: &Path) -> IoResult<()> {
let children = readdir(path); let children = if_ok!(readdir(path));
for child in children.iter() { for child in children.iter() {
if child.is_dir() { if child.is_dir() {
rmdir_recursive(child); if_ok!(rmdir_recursive(child));
} else { } else {
unlink(child); if_ok!(unlink(child));
} }
} }
// Directory should now be empty // Directory should now be empty
rmdir(path); rmdir(path)
} }
/// Changes the timestamps for a file's last modification and access time. /// 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 /// This function will raise on the `io_error` condition if an error
/// happens. /// happens.
// FIXME(#10301) these arguments should not be u64 // FIXME(#10301) these arguments should not be u64
pub fn change_file_times(path: &Path, atime: u64, mtime: u64) { 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)); LocalIo::maybe_raise(|io| io.fs_utime(&path.to_c_str(), atime, mtime))
} }
impl Reader for File { 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) { match self.fd.read(buf) {
Ok(read) => { Ok(read) => {
self.last_nread = read; self.last_nread = read;
match read { match read {
0 => None, 0 => Err(io::standard_error(io::EndOfFile)),
_ => Some(read as uint) _ => Ok(read as uint)
} }
}, },
Err(ioerr) => { Err(e) => Err(e),
// EOF is indicated by returning None
if ioerr.kind != io::EndOfFile {
io_error::cond.raise(ioerr);
}
return None;
}
} }
} }
} }
impl Writer for File { impl Writer for File {
fn write(&mut self, buf: &[u8]) { fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.fd.write(buf) }
match self.fd.write(buf) {
Ok(()) => (),
Err(ioerr) => {
io_error::cond.raise(ioerr);
}
}
}
} }
impl Seek for File { impl Seek for File {
fn tell(&self) -> u64 { fn tell(&self) -> IoResult<u64> {
let res = self.fd.tell(); self.fd.tell()
match res {
Ok(cursor) => cursor,
Err(ioerr) => {
io_error::cond.raise(ioerr);
return -1;
}
}
} }
fn seek(&mut self, pos: i64, style: SeekStyle) { fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
match self.fd.seek(pos, style) { match self.fd.seek(pos, style) {
Ok(_) => { Ok(_) => {
// successful seek resets EOF indicator // successful seek resets EOF indicator
self.last_nread = -1; self.last_nread = -1;
() Ok(())
},
Err(ioerr) => {
io_error::cond.raise(ioerr);
} }
Err(e) => Err(e),
} }
} }
} }
@ -650,7 +633,7 @@ impl path::Path {
/// Consult the `file::stat` documentation for more info. /// Consult the `file::stat` documentation for more info.
/// ///
/// This call preserves identical runtime/error semantics with `file::stat`. /// 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 /// Boolean value indicator whether the underlying file exists on the local
/// filesystem. This will return true if the path points to either a /// filesystem. This will return true if the path points to either a
@ -660,7 +643,7 @@ impl path::Path {
/// ///
/// Will not raise a condition /// Will not raise a condition
pub fn exists(&self) -> bool { 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 /// Whether the underlying implementation (be it a file path, or something
@ -672,7 +655,7 @@ impl path::Path {
/// ///
/// Will not raise a condition /// Will not raise a condition
pub fn is_file(&self) -> bool { pub fn is_file(&self) -> bool {
match io::result(|| self.stat()) { match self.stat() {
Ok(s) => s.kind == io::TypeFile, Ok(s) => s.kind == io::TypeFile,
Err(..) => false Err(..) => false
} }
@ -687,7 +670,7 @@ impl path::Path {
/// ///
/// Will not raise a condition /// Will not raise a condition
pub fn is_dir(&self) -> bool { pub fn is_dir(&self) -> bool {
match io::result(|| self.stat()) { match self.stat() {
Ok(s) => s.kind == io::TypeDirectory, Ok(s) => s.kind == io::TypeDirectory,
Err(..) => false Err(..) => false
} }

View file

@ -13,9 +13,10 @@
use cmp::max; use cmp::max;
use cmp::min; use cmp::min;
use container::Container; use container::Container;
use option::{Option, Some, None}; use option::None;
use super::{Reader, Writer, Seek, Buffer, IoError, SeekStyle, io_error, use result::{Err, Ok};
OtherIoError}; use io;
use io::{Reader, Writer, Seek, Buffer, IoError, SeekStyle, IoResult};
use vec; use vec;
use vec::{Vector, ImmutableVector, MutableVector, OwnedCloneableVector}; use vec::{Vector, ImmutableVector, MutableVector, OwnedCloneableVector};
@ -59,7 +60,7 @@ impl MemWriter {
} }
impl Writer for 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 // Make sure the internal buffer is as least as big as where we
// currently are // currently are
let difference = self.pos as i64 - self.buf.len() as i64; let difference = self.pos as i64 - self.buf.len() as i64;
@ -86,14 +87,15 @@ impl Writer for MemWriter {
// Bump us forward // Bump us forward
self.pos += buf.len(); self.pos += buf.len();
Ok(())
} }
} }
// FIXME(#10432) // FIXME(#10432)
impl Seek for MemWriter { 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 // compute offset as signed and clamp to prevent overflow
let offset = match style { let offset = match style {
SeekSet => { 0 } SeekSet => { 0 }
@ -102,6 +104,7 @@ impl Seek for MemWriter {
} as i64; } as i64;
self.pos = max(0, offset+pos) as uint; self.pos = max(0, offset+pos) as uint;
Ok(())
} }
} }
@ -148,8 +151,8 @@ impl MemReader {
} }
impl Reader for MemReader { impl Reader for MemReader {
fn read(&mut self, buf: &mut [u8]) -> Option<uint> { fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
if self.eof() { return None } if self.eof() { return Err(io::standard_error(io::EndOfFile)) }
let write_len = min(buf.len(), self.buf.len() - self.pos); let write_len = min(buf.len(), self.buf.len() - self.pos);
{ {
@ -161,17 +164,19 @@ impl Reader for MemReader {
self.pos += write_len; self.pos += write_len;
assert!(self.pos <= self.buf.len()); assert!(self.pos <= self.buf.len());
return Some(write_len); return Ok(write_len);
} }
} }
impl Seek for MemReader { impl Seek for MemReader {
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) { fail!() } fn seek(&mut self, _pos: i64, _style: SeekStyle) -> IoResult<()> { fail!() }
} }
impl Buffer for MemReader { 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; } fn consume(&mut self, amt: uint) { self.pos += amt; }
} }
@ -207,28 +212,28 @@ impl<'a> BufWriter<'a> {
} }
impl<'a> Writer for 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 // raises a condition if the entire write does not fit in the buffer
let max_size = self.buf.len(); let max_size = self.buf.len();
if self.pos >= max_size || (self.pos + buf.len()) > max_size { if self.pos >= max_size || (self.pos + buf.len()) > max_size {
io_error::cond.raise(IoError { return Err(IoError {
kind: OtherIoError, kind: io::OtherIoError,
desc: "Trying to write past end of buffer", desc: "Trying to write past end of buffer",
detail: None detail: None
}); })
return;
} }
vec::bytes::copy_memory(self.buf.mut_slice_from(self.pos), buf); vec::bytes::copy_memory(self.buf.mut_slice_from(self.pos), buf);
self.pos += buf.len(); self.pos += buf.len();
Ok(())
} }
} }
// FIXME(#10432) // FIXME(#10432)
impl<'a> Seek for BufWriter<'a> { 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 // compute offset as signed and clamp to prevent overflow
let offset = match style { let offset = match style {
SeekSet => { 0 } SeekSet => { 0 }
@ -237,6 +242,7 @@ impl<'a> Seek for BufWriter<'a> {
} as i64; } as i64;
self.pos = max(0, offset+pos) as uint; self.pos = max(0, offset+pos) as uint;
Ok(())
} }
} }
@ -274,8 +280,8 @@ impl<'a> BufReader<'a> {
} }
impl<'a> Reader for BufReader<'a> { impl<'a> Reader for BufReader<'a> {
fn read(&mut self, buf: &mut [u8]) -> Option<uint> { fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
if self.eof() { return None } if self.eof() { return Err(io::standard_error(io::EndOfFile)) }
let write_len = min(buf.len(), self.buf.len() - self.pos); 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; self.pos += write_len;
assert!(self.pos <= self.buf.len()); assert!(self.pos <= self.buf.len());
return Some(write_len); return Ok(write_len);
} }
} }
impl<'a> Seek for BufReader<'a> { impl<'a> Seek for BufReader<'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) -> IoResult<()> { fail!() }
fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
} }
impl<'a> Buffer for BufReader<'a> { 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; } fn consume(&mut self, amt: uint) { self.pos += amt; }
} }
@ -388,7 +395,7 @@ mod test {
let mut called = false; let mut called = false;
io_error::cond.trap(|err| { io_error::cond.trap(|err| {
assert_eq!(err.kind, OtherIoError); assert_eq!(err.kind, io::OtherIoError);
called = true; called = true;
}).inside(|| { }).inside(|| {
writer.write([0, 0]); writer.write([0, 0]);

View file

@ -290,15 +290,15 @@ Out of scope
use cast; use cast;
use char::Char; use char::Char;
use condition::Guard;
use container::Container; use container::Container;
use fmt;
use int; use int;
use iter::Iterator; use iter::Iterator;
use option::{Option, Some, None}; use option::{Option, Some, None};
use path::Path; use path::Path;
use result::{Ok, Err, Result}; use result::{Ok, Err, Result};
use str;
use str::{StrSlice, OwnedStr}; use str::{StrSlice, OwnedStr};
use str;
use to_str::ToStr; use to_str::ToStr;
use uint; use uint;
use unstable::finally::Finally; use unstable::finally::Finally;
@ -347,8 +347,8 @@ mod mem;
/// Non-blocking access to stdin, stdout, stderr /// Non-blocking access to stdin, stdout, stderr
pub mod stdio; pub mod stdio;
/// Implementations for Option /// Implementations for Result
mod option; mod result;
/// Extension traits /// Extension traits
pub mod extensions; pub mod extensions;
@ -373,17 +373,30 @@ mod comm_adapters;
// https://groups.google.com/forum/#!topic/libuv/oQO1HJAIDdA // https://groups.google.com/forum/#!topic/libuv/oQO1HJAIDdA
static DEFAULT_BUF_SIZE: uint = 1024 * 64; 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 /// The type passed to I/O condition handlers to indicate error
/// ///
/// # FIXME /// # FIXME
/// ///
/// Is something like this sufficient? It's kind of archaic /// Is something like this sufficient? It's kind of archaic
#[deriving(Eq, Clone)]
pub struct IoError { pub struct IoError {
kind: IoErrorKind, kind: IoErrorKind,
desc: &'static str, desc: &'static str,
detail: Option<~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 // FIXME: #8242 implementing manually because deriving doesn't work for some reason
impl ToStr for IoError { impl ToStr for IoError {
fn to_str(&self) -> ~str { fn to_str(&self) -> ~str {
@ -398,9 +411,8 @@ impl ToStr for IoError {
} }
} }
#[deriving(Eq)] #[deriving(Eq, Clone)]
pub enum IoErrorKind { pub enum IoErrorKind {
PreviousIoError,
OtherIoError, OtherIoError,
EndOfFile, EndOfFile,
FileNotFound, FileNotFound,
@ -424,7 +436,6 @@ pub enum IoErrorKind {
impl ToStr for IoErrorKind { impl ToStr for IoErrorKind {
fn to_str(&self) -> ~str { fn to_str(&self) -> ~str {
match *self { match *self {
PreviousIoError => ~"PreviousIoError",
OtherIoError => ~"OtherIoError", OtherIoError => ~"OtherIoError",
EndOfFile => ~"EndOfFile", EndOfFile => ~"EndOfFile",
FileNotFound => ~"FileNotFound", 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 { pub trait Reader {
// Only two methods which need to get implemented for this trait // 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 /// Will people often need to slice their vectors to call this
/// and will that be annoying? /// and will that be annoying?
/// Is it actually possible for 0 bytes to be read successfully? /// 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 // Convenient helper methods based on the above methods
@ -514,16 +493,17 @@ pub trait Reader {
/// ///
/// Raises the same conditions as the `read` method. Returns /// Raises the same conditions as the `read` method. Returns
/// `None` if the condition is handled. /// `None` if the condition is handled.
fn read_byte(&mut self) -> Option<u8> { fn read_byte(&mut self) -> IoResult<u8> {
let mut buf = [0]; let mut buf = [0];
loop {
match self.read(buf) { match self.read(buf) {
Some(0) => { Ok(0) => {
debug!("read 0 bytes. trying again"); debug!("read 0 bytes. trying again");
self.read_byte()
} }
Some(1) => Some(buf[0]), Ok(1) => return Ok(buf[0]),
Some(_) => unreachable!(), Ok(_) => unreachable!(),
None => None Err(e) => return Err(e)
}
} }
} }
@ -537,30 +517,26 @@ pub trait Reader {
/// Raises the same conditions as `read`. Additionally raises `io_error` /// Raises the same conditions as `read`. Additionally raises `io_error`
/// on EOF. If `io_error` is handled then `push_bytes` may push less /// on EOF. If `io_error` is handled then `push_bytes` may push less
/// than the requested number of bytes. /// than the requested number of bytes.
fn push_bytes(&mut self, buf: &mut ~[u8], len: uint) { fn push_bytes(&mut self, buf: &mut ~[u8], len: uint) -> IoResult<()> {
unsafe {
let start_len = buf.len(); let start_len = buf.len();
let mut total_read = 0; let mut total_read = 0;
buf.reserve_additional(len); buf.reserve_additional(len);
buf.set_len(start_len + len); unsafe { buf.set_len(start_len + len); }
(|| { (|| {
while total_read < len { while total_read < len {
let len = buf.len(); let len = buf.len();
let slice = buf.mut_slice(start_len + total_read, len); let slice = buf.mut_slice(start_len + total_read, len);
match self.read(slice) { match self.read(slice) {
Some(nread) => { Ok(nread) => {
total_read += nread; total_read += nread;
} }
None => { Err(e) => return Err(e)
io_error::cond.raise(standard_error(EndOfFile));
break;
} }
} }
} Ok(())
}).finally(|| buf.set_len(start_len + total_read)) }).finally(|| unsafe { buf.set_len(start_len + total_read) })
}
} }
/// Reads `len` bytes and gives you back a new vector of length `len` /// 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` /// Raises the same conditions as `read`. Additionally raises `io_error`
/// on EOF. If `io_error` is handled then the returned vector may /// on EOF. If `io_error` is handled then the returned vector may
/// contain less than the requested number of bytes. /// 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); let mut buf = vec::with_capacity(len);
self.push_bytes(&mut buf, len); if_ok!(self.push_bytes(&mut buf, len));
return buf; return Ok(buf);
} }
/// Reads all remaining bytes from the stream. /// Reads all remaining bytes from the stream.
@ -582,21 +558,16 @@ pub trait Reader {
/// ///
/// Raises the same conditions as the `read` method except for /// Raises the same conditions as the `read` method except for
/// `EndOfFile` which is swallowed. /// `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 buf = vec::with_capacity(DEFAULT_BUF_SIZE);
let mut keep_reading = true; loop {
io_error::cond.trap(|e| { match self.push_bytes(&mut buf, DEFAULT_BUF_SIZE) {
if e.kind == EndOfFile { Ok(()) => {}
keep_reading = false; Err(ref e) if e.kind == EndOfFile => break,
} else { Err(e) => return Err(e)
io_error::cond.raise(e)
} }
}).inside(|| {
while keep_reading {
self.push_bytes(&mut buf, DEFAULT_BUF_SIZE)
} }
}); return Ok(buf);
return buf;
} }
/// Reads all of the remaining bytes of this stream, interpreting them as a /// 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, /// 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. /// along with raising a condition if the input is not valid UTF-8.
fn read_to_str(&mut self) -> ~str { fn read_to_str(&mut self) -> IoResult<~str> {
match str::from_utf8_owned(self.read_to_end()) { self.read_to_end().and_then(|s| {
Some(s) => s, match str::from_utf8_owned(s) {
None => { Some(s) => Ok(s),
io_error::cond.raise(standard_error(InvalidInput)); None => Err(standard_error(InvalidInput)),
~""
}
} }
})
} }
/// Create an iterator that reads a single byte on /// Create an iterator that reads a single byte on
@ -633,225 +603,219 @@ pub trait Reader {
/// Reads `n` little-endian unsigned integer bytes. /// Reads `n` little-endian unsigned integer bytes.
/// ///
/// `n` must be between 1 and 8, inclusive. /// `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); assert!(nbytes > 0 && nbytes <= 8);
let mut val = 0u64; let mut val = 0u64;
let mut pos = 0; let mut pos = 0;
let mut i = nbytes; let mut i = nbytes;
while i > 0 { while i > 0 {
val += (self.read_u8() as u64) << pos; val += (if_ok!(self.read_u8()) as u64) << pos;
pos += 8; pos += 8;
i -= 1; i -= 1;
} }
val Ok(val)
} }
/// Reads `n` little-endian signed integer bytes. /// Reads `n` little-endian signed integer bytes.
/// ///
/// `n` must be between 1 and 8, inclusive. /// `n` must be between 1 and 8, inclusive.
fn read_le_int_n(&mut self, nbytes: uint) -> i64 { fn read_le_int_n(&mut self, nbytes: uint) -> IoResult<i64> {
extend_sign(self.read_le_uint_n(nbytes), nbytes) self.read_le_uint_n(nbytes).map(|i| extend_sign(i, nbytes))
} }
/// Reads `n` big-endian unsigned integer bytes. /// Reads `n` big-endian unsigned integer bytes.
/// ///
/// `n` must be between 1 and 8, inclusive. /// `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); assert!(nbytes > 0 && nbytes <= 8);
let mut val = 0u64; let mut val = 0u64;
let mut i = nbytes; let mut i = nbytes;
while i > 0 { while i > 0 {
i -= 1; 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. /// Reads `n` big-endian signed integer bytes.
/// ///
/// `n` must be between 1 and 8, inclusive. /// `n` must be between 1 and 8, inclusive.
fn read_be_int_n(&mut self, nbytes: uint) -> i64 { fn read_be_int_n(&mut self, nbytes: uint) -> IoResult<i64> {
extend_sign(self.read_be_uint_n(nbytes), nbytes) self.read_be_uint_n(nbytes).map(|i| extend_sign(i, nbytes))
} }
/// Reads a little-endian unsigned integer. /// Reads a little-endian unsigned integer.
/// ///
/// The number of bytes returned is system-dependant. /// The number of bytes returned is system-dependant.
fn read_le_uint(&mut self) -> uint { fn read_le_uint(&mut self) -> IoResult<uint> {
self.read_le_uint_n(uint::BYTES) as uint self.read_le_uint_n(uint::BYTES).map(|i| i as uint)
} }
/// Reads a little-endian integer. /// Reads a little-endian integer.
/// ///
/// The number of bytes returned is system-dependant. /// The number of bytes returned is system-dependant.
fn read_le_int(&mut self) -> int { fn read_le_int(&mut self) -> IoResult<int> {
self.read_le_int_n(int::BYTES) as int self.read_le_int_n(int::BYTES).map(|i| i as int)
} }
/// Reads a big-endian unsigned integer. /// Reads a big-endian unsigned integer.
/// ///
/// The number of bytes returned is system-dependant. /// The number of bytes returned is system-dependant.
fn read_be_uint(&mut self) -> uint { fn read_be_uint(&mut self) -> IoResult<uint> {
self.read_be_uint_n(uint::BYTES) as uint self.read_be_uint_n(uint::BYTES).map(|i| i as uint)
} }
/// Reads a big-endian integer. /// Reads a big-endian integer.
/// ///
/// The number of bytes returned is system-dependant. /// The number of bytes returned is system-dependant.
fn read_be_int(&mut self) -> int { fn read_be_int(&mut self) -> IoResult<int> {
self.read_be_int_n(int::BYTES) as int self.read_be_int_n(int::BYTES).map(|i| i as int)
} }
/// Reads a big-endian `u64`. /// Reads a big-endian `u64`.
/// ///
/// `u64`s are 8 bytes long. /// `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) self.read_be_uint_n(8)
} }
/// Reads a big-endian `u32`. /// Reads a big-endian `u32`.
/// ///
/// `u32`s are 4 bytes long. /// `u32`s are 4 bytes long.
fn read_be_u32(&mut self) -> u32 { fn read_be_u32(&mut self) -> IoResult<u32> {
self.read_be_uint_n(4) as u32 self.read_be_uint_n(4).map(|i| i as u32)
} }
/// Reads a big-endian `u16`. /// Reads a big-endian `u16`.
/// ///
/// `u16`s are 2 bytes long. /// `u16`s are 2 bytes long.
fn read_be_u16(&mut self) -> u16 { fn read_be_u16(&mut self) -> IoResult<u16> {
self.read_be_uint_n(2) as u16 self.read_be_uint_n(2).map(|i| i as u16)
} }
/// Reads a big-endian `i64`. /// Reads a big-endian `i64`.
/// ///
/// `i64`s are 8 bytes long. /// `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) self.read_be_int_n(8)
} }
/// Reads a big-endian `i32`. /// Reads a big-endian `i32`.
/// ///
/// `i32`s are 4 bytes long. /// `i32`s are 4 bytes long.
fn read_be_i32(&mut self) -> i32 { fn read_be_i32(&mut self) -> IoResult<i32> {
self.read_be_int_n(4) as i32 self.read_be_int_n(4).map(|i| i as i32)
} }
/// Reads a big-endian `i16`. /// Reads a big-endian `i16`.
/// ///
/// `i16`s are 2 bytes long. /// `i16`s are 2 bytes long.
fn read_be_i16(&mut self) -> i16 { fn read_be_i16(&mut self) -> IoResult<i16> {
self.read_be_int_n(2) as i16 self.read_be_int_n(2).map(|i| i as i16)
} }
/// Reads a big-endian `f64`. /// Reads a big-endian `f64`.
/// ///
/// `f64`s are 8 byte, IEEE754 double-precision floating point numbers. /// `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
fn read_be_f64(&mut self) -> f64 { fn read_be_f64(&mut self) -> IoResult<f64> {
unsafe { self.read_be_u64().map(|i| unsafe {
cast::transmute::<u64, f64>(self.read_be_u64()) cast::transmute::<u64, f64>(i)
} })
} }
/// Reads a big-endian `f32`. /// Reads a big-endian `f32`.
/// ///
/// `f32`s are 4 byte, IEEE754 single-precision floating point numbers. /// `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
fn read_be_f32(&mut self) -> f32 { fn read_be_f32(&mut self) -> IoResult<f32> {
unsafe { self.read_be_u32().map(|i| unsafe {
cast::transmute::<u32, f32>(self.read_be_u32()) cast::transmute::<u32, f32>(i)
} })
} }
/// Reads a little-endian `u64`. /// Reads a little-endian `u64`.
/// ///
/// `u64`s are 8 bytes long. /// `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) self.read_le_uint_n(8)
} }
/// Reads a little-endian `u32`. /// Reads a little-endian `u32`.
/// ///
/// `u32`s are 4 bytes long. /// `u32`s are 4 bytes long.
fn read_le_u32(&mut self) -> u32 { fn read_le_u32(&mut self) -> IoResult<u32> {
self.read_le_uint_n(4) as u32 self.read_le_uint_n(4).map(|i| i as u32)
} }
/// Reads a little-endian `u16`. /// Reads a little-endian `u16`.
/// ///
/// `u16`s are 2 bytes long. /// `u16`s are 2 bytes long.
fn read_le_u16(&mut self) -> u16 { fn read_le_u16(&mut self) -> IoResult<u16> {
self.read_le_uint_n(2) as u16 self.read_le_uint_n(2).map(|i| i as u16)
} }
/// Reads a little-endian `i64`. /// Reads a little-endian `i64`.
/// ///
/// `i64`s are 8 bytes long. /// `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) self.read_le_int_n(8)
} }
/// Reads a little-endian `i32`. /// Reads a little-endian `i32`.
/// ///
/// `i32`s are 4 bytes long. /// `i32`s are 4 bytes long.
fn read_le_i32(&mut self) -> i32 { fn read_le_i32(&mut self) -> IoResult<i32> {
self.read_le_int_n(4) as i32 self.read_le_int_n(4).map(|i| i as i32)
} }
/// Reads a little-endian `i16`. /// Reads a little-endian `i16`.
/// ///
/// `i16`s are 2 bytes long. /// `i16`s are 2 bytes long.
fn read_le_i16(&mut self) -> i16 { fn read_le_i16(&mut self) -> IoResult<i16> {
self.read_le_int_n(2) as i16 self.read_le_int_n(2).map(|i| i as i16)
} }
/// Reads a little-endian `f64`. /// Reads a little-endian `f64`.
/// ///
/// `f64`s are 8 byte, IEEE754 double-precision floating point numbers. /// `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
fn read_le_f64(&mut self) -> f64 { fn read_le_f64(&mut self) -> IoResult<f64> {
unsafe { self.read_le_u64().map(|i| unsafe {
cast::transmute::<u64, f64>(self.read_le_u64()) cast::transmute::<u64, f64>(i)
} })
} }
/// Reads a little-endian `f32`. /// Reads a little-endian `f32`.
/// ///
/// `f32`s are 4 byte, IEEE754 single-precision floating point numbers. /// `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
fn read_le_f32(&mut self) -> f32 { fn read_le_f32(&mut self) -> IoResult<f32> {
unsafe { self.read_le_u32().map(|i| unsafe {
cast::transmute::<u32, f32>(self.read_le_u32()) cast::transmute::<u32, f32>(i)
} })
} }
/// Read a u8. /// Read a u8.
/// ///
/// `u8`s are 1 byte. /// `u8`s are 1 byte.
fn read_u8(&mut self) -> u8 { fn read_u8(&mut self) -> IoResult<u8> {
match self.read_byte() { self.read_byte()
Some(b) => b,
None => 0
}
} }
/// Read an i8. /// Read an i8.
/// ///
/// `i8`s are 1 byte. /// `i8`s are 1 byte.
fn read_i8(&mut self) -> i8 { fn read_i8(&mut self) -> IoResult<i8> {
match self.read_byte() { self.read_byte().map(|i| i as i8)
Some(b) => b as i8,
None => 0
}
} }
} }
impl Reader for ~Reader { 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 { 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 { fn extend_sign(val: u64, nbytes: uint) -> i64 {
@ -865,14 +829,14 @@ pub trait Writer {
/// # Failure /// # Failure
/// ///
/// Raises the `io_error` condition on error /// 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 /// Flush this output stream, ensuring that all intermediately buffered
/// contents reach their destination. /// contents reach their destination.
/// ///
/// This is by default a no-op and implementers of the `Writer` trait should /// This is by default a no-op and implementers of the `Writer` trait should
/// decide whether their stream needs to be buffered or not. /// 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. /// 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 /// If other encodings are desired, it is recommended to compose this stream
/// with another performing the conversion, or to use `write` with a /// with another performing the conversion, or to use `write` with a
/// converted byte-array instead. /// converted byte-array instead.
fn write_str(&mut self, s: &str) { fn write_str(&mut self, s: &str) -> IoResult<()> {
self.write(s.as_bytes()); self.write(s.as_bytes())
} }
/// Writes a string into this sink, and then writes a literal newline (`\n`) /// 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 /// If other encodings or line ending flavors are desired, it is recommended
/// that the `write` method is used specifically instead. /// that the `write` method is used specifically instead.
fn write_line(&mut self, s: &str) { fn write_line(&mut self, s: &str) -> IoResult<()> {
self.write_str(s); self.write_str(s).and_then(|()| self.write(['\n' as u8]))
self.write(['\n' as u8]);
} }
/// Write a single char, encoded as UTF-8. /// 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 mut buf = [0u8, ..4];
let n = c.encode_utf8(buf.as_mut_slice()); 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`. /// 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)) int::to_str_bytes(n, 10u, |bytes| self.write(bytes))
} }
/// Write the result of passing n through `uint::to_str_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)) uint::to_str_bytes(n, 10u, |bytes| self.write(bytes))
} }
/// Write a little-endian uint (number of bytes depends on system). /// 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)) 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). /// 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)) 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). /// 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)) 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). /// 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)) extensions::u64_to_be_bytes(n as u64, int::BYTES, |v| self.write(v))
} }
/// Write a big-endian u64 (8 bytes). /// 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)) extensions::u64_to_be_bytes(n, 8u, |v| self.write(v))
} }
/// Write a big-endian u32 (4 bytes). /// 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)) extensions::u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
} }
/// Write a big-endian u16 (2 bytes). /// 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)) extensions::u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
} }
/// Write a big-endian i64 (8 bytes). /// 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)) extensions::u64_to_be_bytes(n as u64, 8u, |v| self.write(v))
} }
/// Write a big-endian i32 (4 bytes). /// 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)) extensions::u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
} }
/// Write a big-endian i16 (2 bytes). /// 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)) extensions::u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
} }
/// Write a big-endian IEEE754 double-precision floating-point (8 bytes). /// 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 { unsafe {
self.write_be_u64(cast::transmute(f)) self.write_be_u64(cast::transmute(f))
} }
} }
/// Write a big-endian IEEE754 single-precision floating-point (4 bytes). /// 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 { unsafe {
self.write_be_u32(cast::transmute(f)) self.write_be_u32(cast::transmute(f))
} }
} }
/// Write a little-endian u64 (8 bytes). /// 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)) extensions::u64_to_le_bytes(n, 8u, |v| self.write(v))
} }
/// Write a little-endian u32 (4 bytes). /// 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)) extensions::u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
} }
/// Write a little-endian u16 (2 bytes). /// 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)) extensions::u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
} }
/// Write a little-endian i64 (8 bytes). /// 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)) extensions::u64_to_le_bytes(n as u64, 8u, |v| self.write(v))
} }
/// Write a little-endian i32 (4 bytes). /// 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)) extensions::u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
} }
/// Write a little-endian i16 (2 bytes). /// 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)) extensions::u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
} }
/// Write a little-endian IEEE754 double-precision floating-point /// Write a little-endian IEEE754 double-precision floating-point
/// (8 bytes). /// (8 bytes).
fn write_le_f64(&mut self, f: f64) { fn write_le_f64(&mut self, f: f64) -> IoResult<()> {
unsafe { unsafe {
self.write_le_u64(cast::transmute(f)) self.write_le_u64(cast::transmute(f))
} }
@ -1017,31 +980,31 @@ pub trait Writer {
/// Write a little-endian IEEE754 single-precision floating-point /// Write a little-endian IEEE754 single-precision floating-point
/// (4 bytes). /// (4 bytes).
fn write_le_f32(&mut self, f: f32) { fn write_le_f32(&mut self, f: f32) -> IoResult<()> {
unsafe { unsafe {
self.write_le_u32(cast::transmute(f)) self.write_le_u32(cast::transmute(f))
} }
} }
/// Write a u8 (1 byte). /// Write a u8 (1 byte).
fn write_u8(&mut self, n: u8) { fn write_u8(&mut self, n: u8) -> IoResult<()> {
self.write([n]) self.write([n])
} }
/// Write a i8 (1 byte). /// 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]) self.write([n as u8])
} }
} }
impl Writer for ~Writer { impl Writer for ~Writer {
fn write(&mut self, buf: &[u8]) { self.write(buf) } fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.write(buf) }
fn flush(&mut self) { self.flush() } fn flush(&mut self) -> IoResult<()> { self.flush() }
} }
impl<'a> Writer for &'a mut Writer { impl<'a> Writer for &'a mut Writer {
fn write(&mut self, buf: &[u8]) { self.write(buf) } fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.write(buf) }
fn flush(&mut self) { self.flush() } fn flush(&mut self) -> IoResult<()> { self.flush() }
} }
pub trait Stream: Reader + Writer { } pub trait Stream: Reader + Writer { }
@ -1068,7 +1031,7 @@ pub struct Lines<'r, T> {
impl<'r, T: Buffer> Iterator<~str> for Lines<'r, T> { impl<'r, T: Buffer> Iterator<~str> for Lines<'r, T> {
fn next(&mut self) -> Option<~str> { 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 /// This function will raise on the `io_error` condition if a read error is
/// encountered. /// 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, /// 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`. /// 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. /// `EndOfFile` which is swallowed) if a read error is encountered.
/// The task will also fail if sequence of bytes leading up to /// The task will also fail if sequence of bytes leading up to
/// the newline character are not valid UTF-8. /// 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()) self.read_until('\n' as u8).map(|line| str::from_utf8_owned(line).unwrap())
} }
@ -1140,18 +1103,13 @@ pub trait Buffer: Reader {
/// ///
/// This function will raise on the `io_error` condition if a read error is /// This function will raise on the `io_error` condition if a read error is
/// encountered, except that `EndOfFile` is swallowed. /// 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 = ~[]; let mut res = ~[];
io_error::cond.trap(|e| {
if e.kind != EndOfFile {
io_error::cond.raise(e);
}
}).inside(|| {
let mut used; let mut used;
loop { loop {
{ {
let available = self.fill(); let available = if_ok!(self.fill());
match available.iter().position(|&b| b == byte) { match available.iter().position(|&b| b == byte) {
Some(i) => { Some(i) => {
res.push_all(available.slice_to(i + 1)); res.push_all(available.slice_to(i + 1));
@ -1170,9 +1128,7 @@ pub trait Buffer: Reader {
self.consume(used); self.consume(used);
} }
self.consume(used); self.consume(used);
}); Ok(res)
return if res.len() == 0 {None} else {Some(res)};
} }
/// Reads the next utf8-encoded character from the underlying stream. /// 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 /// This function will raise on the `io_error` condition if a read error is
/// encountered. /// encountered.
fn read_char(&mut self) -> Option<char> { fn read_char(&mut self) -> IoResult<char> {
let width = { let width = {
let available = self.fill(); let available = if_ok!(self.fill());
if available.len() == 0 { return None } // read error
str::utf8_char_width(available[0]) 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 buf = [0, ..4];
{ {
let mut start = 0; let mut start = 0;
loop { loop {
match self.read(buf.mut_slice(start, width)) { match if_ok!(self.read(buf.mut_slice(start, width))) {
Some(n) if n == width - start => break, n if n == width - start => break,
Some(n) if n < width - start => { start += n; } n if n < width - start => { start += n; }
Some(..) | None => return None // read error _ => return Err(standard_error(InvalidInput)),
} }
} }
} }
match str::from_utf8(buf.slice_to(width)) { match str::from_utf8(buf.slice_to(width)) {
Some(s) => Some(s.char_at(0)), Some(s) => Ok(s.char_at(0)),
None => None None => Err(standard_error(InvalidInput))
} }
} }
} }
@ -1222,7 +1177,7 @@ pub enum SeekStyle {
/// * Are `u64` and `i64` the right choices? /// * Are `u64` and `i64` the right choices?
pub trait Seek { pub trait Seek {
/// Return position of file cursor in the stream /// Return position of file cursor in the stream
fn tell(&self) -> u64; fn tell(&self) -> IoResult<u64>;
/// Seek to an offset in a stream /// Seek to an offset in a stream
/// ///
@ -1231,7 +1186,7 @@ pub trait Seek {
/// # FIXME /// # FIXME
/// ///
/// * What is the behavior when seeking past the end of a stream? /// * 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. /// 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, /// Raises `io_error` condition. If the condition is handled,
/// then `listen` returns `None`. /// then `listen` returns `None`.
fn listen(self) -> Option<A>; fn listen(self) -> IoResult<A>;
} }
/// An acceptor is a value that presents incoming connections /// An acceptor is a value that presents incoming connections
@ -1253,7 +1208,7 @@ pub trait Acceptor<T> {
/// # Failure /// # Failure
/// Raise `io_error` condition. If the condition is handled, /// Raise `io_error` condition. If the condition is handled,
/// then `accept` returns `None`. /// then `accept` returns `None`.
fn accept(&mut self) -> Option<T>; fn accept(&mut self) -> IoResult<T>;
/// Create an iterator over incoming connection attempts /// Create an iterator over incoming connection attempts
fn incoming<'r>(&'r mut self) -> IncomingConnections<'r, Self> { fn incoming<'r>(&'r mut self) -> IncomingConnections<'r, Self> {
@ -1272,15 +1227,14 @@ pub struct IncomingConnections<'a, A> {
priv inc: &'a mut A, priv inc: &'a mut A,
} }
impl<'a, T, A: Acceptor<T>> Iterator<Option<T>> for IncomingConnections<'a, A> { impl<'a, T, A: Acceptor<T>> Iterator<IoResult<T>> for IncomingConnections<'a, A> {
fn next(&mut self) -> Option<Option<T>> { fn next(&mut self) -> Option<IoResult<T>> {
Some(self.inc.accept()) Some(self.inc.accept())
} }
} }
pub fn standard_error(kind: IoErrorKind) -> IoError { pub fn standard_error(kind: IoErrorKind) -> IoError {
let desc = match kind { let desc = match kind {
PreviousIoError => "failing due to previous I/O error",
EndOfFile => "end of file", EndOfFile => "end of file",
IoUnavailable => "I/O is unavailable", IoUnavailable => "I/O is unavailable",
InvalidInput => "invalid input", InvalidInput => "invalid input",

View file

@ -17,8 +17,9 @@ getaddrinfo()
*/ */
use option::{Option, Some, None}; use io::IoResult;
use io::net::ip::{SocketAddr, IpAddr}; use io::net::ip::{SocketAddr, IpAddr};
use option::{Option, Some, None};
use rt::rtio::{IoFactory, LocalIo}; use rt::rtio::{IoFactory, LocalIo};
use vec::ImmutableVector; use vec::ImmutableVector;
@ -73,7 +74,7 @@ pub struct Info {
/// # Failure /// # Failure
/// ///
/// On failure, this will raise on the `io_error` condition. /// 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)) 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 /// FIXME: this is not public because the `Hint` structure is not ready for public
/// consumption just yet. /// consumption just yet.
fn lookup(hostname: Option<&str>, servname: Option<&str>, hint: Option<Hint>) 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)) LocalIo::maybe_raise(|io| io.get_host_addresses(hostname, servname, hint))
} }

View file

@ -8,11 +8,8 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use option::{Option, Some, None};
use result::{Ok, Err};
use io::net::ip::SocketAddr; use io::net::ip::SocketAddr;
use io::{Reader, Writer, Listener, Acceptor}; use io::{Reader, Writer, Listener, Acceptor, IoResult};
use io::{io_error, EndOfFile};
use rt::rtio::{IoFactory, LocalIo, RtioSocket, RtioTcpListener}; use rt::rtio::{IoFactory, LocalIo, RtioSocket, RtioTcpListener};
use rt::rtio::{RtioTcpAcceptor, RtioTcpStream}; use rt::rtio::{RtioTcpAcceptor, RtioTcpStream};
@ -25,57 +22,27 @@ impl TcpStream {
TcpStream { obj: s } TcpStream { obj: s }
} }
pub fn connect(addr: SocketAddr) -> Option<TcpStream> { pub fn connect(addr: SocketAddr) -> IoResult<TcpStream> {
LocalIo::maybe_raise(|io| { LocalIo::maybe_raise(|io| {
io.tcp_connect(addr).map(TcpStream::new) io.tcp_connect(addr).map(TcpStream::new)
}) })
} }
pub fn peer_name(&mut self) -> Option<SocketAddr> { pub fn peer_name(&mut self) -> IoResult<SocketAddr> {
match self.obj.peer_name() { 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 socket_name(&mut self) -> Option<SocketAddr> { pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
match self.obj.socket_name() { self.obj.socket_name()
Ok(sn) => Some(sn),
Err(ioerr) => {
debug!("failed to get socket name: {:?}", ioerr);
io_error::cond.raise(ioerr);
None
}
}
} }
} }
impl Reader for TcpStream { impl Reader for TcpStream {
fn read(&mut self, buf: &mut [u8]) -> Option<uint> { fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { self.obj.read(buf) }
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;
}
}
}
} }
impl Writer for TcpStream { impl Writer for TcpStream {
fn write(&mut self, buf: &[u8]) { fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.obj.write(buf) }
match self.obj.write(buf) {
Ok(_) => (),
Err(ioerr) => io_error::cond.raise(ioerr),
}
}
} }
pub struct TcpListener { pub struct TcpListener {
@ -83,33 +50,20 @@ pub struct TcpListener {
} }
impl TcpListener { impl TcpListener {
pub fn bind(addr: SocketAddr) -> Option<TcpListener> { pub fn bind(addr: SocketAddr) -> IoResult<TcpListener> {
LocalIo::maybe_raise(|io| { LocalIo::maybe_raise(|io| {
io.tcp_bind(addr).map(|l| TcpListener { obj: l }) io.tcp_bind(addr).map(|l| TcpListener { obj: l })
}) })
} }
pub fn socket_name(&mut self) -> Option<SocketAddr> { pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
match self.obj.socket_name() { self.obj.socket_name()
Ok(sn) => Some(sn),
Err(ioerr) => {
debug!("failed to get socket name: {:?}", ioerr);
io_error::cond.raise(ioerr);
None
}
}
} }
} }
impl Listener<TcpStream, TcpAcceptor> for TcpListener { impl Listener<TcpStream, TcpAcceptor> for TcpListener {
fn listen(self) -> Option<TcpAcceptor> { fn listen(self) -> IoResult<TcpAcceptor> {
match self.obj.listen() { self.obj.listen().map(|acceptor| TcpAcceptor { obj: acceptor })
Ok(acceptor) => Some(TcpAcceptor { obj: acceptor }),
Err(ioerr) => {
io_error::cond.raise(ioerr);
None
}
}
} }
} }
@ -118,14 +72,8 @@ pub struct TcpAcceptor {
} }
impl Acceptor<TcpStream> for TcpAcceptor { impl Acceptor<TcpStream> for TcpAcceptor {
fn accept(&mut self) -> Option<TcpStream> { fn accept(&mut self) -> IoResult<TcpStream> {
match self.obj.accept() { self.obj.accept().map(TcpStream::new)
Ok(s) => Some(TcpStream::new(s)),
Err(ioerr) => {
io_error::cond.raise(ioerr);
None
}
}
} }
} }

View file

@ -8,11 +8,9 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use option::{Option, Some, None};
use result::{Ok, Err}; use result::{Ok, Err};
use io::net::ip::SocketAddr; use io::net::ip::SocketAddr;
use io::{Reader, Writer}; use io::{Reader, Writer, IoResult};
use io::{io_error, EndOfFile};
use rt::rtio::{RtioSocket, RtioUdpSocket, IoFactory, LocalIo}; use rt::rtio::{RtioSocket, RtioUdpSocket, IoFactory, LocalIo};
pub struct UdpSocket { pub struct UdpSocket {
@ -20,45 +18,26 @@ pub struct UdpSocket {
} }
impl UdpSocket { impl UdpSocket {
pub fn bind(addr: SocketAddr) -> Option<UdpSocket> { pub fn bind(addr: SocketAddr) -> IoResult<UdpSocket> {
LocalIo::maybe_raise(|io| { LocalIo::maybe_raise(|io| {
io.udp_bind(addr).map(|s| UdpSocket { obj: s }) io.udp_bind(addr).map(|s| UdpSocket { obj: s })
}) })
} }
pub fn recvfrom(&mut self, buf: &mut [u8]) -> Option<(uint, SocketAddr)> { pub fn recvfrom(&mut self, buf: &mut [u8]) -> IoResult<(uint, SocketAddr)> {
match self.obj.recvfrom(buf) { 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 sendto(&mut self, buf: &[u8], dst: SocketAddr) { pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
match self.obj.sendto(buf, dst) { self.obj.sendto(buf, dst)
Ok(_) => (),
Err(ioerr) => io_error::cond.raise(ioerr),
}
} }
pub fn connect(self, other: SocketAddr) -> UdpStream { pub fn connect(self, other: SocketAddr) -> UdpStream {
UdpStream { socket: self, connectedTo: other } UdpStream { socket: self, connectedTo: other }
} }
pub fn socket_name(&mut self) -> Option<SocketAddr> { pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
match self.obj.socket_name() { self.obj.socket_name()
Ok(sn) => Some(sn),
Err(ioerr) => {
debug!("failed to get socket name: {:?}", ioerr);
io_error::cond.raise(ioerr);
None
}
}
} }
} }
@ -76,21 +55,21 @@ impl UdpStream {
} }
impl Reader for 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; let peer = self.connectedTo;
self.as_socket(|sock| { self.as_socket(|sock| {
match sock.recvfrom(buf) { match sock.recvfrom(buf) {
Some((_nread, src)) if src != peer => Some(0), Ok((_nread, src)) if src != peer => Ok(0),
Some((nread, _src)) => Some(nread), Ok((nread, _src)) => Ok(nread),
None => None, Err(e) => Err(e),
} }
}) })
} }
} }
impl Writer for UdpStream { impl Writer for UdpStream {
fn write(&mut self, buf: &[u8]) { fn write(&mut self, buf: &[u8]) -> IoResult<()> {
self.as_socket(|sock| sock.sendto(buf, self.connectedTo)); self.as_socket(|sock| sock.sendto(buf, self.connectedTo))
} }
} }

View file

@ -28,7 +28,7 @@ use c_str::ToCStr;
use rt::rtio::{IoFactory, LocalIo, RtioUnixListener}; use rt::rtio::{IoFactory, LocalIo, RtioUnixListener};
use rt::rtio::{RtioUnixAcceptor, RtioPipe}; use rt::rtio::{RtioUnixAcceptor, RtioPipe};
use io::pipe::PipeStream; 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. /// A stream which communicates over a named pipe.
pub struct UnixStream { pub struct UnixStream {
@ -52,13 +52,15 @@ impl UnixStream {
/// ///
/// # Example /// # Example
/// ///
/// ```rust
/// # #[allow(unused_must_use)];
/// use std::io::net::unix::UnixStream; /// use std::io::net::unix::UnixStream;
/// ///
/// let server = Path("path/to/my/socket"); /// let server = Path::new("path/to/my/socket");
/// let mut stream = UnixStream::connect(&server); /// let mut stream = UnixStream::connect(&server);
/// stream.write([1, 2, 3]); /// stream.write([1, 2, 3]);
/// /// ```
pub fn connect<P: ToCStr>(path: &P) -> Option<UnixStream> { pub fn connect<P: ToCStr>(path: &P) -> IoResult<UnixStream> {
LocalIo::maybe_raise(|io| { LocalIo::maybe_raise(|io| {
io.unix_connect(&path.to_c_str()).map(UnixStream::new) io.unix_connect(&path.to_c_str()).map(UnixStream::new)
}) })
@ -66,11 +68,11 @@ impl UnixStream {
} }
impl Reader for 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 { 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 { pub struct UnixListener {
@ -91,16 +93,18 @@ impl UnixListener {
/// ///
/// # Example /// # Example
/// ///
/// ```
/// use std::io::net::unix::UnixListener; /// use std::io::net::unix::UnixListener;
/// use std::io::Listener;
/// ///
/// let server = Path("path/to/my/socket"); /// let server = Path::new("path/to/my/socket");
/// let mut stream = UnixListener::bind(&server); /// let mut stream = UnixListener::bind(&server);
/// for client in stream.incoming() { /// for client in stream.incoming() {
/// let mut client = client; /// let mut client = client;
/// client.write([1, 2, 3, 4]); /// client.write([1, 2, 3, 4]);
/// } /// }
/// /// ```
pub fn bind<P: ToCStr>(path: &P) -> Option<UnixListener> { pub fn bind<P: ToCStr>(path: &P) -> IoResult<UnixListener> {
LocalIo::maybe_raise(|io| { LocalIo::maybe_raise(|io| {
io.unix_bind(&path.to_c_str()).map(|s| UnixListener { obj: s }) io.unix_bind(&path.to_c_str()).map(|s| UnixListener { obj: s })
}) })
@ -108,14 +112,8 @@ impl UnixListener {
} }
impl Listener<UnixStream, UnixAcceptor> for UnixListener { impl Listener<UnixStream, UnixAcceptor> for UnixListener {
fn listen(self) -> Option<UnixAcceptor> { fn listen(self) -> IoResult<UnixAcceptor> {
match self.obj.listen() { self.obj.listen().map(|obj| UnixAcceptor { obj: obj })
Ok(acceptor) => Some(UnixAcceptor { obj: acceptor }),
Err(ioerr) => {
io_error::cond.raise(ioerr);
None
}
}
} }
} }
@ -124,14 +122,8 @@ pub struct UnixAcceptor {
} }
impl Acceptor<UnixStream> for UnixAcceptor { impl Acceptor<UnixStream> for UnixAcceptor {
fn accept(&mut self) -> Option<UnixStream> { fn accept(&mut self) -> IoResult<UnixStream> {
match self.obj.accept() { self.obj.accept().map(UnixStream::new)
Ok(s) => Some(UnixStream::new(s)),
Err(ioerr) => {
io_error::cond.raise(ioerr);
None
}
}
} }
} }

View file

@ -14,7 +14,7 @@
//! enough so that pipes can be created to child processes. //! enough so that pipes can be created to child processes.
use prelude::*; use prelude::*;
use io::{io_error, EndOfFile}; use io::IoResult;
use libc; use libc;
use rt::rtio::{RtioPipe, LocalIo}; use rt::rtio::{RtioPipe, LocalIo};
@ -42,7 +42,7 @@ impl PipeStream {
/// ///
/// If the pipe cannot be created, an error will be raised on the /// If the pipe cannot be created, an error will be raised on the
/// `io_error` condition. /// `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| { LocalIo::maybe_raise(|io| {
io.pipe_open(fd).map(|obj| PipeStream { obj: obj }) io.pipe_open(fd).map(|obj| PipeStream { obj: obj })
}) })
@ -54,29 +54,11 @@ impl PipeStream {
} }
impl Reader for PipeStream { impl Reader for PipeStream {
fn read(&mut self, buf: &mut [u8]) -> Option<uint> { fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { self.obj.read(buf) }
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;
}
}
}
} }
impl Writer for PipeStream { impl Writer for PipeStream {
fn write(&mut self, buf: &[u8]) { fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.obj.write(buf) }
match self.obj.write(buf) {
Ok(_) => (),
Err(ioerr) => {
io_error::cond.raise(ioerr);
}
}
}
} }
#[cfg(test)] #[cfg(test)]

View file

@ -14,7 +14,7 @@ use prelude::*;
use libc; use libc;
use io; use io;
use io::io_error; use io::IoResult;
use rt::rtio::{RtioProcess, IoFactory, LocalIo}; use rt::rtio::{RtioProcess, IoFactory, LocalIo};
use fmt; use fmt;
@ -93,7 +93,7 @@ pub enum ProcessExit {
impl fmt::Show for ProcessExit { impl fmt::Show for ProcessExit {
/// Format a ProcessExit enum, to nicely present the information. /// 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 { match *obj {
ExitStatus(code) => write!(f.buf, "exit code: {}", code), ExitStatus(code) => write!(f.buf, "exit code: {}", code),
ExitSignal(code) => write!(f.buf, "signal: {}", code), ExitSignal(code) => write!(f.buf, "signal: {}", code),
@ -118,7 +118,7 @@ impl ProcessExit {
impl Process { impl Process {
/// Creates a new pipe initialized, but not bound to any particular /// Creates a new pipe initialized, but not bound to any particular
/// source/destination /// source/destination
pub fn new(config: ProcessConfig) -> Option<Process> { pub fn new(config: ProcessConfig) -> IoResult<Process> {
let mut config = Some(config); let mut config = Some(config);
LocalIo::maybe_raise(|io| { LocalIo::maybe_raise(|io| {
io.spawn(config.take_unwrap()).map(|(p, io)| { io.spawn(config.take_unwrap()).map(|(p, io)| {
@ -142,13 +142,8 @@ impl Process {
/// function. /// function.
/// ///
/// If the signal delivery fails, then the `io_error` condition is raised on /// If the signal delivery fails, then the `io_error` condition is raised on
pub fn signal(&mut self, signal: int) { pub fn signal(&mut self, signal: int) -> IoResult<()> {
match self.handle.kill(signal) { self.handle.kill(signal)
Ok(()) => {}
Err(err) => {
io_error::cond.raise(err)
}
}
} }
/// Wait for the child to exit completely, returning the status that it /// Wait for the child to exit completely, returning the status that it

View file

@ -14,80 +14,64 @@
//! These implementations allow e.g. `Option<File>` to be used //! These implementations allow e.g. `Option<File>` to be used
//! as a `Reader` without unwrapping the option first. //! as a `Reader` without unwrapping the option first.
use option::*; use clone::Clone;
use super::{Reader, Writer, Listener, Acceptor, Seek, SeekStyle}; use result::{Ok, Err};
use super::{standard_error, PreviousIoError, io_error, IoError}; use super::{Reader, Writer, Listener, Acceptor, Seek, SeekStyle, IoResult};
fn prev_io_error() -> IoError { impl<W: Writer> Writer for IoResult<W> {
standard_error(PreviousIoError) fn write(&mut self, buf: &[u8]) -> IoResult<()> {
}
impl<W: Writer> Writer for Option<W> {
fn write(&mut self, buf: &[u8]) {
match *self { match *self {
Some(ref mut writer) => writer.write(buf), Ok(ref mut writer) => writer.write(buf),
None => io_error::cond.raise(prev_io_error()) Err(ref e) => Err((*e).clone())
} }
} }
fn flush(&mut self) { fn flush(&mut self) -> IoResult<()> {
match *self { match *self {
Some(ref mut writer) => writer.flush(), Ok(ref mut writer) => writer.flush(),
None => io_error::cond.raise(prev_io_error()) Err(ref e) => Err(e.clone()),
} }
} }
} }
impl<R: Reader> Reader for Option<R> { impl<R: Reader> Reader for IoResult<R> {
fn read(&mut self, buf: &mut [u8]) -> Option<uint> { fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
match *self { match *self {
Some(ref mut reader) => reader.read(buf), Ok(ref mut reader) => reader.read(buf),
None => { Err(ref e) => Err(e.clone()),
io_error::cond.raise(prev_io_error());
None
}
} }
} }
} }
impl<S: Seek> Seek for Option<S> { impl<S: Seek> Seek for IoResult<S> {
fn tell(&self) -> u64 { fn tell(&self) -> IoResult<u64> {
match *self { match *self {
Some(ref seeker) => seeker.tell(), Ok(ref seeker) => seeker.tell(),
None => { Err(ref e) => Err(e.clone()),
io_error::cond.raise(prev_io_error());
0
} }
} }
} fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
fn seek(&mut self, pos: i64, style: SeekStyle) {
match *self { match *self {
Some(ref mut seeker) => seeker.seek(pos, style), Ok(ref mut seeker) => seeker.seek(pos, style),
None => io_error::cond.raise(prev_io_error()) Err(ref e) => Err(e.clone())
} }
} }
} }
impl<T, A: Acceptor<T>, L: Listener<T, A>> Listener<T, A> for Option<L> { impl<T, A: Acceptor<T>, L: Listener<T, A>> Listener<T, A> for IoResult<L> {
fn listen(self) -> Option<A> { fn listen(self) -> IoResult<A> {
match self { match self {
Some(listener) => listener.listen(), Ok(listener) => listener.listen(),
None => { Err(e) => Err(e),
io_error::cond.raise(prev_io_error());
None
}
} }
} }
} }
impl<T, A: Acceptor<T>> Acceptor<T> for Option<A> { impl<T, A: Acceptor<T>> Acceptor<T> for IoResult<A> {
fn accept(&mut self) -> Option<T> { fn accept(&mut self) -> IoResult<T> {
match *self { match *self {
Some(ref mut acceptor) => acceptor.accept(), Ok(ref mut acceptor) => acceptor.accept(),
None => { Err(ref e) => Err(e.clone()),
io_error::cond.raise(prev_io_error());
None
}
} }
} }
} }

View file

@ -20,10 +20,11 @@ definitions for a number of signals.
*/ */
use clone::Clone; use clone::Clone;
use result::{Ok, Err};
use comm::{Port, SharedChan}; use comm::{Port, SharedChan};
use container::{Map, MutableMap}; use container::{Map, MutableMap};
use hashmap; use hashmap;
use option::{Some, None}; use io;
use rt::rtio::{IoFactory, LocalIo, RtioSignal}; use rt::rtio::{IoFactory, LocalIo, RtioSignal};
#[repr(int)] #[repr(int)]
@ -117,18 +118,18 @@ impl Listener {
/// If this function fails to register a signal handler, then an error will /// 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 /// be raised on the `io_error` condition and the function will return
/// false. /// false.
pub fn register(&mut self, signum: Signum) -> bool { pub fn register(&mut self, signum: Signum) -> io::IoResult<()> {
if self.handles.contains_key(&signum) { 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| { match LocalIo::maybe_raise(|io| {
io.signal(signum, self.chan.clone()) io.signal(signum, self.chan.clone())
}) { }) {
Some(handle) => { Ok(handle) => {
self.handles.insert(signum, handle); self.handles.insert(signum, handle);
true Ok(())
} }
None => false Err(e) => Err(e)
} }
} }

View file

@ -28,7 +28,7 @@ out.write(bytes!("Hello, world!"));
use container::Container; use container::Container;
use fmt; use fmt;
use io::{Reader, Writer, io_error, IoError, OtherIoError, use io::{Reader, Writer, IoResult, IoError, OtherIoError,
standard_error, EndOfFile, LineBufferedWriter}; standard_error, EndOfFile, LineBufferedWriter};
use libc; use libc;
use option::{Option, Some, None}; use option::{Option, Some, None};
@ -114,7 +114,8 @@ fn reset_helper(w: ~Writer,
match f(t.get(), w) { match f(t.get(), w) {
Some(mut w) => { Some(mut w) => {
drop(t); drop(t);
w.flush(); // FIXME: is failing right here?
w.flush().unwrap();
Some(w) Some(w)
} }
None => None None => None
@ -155,9 +156,9 @@ pub fn set_stderr(stderr: ~Writer) -> Option<~Writer> {
// // io1 aliases io2 // // 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(); let task: Option<~Task> = Local::try_take();
match task { let result = match task {
Some(mut task) => { Some(mut task) => {
// Printing may run arbitrary code, so ensure that the task is in // 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 // 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() { if my_stdout.is_none() {
my_stdout = Some(~LineBufferedWriter::new(stdout()) as ~Writer); 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 // Note that we need to be careful when putting the stdout handle
// back into the task. If the handle was set to `Some` while // 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); let prev = util::replace(&mut t.get().stdout, my_stdout);
drop(t); drop(t);
drop(prev); drop(prev);
ret
} }
None => { None => {
struct Stdout; struct Stdout;
impl Writer for Stdout { impl Writer for Stdout {
fn write(&mut self, data: &[u8]) { fn write(&mut self, data: &[u8]) -> IoResult<()> {
unsafe { unsafe {
libc::write(libc::STDOUT_FILENO, libc::write(libc::STDOUT_FILENO,
data.as_ptr() as *libc::c_void, data.as_ptr() as *libc::c_void,
data.len() as libc::size_t); data.len() as libc::size_t);
} }
Ok(()) // just ignore the results
} }
} }
let mut io = Stdout; 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. /// `\n` character is printed to the console after the string.
pub fn println(s: &str) { pub fn println(s: &str) {
with_task_stdout(|io| { with_task_stdout(|io| {
io.write(s.as_bytes()); io.write(s.as_bytes()).and_then(|()| io.write(['\n' as u8]))
io.write(['\n' as u8]);
}) })
} }
@ -249,7 +256,7 @@ pub struct StdReader {
} }
impl Reader for 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 { let ret = match self.inner {
TTY(ref mut tty) => tty.read(buf), TTY(ref mut tty) => tty.read(buf),
File(ref mut file) => file.read(buf).map(|i| i as uint), 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 // return an actual EOF error, but apparently for stdin it's a
// little different. Hence, here we convert a 0 length read to an // little different. Hence, here we convert a 0 length read to an
// end-of-file indicator so the caller knows to stop reading. // end-of-file indicator so the caller knows to stop reading.
Ok(0) => { Ok(0) => { Err(standard_error(EndOfFile)) }
io_error::cond.raise(standard_error(EndOfFile)); ret @ Ok(..) | ret @ Err(..) => ret,
None
}
Ok(amt) => Some(amt),
Err(e) => {
io_error::cond.raise(e);
None
}
} }
} }
} }
@ -289,24 +289,15 @@ impl StdWriter {
/// ///
/// This function will raise on the `io_error` condition if an error /// This function will raise on the `io_error` condition if an error
/// happens. /// happens.
pub fn winsize(&mut self) -> Option<(int, int)> { pub fn winsize(&mut self) -> IoResult<(int, int)> {
match self.inner { match self.inner {
TTY(ref mut tty) => { TTY(ref mut tty) => tty.get_winsize(),
match tty.get_winsize() {
Ok(p) => Some(p),
Err(e) => {
io_error::cond.raise(e);
None
}
}
}
File(..) => { File(..) => {
io_error::cond.raise(IoError { Err(IoError {
kind: OtherIoError, kind: OtherIoError,
desc: "stream is not a tty", desc: "stream is not a tty",
detail: None, detail: None,
}); })
None
} }
} }
} }
@ -318,20 +309,15 @@ impl StdWriter {
/// ///
/// This function will raise on the `io_error` condition if an error /// This function will raise on the `io_error` condition if an error
/// happens. /// happens.
pub fn set_raw(&mut self, raw: bool) { pub fn set_raw(&mut self, raw: bool) -> IoResult<()> {
match self.inner { match self.inner {
TTY(ref mut tty) => { TTY(ref mut tty) => tty.set_raw(raw),
match tty.set_raw(raw) {
Ok(()) => {},
Err(e) => io_error::cond.raise(e),
}
}
File(..) => { File(..) => {
io_error::cond.raise(IoError { Err(IoError {
kind: OtherIoError, kind: OtherIoError,
desc: "stream is not a tty", desc: "stream is not a tty",
detail: None, detail: None,
}); })
} }
} }
} }
@ -346,14 +332,10 @@ impl StdWriter {
} }
impl Writer for StdWriter { impl Writer for StdWriter {
fn write(&mut self, buf: &[u8]) { fn write(&mut self, buf: &[u8]) -> IoResult<()> {
let ret = match self.inner { match self.inner {
TTY(ref mut tty) => tty.write(buf), TTY(ref mut tty) => tty.write(buf),
File(ref mut file) => file.write(buf), File(ref mut file) => file.write(buf),
};
match ret {
Ok(()) => {}
Err(e) => io_error::cond.raise(e)
} }
} }
} }

View file

@ -39,8 +39,8 @@ loop {
*/ */
use comm::Port; use comm::Port;
use option::Option;
use rt::rtio::{IoFactory, LocalIo, RtioTimer}; use rt::rtio::{IoFactory, LocalIo, RtioTimer};
use io::IoResult;
pub struct Timer { pub struct Timer {
priv obj: ~RtioTimer priv obj: ~RtioTimer
@ -48,7 +48,8 @@ pub struct Timer {
/// Sleep the current task for `msecs` milliseconds. /// Sleep the current task for `msecs` milliseconds.
pub fn sleep(msecs: u64) { 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) timer.sleep(msecs)
} }
@ -57,7 +58,7 @@ impl Timer {
/// Creates a new timer which can be used to put the current task to sleep /// 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 /// for a number of milliseconds, or to possibly create channels which will
/// get notified after an amount of time has passed. /// 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 })) LocalIo::maybe_raise(|io| io.timer_init().map(|t| Timer { obj: t }))
} }

View file

@ -7,8 +7,10 @@
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use prelude::*; use prelude::*;
use cmp; use cmp;
use io;
use vec::bytes::MutableByteVector; use vec::bytes::MutableByteVector;
/// Wraps a `Reader`, limiting the number of bytes that can be read from it. /// 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> { 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 { if self.limit == 0 {
return None; return Err(io::standard_error(io::EndOfFile));
} }
let len = cmp::min(self.limit, buf.len()); let len = cmp::min(self.limit, buf.len());
@ -43,7 +45,7 @@ pub struct NullWriter;
impl Writer for NullWriter { impl Writer for NullWriter {
#[inline] #[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. /// A `Reader` which returns an infinite stream of 0 bytes, like /dev/zero.
@ -51,9 +53,9 @@ pub struct ZeroReader;
impl Reader for ZeroReader { impl Reader for ZeroReader {
#[inline] #[inline]
fn read(&mut self, buf: &mut [u8]) -> Option<uint> { fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
buf.set_memory(0); buf.set_memory(0);
Some(buf.len()) Ok(buf.len())
} }
} }
@ -62,8 +64,8 @@ pub struct NullReader;
impl Reader for NullReader { impl Reader for NullReader {
#[inline] #[inline]
fn read(&mut self, _buf: &mut [u8]) -> Option<uint> { fn read(&mut self, _buf: &mut [u8]) -> io::IoResult<uint> {
None Err(io::standard_error(io::EndOfFile))
} }
} }
@ -81,17 +83,21 @@ impl MultiWriter {
impl Writer for MultiWriter { impl Writer for MultiWriter {
#[inline] #[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() { for writer in self.writers.mut_iter() {
writer.write(buf); ret = ret.and(writer.write(buf));
} }
return ret;
} }
#[inline] #[inline]
fn flush(&mut self) { fn flush(&mut self) -> io::IoResult<()> {
let mut ret = Ok(());
for writer in self.writers.mut_iter() { 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> { 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 { loop {
match self.cur_reader { let err = match self.cur_reader {
Some(ref mut r) => { Some(ref mut r) => {
match r.read(buf) { match r.read(buf) {
Some(len) => return Some(len), Ok(len) => return Ok(len),
None => {} Err(ref e) if e.kind == io::EndOfFile => None,
Err(e) => Some(e),
} }
} }
None => break 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> { impl<R: Reader, W: Writer> Reader for TeeReader<R, W> {
fn read(&mut self, buf: &mut [u8]) -> Option<uint> { fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
self.reader.read(buf).map(|len| { self.reader.read(buf).and_then(|len| {
self.writer.write(buf.slice_to(len)); self.writer.write(buf.slice_to(len)).map(|()| len)
len
}) })
} }
} }
/// Copies all data from a `Reader` to a `Writer`. /// 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]; let mut buf = [0, ..super::DEFAULT_BUF_SIZE];
loop { loop {
match r.read(buf) { let len = match r.read(buf) {
Some(len) => w.write(buf.slice_to(len)), Ok(len) => len,
None => break Err(ref e) if e.kind == io::EndOfFile => return Ok(()),
} Err(e) => return Err(e),
};
if_ok!(w.write(buf.slice_to(len)));
} }
} }

View file

@ -102,6 +102,7 @@ use io::Writer;
use ops::Drop; use ops::Drop;
use option::{Some, None, Option}; use option::{Some, None, Option};
use prelude::drop; use prelude::drop;
use result::{Ok, Err};
use rt::local::Local; use rt::local::Local;
use rt::task::Task; use rt::task::Task;
use util; use util;
@ -131,13 +132,19 @@ struct DefaultLogger {
impl Logger for DefaultLogger { impl Logger for DefaultLogger {
// by default, just ignore the level // by default, just ignore the level
fn log(&mut self, _level: u32, args: &fmt::Arguments) { 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 { impl Drop for DefaultLogger {
fn drop(&mut self) { fn drop(&mut self) {
self.handle.flush(); match self.handle.flush() {
Err(e) => fail!("failed to flush a logger: {}", e),
Ok(()) => {}
}
} }
} }

View file

@ -197,3 +197,8 @@ macro_rules! local_data_key (
pub static $name: ::std::local_data::Key<$ty> = &::std::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) })
)

View file

@ -382,7 +382,7 @@ impl<T: Default> Option<T> {
impl<T: fmt::Show> fmt::Show for Option<T> { impl<T: fmt::Show> fmt::Show for Option<T> {
#[inline] #[inline]
fn fmt(s: &Option<T>, f: &mut fmt::Formatter) { fn fmt(s: &Option<T>, f: &mut fmt::Formatter) -> fmt::Result {
match *s { match *s {
Some(ref t) => write!(f.buf, "Some({})", *t), Some(ref t) => write!(f.buf, "Some({})", *t),
None => write!(f.buf, "None") None => write!(f.buf, "None")

View file

@ -929,7 +929,7 @@ pub enum MapError {
} }
impl fmt::Show for 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 { let str = match *val {
ErrFdNotAvail => "fd not available for reading or writing", ErrFdNotAvail => "fd not available for reading or writing",
ErrInvalidFd => "Invalid fd", ErrInvalidFd => "Invalid fd",
@ -944,23 +944,19 @@ impl fmt::Show for MapError {
ErrAlreadyExists => "File mapping for specified file already exists", ErrAlreadyExists => "File mapping for specified file already exists",
ErrZeroLength => "Zero-length mapping not allowed", ErrZeroLength => "Zero-length mapping not allowed",
ErrUnknown(code) => { ErrUnknown(code) => {
write!(out.buf, "Unknown error = {}", code); return write!(out.buf, "Unknown error = {}", code)
return
}, },
ErrVirtualAlloc(code) => { ErrVirtualAlloc(code) => {
write!(out.buf, "VirtualAlloc failure = {}", code); return write!(out.buf, "VirtualAlloc failure = {}", code)
return
}, },
ErrCreateFileMappingW(code) => { ErrCreateFileMappingW(code) => {
format!("CreateFileMappingW failure = {}", code); return write!(out.buf, "CreateFileMappingW failure = {}", code)
return
}, },
ErrMapViewOfFile(code) => { ErrMapViewOfFile(code) => {
write!(out.buf, "MapViewOfFile failure = {}", code); return write!(out.buf, "MapViewOfFile failure = {}", code)
return
} }
}; };
write!(out.buf, "{}", str); write!(out.buf, "{}", str)
} }
} }

View file

@ -533,7 +533,7 @@ pub struct Display<'a, P> {
} }
impl<'a, P: GenericPath> fmt::Show for 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)) d.with_str(|s| f.pad(s))
} }
} }

View file

@ -62,7 +62,7 @@ impl OSRng {
pub fn new() -> OSRng { pub fn new() -> OSRng {
use path::Path; use path::Path;
let reader = File::open(&Path::new("/dev/urandom")); 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); let reader_rng = ReaderRng::new(reader);
OSRng { inner: reader_rng } OSRng { inner: reader_rng }

View file

@ -11,7 +11,7 @@
//! A wrapper around any Reader to treat it as an RNG. //! A wrapper around any Reader to treat it as an RNG.
use container::Container; use container::Container;
use option::{Some, None}; use result::{Ok, Err};
use io::Reader; use io::Reader;
use rand::Rng; use rand::Rng;
@ -49,26 +49,26 @@ impl<R: Reader> Rng for ReaderRng<R> {
// platform just involves blitting the bytes into the memory // platform just involves blitting the bytes into the memory
// of the u32, similarly for BE on BE; avoiding byteswapping. // of the u32, similarly for BE on BE; avoiding byteswapping.
if cfg!(target_endian="little") { if cfg!(target_endian="little") {
self.reader.read_le_u32() self.reader.read_le_u32().unwrap()
} else { } else {
self.reader.read_be_u32() self.reader.read_be_u32().unwrap()
} }
} }
fn next_u64(&mut self) -> u64 { fn next_u64(&mut self) -> u64 {
// see above for explanation. // see above for explanation.
if cfg!(target_endian="little") { if cfg!(target_endian="little") {
self.reader.read_le_u64() self.reader.read_le_u64().unwrap()
} else { } else {
self.reader.read_be_u64() self.reader.read_be_u64().unwrap()
} }
} }
fn fill_bytes(&mut self, v: &mut [u8]) { fn fill_bytes(&mut self, v: &mut [u8]) {
if v.len() == 0 { return } if v.len() == 0 { return }
match self.reader.read(v) { match self.reader.read(v) {
Some(n) if n == v.len() => return, Ok(n) if n == v.len() => return,
Some(n) => fail!("ReaderRng.fill_bytes could not fill buffer: \ Ok(n) => fail!("ReaderRng.fill_bytes could not fill buffer: \
read {} out of {} bytes.", n, v.len()), read {} out of {} bytes.", n, v.len()),
None => fail!("ReaderRng.fill_bytes reached eof.") Err(e) => fail!("ReaderRng.fill_bytes error: {}", e)
} }
} }
} }

View file

@ -66,6 +66,8 @@ impl<V:TyVisitor + MovePtr> MovePtrAdaptor<V> {
pub fn bump_past<T>(&mut self) { pub fn bump_past<T>(&mut self) {
self.bump(mem::size_of::<T>()); self.bump(mem::size_of::<T>());
} }
pub fn unwrap(self) -> V { self.inner }
} }
/// Abstract type-directed pointer-movement using the MovePtr trait /// Abstract type-directed pointer-movement using the MovePtr trait

View file

@ -21,48 +21,57 @@ use char;
use container::Container; use container::Container;
use io; use io;
use iter::Iterator; use iter::Iterator;
use option::{Some, None}; use option::{Some, None, Option};
use ptr; use ptr;
use reflect; use reflect;
use reflect::{MovePtr, align}; use reflect::{MovePtr, align};
use result::{Ok, Err};
use str::StrSlice; use str::StrSlice;
use to_str::ToStr; use to_str::ToStr;
use vec::OwnedVector; use vec::OwnedVector;
use unstable::intrinsics::{Disr, Opaque, TyDesc, TyVisitor, get_tydesc, visit_tydesc}; use unstable::intrinsics::{Disr, Opaque, TyDesc, TyVisitor, get_tydesc, visit_tydesc};
use unstable::raw; use unstable::raw;
macro_rules! if_ok( ($me:expr, $e:expr) => (
match $e {
Ok(()) => {},
Err(e) => { $me.last_err = Some(e); return false; }
}
) )
/// Representations /// Representations
trait Repr { trait Repr {
fn write_repr(&self, writer: &mut io::Writer); fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()>;
} }
impl Repr for () { impl Repr for () {
fn write_repr(&self, writer: &mut io::Writer) { fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()> {
writer.write("()".as_bytes()); writer.write("()".as_bytes())
} }
} }
impl Repr for bool { 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" }; let s = if *self { "true" } else { "false" };
writer.write(s.as_bytes()) writer.write(s.as_bytes())
} }
} }
impl Repr for int { 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| { ::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 { 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| { ::$ty::to_str_bytes(*self, 10u, |bits| {
writer.write(bits); writer.write(bits).and_then(|()| {
writer.write(bytes!($suffix)); writer.write(bytes!($suffix))
})
}) })
} }
})) }))
@ -78,10 +87,11 @@ int_repr!(u32, "u32")
int_repr!(u64, "u64") int_repr!(u64, "u64")
macro_rules! num_repr(($ty:ident, $suffix:expr) => (impl Repr for $ty { 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(); let s = self.to_str();
writer.write(s.as_bytes()); writer.write(s.as_bytes()).and_then(|()| {
writer.write(bytes!($suffix)); writer.write(bytes!($suffix))
})
} }
})) }))
@ -100,7 +110,8 @@ pub struct ReprVisitor<'a> {
priv ptr: *u8, priv ptr: *u8,
priv ptr_stk: ~[*u8], priv ptr_stk: ~[*u8],
priv var_stk: ~[VariantState], 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, pub fn ReprVisitor<'a>(ptr: *u8,
@ -110,6 +121,7 @@ pub fn ReprVisitor<'a>(ptr: *u8,
ptr_stk: ~[], ptr_stk: ~[],
var_stk: ~[], var_stk: ~[],
writer: writer, writer: writer,
last_err: None,
} }
} }
@ -130,11 +142,10 @@ impl<'a> ReprVisitor<'a> {
// Various helpers for the TyVisitor impl // Various helpers for the TyVisitor impl
#[inline] #[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 { unsafe {
f(self, transmute::<*u8,&T>(self.ptr)); f(self, transmute::<*u8,&T>(self.ptr))
} }
true
} }
#[inline] #[inline]
@ -152,43 +163,53 @@ impl<'a> ReprVisitor<'a> {
ptr_stk: ~[], ptr_stk: ~[],
var_stk: ~[], var_stk: ~[],
writer: ::cast::transmute_copy(&self.writer), writer: ::cast::transmute_copy(&self.writer),
last_err: None,
}; };
let mut v = reflect::MovePtrAdaptor(u); let mut v = reflect::MovePtrAdaptor(u);
// Obviously this should not be a thing, but blame #8401 for now // Obviously this should not be a thing, but blame #8401 for now
visit_tydesc(inner, &mut v as &mut TyVisitor); 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] #[inline]
pub fn write<T:Repr>(&mut self) -> bool { pub fn write<T:Repr>(&mut self) -> bool {
self.get(|this, v:&T| { 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) { pub fn write_escaped_slice(&mut self, slice: &str) -> bool {
self.writer.write(['"' as u8]); if_ok!(self, self.writer.write(['"' as u8]));
for ch in slice.chars() { 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 { if mtbl == 0 {
self.writer.write("mut ".as_bytes()); if_ok!(self, self.writer.write("mut ".as_bytes()));
} else if mtbl == 1 { } else if mtbl == 1 {
// skip, this is ast::m_imm // skip, this is ast::m_imm
} else { } else {
fail!("invalid mutability value"); fail!("invalid mutability value");
} }
true
} }
pub fn write_vec_range(&mut self, ptr: *(), len: uint, inner: *TyDesc) -> bool { pub fn write_vec_range(&mut self, ptr: *(), len: uint, inner: *TyDesc) -> bool {
let mut p = ptr as *u8; let mut p = ptr as *u8;
let (sz, al) = unsafe { ((*inner).size, (*inner).align) }; 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 first = true;
let mut left = len; let mut left = len;
// unit structs have 0 size, and don't loop forever. // unit structs have 0 size, and don't loop forever.
@ -197,13 +218,13 @@ impl<'a> ReprVisitor<'a> {
if first { if first {
first = false; first = false;
} else { } else {
self.writer.write(", ".as_bytes()); if_ok!(self, self.writer.write(", ".as_bytes()));
} }
self.visit_ptr_inner(p as *u8, inner); self.visit_ptr_inner(p as *u8, inner);
p = align(unsafe { ptr::offset(p, sz as int) as uint }, al) as *u8; p = align(unsafe { ptr::offset(p, sz as int) as uint }, al) as *u8;
left -= dec; left -= dec;
} }
self.writer.write([']' as u8]); if_ok!(self, self.writer.write([']' as u8]));
true true
} }
@ -211,8 +232,8 @@ impl<'a> ReprVisitor<'a> {
self.write_vec_range(ptr::to_unsafe_ptr(&v.data), v.fill, inner) self.write_vec_range(ptr::to_unsafe_ptr(&v.data), v.fill, inner)
} }
fn write_escaped_char(&mut self, ch: char, is_str: bool) { fn write_escaped_char(&mut self, ch: char, is_str: bool) -> bool {
match ch { if_ok!(self, match ch {
'\t' => self.writer.write("\\t".as_bytes()), '\t' => self.writer.write("\\t".as_bytes()),
'\r' => self.writer.write("\\r".as_bytes()), '\r' => self.writer.write("\\r".as_bytes()),
'\n' => self.writer.write("\\n".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]), '\x20'..'\x7e' => self.writer.write([ch as u8]),
_ => { _ => {
char::escape_unicode(ch, |c| { 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> { impl<'a> TyVisitor for ReprVisitor<'a> {
fn visit_bot(&mut self) -> bool { fn visit_bot(&mut self) -> bool {
self.writer.write("!".as_bytes()); if_ok!(self, self.writer.write("!".as_bytes()));
true true
} }
fn visit_nil(&mut self) -> bool { self.write::<()>() } fn visit_nil(&mut self) -> bool { self.write::<()>() }
@ -265,9 +288,10 @@ impl<'a> TyVisitor for ReprVisitor<'a> {
fn visit_char(&mut self) -> bool { fn visit_char(&mut self) -> bool {
self.get::<char>(|this, &ch| { self.get::<char>(|this, &ch| {
this.writer.write(['\'' as u8]); if_ok!(this, this.writer.write(['\'' as u8]));
this.write_escaped_char(ch, false); if !this.write_escaped_char(ch, false) { return false }
this.writer.write(['\'' as u8]); 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 { fn visit_estr_uniq(&mut self) -> bool {
self.get::<~str>(|this, s| { self.get::<~str>(|this, s| {
this.writer.write(['~' as u8]); if_ok!(this, this.writer.write(['~' as u8]));
this.write_escaped_slice(*s); this.write_escaped_slice(*s)
}) })
} }
@ -291,34 +315,35 @@ impl<'a> TyVisitor for ReprVisitor<'a> {
_align: uint) -> bool { fail!(); } _align: uint) -> bool { fail!(); }
fn visit_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool { 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.write_mut_qualifier(mtbl);
self.get::<&raw::Box<()>>(|this, b| { self.get::<&raw::Box<()>>(|this, b| {
let p = ptr::to_unsafe_ptr(&b.data) as *u8; 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 { 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| { 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 { fn visit_ptr(&mut self, mtbl: uint, _inner: *TyDesc) -> bool {
self.get::<*u8>(|this, p| { self.get::<*u8>(|this, p| {
write!(this.writer, "({} as *", *p); if_ok!(this, write!(this.writer, "({} as *", *p));
this.write_mut_qualifier(mtbl); 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 { 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.write_mut_qualifier(mtbl);
self.get::<*u8>(|this, p| { 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 { fn visit_unboxed_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
self.get::<raw::Vec<()>>(|this, b| { 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 { fn visit_evec_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
self.get::<&raw::Box<raw::Vec<()>>>(|this, b| { 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_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 { fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
self.get::<&raw::Vec<()>>(|this, b| { self.get::<&raw::Vec<()>>(|this, b| {
this.writer.write(['~' as u8]); if_ok!(this, this.writer.write(['~' as u8]));
this.write_unboxed_vec_repr(mtbl, *b, inner); this.write_unboxed_vec_repr(mtbl, *b, inner)
}) })
} }
fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool { fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
self.get::<raw::Slice<()>>(|this, s| { self.get::<raw::Slice<()>>(|this, s| {
this.writer.write(['&' as u8]); if_ok!(this, this.writer.write(['&' as u8]));
this.write_mut_qualifier(mtbl); this.write_mut_qualifier(mtbl);
let size = unsafe { let size = unsafe {
if (*inner).size == 0 { 1 } else { (*inner).size } 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 { _: uint, inner: *TyDesc) -> bool {
let assumed_size = if sz == 0 { n } else { sz }; let assumed_size = if sz == 0 { n } else { sz };
self.get::<()>(|this, b| { 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, fn visit_enter_rec(&mut self, _n_fields: uint,
_sz: uint, _align: uint) -> bool { _sz: uint, _align: uint) -> bool {
self.writer.write(['{' as u8]); if_ok!(self, self.writer.write(['{' as u8]));
true true
} }
fn visit_rec_field(&mut self, i: uint, name: &str, fn visit_rec_field(&mut self, i: uint, name: &str,
mtbl: uint, inner: *TyDesc) -> bool { mtbl: uint, inner: *TyDesc) -> bool {
if i != 0 { if i != 0 {
self.writer.write(", ".as_bytes()); if_ok!(self, self.writer.write(", ".as_bytes()));
} }
self.write_mut_qualifier(mtbl); self.write_mut_qualifier(mtbl);
self.writer.write(name.as_bytes()); if_ok!(self, self.writer.write(name.as_bytes()));
self.writer.write(": ".as_bytes()); if_ok!(self, self.writer.write(": ".as_bytes()));
self.visit_inner(inner); self.visit_inner(inner);
true true
} }
fn visit_leave_rec(&mut self, _n_fields: uint, fn visit_leave_rec(&mut self, _n_fields: uint,
_sz: uint, _align: uint) -> bool { _sz: uint, _align: uint) -> bool {
self.writer.write(['}' as u8]); if_ok!(self, self.writer.write(['}' as u8]));
true true
} }
fn visit_enter_class(&mut self, name: &str, named_fields: bool, n_fields: uint, fn visit_enter_class(&mut self, name: &str, named_fields: bool, n_fields: uint,
_sz: uint, _align: uint) -> bool { _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 n_fields != 0 {
if named_fields { if named_fields {
self.writer.write(['{' as u8]); if_ok!(self, self.writer.write(['{' as u8]));
} else { } else {
self.writer.write(['(' as u8]); if_ok!(self, self.writer.write(['(' as u8]));
} }
} }
true true
@ -405,11 +430,11 @@ impl<'a> TyVisitor for ReprVisitor<'a> {
fn visit_class_field(&mut self, i: uint, name: &str, named: bool, fn visit_class_field(&mut self, i: uint, name: &str, named: bool,
_mtbl: uint, inner: *TyDesc) -> bool { _mtbl: uint, inner: *TyDesc) -> bool {
if i != 0 { if i != 0 {
self.writer.write(", ".as_bytes()); if_ok!(self, self.writer.write(", ".as_bytes()));
} }
if named { if named {
self.writer.write(name.as_bytes()); if_ok!(self, self.writer.write(name.as_bytes()));
self.writer.write(": ".as_bytes()); if_ok!(self, self.writer.write(": ".as_bytes()));
} }
self.visit_inner(inner); self.visit_inner(inner);
true true
@ -419,9 +444,9 @@ impl<'a> TyVisitor for ReprVisitor<'a> {
_sz: uint, _align: uint) -> bool { _sz: uint, _align: uint) -> bool {
if n_fields != 0 { if n_fields != 0 {
if named_fields { if named_fields {
self.writer.write(['}' as u8]); if_ok!(self, self.writer.write(['}' as u8]));
} else { } else {
self.writer.write([')' as u8]); if_ok!(self, self.writer.write([')' as u8]));
} }
} }
true true
@ -429,13 +454,13 @@ impl<'a> TyVisitor for ReprVisitor<'a> {
fn visit_enter_tup(&mut self, _n_fields: uint, fn visit_enter_tup(&mut self, _n_fields: uint,
_sz: uint, _align: uint) -> bool { _sz: uint, _align: uint) -> bool {
self.writer.write(['(' as u8]); if_ok!(self, self.writer.write(['(' as u8]));
true true
} }
fn visit_tup_field(&mut self, i: uint, inner: *TyDesc) -> bool { fn visit_tup_field(&mut self, i: uint, inner: *TyDesc) -> bool {
if i != 0 { if i != 0 {
self.writer.write(", ".as_bytes()); if_ok!(self, self.writer.write(", ".as_bytes()));
} }
self.visit_inner(inner); self.visit_inner(inner);
true true
@ -444,9 +469,9 @@ impl<'a> TyVisitor for ReprVisitor<'a> {
fn visit_leave_tup(&mut self, _n_fields: uint, fn visit_leave_tup(&mut self, _n_fields: uint,
_sz: uint, _align: uint) -> bool { _sz: uint, _align: uint) -> bool {
if _n_fields == 1 { 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 true
} }
@ -482,9 +507,9 @@ impl<'a> TyVisitor for ReprVisitor<'a> {
} }
if write { if write {
self.writer.write(name.as_bytes()); if_ok!(self, self.writer.write(name.as_bytes()));
if n_fields > 0 { if n_fields > 0 {
self.writer.write(['(' as u8]); if_ok!(self, self.writer.write(['(' as u8]));
} }
} }
true true
@ -498,7 +523,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> {
match self.var_stk[self.var_stk.len() - 1] { match self.var_stk[self.var_stk.len() - 1] {
Matched => { Matched => {
if i != 0 { if i != 0 {
self.writer.write(", ".as_bytes()); if_ok!(self, self.writer.write(", ".as_bytes()));
} }
if ! self.visit_inner(inner) { if ! self.visit_inner(inner) {
return false; return false;
@ -516,7 +541,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> {
match self.var_stk[self.var_stk.len() - 1] { match self.var_stk[self.var_stk.len() - 1] {
Matched => { Matched => {
if n_fields > 0 { 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, fn visit_enter_fn(&mut self, _purity: uint, _proto: uint,
_n_inputs: uint, _retstyle: uint) -> bool { _n_inputs: uint, _retstyle: uint) -> bool {
self.writer.write("fn(".as_bytes()); if_ok!(self, self.writer.write("fn(".as_bytes()));
true true
} }
fn visit_fn_input(&mut self, i: uint, _mode: uint, inner: *TyDesc) -> bool { fn visit_fn_input(&mut self, i: uint, _mode: uint, inner: *TyDesc) -> bool {
if i != 0 { if i != 0 {
self.writer.write(", ".as_bytes()); if_ok!(self, self.writer.write(", ".as_bytes()));
} }
let name = unsafe { (*inner).name }; let name = unsafe { (*inner).name };
self.writer.write(name.as_bytes()); if_ok!(self, self.writer.write(name.as_bytes()));
true 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 { 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 }; let name = unsafe { (*inner).name };
if name != "()" { if name != "()" {
self.writer.write(" -> ".as_bytes()); if_ok!(self, self.writer.write(" -> ".as_bytes()));
self.writer.write(name.as_bytes()); if_ok!(self, self.writer.write(name.as_bytes()));
} }
true true
} }
@ -569,7 +595,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> {
fn visit_trait(&mut self, name: &str) -> bool { fn visit_trait(&mut self, name: &str) -> bool {
self.writer.write(name.as_bytes()); if_ok!(self, self.writer.write(name.as_bytes()));
true true
} }
@ -582,13 +608,17 @@ impl<'a> TyVisitor for ReprVisitor<'a> {
fn visit_closure_ptr(&mut self, _ck: uint) -> bool { true } 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 { unsafe {
let ptr = ptr::to_unsafe_ptr(object) as *u8; let ptr = ptr::to_unsafe_ptr(object) as *u8;
let tydesc = get_tydesc::<T>(); let tydesc = get_tydesc::<T>();
let u = ReprVisitor(ptr, writer); let u = ReprVisitor(ptr, writer);
let mut v = reflect::MovePtrAdaptor(u); let mut v = reflect::MovePtrAdaptor(u);
visit_tydesc(tydesc, &mut v as &mut TyVisitor); 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; use io;
let mut result = io::MemWriter::new(); 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() str::from_utf8_owned(result.unwrap()).unwrap()
} }
@ -615,7 +645,7 @@ fn test_repr() {
fn exact_test<T>(t: &T, e:&str) { fn exact_test<T>(t: &T, e:&str) {
let mut m = io::MemWriter::new(); 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(); let s = str::from_utf8_owned(m.unwrap()).unwrap();
assert_eq!(s.as_slice(), e); assert_eq!(s.as_slice(), e);
} }

View file

@ -208,7 +208,7 @@ impl<T, E> Result<T, E> {
impl<T: fmt::Show, E: fmt::Show> fmt::Show for Result<T, E> { impl<T: fmt::Show, E: fmt::Show> fmt::Show for Result<T, E> {
#[inline] #[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 { match *s {
Ok(ref t) => write!(f.buf, "Ok({})", *t), Ok(ref t) => write!(f.buf, "Ok({})", *t),
Err(ref e) => write!(f.buf, "Err({})", *e) Err(ref e) => write!(f.buf, "Err({})", *e)

View file

@ -16,13 +16,13 @@ use libc;
use ops::Drop; use ops::Drop;
use option::{Option, Some, None}; use option::{Option, Some, None};
use path::Path; use path::Path;
use result::{Result, Ok, Err}; use result::{Result, Err};
use rt::task::Task; use rt::task::Task;
use rt::local::Local; use rt::local::Local;
use ai = io::net::addrinfo; use ai = io::net::addrinfo;
use io; use io;
use io::IoError; use io::{IoError, IoResult};
use io::net::ip::{IpAddr, SocketAddr}; use io::net::ip::{IpAddr, SocketAddr};
use io::process::{ProcessConfig, ProcessExit}; use io::process::{ProcessConfig, ProcessExit};
use io::signal::Signum; use io::signal::Signum;
@ -116,23 +116,12 @@ impl<'a> LocalIo<'a> {
return ret; return ret;
} }
pub fn maybe_raise<T>(f: |io: &mut IoFactory| -> Result<T, IoError>) pub fn maybe_raise<T>(f: |io: &mut IoFactory| -> IoResult<T>)
-> Option<T> -> IoResult<T>
{ {
match LocalIo::borrow() { match LocalIo::borrow() {
None => { None => Err(io::standard_error(io::IoUnavailable)),
io::io_error::cond.raise(io::standard_error(io::IoUnavailable)); Some(mut io) => f(io.get()),
None
}
Some(mut io) => {
match f(io.get()) {
Ok(t) => Some(t),
Err(ioerr) => {
io::io_error::cond.raise(ioerr);
None
}
}
}
} }
} }

View file

@ -119,6 +119,7 @@ impl Task {
// Run the task main function, then do some cleanup. // Run the task main function, then do some cleanup.
f.finally(|| { f.finally(|| {
#[allow(unused_must_use)]
fn close_outputs() { fn close_outputs() {
let mut task = Local::borrow(None::<Task>); let mut task = Local::borrow(None::<Task>);
let logger = task.get().logger.take(); let logger = task.get().logger.take();
@ -126,8 +127,8 @@ impl Task {
let stdout = task.get().stdout.take(); let stdout = task.get().stdout.take();
drop(task); drop(task);
drop(logger); // loggers are responsible for flushing drop(logger); // loggers are responsible for flushing
match stdout { Some(mut w) => w.flush(), None => {} } match stdout { Some(mut w) => { w.flush(); }, None => {} }
match stderr { Some(mut w) => w.flush(), None => {} } match stderr { Some(mut w) => { w.flush(); }, None => {} }
} }
// First, flush/destroy the user stdout/logger because these // First, flush/destroy the user stdout/logger because these

View file

@ -464,7 +464,8 @@ fn begin_unwind_inner(msg: ~Any, file: &'static str, line: uint) -> ! {
match task.stderr.take() { match task.stderr.take() {
Some(mut stderr) => { Some(mut stderr) => {
Local::put(task); Local::put(task);
format_args!(|args| ::fmt::writeln(stderr, args), // FIXME: what to do when the task printing fails?
let _err = format_args!(|args| ::fmt::writeln(stderr, args),
"task '{}' failed at '{}', {}:{}", "task '{}' failed at '{}', {}:{}",
n, msg_s, file, line); n, msg_s, file, line);
task = Local::take(); task = Local::take();

View file

@ -11,10 +11,12 @@
use container::Container; use container::Container;
use fmt; use fmt;
use from_str::FromStr; use from_str::FromStr;
use io::IoResult;
use iter::Iterator; use iter::Iterator;
use libc; use libc;
use option::{Some, None, Option}; use option::{Some, None, Option};
use os; use os;
use result::Ok;
use str::StrSlice; use str::StrSlice;
use unstable::running_on_valgrind; use unstable::running_on_valgrind;
use vec::ImmutableVector; use vec::ImmutableVector;
@ -73,16 +75,17 @@ pub fn dumb_println(args: &fmt::Arguments) {
struct Stderr; struct Stderr;
impl io::Writer for Stderr { impl io::Writer for Stderr {
fn write(&mut self, data: &[u8]) { fn write(&mut self, data: &[u8]) -> IoResult<()> {
unsafe { unsafe {
libc::write(libc::STDERR_FILENO, libc::write(libc::STDERR_FILENO,
data.as_ptr() as *libc::c_void, data.as_ptr() as *libc::c_void,
data.len() as libc::size_t); data.len() as libc::size_t);
} }
Ok(()) // yes, we're lying
} }
} }
let mut w = Stderr; 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) -> ! { pub fn abort(msg: &str) -> ! {

View file

@ -119,7 +119,8 @@ impl Process {
* * options - Options to configure the environment of the process, * * options - Options to configure the environment of the process,
* the working directory and the standard IO streams. * 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 ProcessOptions { env, dir, in_fd, out_fd, err_fd } = options;
let env = env.as_ref().map(|a| a.as_slice()); let env = env.as_ref().map(|a| a.as_slice());
let cwd = dir.as_ref().map(|a| a.as_str().unwrap()); let cwd = dir.as_ref().map(|a| a.as_str().unwrap());
@ -138,10 +139,7 @@ impl Process {
cwd: cwd, cwd: cwd,
io: rtio, io: rtio,
}; };
match process::Process::new(rtconfig) { process::Process::new(rtconfig).map(|p| Process { inner: p })
Some(inner) => Some(Process { inner: inner }),
None => None
}
} }
/// Returns the unique id of the process /// Returns the unique id of the process
@ -224,19 +222,17 @@ impl Process {
let ch_clone = ch.clone(); let ch_clone = ch.clone();
spawn(proc() { spawn(proc() {
let _guard = io::ignore_io_error();
let mut error = error; let mut error = error;
match error { match error {
Some(ref mut e) => ch.send((2, e.read_to_end())), Some(ref mut e) => ch.send((2, e.read_to_end())),
None => ch.send((2, ~[])) None => ch.send((2, Ok(~[])))
} }
}); });
spawn(proc() { spawn(proc() {
let _guard = io::ignore_io_error();
let mut output = output; let mut output = output;
match output { match output {
Some(ref mut e) => ch_clone.send((1, e.read_to_end())), 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, return ProcessOutput {status: status,
output: outs, output: outs.ok().unwrap_or(~[]),
error: errs}; error: errs.ok().unwrap_or(~[]) };
} }
/** /**
@ -263,7 +259,8 @@ impl Process {
* TerminateProcess(..) will be called. * TerminateProcess(..) will be called.
*/ */
pub fn destroy(&mut self) { 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(); self.finish();
} }
@ -275,8 +272,10 @@ impl Process {
* TerminateProcess(..) will be called. * TerminateProcess(..) will be called.
*/ */
pub fn force_destroy(&mut self) { 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(); self.finish();
} }
} }
@ -293,18 +292,14 @@ impl Process {
* *
* The process's exit code, or None if the child process could not be started * 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> { pub fn process_status(prog: &str, args: &[~str]) -> io::IoResult<ProcessExit> {
let mut opt_prog = Process::new(prog, args, ProcessOptions { Process::new(prog, args, ProcessOptions {
env: None, env: None,
dir: None, dir: None,
in_fd: Some(unsafe { libc::dup(libc::STDIN_FILENO) }), in_fd: Some(unsafe { libc::dup(libc::STDIN_FILENO) }),
out_fd: Some(unsafe { libc::dup(libc::STDOUT_FILENO) }), out_fd: Some(unsafe { libc::dup(libc::STDOUT_FILENO) }),
err_fd: Some(unsafe { libc::dup(libc::STDERR_FILENO) }) err_fd: Some(unsafe { libc::dup(libc::STDERR_FILENO) })
}); }).map(|mut p| p.finish())
match opt_prog {
Some(ref mut prog) => Some(prog.finish()),
None => None
}
} }
/** /**
@ -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 * The process's stdout/stderr output and exit code, or None if the child process could not be
* started. * started.
*/ */
pub fn process_output(prog: &str, args: &[~str]) -> Option<ProcessOutput> { pub fn process_output(prog: &str, args: &[~str]) -> io::IoResult<ProcessOutput> {
let mut opt_prog = Process::new(prog, args, ProcessOptions::new()); Process::new(prog, args, ProcessOptions::new()).map(|mut p| {
match opt_prog { p.finish_with_output()
Some(ref mut prog) => Some(prog.finish_with_output()), })
None => None
}
} }
#[cfg(test)] #[cfg(test)]

View file

@ -349,7 +349,7 @@ impl<A:IterBytes> ToBytes for A {
let mut m = ::io::MemWriter::new(); let mut m = ::io::MemWriter::new();
self.iter_bytes(lsb0, |bytes| { self.iter_bytes(lsb0, |bytes| {
m.write(bytes); m.write(bytes).unwrap();
true true
}); });
m.unwrap() m.unwrap()