Skip to content

Commit 2cbd5d1

Browse files
committed
Specialize io::Bytes::size_hint for more types
1 parent 0279cb1 commit 2cbd5d1

File tree

4 files changed

+96
-3
lines changed

4 files changed

+96
-3
lines changed

library/std/src/io/buffered/bufreader.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,13 @@ impl<R: Seek> Seek for BufReader<R> {
438438
}
439439

440440
impl<T> SizeHint for BufReader<T> {
441+
#[inline]
441442
fn lower_bound(&self) -> usize {
442-
self.buffer().len()
443+
SizeHint::lower_bound(self.get_ref()) + self.buffer().len()
444+
}
445+
446+
#[inline]
447+
fn upper_bound(&self) -> Option<usize> {
448+
SizeHint::upper_bound(self.get_ref()).and_then(|up| self.buffer().len().checked_add(up))
443449
}
444450
}

library/std/src/io/mod.rs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@
252252
mod tests;
253253

254254
use crate::cmp;
255+
use crate::convert::TryInto;
255256
use crate::fmt;
256257
use crate::ops::{Deref, DerefMut};
257258
use crate::ptr;
@@ -2291,13 +2292,15 @@ impl<T: BufRead, U: BufRead> BufRead for Chain<T, U> {
22912292
}
22922293

22932294
impl<T, U> SizeHint for Chain<T, U> {
2295+
#[inline]
22942296
fn lower_bound(&self) -> usize {
22952297
SizeHint::lower_bound(&self.first) + SizeHint::lower_bound(&self.second)
22962298
}
22972299

2300+
#[inline]
22982301
fn upper_bound(&self) -> Option<usize> {
22992302
match (SizeHint::upper_bound(&self.first), SizeHint::upper_bound(&self.second)) {
2300-
(Some(first), Some(second)) => Some(first + second),
2303+
(Some(first), Some(second)) => first.checked_add(second),
23012304
_ => None,
23022305
}
23032306
}
@@ -2502,6 +2505,21 @@ impl<T: BufRead> BufRead for Take<T> {
25022505
}
25032506
}
25042507

2508+
impl<T> SizeHint for Take<T> {
2509+
#[inline]
2510+
fn lower_bound(&self) -> usize {
2511+
cmp::min(SizeHint::lower_bound(&self.inner) as u64, self.limit) as usize
2512+
}
2513+
2514+
#[inline]
2515+
fn upper_bound(&self) -> Option<usize> {
2516+
match SizeHint::upper_bound(&self.inner) {
2517+
Some(upper_bound) => Some(cmp::min(upper_bound as u64, self.limit) as usize),
2518+
None => self.limit.try_into().ok(),
2519+
}
2520+
}
2521+
}
2522+
25052523
/// An iterator over `u8` values of a reader.
25062524
///
25072525
/// This struct is generally created by calling [`bytes`] on a reader.
@@ -2546,15 +2564,53 @@ trait SizeHint {
25462564
}
25472565

25482566
impl<T> SizeHint for T {
2567+
#[inline]
25492568
default fn lower_bound(&self) -> usize {
25502569
0
25512570
}
25522571

2572+
#[inline]
25532573
default fn upper_bound(&self) -> Option<usize> {
25542574
None
25552575
}
25562576
}
25572577

2578+
impl<T> SizeHint for &mut T {
2579+
#[inline]
2580+
fn lower_bound(&self) -> usize {
2581+
SizeHint::lower_bound(*self)
2582+
}
2583+
2584+
#[inline]
2585+
fn upper_bound(&self) -> Option<usize> {
2586+
SizeHint::upper_bound(*self)
2587+
}
2588+
}
2589+
2590+
impl<T> SizeHint for Box<T> {
2591+
#[inline]
2592+
fn lower_bound(&self) -> usize {
2593+
SizeHint::lower_bound(&**self)
2594+
}
2595+
2596+
#[inline]
2597+
fn upper_bound(&self) -> Option<usize> {
2598+
SizeHint::upper_bound(&**self)
2599+
}
2600+
}
2601+
2602+
impl SizeHint for &[u8] {
2603+
#[inline]
2604+
fn lower_bound(&self) -> usize {
2605+
self.len()
2606+
}
2607+
2608+
#[inline]
2609+
fn upper_bound(&self) -> Option<usize> {
2610+
Some(self.len())
2611+
}
2612+
}
2613+
25582614
/// An iterator over the contents of an instance of `BufRead` split on a
25592615
/// particular byte.
25602616
///

library/std/src/io/tests.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,24 @@ fn empty_size_hint() {
224224
assert_eq!(size_hint, (0, Some(0)));
225225
}
226226

227+
#[test]
228+
fn slice_size_hint() {
229+
let size_hint = (&[1, 2, 3]).bytes().size_hint();
230+
assert_eq!(size_hint, (3, Some(3)));
231+
}
232+
233+
#[test]
234+
fn take_size_hint() {
235+
let size_hint = (&[1, 2, 3]).take(2).bytes().size_hint();
236+
assert_eq!(size_hint, (2, Some(2)));
237+
238+
let size_hint = (&[1, 2, 3]).take(4).bytes().size_hint();
239+
assert_eq!(size_hint, (3, Some(3)));
240+
241+
let size_hint = io::repeat(0).take(3).bytes().size_hint();
242+
assert_eq!(size_hint, (3, Some(3)));
243+
}
244+
227245
#[test]
228246
fn chain_empty_size_hint() {
229247
let chain = io::empty().chain(io::empty());
@@ -242,7 +260,7 @@ fn chain_size_hint() {
242260

243261
let chain = buf_reader_1.chain(buf_reader_2);
244262
let size_hint = chain.bytes().size_hint();
245-
assert_eq!(size_hint, (testdata.len(), None));
263+
assert_eq!(size_hint, (testdata.len(), Some(testdata.len())));
246264
}
247265

248266
#[test]

library/std/src/io/util.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ impl fmt::Debug for Empty {
8383
}
8484

8585
impl SizeHint for Empty {
86+
#[inline]
8687
fn upper_bound(&self) -> Option<usize> {
8788
Some(0)
8889
}
@@ -147,6 +148,18 @@ impl Read for Repeat {
147148
}
148149
}
149150

151+
impl SizeHint for Repeat {
152+
#[inline]
153+
fn lower_bound(&self) -> usize {
154+
usize::MAX
155+
}
156+
157+
#[inline]
158+
fn upper_bound(&self) -> Option<usize> {
159+
None
160+
}
161+
}
162+
150163
#[stable(feature = "std_debug", since = "1.16.0")]
151164
impl fmt::Debug for Repeat {
152165
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

0 commit comments

Comments
 (0)