Skip to content

Commit 24978bd

Browse files
committed
Implement default methods for io::Empty and io::Sink
Eliminate any redundant, unobservable logic from the their default method implementations. The observable changes are that `Write::write_fmt` for both types now ignores the formatting arguments, so a user fmt impl which has side effects is not invoked, and `Write::write_all_vectored` for both types does not advance the borrowed buffers. Neither behavior is guaranteed by the docs and the latter is documented as unspecified. `Empty` is not marked as vectored, so that `Chain<Empty, _>` and `Chain<_, Empty>` are not forced to be vectored.
1 parent 2c6a12e commit 24978bd

File tree

3 files changed

+218
-13
lines changed

3 files changed

+218
-13
lines changed

library/std/src/io/util.rs

+116
Original file line numberDiff line numberDiff line change
@@ -68,27 +68,83 @@ impl Read for Empty {
6868
fn read_buf(&mut self, _cursor: BorrowedCursor<'_>) -> io::Result<()> {
6969
Ok(())
7070
}
71+
72+
#[inline]
73+
fn read_vectored(&mut self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
74+
Ok(0)
75+
}
76+
77+
#[inline]
78+
fn is_read_vectored(&self) -> bool {
79+
// Do not force `Chain<Empty, _>` / `Chain<_, Empty>` to use vectored
80+
// reads, unless the other reader is vectored.
81+
false
82+
}
83+
84+
#[inline]
85+
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
86+
if !buf.is_empty() { Err(io::Error::READ_EXACT_EOF) } else { Ok(()) }
87+
}
88+
89+
#[inline]
90+
fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
91+
if cursor.capacity() != 0 { Err(io::Error::READ_EXACT_EOF) } else { Ok(()) }
92+
}
93+
94+
#[inline]
95+
fn read_to_end(&mut self, _buf: &mut Vec<u8>) -> io::Result<usize> {
96+
Ok(0)
97+
}
98+
99+
#[inline]
100+
fn read_to_string(&mut self, _buf: &mut String) -> io::Result<usize> {
101+
Ok(0)
102+
}
71103
}
72104
#[stable(feature = "rust1", since = "1.0.0")]
73105
impl BufRead for Empty {
74106
#[inline]
75107
fn fill_buf(&mut self) -> io::Result<&[u8]> {
76108
Ok(&[])
77109
}
110+
78111
#[inline]
79112
fn consume(&mut self, _n: usize) {}
113+
114+
#[inline]
115+
fn has_data_left(&mut self) -> io::Result<bool> {
116+
Ok(false)
117+
}
118+
119+
#[inline]
120+
fn read_until(&mut self, _byte: u8, _buf: &mut Vec<u8>) -> io::Result<usize> {
121+
Ok(0)
122+
}
123+
124+
#[inline]
125+
fn skip_until(&mut self, _byte: u8) -> io::Result<usize> {
126+
Ok(0)
127+
}
128+
129+
#[inline]
130+
fn read_line(&mut self, _buf: &mut String) -> io::Result<usize> {
131+
Ok(0)
132+
}
80133
}
81134

82135
#[stable(feature = "empty_seek", since = "1.51.0")]
83136
impl Seek for Empty {
137+
#[inline]
84138
fn seek(&mut self, _pos: SeekFrom) -> io::Result<u64> {
85139
Ok(0)
86140
}
87141

142+
#[inline]
88143
fn stream_len(&mut self) -> io::Result<u64> {
89144
Ok(0)
90145
}
91146

147+
#[inline]
92148
fn stream_position(&mut self) -> io::Result<u64> {
93149
Ok(0)
94150
}
@@ -119,6 +175,21 @@ impl Write for Empty {
119175
true
120176
}
121177

178+
#[inline]
179+
fn write_all(&mut self, _buf: &[u8]) -> io::Result<()> {
180+
Ok(())
181+
}
182+
183+
#[inline]
184+
fn write_all_vectored(&mut self, _bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
185+
Ok(())
186+
}
187+
188+
#[inline]
189+
fn write_fmt(&mut self, _fmt: fmt::Arguments<'_>) -> io::Result<()> {
190+
Ok(())
191+
}
192+
122193
#[inline]
123194
fn flush(&mut self) -> io::Result<()> {
124195
Ok(())
@@ -143,6 +214,21 @@ impl Write for &Empty {
143214
true
144215
}
145216

217+
#[inline]
218+
fn write_all(&mut self, _buf: &[u8]) -> io::Result<()> {
219+
Ok(())
220+
}
221+
222+
#[inline]
223+
fn write_all_vectored(&mut self, _bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
224+
Ok(())
225+
}
226+
227+
#[inline]
228+
fn write_fmt(&mut self, _fmt: fmt::Arguments<'_>) -> io::Result<()> {
229+
Ok(())
230+
}
231+
146232
#[inline]
147233
fn flush(&mut self) -> io::Result<()> {
148234
Ok(())
@@ -302,6 +388,21 @@ impl Write for Sink {
302388
true
303389
}
304390

391+
#[inline]
392+
fn write_all(&mut self, _buf: &[u8]) -> io::Result<()> {
393+
Ok(())
394+
}
395+
396+
#[inline]
397+
fn write_all_vectored(&mut self, _bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
398+
Ok(())
399+
}
400+
401+
#[inline]
402+
fn write_fmt(&mut self, _fmt: fmt::Arguments<'_>) -> io::Result<()> {
403+
Ok(())
404+
}
405+
305406
#[inline]
306407
fn flush(&mut self) -> io::Result<()> {
307408
Ok(())
@@ -326,6 +427,21 @@ impl Write for &Sink {
326427
true
327428
}
328429

430+
#[inline]
431+
fn write_all(&mut self, _buf: &[u8]) -> io::Result<()> {
432+
Ok(())
433+
}
434+
435+
#[inline]
436+
fn write_all_vectored(&mut self, _bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
437+
Ok(())
438+
}
439+
440+
#[inline]
441+
fn write_fmt(&mut self, _fmt: fmt::Arguments<'_>) -> io::Result<()> {
442+
Ok(())
443+
}
444+
329445
#[inline]
330446
fn flush(&mut self) -> io::Result<()> {
331447
Ok(())

library/std/src/io/util/tests.rs

+100-11
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,51 @@
1+
use crate::fmt;
12
use crate::io::prelude::*;
2-
use crate::io::{BorrowedBuf, Empty, Repeat, SeekFrom, Sink, empty, repeat, sink};
3+
use crate::io::{
4+
BorrowedBuf, Empty, ErrorKind, IoSlice, IoSliceMut, Repeat, SeekFrom, Sink, empty, repeat, sink,
5+
};
36
use crate::mem::MaybeUninit;
47

8+
struct ErrorDisplay;
9+
10+
impl fmt::Display for ErrorDisplay {
11+
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
12+
Err(fmt::Error)
13+
}
14+
}
15+
16+
struct PanicDisplay;
17+
18+
impl fmt::Display for PanicDisplay {
19+
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
20+
panic!()
21+
}
22+
}
23+
24+
#[track_caller]
25+
fn test_sinking<W: Write>(mut w: W) {
26+
assert_eq!(w.write(&[]).unwrap(), 0);
27+
assert_eq!(w.write(&[0]).unwrap(), 1);
28+
assert_eq!(w.write(&[0; 1024]).unwrap(), 1024);
29+
w.write_all(&[]).unwrap();
30+
w.write_all(&[0]).unwrap();
31+
w.write_all(&[0; 1024]).unwrap();
32+
let mut bufs =
33+
[IoSlice::new(&[]), IoSlice::new(&[0]), IoSlice::new(&[0; 1024]), IoSlice::new(&[])];
34+
assert!(w.is_write_vectored());
35+
assert_eq!(w.write_vectored(&[]).unwrap(), 0);
36+
assert_eq!(w.write_vectored(&bufs).unwrap(), 1025);
37+
w.write_all_vectored(&mut []).unwrap();
38+
w.write_all_vectored(&mut bufs).unwrap();
39+
assert!(w.flush().is_ok());
40+
assert_eq!(w.by_ref().write(&[0; 1024]).unwrap(), 1024);
41+
// Ignores fmt arguments
42+
w.write_fmt(format_args!("{}", ErrorDisplay)).unwrap();
43+
w.write_fmt(format_args!("{}", PanicDisplay)).unwrap();
44+
}
45+
546
#[test]
647
fn sink_sinks() {
7-
let mut s = sink();
8-
assert_eq!(s.write(&[]).unwrap(), 0);
9-
assert_eq!(s.write(&[0]).unwrap(), 1);
10-
assert_eq!(s.write(&[0; 1024]).unwrap(), 1024);
11-
assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024);
48+
test_sinking(sink());
1249
}
1350

1451
#[test]
@@ -19,6 +56,21 @@ fn empty_reads() {
1956
assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0);
2057
assert_eq!(Read::by_ref(&mut e).read(&mut [0; 1024]).unwrap(), 0);
2158

59+
e.read_exact(&mut []).unwrap();
60+
assert_eq!(e.read_exact(&mut [0]).unwrap_err().kind(), ErrorKind::UnexpectedEof);
61+
assert_eq!(e.read_exact(&mut [0; 1024]).unwrap_err().kind(), ErrorKind::UnexpectedEof);
62+
63+
assert!(!e.is_read_vectored());
64+
assert_eq!(e.read_vectored(&mut []).unwrap(), 0);
65+
let (mut buf1, mut buf1024) = ([0], [0; 1024]);
66+
let bufs = &mut [
67+
IoSliceMut::new(&mut []),
68+
IoSliceMut::new(&mut buf1),
69+
IoSliceMut::new(&mut buf1024),
70+
IoSliceMut::new(&mut []),
71+
];
72+
assert_eq!(e.read_vectored(bufs).unwrap(), 0);
73+
2274
let buf: &mut [MaybeUninit<_>] = &mut [];
2375
let mut buf: BorrowedBuf<'_> = buf.into();
2476
e.read_buf(buf.unfilled()).unwrap();
@@ -42,6 +94,47 @@ fn empty_reads() {
4294
Read::by_ref(&mut e).read_buf(buf.unfilled()).unwrap();
4395
assert_eq!(buf.len(), 0);
4496
assert_eq!(buf.init_len(), 0);
97+
98+
let buf: &mut [MaybeUninit<_>] = &mut [];
99+
let mut buf: BorrowedBuf<'_> = buf.into();
100+
e.read_buf_exact(buf.unfilled()).unwrap();
101+
assert_eq!(buf.len(), 0);
102+
assert_eq!(buf.init_len(), 0);
103+
104+
let buf: &mut [_] = &mut [MaybeUninit::uninit()];
105+
let mut buf: BorrowedBuf<'_> = buf.into();
106+
assert_eq!(e.read_buf_exact(buf.unfilled()).unwrap_err().kind(), ErrorKind::UnexpectedEof);
107+
assert_eq!(buf.len(), 0);
108+
assert_eq!(buf.init_len(), 0);
109+
110+
let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1024];
111+
let mut buf: BorrowedBuf<'_> = buf.into();
112+
assert_eq!(e.read_buf_exact(buf.unfilled()).unwrap_err().kind(), ErrorKind::UnexpectedEof);
113+
assert_eq!(buf.len(), 0);
114+
assert_eq!(buf.init_len(), 0);
115+
116+
let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1024];
117+
let mut buf: BorrowedBuf<'_> = buf.into();
118+
assert_eq!(
119+
Read::by_ref(&mut e).read_buf_exact(buf.unfilled()).unwrap_err().kind(),
120+
ErrorKind::UnexpectedEof,
121+
);
122+
assert_eq!(buf.len(), 0);
123+
assert_eq!(buf.init_len(), 0);
124+
125+
let mut buf = Vec::new();
126+
assert_eq!(e.read_to_end(&mut buf).unwrap(), 0);
127+
assert_eq!(buf, vec![]);
128+
let mut buf = vec![1, 2, 3];
129+
assert_eq!(e.read_to_end(&mut buf).unwrap(), 0);
130+
assert_eq!(buf, vec![1, 2, 3]);
131+
132+
let mut buf = String::new();
133+
assert_eq!(e.read_to_string(&mut buf).unwrap(), 0);
134+
assert_eq!(buf, "");
135+
let mut buf = "hello".to_owned();
136+
assert_eq!(e.read_to_string(&mut buf).unwrap(), 0);
137+
assert_eq!(buf, "hello");
45138
}
46139

47140
#[test]
@@ -66,11 +159,7 @@ fn empty_seeks() {
66159

67160
#[test]
68161
fn empty_sinks() {
69-
let mut e = empty();
70-
assert_eq!(e.write(&[]).unwrap(), 0);
71-
assert_eq!(e.write(&[0]).unwrap(), 1);
72-
assert_eq!(e.write(&[0; 1024]).unwrap(), 1024);
73-
assert_eq!(Write::by_ref(&mut e).write(&[0; 1024]).unwrap(), 1024);
162+
test_sinking(empty());
74163
}
75164

76165
#[test]

tests/ui/write-fmt-errors.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#![feature(io_error_uncategorized)]
55

66
use std::fmt;
7-
use std::io::{self, Error, Write, sink};
7+
use std::io::{self, Error, Write};
88
use std::panic::catch_unwind;
99

1010
struct ErrorDisplay;
@@ -33,7 +33,7 @@ fn main() {
3333
assert!(res.is_err(), "writer error did not propagate");
3434

3535
// Test that the error from the formatter is detected.
36-
let res = catch_unwind(|| write!(sink(), "{} {} {}", 1, ErrorDisplay, "bar"));
36+
let res = catch_unwind(|| write!(vec![], "{} {} {}", 1, ErrorDisplay, "bar"));
3737
let err = res.expect_err("formatter error did not lead to panic").downcast::<&str>().unwrap();
3838
assert!(
3939
err.contains("formatting trait implementation returned an error"),

0 commit comments

Comments
 (0)