Skip to content

Commit 44c93ce

Browse files
committed
Add Read::size_hint, similar to Iterator::size_hint
1 parent 7c09cd5 commit 44c93ce

File tree

5 files changed

+65
-0
lines changed

5 files changed

+65
-0
lines changed

src/libstd/fs.rs

+11
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,13 @@ impl Read for File {
449449
self.inner.read(buf)
450450
}
451451

452+
fn size_hint(&self) -> usize {
453+
match self.metadata() {
454+
Ok(meta) => meta.len() as usize,
455+
Err(_) => 0,
456+
}
457+
}
458+
452459
#[inline]
453460
unsafe fn initializer(&self) -> Initializer {
454461
Initializer::nop()
@@ -473,6 +480,10 @@ impl<'a> Read for &'a File {
473480
self.inner.read(buf)
474481
}
475482

483+
fn size_hint(&self) -> usize {
484+
(**self).size_hint()
485+
}
486+
476487
#[inline]
477488
unsafe fn initializer(&self) -> Initializer {
478489
Initializer::nop()

src/libstd/io/buffered.rs

+6
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,12 @@ impl<R: Read> Read for BufReader<R> {
211211
Ok(nread)
212212
}
213213

214+
#[inline]
215+
fn size_hint(&self) -> usize {
216+
let buffered_len = self.cap - self.pos;
217+
buffered_len.saturating_add(self.inner.size_hint())
218+
}
219+
214220
// we can't skip unconditionally because of the large buffer case in read.
215221
unsafe fn initializer(&self) -> Initializer {
216222
self.inner.initializer()

src/libstd/io/cursor.rs

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

233+
fn size_hint(&self) -> usize {
234+
(self.inner.as_ref().len() as u64).saturating_sub(self.pos) as usize
235+
}
236+
233237
#[inline]
234238
unsafe fn initializer(&self) -> Initializer {
235239
Initializer::nop()

src/libstd/io/impls.rs

+15
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ impl<'a, R: Read + ?Sized> Read for &'a mut R {
2323
(**self).read(buf)
2424
}
2525

26+
#[inline]
27+
fn size_hint(&self) -> usize {
28+
(**self).size_hint()
29+
}
30+
2631
#[inline]
2732
unsafe fn initializer(&self) -> Initializer {
2833
(**self).initializer()
@@ -92,6 +97,11 @@ impl<R: Read + ?Sized> Read for Box<R> {
9297
(**self).read(buf)
9398
}
9499

100+
#[inline]
101+
fn size_hint(&self) -> usize {
102+
(**self).size_hint()
103+
}
104+
95105
#[inline]
96106
unsafe fn initializer(&self) -> Initializer {
97107
(**self).initializer()
@@ -181,6 +191,11 @@ impl<'a> Read for &'a [u8] {
181191
Ok(amt)
182192
}
183193

194+
#[inline]
195+
fn size_hint(&self) -> usize {
196+
self.len()
197+
}
198+
184199
#[inline]
185200
unsafe fn initializer(&self) -> Initializer {
186201
Initializer::nop()

src/libstd/io/mod.rs

+29
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,19 @@ pub trait Read {
544544
Initializer::zeroing()
545545
}
546546

547+
/// Return an estimate of how many bytes would be read from this source until EOF,
548+
/// or zero if that is unknown.
549+
///
550+
/// This is used by [`read_to_end`] and [`read_to_string`] to pre-allocate a memory buffer.
551+
///
552+
/// [`read_to_end`]: #method.read_to_end
553+
/// [`read_to_string`]: #method.read_to_string
554+
#[unstable(feature = "read_size_hint", issue = /* FIXME */ "0")]
555+
#[inline]
556+
fn size_hint(&self) -> usize {
557+
0
558+
}
559+
547560
/// Read all bytes until EOF in this source, placing them into `buf`.
548561
///
549562
/// All bytes read from this source will be appended to the specified buffer
@@ -1720,6 +1733,14 @@ impl<T: Read, U: Read> Read for Chain<T, U> {
17201733
self.second.read(buf)
17211734
}
17221735

1736+
fn size_hint(&self) -> usize {
1737+
if self.done_first {
1738+
self.second.size_hint()
1739+
} else {
1740+
self.first.size_hint().saturating_add(self.second.size_hint())
1741+
}
1742+
}
1743+
17231744
unsafe fn initializer(&self) -> Initializer {
17241745
let initializer = self.first.initializer();
17251746
if initializer.should_initialize() {
@@ -1918,6 +1939,14 @@ impl<T: Read> Read for Take<T> {
19181939
Ok(n)
19191940
}
19201941

1942+
fn size_hint(&self) -> usize {
1943+
if self.limit == 0 {
1944+
0
1945+
} else {
1946+
cmp::min(self.limit, self.inner.size_hint() as u64) as usize
1947+
}
1948+
}
1949+
19211950
unsafe fn initializer(&self) -> Initializer {
19221951
self.inner.initializer()
19231952
}

0 commit comments

Comments
 (0)