diff options
| author | Piotr Czarnecki <pioczarn@gmail.com> | 2014-08-21 14:34:00 +0100 |
|---|---|---|
| committer | Piotr Czarnecki <pioczarn@gmail.com> | 2014-09-09 20:34:41 +0100 |
| commit | 696367fb8de63a3ff264c65981457b9fbd0e7b06 (patch) | |
| tree | 4b5d33c711873f1fd881300a13f91b7a90d12be7 /src/libcore/fmt | |
| parent | 6f34760e4173dda94162502153fe4c5a2a96fc9d (diff) | |
| download | rust-696367fb8de63a3ff264c65981457b9fbd0e7b06.tar.gz rust-696367fb8de63a3ff264c65981457b9fbd0e7b06.zip | |
Decouple string and argument pieces
Diffstat (limited to 'src/libcore/fmt')
| -rw-r--r-- | src/libcore/fmt/mod.rs | 71 | ||||
| -rw-r--r-- | src/libcore/fmt/rt.rs | 2 |
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), |
