Skip to main content

dfir_pipes/push/
filter_map.rs

1//! [`FilterMap`] 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 both filters and maps items.
10    #[must_use = "`Push`es do nothing unless items are pushed into them"]
11    #[derive(Clone, Debug)]
12    pub struct FilterMap<Next, Func> {
13        #[pin]
14        next: Next,
15        func: Func,
16    }
17}
18
19impl<Next, Func> FilterMap<Next, Func> {
20    /// Creates with filter-mapping `func` and next `push`.
21    pub(crate) const fn new<In, Out>(func: Func, next: Next) -> Self
22    where
23        Func: FnMut(In) -> Option<Out>,
24    {
25        Self { next, func }
26    }
27}
28
29impl<Next, Func, In, Out, Meta> Push<In, Meta> for FilterMap<Next, Func>
30where
31    Next: Push<Out, Meta>,
32    Func: FnMut(In) -> Option<Out>,
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: In, meta: Meta) {
44        let this = self.project();
45        if let Some(item) = (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}