p2panda_stream/processors/
stream.rs1use std::pin::Pin;
4use std::task::{Context, Poll};
5
6use futures_core::Stream;
7use pin_project::pin_project;
8
9use crate::processors::Processor;
10use crate::processors::buffered::{Buffer, BufferReceiver, BufferSender};
11
12pub trait ProcessorExt<T>: Processor<T>
14where
15 Self: 'static,
16 T: 'static,
17{
18 fn into_stream<S: Stream<Item = T>>(self, input_stream: S) -> ProcessorStream<Self, S, T>
21 where
22 Self: Sized,
23 {
24 ProcessorStream::new(self, input_stream)
25 }
26}
27
28impl<P, T: 'static> ProcessorExt<T> for P where P: Processor<T> + 'static {}
29
30#[pin_project]
31#[must_use = "streams do nothing unless polled"]
32pub struct ProcessorStream<P, S, T>
33where
34 P: Processor<T>,
35 S: Stream<Item = T>,
36{
37 #[pin]
38 input_stream: S,
39 buffer: Buffer,
40 tx: BufferSender<T>,
41 rx: BufferReceiver<P, T>,
42}
43
44impl<P, S, T> ProcessorStream<P, S, T>
45where
46 P: Processor<T> + 'static,
47 S: Stream<Item = T>,
48 T: 'static,
49{
50 pub(crate) fn new(processor: P, input_stream: S) -> ProcessorStream<P, S, T> {
51 let (buffer, tx, rx) = Buffer::new(processor);
55 ProcessorStream {
56 input_stream,
57 buffer,
58 tx,
59 rx,
60 }
61 }
62}
63
64impl<P, S, T> Stream for ProcessorStream<P, S, T>
65where
66 P: Processor<T>,
67 S: Stream<Item = T>,
68{
69 type Item = Result<P::Output, P::Error>;
70
71 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
72 let mut this = self.project();
73 let mut made_progress = false;
74
75 match this.input_stream.as_mut().poll_next(cx) {
85 Poll::Ready(Some(input)) => {
86 let _ = this.tx.send(input);
87 made_progress = true;
88 }
89 Poll::Ready(None) | Poll::Pending => (),
90 };
91
92 match this.rx.poll_recv(cx) {
100 Poll::Ready(item) => Poll::Ready(item),
101 Poll::Pending => {
102 if made_progress {
103 cx.waker().wake_by_ref();
105 }
106 Poll::Pending
107 }
108 }
109 }
110}
111
112pub trait StreamLayerExt<T>: Stream<Item = T> + Sized
114where
115 T: 'static,
116{
117 fn layer<P>(self, processor: P) -> ProcessorStream<P, Self, T>
119 where
120 P: Processor<T> + 'static,
121 {
122 ProcessorStream::new(processor, self)
123 }
124}
125
126impl<S, T: 'static> StreamLayerExt<T> for S where S: Stream<Item = T> {}