futures_util/stream/
take.rs

1use futures_core::{Async, Poll, Stream};
2use futures_core::task;
3use futures_sink::{ Sink};
4
5/// A stream combinator which returns a maximum number of elements.
6///
7/// This structure is produced by the `Stream::take` method.
8#[derive(Debug)]
9#[must_use = "streams do nothing unless polled"]
10pub struct Take<S> {
11    stream: S,
12    remaining: u64,
13}
14
15pub fn new<S>(s: S, amt: u64) -> Take<S>
16    where S: Stream,
17{
18    Take {
19        stream: s,
20        remaining: amt,
21    }
22}
23
24impl<S> Take<S> {
25    /// Acquires a reference to the underlying stream that this combinator is
26    /// pulling from.
27    pub fn get_ref(&self) -> &S {
28        &self.stream
29    }
30
31    /// Acquires a mutable reference to the underlying stream that this
32    /// combinator is pulling from.
33    ///
34    /// Note that care must be taken to avoid tampering with the state of the
35    /// stream which may otherwise confuse this combinator.
36    pub fn get_mut(&mut self) -> &mut S {
37        &mut self.stream
38    }
39
40    /// Consumes this combinator, returning the underlying stream.
41    ///
42    /// Note that this may discard intermediate state of this combinator, so
43    /// care should be taken to avoid losing resources when this is called.
44    pub fn into_inner(self) -> S {
45        self.stream
46    }
47}
48
49// Forwarding impl of Sink from the underlying stream
50impl<S> Sink for Take<S>
51    where S: Sink + Stream
52{
53    type SinkItem = S::SinkItem;
54    type SinkError = S::SinkError;
55
56    delegate_sink!(stream);
57}
58
59impl<S> Stream for Take<S>
60    where S: Stream,
61{
62    type Item = S::Item;
63    type Error = S::Error;
64
65    fn poll_next(&mut self, cx: &mut task::Context) -> Poll<Option<S::Item>, S::Error> {
66        if self.remaining == 0 {
67            Ok(Async::Ready(None))
68        } else {
69            let next = try_ready!(self.stream.poll_next(cx));
70            match next {
71                Some(_) => self.remaining -= 1,
72                None => self.remaining = 0,
73            }
74            Ok(Async::Ready(next))
75        }
76    }
77}