about summary refs log tree commit diff
path: root/library/std/src/io/buffered/bufreader.rs
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-01-17 14:50:24 +0000
committerbors <bors@rust-lang.org>2021-01-17 14:50:24 +0000
commitedeb631ad0cd6fdf31e2e31ec90e105d1768be28 (patch)
tree48c316c067559b3c58d2b652aa836953f0dced5b /library/std/src/io/buffered/bufreader.rs
parent7d3818152d8ab5649d2e5cc6d7851ed7c03055fe (diff)
parent801684620bd4e0bc12b98a071851e3d3064429e4 (diff)
Auto merge of #81113 - m-ou-se:rollup-a1unz4x, r=m-ou-se
Rollup of 13 pull requests

Successful merges:

 - #79298 (correctly deal with late-bound lifetimes in anon consts)
 - #80031 (resolve: Reject ambiguity built-in attr vs different built-in attr)
 - #80201 (Add benchmark and fast path for BufReader::read_exact)
 - #80635 (Improve diagnostics when closure doesn't meet trait bound)
 - #80765 (resolve: Simplify collection of traits in scope)
 - #80932 (Allow downloading LLVM on Windows and MacOS)
 - #80983 (Remove is_dllimport_foreign_item definition from cg_ssa)
 - #81064 (Support non-stage0 check)
 - #81080 (Force vec![] to expression position only)
 - #81082 (BTreeMap: clean up a few more comments)
 - #81084 (Use Option::map instead of open-coding it)
 - #81095 (Use Option::unwrap_or instead of open-coding it)
 - #81107 (Add NonZeroUn::is_power_of_two)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'library/std/src/io/buffered/bufreader.rs')
-rw-r--r--library/std/src/io/buffered/bufreader.rs14
1 files changed, 14 insertions, 0 deletions
diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs
index 16c18d6e146..8bae3da1273 100644
--- a/library/std/src/io/buffered/bufreader.rs
+++ b/library/std/src/io/buffered/bufreader.rs
@@ -271,6 +271,20 @@ impl<R: Read> Read for BufReader<R> {
         Ok(nread)
     }
 
+    // Small read_exacts from a BufReader are extremely common when used with a deserializer.
+    // The default implementation calls read in a loop, which results in surprisingly poor code
+    // generation for the common path where the buffer has enough bytes to fill the passed-in
+    // buffer.
+    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
+        if self.buffer().len() >= buf.len() {
+            buf.copy_from_slice(&self.buffer()[..buf.len()]);
+            self.consume(buf.len());
+            return Ok(());
+        }
+
+        crate::io::default_read_exact(self, buf)
+    }
+
     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
         if self.pos == self.cap && total_len >= self.buf.len() {