Skip to content

Commit 8ccbf4f

Browse files
committed
Make String formatting available without libstd
Fixes rust-lang#14342.
1 parent 3372046 commit 8ccbf4f

File tree

9 files changed

+118
-23
lines changed

9 files changed

+118
-23
lines changed

src/libcollections/lib.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -556,22 +556,22 @@ pub trait Deque<T> : MutableSeq<T> {
556556
#[doc(hidden)]
557557
pub fn fixme_14344_be_sure_to_link_to_collections() {}
558558

559+
// NOTE: Remove after next snapshot
560+
#[cfg(stage0)]
559561
#[cfg(not(test))]
560562
mod std {
561-
// NOTE: Remove after next snapshot
562-
#[cfg(stage0)] pub use core::option; // necessary for fail!()
563-
#[cfg(stage0)] pub use core::clone; // deriving(Clone)
564-
#[cfg(stage0)] pub use core::cmp; // deriving(Eq, Ord, etc.)
565-
#[cfg(stage0)] pub use hash; // deriving(Hash)
566-
563+
pub use core::option; // necessary for fail!()
567564
pub use core::fmt; // necessary for fail!()
565+
pub use core::clone; // deriving(Clone)
566+
pub use core::cmp; // deriving(Eq, Ord, etc.)
567+
pub use hash; // deriving(Hash)
568568

569-
#[cfg(stage0)]
570569
pub mod collections {
571570
pub use MutableSeq;
572571
}
573572
}
574573

575574
mod collections {
576-
pub use hash; // deriving(Hsah)
575+
pub use hash; // deriving(Hsah)
576+
pub use string; // format!()
577577
}

src/libcollections/macros.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,20 @@ macro_rules! vec(
2020
});
2121
($($e:expr),+,) => (vec!($($e),+))
2222
)
23+
24+
/// Use the syntax described in `core::fmt` to create a value of type `String`.
25+
/// See `core::fmt` for more information.
26+
///
27+
/// # Example
28+
///
29+
/// ```
30+
/// format!("test");
31+
/// format!("hello {}", "world!");
32+
/// format!("x = {}, y = {y}", 10i, y = 30i);
33+
/// ```
34+
#[macro_export]
35+
macro_rules! format(
36+
($($arg:tt)*) => (
37+
format_args!(::collections::string::String::format, $($arg)*)
38+
)
39+
)

src/libcollections/string.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use core::prelude::*;
1616

1717
use core::default::Default;
1818
use core::fmt;
19+
use core::fmt::FormatWriter;
1920
use core::mem;
2021
use core::ptr;
2122
// FIXME: ICE's abound if you import the `Slice` type while importing `Slice` trait
@@ -726,6 +727,28 @@ impl String {
726727
pub unsafe fn as_mut_vec<'a>(&'a mut self) -> &'a mut Vec<u8> {
727728
&mut self.vec
728729
}
730+
731+
/// The format function takes a precompiled format string and a list of
732+
/// arguments, to return the resulting formatted string.
733+
///
734+
/// # Arguments
735+
///
736+
/// * args - a structure of arguments generated via the `format_args!` macro.
737+
/// Because this structure can only be safely generated at
738+
/// compile-time, this function is safe.
739+
///
740+
/// # Example
741+
///
742+
/// ```rust
743+
/// let s = format_args!(String::format, "Hello, {}!", "world");
744+
/// assert_eq!(s, "Hello, world!".to_string());
745+
/// ```
746+
pub fn format(args: &fmt::Arguments) -> String {
747+
let mut output = vec!();
748+
let _ = write!(&mut output, "{}", args);
749+
String::from_utf8(output)
750+
.ok().expect("non-utf8 result from write!()")
751+
}
729752
}
730753

731754
impl Collection for String {
@@ -1142,6 +1165,12 @@ mod tests {
11421165
assert_eq!(b.as_slice(), "1234522");
11431166
}
11441167

1168+
#[test]
1169+
fn test_format() {
1170+
let s = format_args!(String::format, "Hello, {}!", "world");
1171+
assert_eq!(s.as_slice(), "Hello, world!");
1172+
}
1173+
11451174
#[bench]
11461175
fn bench_with_capacity(b: &mut Bencher) {
11471176
b.iter(|| {

src/libcollections/vec.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,6 +1611,13 @@ impl<T> MutableSeq<T> for Vec<T> {
16111611

16121612
}
16131613

1614+
impl fmt::FormatWriter for Vec<u8> {
1615+
fn write(&mut self, bytes: &[u8]) -> fmt::Result {
1616+
self.push_all(bytes);
1617+
Ok(())
1618+
}
1619+
}
1620+
16141621
/// An iterator that moves out of a vector.
16151622
pub struct MoveItems<T> {
16161623
allocation: *mut T, // the block of memory allocated for the vector
@@ -2041,6 +2048,14 @@ mod tests {
20412048
assert_eq!(vec.len(), 0);
20422049
}
20432050

2051+
#[test]
2052+
fn test_format_writer() {
2053+
use core::fmt::FormatWriter;
2054+
let mut vec: Vec<u8> = vec!(b'x', b'y');
2055+
vec.write("abc".as_bytes());
2056+
assert_eq!(vec.as_slice(), b"xyabc");
2057+
}
2058+
20442059
#[bench]
20452060
fn bench_new(b: &mut Bencher) {
20462061
b.iter(|| {

src/libcore/lib.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -133,14 +133,14 @@ pub mod tuple;
133133
pub mod unit;
134134
pub mod fmt;
135135

136+
// NOTE: Remove after next snapshot
136137
#[doc(hidden)]
138+
#[cfg(stage0)]
137139
mod std {
138-
// NOTE: Remove after next snapshot
139-
#[cfg(stage0)] pub use clone;
140-
#[cfg(stage0)] pub use cmp;
141-
#[cfg(stage0)] pub use kinds;
142-
#[cfg(stage0)] pub use option;
143-
140+
pub use clone;
141+
pub use cmp;
142+
pub use kinds;
143+
pub use option;
144144
pub use fmt;
145145
}
146146

src/libcore/macros.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ macro_rules! fail(
3838
// insufficient, since the user may have
3939
// `#[forbid(dead_code)]` and which cannot be overridden.
4040
#[inline(always)]
41-
fn _run_fmt(fmt: &::std::fmt::Arguments) -> ! {
41+
fn _run_fmt(fmt: &::core::fmt::Arguments) -> ! {
4242
static _FILE_LINE: (&'static str, uint) = (file!(), line!());
4343
::core::failure::begin_unwind(fmt, &_FILE_LINE)
4444
}

src/librustrt/lib.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,9 @@ pub mod shouldnt_be_public {
164164
pub use super::local_ptr::compiled::RT_TLS_PTR;
165165
}
166166

167+
// NOTE: Remove after next snapshot
168+
#[cfg(stage0)]
167169
#[cfg(not(test))]
168170
mod std {
169-
// NOTE: Remove after next snapshot
170-
#[cfg(stage0)] pub use core::{option, cmp};
171-
172-
pub use core::fmt;
171+
pub use core::{fmt, option, cmp};
173172
}

src/libstd/fmt.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -459,10 +459,8 @@ pub use core::fmt::{secret_pointer};
459459
/// let s = format_args!(fmt::format, "Hello, {}!", "world");
460460
/// assert_eq!(s, "Hello, world!".to_string());
461461
/// ```
462-
pub fn format(args: &Arguments) -> string::String{
463-
let mut output = io::MemWriter::new();
464-
let _ = write!(&mut output, "{}", args);
465-
string::String::from_utf8(output.unwrap()).unwrap()
462+
pub fn format(args: &Arguments) -> string::String {
463+
string::String::format(args)
466464
}
467465

468466
impl<'a> Writer for Formatter<'a> {

src/test/run-pass/format-no-std.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(phase)]
12+
#![deny(warnings)]
13+
#![no_std]
14+
15+
#[phase(plugin, link)]
16+
extern crate core;
17+
18+
#[phase(plugin, link)]
19+
extern crate collections;
20+
21+
extern crate native;
22+
23+
use core::str::Str;
24+
25+
pub fn main() {
26+
let s = format!("{}", 1i);
27+
assert_eq!(s.as_slice(), "1");
28+
29+
let s = format!("test");
30+
assert_eq!(s.as_slice(), "test");
31+
32+
let s = format!("{test}", test=3i);
33+
assert_eq!(s.as_slice(), "3");
34+
35+
let s = format!("hello {}", "world");
36+
assert_eq!(s.as_slice(), "hello world");
37+
}

0 commit comments

Comments
 (0)