about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-05-21 00:47:01 +0200
committerGitHub <noreply@github.com>2024-05-21 00:47:01 +0200
commit62da957c92b28771337f99b6869ac3d1201681c4 (patch)
tree027204f85e3a422a3d6d8fdfebddfa23f0742843
parente275d2dad67cc6b1c5b64c731d6795c50e880cf8 (diff)
parenta197ff325989ed200fc4730d35501b9e4064316b (diff)
downloadrust-62da957c92b28771337f99b6869ac3d1201681c4.tar.gz
rust-62da957c92b28771337f99b6869ac3d1201681c4.zip
Rollup merge of #125123 - a1phyr:fix-read_exact, r=workingjubilee
Fix `read_exact` and `read_buf_exact` for `&[u8]` and `io:Cursor`

- Drain after `read_exact` and `read_buf_exact`
- Append to cursor in `read_buf_exact`
-rw-r--r--library/std/src/io/cursor.rs27
-rw-r--r--library/std/src/io/impls.rs6
-rw-r--r--library/std/src/io/tests.rs32
3 files changed, 55 insertions, 10 deletions
diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs
index 37492e9efab..a1a8b2a3505 100644
--- a/library/std/src/io/cursor.rs
+++ b/library/std/src/io/cursor.rs
@@ -328,7 +328,7 @@ where
     fn read_buf(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> {
         let prev_written = cursor.written();
 
-        Read::read_buf(&mut self.fill_buf()?, cursor.reborrow())?;
+        Read::read_buf(&mut self.remaining_slice(), cursor.reborrow())?;
 
         self.pos += (cursor.written() - prev_written) as u64;
 
@@ -352,17 +352,24 @@ where
     }
 
     fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
-        let n = buf.len();
-        Read::read_exact(&mut self.remaining_slice(), buf)?;
-        self.pos += n as u64;
-        Ok(())
+        let result = Read::read_exact(&mut self.remaining_slice(), buf);
+
+        match result {
+            Ok(_) => self.pos += buf.len() as u64,
+            // The only possible error condition is EOF, so place the cursor at "EOF"
+            Err(_) => self.pos = self.inner.as_ref().len() as u64,
+        }
+
+        result
     }
 
-    fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
-        let n = cursor.capacity();
-        Read::read_buf_exact(&mut self.remaining_slice(), cursor)?;
-        self.pos += n as u64;
-        Ok(())
+    fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> {
+        let prev_written = cursor.written();
+
+        let result = Read::read_buf_exact(&mut self.remaining_slice(), cursor.reborrow());
+        self.pos += (cursor.written() - prev_written) as u64;
+
+        result
     }
 
     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs
index 46f04c7cd39..a8a2e9413e1 100644
--- a/library/std/src/io/impls.rs
+++ b/library/std/src/io/impls.rs
@@ -287,6 +287,9 @@ impl Read for &[u8] {
     #[inline]
     fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
         if buf.len() > self.len() {
+            // `read_exact` makes no promise about the content of `buf` if it
+            // fails so don't bother about that.
+            *self = &self[self.len()..];
             return Err(io::Error::READ_EXACT_EOF);
         }
         let (a, b) = self.split_at(buf.len());
@@ -307,6 +310,9 @@ impl Read for &[u8] {
     #[inline]
     fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> {
         if cursor.capacity() > self.len() {
+            // Append everything we can to the cursor.
+            cursor.append(*self);
+            *self = &self[self.len()..];
             return Err(io::Error::READ_EXACT_EOF);
         }
         let (a, b) = self.split_at(cursor.capacity());
diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs
index 090a091b09a..a2c1c430863 100644
--- a/library/std/src/io/tests.rs
+++ b/library/std/src/io/tests.rs
@@ -653,6 +653,38 @@ fn test_take_wrong_length() {
     let _ = reader.read(&mut buffer[..]);
 }
 
+#[test]
+fn slice_read_exact_eof() {
+    let slice = &b"123456"[..];
+
+    let mut r = slice;
+    assert!(r.read_exact(&mut [0; 10]).is_err());
+    assert!(r.is_empty());
+
+    let mut r = slice;
+    let buf = &mut [0; 10];
+    let mut buf = BorrowedBuf::from(buf.as_mut_slice());
+    assert!(r.read_buf_exact(buf.unfilled()).is_err());
+    assert!(r.is_empty());
+    assert_eq!(buf.filled(), b"123456");
+}
+
+#[test]
+fn cursor_read_exact_eof() {
+    let slice = Cursor::new(b"123456");
+
+    let mut r = slice.clone();
+    assert!(r.read_exact(&mut [0; 10]).is_err());
+    assert!(r.is_empty());
+
+    let mut r = slice;
+    let buf = &mut [0; 10];
+    let mut buf = BorrowedBuf::from(buf.as_mut_slice());
+    assert!(r.read_buf_exact(buf.unfilled()).is_err());
+    assert!(r.is_empty());
+    assert_eq!(buf.filled(), b"123456");
+}
+
 #[bench]
 fn bench_take_read(b: &mut test::Bencher) {
     b.iter(|| {