]> git.lizzy.rs Git - rust.git/blobdiff - src/libcore/fmt/mod.rs
rollup merge of #20482: kmcallister/macro-reform
[rust.git] / src / libcore / fmt / mod.rs
index 87fcb12e29f9c95ddc442e94899f7f1dd7d47890..951f5c29f00e8c923c5520e0bb9c0c341360f7b7 100644 (file)
 use option::Option;
 use option::Option::{Some, None};
 use ops::{Deref, FnOnce};
-use result::Result::{Ok, Err};
+use result::Result::Ok;
 use result;
 use slice::SliceExt;
 use slice;
-use str::{StrExt, Utf8Error};
+use str::{self, StrExt, Utf8Error};
+
+// NOTE: for old macros; remove after the next snapshot
+#[cfg(stage0)] use result::Result::Err;
 
 pub use self::num::radix;
 pub use self::num::Radix;
@@ -44,7 +47,7 @@
 /// occurred. Any extra information must be arranged to be transmitted through
 /// some other means.
 #[experimental = "core and I/O reconciliation may alter this definition"]
-#[deriving(Copy)]
+#[derive(Copy)]
 pub struct Error;
 
 /// A collection of methods that are required to format a message into a stream.
@@ -57,7 +60,7 @@
 /// library. The `write!` macro accepts an instance of `io::Writer`, and the
 /// `io::Writer` trait is favored over implementing this trait.
 #[experimental = "waiting for core and I/O reconciliation"]
-pub trait FormatWriter {
+pub trait Writer {
     /// Writes a slice of bytes into this writer, returning whether the write
     /// succeeded.
     ///
@@ -68,13 +71,32 @@ pub trait FormatWriter {
     /// # Errors
     ///
     /// This function will return an instance of `FormatError` on error.
-    fn write(&mut self, bytes: &[u8]) -> Result;
+    fn write_str(&mut self, s: &str) -> Result;
 
     /// Glue for usage of the `write!` macro with implementers of this trait.
     ///
     /// This method should generally not be invoked manually, but rather through
     /// the `write!` macro itself.
-    fn write_fmt(&mut self, args: Arguments) -> Result { write(self, args) }
+    fn write_fmt(&mut self, args: Arguments) -> Result {
+        // This Adapter is needed to allow `self` (of type `&mut
+        // Self`) to be cast to a FormatWriter (below) without
+        // requiring a `Sized` bound.
+        struct Adapter<'a,T: ?Sized +'a>(&'a mut T);
+
+        impl<'a, T: ?Sized> Writer for Adapter<'a, T>
+            where T: Writer
+        {
+            fn write_str(&mut self, s: &str) -> Result {
+                self.0.write_str(s)
+            }
+
+            fn write_fmt(&mut self, args: Arguments) -> Result {
+                self.0.write_fmt(args)
+            }
+        }
+
+        write(&mut Adapter(self), args)
+    }
 }
 
 /// A struct to represent both where to emit formatting strings to and how they
@@ -88,7 +110,7 @@ pub struct Formatter<'a> {
     width: Option<uint>,
     precision: Option<uint>,
 
-    buf: &'a mut (FormatWriter+'a),
+    buf: &'a mut (Writer+'a),
     curarg: slice::Iter<'a, Argument<'a>>,
     args: &'a [Argument<'a>],
 }
@@ -103,7 +125,7 @@ enum Void {}
 /// 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.
 #[experimental = "implementation detail of the `format_args!` macro"]
-#[deriving(Copy)]
+#[derive(Copy)]
 pub struct Argument<'a> {
     value: &'a Void,
     formatter: fn(&Void, &mut Formatter) -> Result,
@@ -180,7 +202,7 @@ pub fn with_placeholders(pieces: &'a [&'a str],
 /// macro validates the format string at compile-time so usage of the `write`
 /// and `format` functions can be safely performed.
 #[stable]
-#[deriving(Copy)]
+#[derive(Copy)]
 pub struct Arguments<'a> {
     // Format string pieces to print.
     pieces: &'a [&'a str],
@@ -203,7 +225,7 @@ fn fmt(&self, fmt: &mut Formatter) -> Result {
 /// 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.
 #[unstable = "I/O and core have yet to be reconciled"]
-pub trait Show for Sized? {
+pub trait Show {
     /// Formats the value using the given formatter.
     fn fmt(&self, &mut Formatter) -> Result;
 }
@@ -211,64 +233,53 @@ pub trait Show for Sized? {
 
 /// Format trait for the `o` character
 #[unstable = "I/O and core have yet to be reconciled"]
-pub trait Octal for Sized? {
+pub trait Octal {
     /// Formats the value using the given formatter.
     fn fmt(&self, &mut Formatter) -> Result;
 }
 
 /// Format trait for the `b` character
 #[unstable = "I/O and core have yet to be reconciled"]
-pub trait Binary for Sized? {
+pub trait Binary {
     /// Formats the value using the given formatter.
     fn fmt(&self, &mut Formatter) -> Result;
 }
 
 /// Format trait for the `x` character
 #[unstable = "I/O and core have yet to be reconciled"]
-pub trait LowerHex for Sized? {
+pub trait LowerHex {
     /// Formats the value using the given formatter.
     fn fmt(&self, &mut Formatter) -> Result;
 }
 
 /// Format trait for the `X` character
 #[unstable = "I/O and core have yet to be reconciled"]
-pub trait UpperHex for Sized? {
+pub trait UpperHex {
     /// Formats the value using the given formatter.
     fn fmt(&self, &mut Formatter) -> Result;
 }
 
 /// Format trait for the `p` character
 #[unstable = "I/O and core have yet to be reconciled"]
-pub trait Pointer for Sized? {
+pub trait Pointer {
     /// Formats the value using the given formatter.
     fn fmt(&self, &mut Formatter) -> Result;
 }
 
 /// Format trait for the `e` character
 #[unstable = "I/O and core have yet to be reconciled"]
-pub trait LowerExp for Sized? {
+pub trait LowerExp {
     /// Formats the value using the given formatter.
     fn fmt(&self, &mut Formatter) -> Result;
 }
 
 /// Format trait for the `E` character
 #[unstable = "I/O and core have yet to be reconciled"]
-pub trait UpperExp for Sized? {
+pub trait UpperExp {
     /// Formats the value using the given formatter.
     fn fmt(&self, &mut Formatter) -> Result;
 }
 
-static DEFAULT_ARGUMENT: rt::Argument<'static> = rt::Argument {
-    position: rt::ArgumentNext,
-    format: rt::FormatSpec {
-        fill: ' ',
-        align: rt::AlignUnknown,
-        flags: 0,
-        precision: rt::CountImplied,
-        width: rt::CountImplied,
-    }
-};
-
 /// The `write` function takes an output stream, a precompiled format string,
 /// and a list of arguments. The arguments will be formatted according to the
 /// specified format string into the output stream provided.
@@ -279,7 +290,7 @@ pub trait UpperExp for Sized? {
 ///   * args - the precompiled arguments generated by `format_args!`
 #[experimental = "libcore and I/O have yet to be reconciled, and this is an \
                   implementation detail which should not otherwise be exported"]
-pub fn write(output: &mut FormatWriter, args: Arguments) -> Result {
+pub fn write(output: &mut Writer, args: Arguments) -> Result {
     let mut formatter = Formatter {
         flags: 0,
         width: None,
@@ -296,16 +307,16 @@ pub fn write(output: &mut FormatWriter, args: Arguments) -> Result {
     match args.fmt {
         None => {
             // We can use default formatting parameters for all arguments.
-            for _ in range(0, args.args.len()) {
-                try!(formatter.buf.write(pieces.next().unwrap().as_bytes()));
-                try!(formatter.run(&DEFAULT_ARGUMENT));
+            for (arg, piece) in args.args.iter().zip(pieces.by_ref()) {
+                try!(formatter.buf.write_str(*piece));
+                try!((arg.formatter)(arg.value, &mut formatter));
             }
         }
         Some(fmt) => {
             // Every spec has a corresponding argument that is preceded by
             // a string piece.
             for (arg, piece) in fmt.iter().zip(pieces.by_ref()) {
-                try!(formatter.buf.write(piece.as_bytes()));
+                try!(formatter.buf.write_str(*piece));
                 try!(formatter.run(arg));
             }
         }
@@ -314,7 +325,7 @@ pub fn write(output: &mut FormatWriter, args: Arguments) -> Result {
     // There can be only one trailing string piece left.
     match pieces.next() {
         Some(piece) => {
-            try!(formatter.buf.write(piece.as_bytes()));
+            try!(formatter.buf.write_str(*piece));
         }
         None => {}
     }
@@ -378,9 +389,9 @@ fn getcount(&mut self, cnt: &rt::Count) -> Option<uint> {
     pub fn pad_integral(&mut self,
                         is_positive: bool,
                         prefix: &str,
-                        buf: &[u8])
+                        buf: &str)
                         -> Result {
-        use char::Char;
+        use char::CharExt;
         use fmt::rt::{FlagAlternate, FlagSignPlus, FlagSignAwareZeroPad};
 
         let mut width = buf.len();
@@ -402,9 +413,10 @@ pub fn pad_integral(&mut self,
             for c in sign.into_iter() {
                 let mut b = [0; 4];
                 let n = c.encode_utf8(&mut b).unwrap_or(0);
-                try!(f.buf.write(b[..n]));
+                let b = unsafe { str::from_utf8_unchecked(b[0..n]) };
+                try!(f.buf.write_str(b));
             }
-            if prefixed { f.buf.write(prefix.as_bytes()) }
+            if prefixed { f.buf.write_str(prefix) }
             else { Ok(()) }
         };
 
@@ -413,24 +425,26 @@ pub fn pad_integral(&mut self,
             // If there's no minimum length requirements then we can just
             // write the bytes.
             None => {
-                try!(write_prefix(self)); self.buf.write(buf)
+                try!(write_prefix(self)); self.buf.write_str(buf)
             }
             // Check if we're over the minimum width, if so then we can also
             // just write the bytes.
             Some(min) if width >= min => {
-                try!(write_prefix(self)); self.buf.write(buf)
+                try!(write_prefix(self)); self.buf.write_str(buf)
             }
             // The sign and prefix goes before the padding if the fill character
             // is zero
             Some(min) if self.flags & (1 << (FlagSignAwareZeroPad as uint)) != 0 => {
                 self.fill = '0';
                 try!(write_prefix(self));
-                self.with_padding(min - width, rt::AlignRight, |f| f.buf.write(buf))
+                self.with_padding(min - width, rt::AlignRight, |f| {
+                    f.buf.write_str(buf)
+                })
             }
             // Otherwise, the sign and prefix goes after the padding
             Some(min) => {
                 self.with_padding(min - width, rt::AlignRight, |f| {
-                    try!(write_prefix(f)); f.buf.write(buf)
+                    try!(write_prefix(f)); f.buf.write_str(buf)
                 })
             }
         }
@@ -451,7 +465,7 @@ pub fn pad_integral(&mut self,
     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() {
-            return self.buf.write(s.as_bytes());
+            return self.buf.write_str(s);
         }
         // The `precision` field can be interpreted as a `max-width` for the
         // string being formatted
@@ -463,7 +477,7 @@ pub fn pad(&mut self, s: &str) -> Result {
                 let char_len = s.char_len();
                 if char_len >= max {
                     let nchars = ::cmp::min(max, char_len);
-                    return self.buf.write(s.slice_chars(0, nchars).as_bytes());
+                    return self.buf.write_str(s.slice_chars(0, nchars));
                 }
             }
             None => {}
@@ -472,17 +486,17 @@ pub fn pad(&mut self, s: &str) -> Result {
         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_str(s),
             // 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.
             Some(width) if s.char_len() >= width => {
-                self.buf.write(s.as_bytes())
+                self.buf.write_str(s)
             }
             // If we're under both the maximum and the minimum width, then fill
             // up the minimum width with the specified string + some alignment.
             Some(width) => {
                 self.with_padding(width - s.char_len(), rt::AlignLeft, |me| {
-                    me.buf.write(s.as_bytes())
+                    me.buf.write_str(s)
                 })
             }
         }
@@ -493,7 +507,7 @@ pub fn pad(&mut self, s: &str) -> Result {
     fn with_padding<F>(&mut self, padding: uint, default: rt::Alignment, f: F) -> Result where
         F: FnOnce(&mut Formatter) -> Result,
     {
-        use char::Char;
+        use char::CharExt;
         let align = match self.align {
             rt::AlignUnknown => default,
             _ => self.align
@@ -507,15 +521,16 @@ fn with_padding<F>(&mut self, padding: uint, default: rt::Alignment, f: F) -> Re
 
         let mut fill = [0u8; 4];
         let len = self.fill.encode_utf8(&mut fill).unwrap_or(0);
+        let fill = unsafe { str::from_utf8_unchecked(fill[..len]) };
 
         for _ in range(0, pre_pad) {
-            try!(self.buf.write(fill[..len]));
+            try!(self.buf.write_str(fill));
         }
 
         try!(f(self));
 
         for _ in range(0, post_pad) {
-            try!(self.buf.write(fill[..len]));
+            try!(self.buf.write_str(fill));
         }
 
         Ok(())
@@ -524,8 +539,8 @@ fn with_padding<F>(&mut self, padding: uint, default: rt::Alignment, f: F) -> Re
     /// Writes some data to the underlying buffer contained within this
     /// formatter.
     #[unstable = "reconciling core and I/O may alter this definition"]
-    pub fn write(&mut self, data: &[u8]) -> Result {
-        self.buf.write(data)
+    pub fn write_str(&mut self, data: &str) -> Result {
+        self.buf.write_str(data)
     }
 
     /// Writes some formatted information into this instance
@@ -580,15 +595,12 @@ pub fn argumentuint<'a>(s: &'a uint) -> Argument<'a> {
 
 // Implementations of the core formatting traits
 
-impl<'a, Sized? T: Show> Show for &'a T {
+impl<'a, T: ?Sized + Show> Show for &'a T {
     fn fmt(&self, f: &mut Formatter) -> Result { (**self).fmt(f) }
 }
-impl<'a, Sized? T: Show> Show for &'a mut T {
+impl<'a, T: ?Sized + Show> Show for &'a mut T {
     fn fmt(&self, f: &mut Formatter) -> Result { (**self).fmt(f) }
 }
-impl<'a> Show for &'a (Show+'a) {
-    fn fmt(&self, f: &mut Formatter) -> Result { (*self).fmt(f) }
-}
 
 impl Show for bool {
     fn fmt(&self, f: &mut Formatter) -> Result {
@@ -604,7 +616,7 @@ fn fmt(&self, f: &mut Formatter) -> Result {
 
 impl Show for char {
     fn fmt(&self, f: &mut Formatter) -> Result {
-        use char::Char;
+        use char::CharExt;
 
         let mut utf8 = [0u8; 4];
         let amt = self.encode_utf8(&mut utf8).unwrap_or(0);
@@ -616,7 +628,9 @@ fn fmt(&self, f: &mut Formatter) -> Result {
 impl<T> Pointer for *const T {
     fn fmt(&self, f: &mut Formatter) -> Result {
         f.flags |= 1 << (rt::FlagAlternate as uint);
-        LowerHex::fmt(&(*self as uint), f)
+        let ret = LowerHex::fmt(&(*self as uint), f);
+        f.flags &= !(1 << (rt::FlagAlternate as uint));
+        ret
     }
 }