1use std::{
35 collections::HashMap,
36 sync::{Arc, Mutex, OnceLock, Weak},
37};
38
39use super::{AsyncEngine, AsyncEngineContextProvider};
40use async_trait::async_trait;
41use tokio::sync::oneshot;
42
43use super::{Data, Error, PipelineError, PipelineIO};
44
45mod sinks;
46mod sources;
47
48pub use sinks::{SegmentSink, ServiceBackend};
49pub use sources::{SegmentSource, ServiceFrontend};
50
51pub type Service<In, Out> = Arc<ServiceFrontend<In, Out>>;
52
53mod private {
54 pub struct Token;
55}
56
57#[async_trait]
60pub trait Source<T: PipelineIO>: Data {
61 async fn on_next(&self, data: T, _: private::Token) -> Result<(), Error>;
62
63 fn set_edge(&self, edge: Edge<T>, _: private::Token) -> Result<(), PipelineError>;
64
65 fn link<S: Sink<T> + 'static>(&self, sink: Arc<S>) -> Result<Arc<S>, PipelineError> {
66 let edge = Edge::new(sink.clone());
67 self.set_edge(edge, private::Token)?;
68 Ok(sink)
69 }
70
71 fn link_terminal<S: Sink<T> + 'static>(&self, sink: Arc<S>) -> Result<Arc<S>, PipelineError> {
75 let edge = Edge::new_weak(sink.clone());
76 self.set_edge(edge, private::Token)?;
77 Ok(sink)
78 }
79}
80
81#[async_trait]
83pub trait Sink<T: PipelineIO>: Data {
84 async fn on_data(&self, data: T, _: private::Token) -> Result<(), Error>;
85}
86
87pub struct Edge<T: PipelineIO> {
89 downstream: EdgeTarget<T>,
90}
91
92enum EdgeTarget<T: PipelineIO> {
93 Strong(Arc<dyn Sink<T>>),
94 Weak(Weak<dyn Sink<T>>),
95}
96
97impl<T: PipelineIO> Edge<T> {
98 fn new(downstream: Arc<dyn Sink<T>>) -> Self {
99 Edge {
100 downstream: EdgeTarget::Strong(downstream),
101 }
102 }
103
104 fn new_weak<S: Sink<T> + 'static>(downstream: Arc<S>) -> Self {
105 let downstream: Arc<dyn Sink<T>> = downstream;
106 Edge {
107 downstream: EdgeTarget::Weak(Arc::downgrade(&downstream)),
108 }
109 }
110
111 async fn write(&self, data: T) -> Result<(), Error> {
112 match &self.downstream {
113 EdgeTarget::Strong(downstream) => downstream.on_data(data, private::Token).await,
114 EdgeTarget::Weak(downstream) => {
115 let Some(downstream) = downstream.upgrade() else {
116 data.context().stop_generating();
117 return Err(PipelineError::DetachedStreamReceiver.into());
118 };
119 downstream.on_data(data, private::Token).await
120 }
121 }
122 }
123}
124
125type NodeFn<In, Out> = Box<dyn Fn(In) -> Result<Out, Error> + Send + Sync>;
126
127#[async_trait]
142pub trait Operator<UpIn: PipelineIO, UpOut: PipelineIO, DownIn: PipelineIO, DownOut: PipelineIO>:
143 Data
144{
145 async fn generate(
149 &self,
150 req: UpIn,
151 next: Arc<dyn AsyncEngine<DownIn, DownOut, Error>>,
152 ) -> Result<UpOut, Error>;
153
154 fn into_operator(self: &Arc<Self>) -> Arc<PipelineOperator<UpIn, UpOut, DownIn, DownOut>>
155 where
156 Self: Sized,
157 {
158 PipelineOperator::new(self.clone())
159 }
160}
161
162pub struct PipelineOperatorForwardEdge<
165 UpIn: PipelineIO,
166 UpOut: PipelineIO,
167 DownIn: PipelineIO,
168 DownOut: PipelineIO,
169> {
170 parent: Arc<PipelineOperator<UpIn, UpOut, DownIn, DownOut>>,
171}
172
173pub struct PipelineOperatorBackwardEdge<
176 UpIn: PipelineIO,
177 UpOut: PipelineIO,
178 DownIn: PipelineIO,
179 DownOut: PipelineIO,
180> {
181 parent: Weak<PipelineOperator<UpIn, UpOut, DownIn, DownOut>>,
182}
183
184pub struct PipelineOperator<
187 UpIn: PipelineIO,
188 UpOut: PipelineIO,
189 DownIn: PipelineIO,
190 DownOut: PipelineIO,
191> {
192 operator: Arc<dyn Operator<UpIn, UpOut, DownIn, DownOut>>,
194
195 downstream: Arc<sources::Frontend<DownIn, DownOut>>,
198
199 upstream: sinks::SinkEdge<UpOut>,
202}
203
204impl<UpIn, UpOut, DownIn, DownOut> PipelineOperator<UpIn, UpOut, DownIn, DownOut>
205where
206 UpIn: PipelineIO,
207 UpOut: PipelineIO,
208 DownIn: PipelineIO,
209 DownOut: PipelineIO,
210{
211 pub fn new(operator: Arc<dyn Operator<UpIn, UpOut, DownIn, DownOut>>) -> Arc<Self> {
213 Arc::new(PipelineOperator {
214 operator,
215 downstream: Arc::new(sources::Frontend::default()),
216 upstream: sinks::SinkEdge::default(),
217 })
218 }
219
220 pub fn forward_edge(
222 self: &Arc<Self>,
223 ) -> Arc<PipelineOperatorForwardEdge<UpIn, UpOut, DownIn, DownOut>> {
224 Arc::new(PipelineOperatorForwardEdge {
225 parent: self.clone(),
226 })
227 }
228
229 pub fn backward_edge(
231 self: &Arc<Self>,
232 ) -> Arc<PipelineOperatorBackwardEdge<UpIn, UpOut, DownIn, DownOut>> {
233 Arc::new(PipelineOperatorBackwardEdge {
234 parent: Arc::downgrade(self),
235 })
236 }
237}
238
239#[async_trait]
241impl<UpIn, UpOut, DownIn, DownOut> AsyncEngine<UpIn, UpOut, Error>
242 for PipelineOperator<UpIn, UpOut, DownIn, DownOut>
243where
244 UpIn: PipelineIO + Sync,
245 DownIn: PipelineIO + Sync,
246 DownOut: PipelineIO,
247 UpOut: PipelineIO,
248{
249 async fn generate(&self, req: UpIn) -> Result<UpOut, Error> {
250 self.operator.generate(req, self.downstream.clone()).await
251 }
252}
253
254#[async_trait]
255impl<UpIn, UpOut, DownIn, DownOut> Sink<UpIn>
256 for PipelineOperatorForwardEdge<UpIn, UpOut, DownIn, DownOut>
257where
258 UpIn: PipelineIO + Sync,
259 DownIn: PipelineIO + Sync,
260 DownOut: PipelineIO,
261 UpOut: PipelineIO,
262{
263 async fn on_data(&self, data: UpIn, _token: private::Token) -> Result<(), Error> {
264 let stream = self.parent.generate(data).await?;
265 self.parent.upstream.on_next(stream, private::Token).await
266 }
267}
268
269#[async_trait]
270impl<UpIn, UpOut, DownIn, DownOut> Source<DownIn>
271 for PipelineOperatorForwardEdge<UpIn, UpOut, DownIn, DownOut>
272where
273 UpIn: PipelineIO,
274 DownIn: PipelineIO,
275 DownOut: PipelineIO,
276 UpOut: PipelineIO,
277{
278 async fn on_next(&self, data: DownIn, token: private::Token) -> Result<(), Error> {
279 self.parent.downstream.on_next(data, token).await
280 }
281
282 fn set_edge(&self, edge: Edge<DownIn>, token: private::Token) -> Result<(), PipelineError> {
283 self.parent.downstream.set_edge(edge, token)
284 }
285}
286
287#[async_trait]
288impl<UpIn, UpOut, DownIn, DownOut> Sink<DownOut>
289 for PipelineOperatorBackwardEdge<UpIn, UpOut, DownIn, DownOut>
290where
291 UpIn: PipelineIO,
292 DownIn: PipelineIO,
293 DownOut: PipelineIO,
294 UpOut: PipelineIO,
295{
296 async fn on_data(&self, data: DownOut, token: private::Token) -> Result<(), Error> {
297 let Some(parent) = self.parent.upgrade() else {
298 data.context().stop_generating();
299 return Err(PipelineError::DetachedStreamReceiver.into());
300 };
301 parent.downstream.on_data(data, token).await
302 }
303}
304
305#[async_trait]
306impl<UpIn, UpOut, DownIn, DownOut> Source<UpOut>
307 for PipelineOperatorBackwardEdge<UpIn, UpOut, DownIn, DownOut>
308where
309 UpIn: PipelineIO,
310 DownIn: PipelineIO,
311 DownOut: PipelineIO,
312 UpOut: PipelineIO,
313{
314 async fn on_next(&self, data: UpOut, token: private::Token) -> Result<(), Error> {
315 let Some(parent) = self.parent.upgrade() else {
316 data.context().stop_generating();
317 return Err(PipelineError::DetachedStreamReceiver.into());
318 };
319 parent.upstream.on_next(data, token).await
320 }
321
322 fn set_edge(&self, edge: Edge<UpOut>, token: private::Token) -> Result<(), PipelineError> {
323 self.parent
324 .upgrade()
325 .ok_or(PipelineError::DetachedStreamReceiver)?
326 .upstream
327 .set_edge(edge, token)
328 }
329}
330
331pub struct PipelineNode<In: PipelineIO, Out: PipelineIO> {
332 edge: OnceLock<Edge<Out>>,
333 map_fn: NodeFn<In, Out>,
334}
335
336impl<In: PipelineIO, Out: PipelineIO> PipelineNode<In, Out> {
337 pub fn new(map_fn: NodeFn<In, Out>) -> Arc<Self> {
338 Arc::new(PipelineNode::<In, Out> {
339 edge: OnceLock::new(),
340 map_fn,
341 })
342 }
343}
344
345#[async_trait]
346impl<In: PipelineIO, Out: PipelineIO> Source<Out> for PipelineNode<In, Out> {
347 async fn on_next(&self, data: Out, _: private::Token) -> Result<(), Error> {
348 self.edge
349 .get()
350 .ok_or(PipelineError::NoEdge)?
351 .write(data)
352 .await
353 }
354
355 fn set_edge(&self, edge: Edge<Out>, _: private::Token) -> Result<(), PipelineError> {
356 self.edge
357 .set(edge)
358 .map_err(|_| PipelineError::EdgeAlreadySet)?;
359
360 Ok(())
361 }
362}
363
364#[async_trait]
365impl<In: PipelineIO, Out: PipelineIO> Sink<In> for PipelineNode<In, Out> {
366 async fn on_data(&self, data: In, _: private::Token) -> Result<(), Error> {
367 self.on_next((self.map_fn)(data)?, private::Token).await
368 }
369}
370
371#[cfg(test)]
372mod tests {
373
374 use super::*;
375 use crate::pipeline::*;
376
377 #[tokio::test]
378 async fn test_pipeline_source_no_edge() {
379 let source = ServiceFrontend::<SingleIn<()>, ManyOut<()>>::new();
380 let stream = source.generate(().into()).await;
381 assert!(stream.is_err());
382 }
383}