Skip to content

Commit c16f480

Browse files
committed
Auto merge of #46485 - khuey:cursor-read_exact, r=Manishearth
Add a specialization of read_exact for Cursor. The read_exact implementation for &[u8] is optimized and usually allows LLVM to reduce a read_exact call for small numbers of bytes to a bounds check and a register load instead of a generic memcpy. On a workload I have that decompresses, deserializes (via bincode), and processes some data, this leads to a 40% speedup by essentially eliminating the deserialization overhead entirely.
2 parents fdfbcf8 + 02c1862 commit c16f480

File tree

1 file changed

+25
-0
lines changed

1 file changed

+25
-0
lines changed

src/libstd/io/cursor.rs

+25
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,13 @@ impl<T> Read for Cursor<T> where T: AsRef<[u8]> {
230230
Ok(n)
231231
}
232232

233+
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
234+
let n = buf.len();
235+
Read::read_exact(&mut self.fill_buf()?, buf)?;
236+
self.pos += n as u64;
237+
Ok(())
238+
}
239+
233240
#[inline]
234241
unsafe fn initializer(&self) -> Initializer {
235242
Initializer::nop()
@@ -475,6 +482,24 @@ mod tests {
475482
assert_eq!(reader.read(&mut buf).unwrap(), 0);
476483
}
477484

485+
#[test]
486+
fn test_read_exact() {
487+
let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
488+
let reader = &mut &in_buf[..];
489+
let mut buf = [];
490+
assert!(reader.read_exact(&mut buf).is_ok());
491+
let mut buf = [8];
492+
assert!(reader.read_exact(&mut buf).is_ok());
493+
assert_eq!(buf[0], 0);
494+
assert_eq!(reader.len(), 7);
495+
let mut buf = [0, 0, 0, 0, 0, 0, 0];
496+
assert!(reader.read_exact(&mut buf).is_ok());
497+
assert_eq!(buf, [1, 2, 3, 4, 5, 6, 7]);
498+
assert_eq!(reader.len(), 0);
499+
let mut buf = [0];
500+
assert!(reader.read_exact(&mut buf).is_err());
501+
}
502+
478503
#[test]
479504
fn test_buf_reader() {
480505
let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];

0 commit comments

Comments
 (0)