Skip to content

Commit 295e573

Browse files
committed
Reserve before write_fmt for owned buffers
Reserve before formatting with `fmt::Arguments::estimated_capacity()` in `fmt::Write::write_fmt` and `io::Write::write_fmt` implementations for owned buffer types. Adding `#[inline]` to `write_fmt` shows minor perf regressions, so leave it off like the default impl.
1 parent a4a11ac commit 295e573

File tree

4 files changed

+56
-1
lines changed

4 files changed

+56
-1
lines changed

library/alloc/src/string.rs

+9
Original file line numberDiff line numberDiff line change
@@ -3172,6 +3172,15 @@ impl fmt::Write for String {
31723172
self.push(c);
31733173
Ok(())
31743174
}
3175+
3176+
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result {
3177+
if let Some(s) = args.as_statically_known_str() {
3178+
self.write_str(s)
3179+
} else {
3180+
self.reserve(args.estimated_capacity());
3181+
fmt::write(self, args)
3182+
}
3183+
}
31753184
}
31763185

31773186
/// An iterator over the [`char`]s of a string.

library/std/src/ffi/os_str.rs

+10
Original file line numberDiff line numberDiff line change
@@ -799,10 +799,20 @@ impl Hash for OsString {
799799

800800
#[stable(feature = "os_string_fmt_write", since = "1.64.0")]
801801
impl fmt::Write for OsString {
802+
#[inline]
802803
fn write_str(&mut self, s: &str) -> fmt::Result {
803804
self.push(s);
804805
Ok(())
805806
}
807+
808+
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result {
809+
if let Some(s) = args.as_statically_known_str() {
810+
self.write_str(s)
811+
} else {
812+
self.reserve(args.estimated_capacity());
813+
fmt::write(self, args)
814+
}
815+
}
806816
}
807817

808818
impl OsStr {

library/std/src/io/cursor.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
mod tests;
33

44
use crate::alloc::Allocator;
5-
use crate::cmp;
65
use crate::io::prelude::*;
76
use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut, SeekFrom};
7+
use crate::{cmp, fmt};
88

99
/// A `Cursor` wraps an in-memory buffer and provides it with a
1010
/// [`Seek`] implementation.
@@ -647,6 +647,15 @@ where
647647
Ok(())
648648
}
649649

650+
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
651+
if let Some(s) = args.as_statically_known_str() {
652+
self.write_all(s.as_bytes())
653+
} else {
654+
self.inner.reserve(args.estimated_capacity());
655+
io::default_write_fmt(self, args)
656+
}
657+
}
658+
650659
#[inline]
651660
fn flush(&mut self) -> io::Result<()> {
652661
Ok(())
@@ -681,6 +690,15 @@ where
681690
Ok(())
682691
}
683692

693+
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
694+
if let Some(s) = args.as_statically_known_str() {
695+
self.write_all(s.as_bytes())
696+
} else {
697+
self.inner.reserve(args.estimated_capacity());
698+
io::default_write_fmt(self, args)
699+
}
700+
}
701+
684702
#[inline]
685703
fn flush(&mut self) -> io::Result<()> {
686704
Ok(())

library/std/src/io/impls.rs

+18
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,15 @@ impl<A: Allocator> Write for Vec<u8, A> {
511511
Ok(())
512512
}
513513

514+
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
515+
if let Some(s) = args.as_statically_known_str() {
516+
self.write_all(s.as_bytes())
517+
} else {
518+
self.reserve(args.estimated_capacity());
519+
io::default_write_fmt(self, args)
520+
}
521+
}
522+
514523
#[inline]
515524
fn flush(&mut self) -> io::Result<()> {
516525
Ok(())
@@ -662,6 +671,15 @@ impl<A: Allocator> Write for VecDeque<u8, A> {
662671
Ok(())
663672
}
664673

674+
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
675+
if let Some(s) = args.as_statically_known_str() {
676+
self.write_all(s.as_bytes())
677+
} else {
678+
self.reserve(args.estimated_capacity());
679+
io::default_write_fmt(self, args)
680+
}
681+
}
682+
665683
#[inline]
666684
fn flush(&mut self) -> io::Result<()> {
667685
Ok(())

0 commit comments

Comments
 (0)