summary refs log tree commit diff
path: root/src/libcore/fmt
diff options
context:
space:
mode:
authorPiotr Czarnecki <pioczarn@gmail.com>2014-08-21 14:34:00 +0100
committerPiotr Czarnecki <pioczarn@gmail.com>2014-09-09 20:34:41 +0100
commit696367fb8de63a3ff264c65981457b9fbd0e7b06 (patch)
tree4b5d33c711873f1fd881300a13f91b7a90d12be7 /src/libcore/fmt
parent6f34760e4173dda94162502153fe4c5a2a96fc9d (diff)
downloadrust-696367fb8de63a3ff264c65981457b9fbd0e7b06.tar.gz
rust-696367fb8de63a3ff264c65981457b9fbd0e7b06.zip
Decouple string and argument pieces
Diffstat (limited to 'src/libcore/fmt')
-rw-r--r--src/libcore/fmt/mod.rs71
-rw-r--r--src/libcore/fmt/rt.rs2
2 files changed, 72 insertions, 1 deletions
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 7c4494358b1..9f64e1aa492 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -113,6 +113,19 @@ impl<'a> Arguments<'a> {
     /// Arguments structure. The compiler inserts an `unsafe` block to call this,
     /// which is valid because the compiler performs all necessary validation to
     /// ensure that the resulting call to format/write would be safe.
+    #[cfg(not(stage0))]
+    #[doc(hidden)] #[inline]
+    pub unsafe fn new<'a>(pieces: &'static [&'static str],
+                          fmt: &'static [rt::Argument<'static>],
+                          args: &'a [Argument<'a>]) -> Arguments<'a> {
+        Arguments {
+            pieces: mem::transmute(pieces),
+            fmt: mem::transmute(fmt),
+            args: args
+        }
+    }
+
+    #[cfg(stage0)]
     #[doc(hidden)] #[inline]
     pub unsafe fn new<'a>(fmt: &'static [rt::Piece<'static>],
                           args: &'a [Argument<'a>]) -> Arguments<'a> {
@@ -129,6 +142,14 @@ impl<'a> Arguments<'a> {
 /// and pass it to a function or closure, passed as the first argument. The
 /// macro validates the format string at compile-time so usage of the `write`
 /// and `format` functions can be safely performed.
+#[cfg(not(stage0))]
+pub struct Arguments<'a> {
+    pieces: &'a [&'a str],
+    fmt: &'a [rt::Argument<'a>],
+    args: &'a [Argument<'a>],
+}
+
+#[cfg(stage0)] #[doc(hidden)]
 pub struct Arguments<'a> {
     fmt: &'a [rt::Piece<'a>],
     args: &'a [Argument<'a>],
@@ -263,6 +284,37 @@ uniform_fn_call_workaround! {
 ///
 ///   * output - the buffer to write output to
 ///   * args - the precompiled arguments generated by `format_args!`
+#[cfg(not(stage0))]
+pub fn write(output: &mut FormatWriter, args: &Arguments) -> Result {
+    let mut formatter = Formatter {
+        flags: 0,
+        width: None,
+        precision: None,
+        buf: output,
+        align: rt::AlignUnknown,
+        fill: ' ',
+        args: args.args,
+        curarg: args.args.iter(),
+    };
+
+    let mut pieces = args.pieces.iter();
+
+    for arg in args.fmt.iter() {
+        try!(formatter.buf.write(pieces.next().unwrap().as_bytes()));
+        try!(formatter.run(arg));
+    }
+
+    match pieces.next() {
+        Some(piece) => {
+            try!(formatter.buf.write(piece.as_bytes()));
+        }
+        None => {}
+    }
+
+    Ok(())
+}
+
+#[cfg(stage0)] #[doc(hidden)]
 pub fn write(output: &mut FormatWriter, args: &Arguments) -> Result {
     let mut formatter = Formatter {
         flags: 0,
@@ -285,7 +337,26 @@ impl<'a> Formatter<'a> {
     // First up is the collection of functions used to execute a format string
     // at runtime. This consumes all of the compile-time statics generated by
     // the format! syntax extension.
+    #[cfg(not(stage0))]
+    fn run(&mut self, arg: &rt::Argument) -> Result {
+        // Fill in the format parameters into the formatter
+        self.fill = arg.format.fill;
+        self.align = arg.format.align;
+        self.flags = arg.format.flags;
+        self.width = self.getcount(&arg.format.width);
+        self.precision = self.getcount(&arg.format.precision);
+
+        // Extract the correct argument
+        let value = match arg.position {
+            rt::ArgumentNext => { *self.curarg.next().unwrap() }
+            rt::ArgumentIs(i) => self.args[i],
+        };
+
+        // Then actually do some printing
+        (value.formatter)(value.value, self)
+    }
 
+    #[cfg(stage0)] #[doc(hidden)]
     fn run(&mut self, piece: &rt::Piece) -> Result {
         match *piece {
             rt::String(s) => self.buf.write(s.as_bytes()),
diff --git a/src/libcore/fmt/rt.rs b/src/libcore/fmt/rt.rs
index 1f5449130ec..59fbde88d8b 100644
--- a/src/libcore/fmt/rt.rs
+++ b/src/libcore/fmt/rt.rs
@@ -14,7 +14,7 @@
 //! These definitions are similar to their `ct` equivalents, but differ in that
 //! these can be statically allocated and are slightly optimized for the runtime
 
-
+#[cfg(stage0)]
 #[doc(hidden)]
 pub enum Piece<'a> {
     String(&'a str),