Skip to main content

dfir_pipes/pull/
for_each.rs

1use core::pin::Pin;
2use core::task::Poll;
3
4use pin_project_lite::pin_project;
5
6use crate::Context;
7use crate::pull::{Pull, PullStep};
8
9pin_project! {
10    /// Future that runs a closure on each item from a pull.
11    #[must_use = "futures do nothing unless polled"]
12    #[derive(Clone, Debug)]
13    pub struct ForEach<Prev, Func> {
14        #[pin]
15        prev: Prev,
16        func: Func,
17    }
18}
19
20impl<Prev, Func> ForEach<Prev, Func>
21where
22    Self: Future,
23{
24    pub(crate) const fn new(prev: Prev, func: Func) -> Self {
25        Self { prev, func }
26    }
27}
28
29impl<Prev, Func, Item> Future for ForEach<Prev, Func>
30where
31    Prev: Pull<Item = Item>,
32    Func: FnMut(Item),
33    for<'ctx> Prev::Ctx<'ctx>: Context<'ctx>,
34{
35    type Output = ();
36
37    fn poll(self: Pin<&mut Self>, cx: &mut core::task::Context<'_>) -> Poll<Self::Output> {
38        let mut this = self.project();
39        let ctx = <Prev::Ctx<'_> as Context<'_>>::from_task(cx);
40        loop {
41            return match this.prev.as_mut().pull(ctx) {
42                PullStep::Ready(item, _meta) => {
43                    let () = (this.func)(item);
44                    continue;
45                }
46                PullStep::Pending(_) => Poll::Pending,
47                PullStep::Ended(_) => Poll::Ready(()),
48            };
49        }
50    }
51}