|
| 1 | +pub use crate::stream::Stream; |
| 2 | + |
| 3 | +/// A stream that knows its exact length. |
| 4 | +/// |
| 5 | +/// Many [`Stream`]s don't know how many times they will iterate, but some do. |
| 6 | +/// If a stream knows how many times it can iterate, providing access to |
| 7 | +/// that information can be useful. For example, if you want to iterate |
| 8 | +/// backwards, a good start is to know where the end is. |
| 9 | +/// |
| 10 | +/// When implementing an `ExactSizeStream`, you must also implement |
| 11 | +/// [`Stream`]. When doing so, the implementation of [`size_hint`] *must* |
| 12 | +/// return the exact size of the stream. |
| 13 | +/// |
| 14 | +/// [`Stream`]: trait.Stream.html |
| 15 | +/// [`size_hint`]: trait.Stream.html#method.size_hint |
| 16 | +/// |
| 17 | +/// The [`len`] method has a default implementation, so you usually shouldn't |
| 18 | +/// implement it. However, you may be able to provide a more performant |
| 19 | +/// implementation than the default, so overriding it in this case makes sense. |
| 20 | +/// |
| 21 | +/// [`len`]: #method.len |
| 22 | +/// |
| 23 | +/// # Examples |
| 24 | +/// |
| 25 | +/// Basic usage: |
| 26 | +/// |
| 27 | +/// ``` |
| 28 | +/// // a finite range knows exactly how many times it will iterate |
| 29 | +/// let five = 0..5; |
| 30 | +/// |
| 31 | +/// assert_eq!(5, five.len()); |
| 32 | +/// ``` |
| 33 | +/// |
| 34 | +/// In the [module level docs][moddocs], we implemented an [`Stream`], |
| 35 | +/// `Counter`. Let's implement `ExactSizeStream` for it as well: |
| 36 | +/// |
| 37 | +/// [moddocs]: index.html |
| 38 | +/// |
| 39 | +/// ``` |
| 40 | +/// # use std::task::{Context, Poll}; |
| 41 | +/// # use std::pin::Pin; |
| 42 | +/// # use async_std::prelude::*; |
| 43 | +/// # struct Counter { |
| 44 | +/// # count: usize, |
| 45 | +/// # } |
| 46 | +/// # impl Counter { |
| 47 | +/// # fn new() -> Counter { |
| 48 | +/// # Counter { count: 0 } |
| 49 | +/// # } |
| 50 | +/// # } |
| 51 | +/// # impl Stream for Counter { |
| 52 | +/// # type Item = usize; |
| 53 | +/// # fn poll_next(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { |
| 54 | +/// # self.count += 1; |
| 55 | +/// # if self.count < 6 { |
| 56 | +/// # Poll::Ready(Some(self.count)) |
| 57 | +/// # } else { |
| 58 | +/// # Poll::Ready(None) |
| 59 | +/// # } |
| 60 | +/// # } |
| 61 | +/// # } |
| 62 | +/// # fn main() { async_std::task::block_on(async { |
| 63 | +/// # |
| 64 | +/// impl ExactSizeStream for Counter { |
| 65 | +/// // We can easily calculate the remaining number of iterations. |
| 66 | +/// fn len(&self) -> usize { |
| 67 | +/// 5 - self.count |
| 68 | +/// } |
| 69 | +/// } |
| 70 | +/// |
| 71 | +/// // And now we can use it! |
| 72 | +/// |
| 73 | +/// let counter = Counter::new(); |
| 74 | +/// |
| 75 | +/// assert_eq!(5, counter.len()); |
| 76 | +/// # }); |
| 77 | +/// # } |
| 78 | +/// ``` |
| 79 | +#[cfg_attr(feature = "docs", doc(cfg(unstable)))] |
| 80 | +#[cfg(any(feature = "unstable", feature = "docs"))] |
| 81 | +pub trait ExactSizeStream: Stream { |
| 82 | + /// Returns the exact number of times the stream will iterate. |
| 83 | + /// |
| 84 | + /// This method has a default implementation, so you usually should not |
| 85 | + /// implement it directly. However, if you can provide a more efficient |
| 86 | + /// implementation, you can do so. See the [trait-level] docs for an |
| 87 | + /// example. |
| 88 | + /// |
| 89 | + /// This function has the same safety guarantees as the [`size_hint`] |
| 90 | + /// function. |
| 91 | + /// |
| 92 | + /// [trait-level]: trait.ExactSizeStream.html |
| 93 | + /// [`size_hint`]: trait.Stream.html#method.size_hint |
| 94 | + /// |
| 95 | + /// # Examples |
| 96 | + /// |
| 97 | + /// Basic usage: |
| 98 | + /// |
| 99 | + /// ``` |
| 100 | + /// // a finite range knows exactly how many times it will iterate |
| 101 | + /// let five = 0..5; |
| 102 | + /// |
| 103 | + /// assert_eq!(5, five.len()); |
| 104 | + /// ``` |
| 105 | + fn len(&self) -> usize { |
| 106 | + let (lower, upper) = self.size_hint(); |
| 107 | + // Note: This assertion is overly defensive, but it checks the invariant |
| 108 | + // guaranteed by the trait. If this trait were rust-internal, |
| 109 | + // we could use debug_assert!; assert_eq! will check all Rust user |
| 110 | + // implementations too. |
| 111 | + assert_eq!(upper, Some(lower)); |
| 112 | + lower |
| 113 | + } |
| 114 | +} |
| 115 | + |
| 116 | +impl<I: ExactSizeStream + ?Sized + Unpin> ExactSizeStream for &mut I { |
| 117 | + fn len(&self) -> usize { |
| 118 | + (**self).len() |
| 119 | + } |
| 120 | +} |
0 commit comments