1use core::pin::Pin;
2use futures_core::ready;
3use futures_core::stream::{FusedStream, Stream};
4use futures_core::task::{Context, Poll};
5#[cfg(feature = "sink")]
6use futures_sink::Sink;
7use pin_project_lite::pin_project;
8
9pin_project! {
10 /// Stream for the [`skip`](super::StreamExt::skip) method.
11 #[derive(Debug)]
12 #[must_use = "streams do nothing unless polled"]
13 pub struct Skip<St> {
14 #[pin]
15 stream: St,
16 remaining: usize,
17 }
18}
19
20impl<St: Stream> Skip<St> {
21 pub(super) fn new(stream: St, n: usize) -> Self {
22 Self { stream, remaining: n }
23 }
24
25 delegate_access_inner!(stream, St, ());
26}
27
28impl<St: FusedStream> FusedStream for Skip<St> {
29 fn is_terminated(&self) -> bool {
30 self.stream.is_terminated()
31 }
32}
33
34impl<St: Stream> Stream for Skip<St> {
35 type Item = St::Item;
36
37 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<St::Item>> {
38 let mut this = self.project();
39
40 while *this.remaining > 0 {
41 if ready!(this.stream.as_mut().poll_next(cx)).is_some() {
42 *this.remaining -= 1;
43 } else {
44 return Poll::Ready(None);
45 }
46 }
47
48 this.stream.poll_next(cx)
49 }
50
51 fn size_hint(&self) -> (usize, Option<usize>) {
52 let (lower, upper) = self.stream.size_hint();
53
54 let lower = lower.saturating_sub(self.remaining);
55 let upper = upper.map(|x| x.saturating_sub(self.remaining));
56
57 (lower, upper)
58 }
59}
60
61// Forwarding impl of Sink from the underlying stream
62#[cfg(feature = "sink")]
63impl<S, Item> Sink<Item> for Skip<S>
64where
65 S: Stream + Sink<Item>,
66{
67 type Error = S::Error;
68
69 delegate_sink!(stream, Item);
70}
71