From 13ae7391a55f0046caceddc598efc4b07d340eea Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 2 Sep 2020 11:51:39 +0200 Subject: [PATCH] Add format_to! macro It's a version of `format!` which allows appending to an existing `String`. Unlike `write!`, it doesn't require a trait import and unwrap. See https://internals.rust-lang.org/t/add-an-easier-way-to-append-t-display-to-string-to-stdlib/10607 for some preliminary discussion. See https://github.com/rust-analyzer/rust-analyzer/blob/3ffa915cbcf4d7a3988142cd94da0463acc87c8a/crates/stdx/src/macros.rs#L12-L19 for an equivalent macro used in rust-analyzer quite a bit. --- library/alloc/src/macros.rs | 25 +++++++++++++++++++++++++ library/alloc/src/string.rs | 6 ++++++ library/std/src/lib.rs | 3 +++ 3 files changed, 34 insertions(+) diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs index 2f744618d6936..2b72e24f24d59 100644 --- a/library/alloc/src/macros.rs +++ b/library/alloc/src/macros.rs @@ -107,3 +107,28 @@ macro_rules! format { res }} } + +/// Like [`format!`], but appends to an existing string +/// +/// +/// [`format!`]: crate::format +/// +/// # Examples +/// +/// ``` +/// #![feature(format_to)] +/// +/// let mut buf = String::new(); +/// format_to!(buf, "hello"); +/// format_to!(buf, ", world!"); +/// assert_eq!(buf, "hello, world!"); +/// ``` +#[macro_export] +#[unstable(feature = "format_to", issue = "none", reason = "new API")] +#[allow_internal_unstable(liballoc_internals)] +macro_rules! format_to { + ($buf:expr $(, $($arg:tt)*)? ) => {{ + // Redirect via method call syntax to get autoref behavior + $buf.__push_fmt($crate::__export::format_args!($($($arg)*)?)); + }} +} diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 1bec9e0ff26be..f0041e4596dc4 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -1585,6 +1585,12 @@ impl String { let slice = self.vec.into_boxed_slice(); unsafe { from_boxed_utf8_unchecked(slice) } } + + #[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")] + #[doc(hidden)] + pub fn __push_fmt(&mut self, args: fmt::Arguments<'_>) { + fmt::Write::write_fmt(self, args).unwrap(); + } } impl FromUtf8Error { diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 30e7a7f3c3b10..d99dc27bde009 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -261,6 +261,7 @@ #![feature(external_doc)] #![feature(fn_traits)] #![feature(format_args_nl)] +#![feature(format_to)] #![feature(gen_future)] #![feature(generator_trait)] #![feature(global_asm)] @@ -373,6 +374,8 @@ pub use alloc_crate::boxed; pub use alloc_crate::fmt; #[stable(feature = "rust1", since = "1.0.0")] pub use alloc_crate::format; +#[unstable(feature = "format_to", issue = "none", reason = "new API")] +pub use alloc_crate::format_to; #[stable(feature = "rust1", since = "1.0.0")] pub use alloc_crate::rc; #[stable(feature = "rust1", since = "1.0.0")]