Skip to main content

dfir_pipes/pull/
enumerate.rs

1use core::pin::Pin;
2
3use pin_project_lite::pin_project;
4
5use crate::pull::{FusedPull, Pull, PullStep};
6
7pin_project! {
8    /// Pull combinator that pairs each item with its index.
9    #[must_use = "`Pull`s do nothing unless polled"]
10    #[derive(Clone, Debug, Default)]
11    pub struct Enumerate<Prev> {
12        #[pin]
13        prev: Prev,
14        index: usize,
15    }
16}
17
18impl<Prev> Enumerate<Prev>
19where
20    Self: Pull,
21{
22    pub(crate) const fn new(prev: Prev) -> Self {
23        Self { prev, index: 0 }
24    }
25}
26
27impl<Prev> Pull for Enumerate<Prev>
28where
29    Prev: Pull,
30{
31    type Ctx<'ctx> = Prev::Ctx<'ctx>;
32
33    type Item = (usize, Prev::Item);
34    type Meta = Prev::Meta;
35    type CanPend = Prev::CanPend;
36    type CanEnd = Prev::CanEnd;
37
38    fn pull(
39        self: Pin<&mut Self>,
40        ctx: &mut Self::Ctx<'_>,
41    ) -> PullStep<Self::Item, Self::Meta, Self::CanPend, Self::CanEnd> {
42        let this = self.project();
43        match this.prev.pull(ctx) {
44            PullStep::Ready(item, meta) => {
45                let idx = *this.index;
46                *this.index += 1;
47                PullStep::Ready((idx, item), meta)
48            }
49            PullStep::Pending(can_pend) => PullStep::Pending(can_pend),
50            PullStep::Ended(can_end) => PullStep::Ended(can_end),
51        }
52    }
53
54    fn size_hint(&self) -> (usize, Option<usize>) {
55        self.prev.size_hint()
56    }
57}
58
59impl<Prev> FusedPull for Enumerate<Prev> where Prev: FusedPull {}