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