Skip to main content

dfir_pipes/push/
filter.rs

1//! [`Filter`] push combinator.
2use core::pin::Pin;
3
4use pin_project_lite::pin_project;
5
6use crate::push::{Push, PushStep};
7
8pin_project! {
9    /// Push combinator that only pushes items matching a predicate.
10    #[must_use = "`Push`es do nothing unless items are pushed into them"]
11    #[derive(Clone, Debug)]
12    pub struct Filter<Next, Func> {
13        #[pin]
14        next: Next,
15        func: Func,
16    }
17}
18
19impl<Next, Func> Filter<Next, Func> {
20    /// Creates with filtering `func` and next `push`.
21    pub(crate) const fn new<Item>(func: Func, next: Next) -> Self
22    where
23        Func: FnMut(&Item) -> bool,
24    {
25        Self { next, func }
26    }
27}
28
29impl<Next, Func, Item, Meta> Push<Item, Meta> for Filter<Next, Func>
30where
31    Next: Push<Item, Meta>,
32    Func: FnMut(&Item) -> bool,
33    Meta: Copy,
34{
35    type Ctx<'ctx> = Next::Ctx<'ctx>;
36
37    type CanPend = Next::CanPend;
38
39    fn poll_ready(self: Pin<&mut Self>, ctx: &mut Self::Ctx<'_>) -> PushStep<Self::CanPend> {
40        self.project().next.poll_ready(ctx)
41    }
42
43    fn start_send(self: Pin<&mut Self>, item: Item, meta: Meta) {
44        let this = self.project();
45        if (this.func)(&item) {
46            this.next.start_send(item, meta)
47        }
48    }
49
50    fn poll_flush(self: Pin<&mut Self>, ctx: &mut Self::Ctx<'_>) -> PushStep<Self::CanPend> {
51        self.project().next.poll_flush(ctx)
52    }
53
54    fn size_hint(self: Pin<&mut Self>, hint: (usize, Option<usize>)) {
55        self.project().next.size_hint((0, hint.1));
56    }
57}