1use super::*;
16use crate::ScalarArithmeticOp;
17use crate::stream::scalar::{ScalarChunkStep, ScalarI64Op};
18
19#[derive(Clone, Debug)]
21pub struct Identity<T: 'static> {
22 _marker: PhantomData<fn() -> T>,
23}
24
25impl<T: 'static> Identity<T> {
26 #[must_use]
27 pub fn new() -> Self {
28 Self {
29 _marker: PhantomData,
30 }
31 }
32}
33
34impl<T: 'static> Default for Identity<T> {
35 fn default() -> Self {
36 Self::new()
37 }
38}
39
40impl<T> GraphStage for Identity<T>
41where
42 T: Clone + Send + 'static,
43{
44 type Shape = FlowShape<T, T>;
45
46 fn name(&self) -> &str {
47 "Identity"
48 }
49
50 fn allocate_shape(&self, _allocator: &mut PortAllocator) -> Self::Shape {
51 let first_id = next_port_id_block(2);
52 FlowShape::new(
53 Inlet::with_arc_name(first_id, identity_inlet_name()),
54 Outlet::with_arc_name(first_id.offset(1), identity_outlet_name()),
55 )
56 }
57
58 fn stage_spec(&self, shape: &Self::Shape) -> StageSpec {
59 StageSpec::identity(shape.inlets(), shape.outlets())
60 }
61
62 fn stage_spec_with_ports(
63 &self,
64 _shape: &Self::Shape,
65 inlets: Vec<AnyInlet>,
66 outlets: Vec<AnyOutlet>,
67 ) -> StageSpec {
68 StageSpec::identity(inlets, outlets)
69 }
70}
71
72#[derive(Clone)]
74pub struct MapStage<In: 'static, Out: 'static> {
75 f: Arc<dyn Fn(In) -> Out + Send + Sync>,
76 scalar_erased: Option<Arc<StageMapFn>>,
77 scalar_i64: Option<Arc<StageTypedMapFn>>,
78 scalar_finish: Option<Arc<StageTypedMapFn>>,
79 _marker: PhantomData<fn(In) -> Out>,
80}
81
82impl<In: 'static, Out: 'static> fmt::Debug for MapStage<In, Out> {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 f.debug_struct("MapStage")
85 .field("name", &"Map")
86 .finish_non_exhaustive()
87 }
88}
89
90impl<In: 'static, Out: 'static> MapStage<In, Out> {
91 #[must_use]
92 pub fn new<F>(f: F) -> Self
93 where
94 F: Fn(In) -> Out + Send + Sync + 'static,
95 {
96 Self {
97 f: Arc::new(f),
98 scalar_erased: None,
99 scalar_i64: None,
100 scalar_finish: None,
101 _marker: PhantomData,
102 }
103 }
104}
105
106impl MapStage<i64, i64> {
107 fn scalar(op: ScalarArithmeticOp, operand: i64) -> Self {
108 let step = ScalarChunkStep::new(ScalarI64Op::Arithmetic(op), operand);
109 let checked_step = step.clone();
110 let scalar_erased: Arc<StageMapFn> = Arc::new(move |value| {
111 let value: i64 = downcast_datum(value, "map", || "Map.in")?;
112 let value = checked_step
113 .apply_checked(value)?
114 .expect("arithmetic maps always retain their input");
115 Ok(datum(value))
116 });
117 let scalar_i64 = Arc::new(step) as Arc<StageTypedMapFn>;
118 let finish: Arc<dyn Fn(i64) -> i64 + Send + Sync> = Arc::new(|value| value);
119 let scalar_finish = Arc::new(finish) as Arc<StageTypedMapFn>;
120 let f: Arc<dyn Fn(i64) -> i64 + Send + Sync> = Arc::new(move |value| match op {
121 ScalarArithmeticOp::Add => value.wrapping_add(operand),
122 ScalarArithmeticOp::Subtract => value.wrapping_sub(operand),
123 ScalarArithmeticOp::Multiply => value.wrapping_mul(operand),
124 });
125 Self {
126 f,
127 scalar_erased: Some(scalar_erased),
128 scalar_i64: Some(scalar_i64),
129 scalar_finish: Some(scalar_finish),
130 _marker: PhantomData,
131 }
132 }
133
134 #[must_use]
136 pub fn map_op(op: ScalarArithmeticOp, operand: i64) -> Self {
137 Self::scalar(op, operand)
138 }
139
140 #[must_use]
141 pub fn map_add(operand: i64) -> Self {
142 Self::scalar(ScalarArithmeticOp::Add, operand)
143 }
144
145 #[must_use]
146 pub fn map_subtract(operand: i64) -> Self {
147 Self::scalar(ScalarArithmeticOp::Subtract, operand)
148 }
149
150 #[must_use]
151 pub fn map_multiply(operand: i64) -> Self {
152 Self::scalar(ScalarArithmeticOp::Multiply, operand)
153 }
154}
155
156impl<In, Out> GraphStage for MapStage<In, Out>
157where
158 In: Clone + Send + 'static,
159 Out: Clone + Send + 'static,
160{
161 type Shape = FlowShape<In, Out>;
162
163 fn name(&self) -> &str {
164 "Map"
165 }
166
167 fn allocate_shape(&self, _allocator: &mut PortAllocator) -> Self::Shape {
168 let first_id = next_port_id_block(2);
169 FlowShape::new(
170 Inlet::with_arc_name(first_id, map_inlet_name()),
171 Outlet::with_arc_name(first_id.offset(1), map_outlet_name()),
172 )
173 }
174
175 fn stage_spec(&self, shape: &Self::Shape) -> StageSpec {
176 self.stage_spec_with_ports(shape, shape.inlets(), shape.outlets())
177 }
178
179 fn stage_spec_with_ports(
180 &self,
181 _shape: &Self::Shape,
182 inlets: Vec<AnyInlet>,
183 outlets: Vec<AnyOutlet>,
184 ) -> StageSpec {
185 let f = Arc::clone(&self.f);
186 let typed = Arc::new(Arc::clone(&self.f)) as Arc<StageTypedMapFn>;
187 let mapper = self.scalar_erased.clone().unwrap_or_else(|| {
188 Arc::new(move |value: DatumValue| {
189 let value: In = downcast_datum(value, "map", || "Map.in")?;
190 Ok(datum(f(value)))
191 })
192 });
193 StageSpec::map(
194 map_stage_name(),
195 inlets,
196 outlets,
197 mapper,
198 typed,
199 self.scalar_i64.clone(),
200 self.scalar_finish.clone(),
201 )
202 }
203}
204
205#[derive(Clone, Debug)]
210pub struct Buffer<T: 'static> {
211 capacity: usize,
212 strategy: OverflowStrategy,
213 _marker: PhantomData<fn() -> T>,
214}
215
216impl<T: 'static> Buffer<T> {
217 #[must_use]
218 pub fn new(capacity: usize, strategy: OverflowStrategy) -> Self {
219 assert!(capacity > 0, "buffer capacity must be greater than zero");
220 Self {
221 capacity,
222 strategy,
223 _marker: PhantomData,
224 }
225 }
226}
227
228impl<T> GraphStage for Buffer<T>
229where
230 T: Clone + Send + 'static,
231{
232 type Shape = FlowShape<T, T>;
233
234 fn name(&self) -> &str {
235 "Buffer"
236 }
237
238 fn allocate_shape(&self, _allocator: &mut PortAllocator) -> Self::Shape {
239 let first_id = next_port_id_block(2);
240 FlowShape::new(
241 Inlet::with_id(first_id, "Buffer.in"),
242 Outlet::with_id(first_id.offset(1), "Buffer.out"),
243 )
244 }
245
246 fn stage_spec(&self, shape: &Self::Shape) -> StageSpec {
247 StageSpec::opaque(self.name(), shape.inlets(), shape.outlets())
251 .with_typed_cyclic(TypedCyclicOp::BufferPassthrough)
252 }
253
254 fn create_logic(&self, shape: &Self::Shape) -> GraphStageLogic {
255 struct State<T> {
256 queue: VecDeque<T>,
257 upstream_closed: bool,
258 }
259
260 fn lock_state<T>(
261 state: &Arc<Mutex<State<T>>>,
262 ) -> StreamResult<std::sync::MutexGuard<'_, State<T>>> {
263 state
264 .lock()
265 .map_err(|_| StreamError::Failed("graph buffer state poisoned".into()))
266 }
267
268 fn enqueue<T>(
269 state: &mut State<T>,
270 value: T,
271 capacity: usize,
272 strategy: OverflowStrategy,
273 ) -> StreamResult<()> {
274 if state.queue.len() < capacity {
275 state.queue.push_back(value);
276 return Ok(());
277 }
278
279 match strategy {
280 OverflowStrategy::Backpressure | OverflowStrategy::Fail => Err(
281 StreamError::Failed(format!("Buffer overflow (max capacity was: {capacity})!")),
282 ),
283 OverflowStrategy::DropHead => {
284 let _ = state.queue.pop_front();
285 state.queue.push_back(value);
286 Ok(())
287 }
288 OverflowStrategy::DropTail => {
289 let _ = state.queue.pop_back();
290 state.queue.push_back(value);
291 Ok(())
292 }
293 OverflowStrategy::DropBuffer => {
294 state.queue.clear();
295 state.queue.push_back(value);
296 Ok(())
297 }
298 OverflowStrategy::DropNew => Ok(()),
299 }
300 }
301
302 fn drain_one<T>(
303 logic: &mut GraphStageLogic,
304 outlet: &Outlet<T>,
305 state: &Arc<Mutex<State<T>>>,
306 ) -> StreamResult<()>
307 where
308 T: Clone + Send + 'static,
309 {
310 if !logic.is_available(outlet) {
311 return Ok(());
312 }
313 let next = lock_state(state)?.queue.pop_front();
314 if let Some(value) = next {
315 logic.push(outlet, value)?;
316 }
317 Ok(())
318 }
319
320 fn maybe_pull<T>(
321 logic: &mut GraphStageLogic,
322 inlet: &Inlet<T>,
323 state: &Arc<Mutex<State<T>>>,
324 capacity: usize,
325 ) -> StreamResult<()>
326 where
327 T: 'static,
328 {
329 let can_pull = {
330 let state = lock_state(state)?;
331 !state.upstream_closed && state.queue.len() < capacity
332 };
333 if can_pull && !logic.has_been_pulled(inlet) {
334 logic.pull(inlet)?;
335 }
336 Ok(())
337 }
338
339 fn maybe_complete<T>(
340 logic: &mut GraphStageLogic,
341 outlet: &Outlet<T>,
342 state: &Arc<Mutex<State<T>>>,
343 ) -> StreamResult<()>
344 where
345 T: 'static,
346 {
347 let done = {
348 let state = lock_state(state)?;
349 state.upstream_closed && state.queue.is_empty()
350 };
351 if done && !logic.is_closed(outlet) {
352 logic.complete(outlet)?;
353 }
354 Ok(())
355 }
356
357 struct In<T: 'static> {
358 inlet: Inlet<T>,
359 outlet: Outlet<T>,
360 state: Arc<Mutex<State<T>>>,
361 capacity: usize,
362 strategy: OverflowStrategy,
363 }
364
365 impl<T> InHandler for In<T>
366 where
367 T: Clone + Send + 'static,
368 {
369 fn on_push(
370 &mut self,
371 logic: &mut GraphStageLogic,
372 _inlet: AnyInlet,
373 ) -> StreamResult<()> {
374 let value = logic.grab(&self.inlet)?;
375 {
376 let mut state = lock_state(&self.state)?;
377 enqueue(&mut state, value, self.capacity, self.strategy)?;
378 }
379 drain_one(logic, &self.outlet, &self.state)?;
380 maybe_pull(logic, &self.inlet, &self.state, self.capacity)?;
381 maybe_complete(logic, &self.outlet, &self.state)
382 }
383
384 fn on_upstream_finish(
385 &mut self,
386 logic: &mut GraphStageLogic,
387 _inlet: AnyInlet,
388 ) -> StreamResult<()> {
389 lock_state(&self.state)?.upstream_closed = true;
390 drain_one(logic, &self.outlet, &self.state)?;
391 maybe_complete(logic, &self.outlet, &self.state)
392 }
393 }
394
395 struct Out<T: 'static> {
396 inlet: Inlet<T>,
397 outlet: Outlet<T>,
398 state: Arc<Mutex<State<T>>>,
399 capacity: usize,
400 }
401
402 impl<T> OutHandler for Out<T>
403 where
404 T: Clone + Send + 'static,
405 {
406 fn on_pull(
407 &mut self,
408 logic: &mut GraphStageLogic,
409 _outlet: AnyOutlet,
410 ) -> StreamResult<()> {
411 drain_one(logic, &self.outlet, &self.state)?;
412 maybe_pull(logic, &self.inlet, &self.state, self.capacity)?;
413 maybe_complete(logic, &self.outlet, &self.state)
414 }
415
416 fn on_downstream_finish(
417 &mut self,
418 logic: &mut GraphStageLogic,
419 _outlet: AnyOutlet,
420 ) -> StreamResult<()> {
421 logic.complete_stage()
422 }
423 }
424
425 let state = Arc::new(Mutex::new(State {
426 queue: VecDeque::new(),
427 upstream_closed: false,
428 }));
429 let mut logic = GraphStageLogic::new(shape);
430 logic.pull(&shape.inlet()).unwrap();
431 logic
432 .set_handler(
433 &shape.inlet(),
434 Box::new(In {
435 inlet: shape.inlet(),
436 outlet: shape.outlet(),
437 state: Arc::clone(&state),
438 capacity: self.capacity,
439 strategy: self.strategy,
440 }),
441 )
442 .unwrap();
443 logic
444 .set_out_handler(
445 &shape.outlet(),
446 Box::new(Out {
447 inlet: shape.inlet(),
448 outlet: shape.outlet(),
449 state,
450 capacity: self.capacity,
451 }),
452 )
453 .unwrap();
454 logic
455 }
456}
457
458#[derive(Clone)]
460pub struct TakeWhile<T: 'static> {
461 predicate: Arc<dyn Fn(&T) -> bool + Send + Sync>,
462 _marker: PhantomData<fn() -> T>,
463}
464
465impl<T: 'static> fmt::Debug for TakeWhile<T> {
466 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
467 f.debug_struct("TakeWhile")
468 .field("name", &"TakeWhile")
469 .finish_non_exhaustive()
470 }
471}
472
473impl<T: 'static> TakeWhile<T> {
474 #[must_use]
475 pub fn new<F>(predicate: F) -> Self
476 where
477 F: Fn(&T) -> bool + Send + Sync + 'static,
478 {
479 Self {
480 predicate: Arc::new(predicate),
481 _marker: PhantomData,
482 }
483 }
484}
485
486impl<T> GraphStage for TakeWhile<T>
487where
488 T: Clone + Send + 'static,
489{
490 type Shape = FlowShape<T, T>;
491
492 fn name(&self) -> &str {
493 "TakeWhile"
494 }
495
496 fn allocate_shape(&self, _allocator: &mut PortAllocator) -> Self::Shape {
497 let first_id = next_port_id_block(2);
498 FlowShape::new(
499 Inlet::with_id(first_id, "TakeWhile.in"),
500 Outlet::with_id(first_id.offset(1), "TakeWhile.out"),
501 )
502 }
503
504 fn stage_spec(&self, shape: &Self::Shape) -> StageSpec {
505 let predicate: Arc<dyn Fn(&T) -> bool + Send + Sync> = Arc::clone(&self.predicate);
510 StageSpec::opaque(self.name(), shape.inlets(), shape.outlets()).with_typed_cyclic(
511 TypedCyclicOp::TakeWhile(Arc::new(predicate) as Arc<dyn Any + Send + Sync>),
512 )
513 }
514
515 fn create_logic(&self, shape: &Self::Shape) -> GraphStageLogic {
516 struct In<T: 'static> {
517 inlet: Inlet<T>,
518 outlet: Outlet<T>,
519 predicate: Arc<dyn Fn(&T) -> bool + Send + Sync>,
520 }
521
522 impl<T> InHandler for In<T>
523 where
524 T: Clone + Send + 'static,
525 {
526 fn on_push(
527 &mut self,
528 logic: &mut GraphStageLogic,
529 _inlet: AnyInlet,
530 ) -> StreamResult<()> {
531 let value = logic.grab(&self.inlet)?;
532 if (self.predicate)(&value) {
533 logic.emit(&self.outlet, value)
534 } else if logic.is_closed(&self.outlet) {
535 Ok(())
536 } else {
537 logic.complete(&self.outlet)
538 }
539 }
540
541 fn on_upstream_finish(
542 &mut self,
543 logic: &mut GraphStageLogic,
544 _inlet: AnyInlet,
545 ) -> StreamResult<()> {
546 if logic.is_closed(&self.outlet) {
547 Ok(())
548 } else {
549 logic.complete(&self.outlet)
550 }
551 }
552 }
553
554 struct Out<T: 'static> {
555 inlet: Inlet<T>,
556 }
557
558 impl<T> OutHandler for Out<T>
559 where
560 T: Clone + Send + 'static,
561 {
562 fn on_pull(
563 &mut self,
564 logic: &mut GraphStageLogic,
565 _outlet: AnyOutlet,
566 ) -> StreamResult<()> {
567 if !logic.has_been_pulled(&self.inlet) {
568 logic.pull(&self.inlet)?;
569 }
570 Ok(())
571 }
572
573 fn on_downstream_finish(
574 &mut self,
575 logic: &mut GraphStageLogic,
576 _outlet: AnyOutlet,
577 ) -> StreamResult<()> {
578 logic.complete_stage()
579 }
580 }
581
582 let mut logic = GraphStageLogic::new(shape);
583 logic
584 .set_handler(
585 &shape.inlet(),
586 Box::new(In {
587 inlet: shape.inlet(),
588 outlet: shape.outlet(),
589 predicate: Arc::clone(&self.predicate),
590 }),
591 )
592 .unwrap();
593 logic
594 .set_out_handler(
595 &shape.outlet(),
596 Box::new(Out {
597 inlet: shape.inlet(),
598 }),
599 )
600 .unwrap();
601 logic
602 }
603}
604
605#[derive(Clone, Debug)]
607pub struct Broadcast<T: 'static> {
608 outputs: usize,
609 _marker: PhantomData<fn() -> T>,
610}
611
612impl<T: 'static> Broadcast<T> {
613 #[must_use]
614 pub fn new(outputs: usize) -> Self {
615 assert!(
616 outputs > 0,
617 "broadcast output count must be greater than zero"
618 );
619 Self {
620 outputs,
621 _marker: PhantomData,
622 }
623 }
624}
625
626impl<T> GraphStage for Broadcast<T>
627where
628 T: Clone + Send + 'static,
629{
630 type Shape = FanOutShape<T, T>;
631
632 fn name(&self) -> &str {
633 "Broadcast"
634 }
635
636 fn allocate_shape(&self, allocator: &mut PortAllocator) -> Self::Shape {
637 let inlet = allocator.inlet_arc(broadcast_inlet_name());
638 let outlets = (0..self.outputs)
639 .map(|index| allocator.outlet(format!("Broadcast.out{index}")))
640 .collect();
641 FanOutShape::new(inlet, outlets)
642 }
643
644 fn stage_spec(&self, shape: &Self::Shape) -> StageSpec {
645 self.stage_spec_with_ports(shape, shape.inlets(), shape.outlets())
646 }
647
648 fn stage_spec_with_ports(
649 &self,
650 _shape: &Self::Shape,
651 inlets: Vec<AnyInlet>,
652 outlets: Vec<AnyOutlet>,
653 ) -> StageSpec {
654 StageSpec::broadcast(broadcast_stage_name(), inlets, outlets)
655 }
656}
657
658#[derive(Clone, Debug)]
661pub struct Balance<T: 'static> {
662 outputs: usize,
663 _marker: PhantomData<fn() -> T>,
664}
665
666impl<T: 'static> Balance<T> {
667 #[must_use]
668 pub fn new(outputs: usize) -> Self {
669 assert!(
670 outputs > 0,
671 "balance output count must be greater than zero"
672 );
673 Self {
674 outputs,
675 _marker: PhantomData,
676 }
677 }
678}
679
680impl<T> GraphStage for Balance<T>
681where
682 T: Clone + Send + 'static,
683{
684 type Shape = FanOutShape<T, T>;
685
686 fn name(&self) -> &str {
687 "Balance"
688 }
689
690 fn allocate_shape(&self, allocator: &mut PortAllocator) -> Self::Shape {
691 let inlet = allocator.inlet_arc(balance_inlet_name());
692 let outlets = (0..self.outputs)
693 .map(|index| allocator.outlet(format!("Balance.out{index}")))
694 .collect();
695 FanOutShape::new(inlet, outlets)
696 }
697
698 fn stage_spec(&self, shape: &Self::Shape) -> StageSpec {
699 self.stage_spec_with_ports(shape, shape.inlets(), shape.outlets())
700 }
701
702 fn stage_spec_with_ports(
703 &self,
704 _shape: &Self::Shape,
705 inlets: Vec<AnyInlet>,
706 outlets: Vec<AnyOutlet>,
707 ) -> StageSpec {
708 StageSpec::balance(balance_stage_name(), inlets, outlets)
709 }
710}
711
712#[derive(Clone, Debug)]
715pub struct Merge<T: 'static> {
716 inputs: usize,
717 _marker: PhantomData<fn() -> T>,
718}
719
720impl<T: 'static> Merge<T> {
721 #[must_use]
722 pub fn new(inputs: usize) -> Self {
723 assert!(inputs > 0, "merge input count must be greater than zero");
724 Self {
725 inputs,
726 _marker: PhantomData,
727 }
728 }
729}
730
731impl<T> GraphStage for Merge<T>
732where
733 T: Clone + Send + 'static,
734{
735 type Shape = FanInShape<T, T>;
736
737 fn name(&self) -> &str {
738 "Merge"
739 }
740
741 fn allocate_shape(&self, allocator: &mut PortAllocator) -> Self::Shape {
742 let inlets = (0..self.inputs)
743 .map(|index| allocator.inlet(format!("Merge.in{index}")))
744 .collect();
745 FanInShape::new(inlets, allocator.outlet_arc(merge_outlet_name()))
746 }
747
748 fn stage_spec(&self, shape: &Self::Shape) -> StageSpec {
749 self.stage_spec_with_ports(shape, shape.inlets(), shape.outlets())
750 }
751
752 fn stage_spec_with_ports(
753 &self,
754 _shape: &Self::Shape,
755 inlets: Vec<AnyInlet>,
756 outlets: Vec<AnyOutlet>,
757 ) -> StageSpec {
758 StageSpec::merge(merge_stage_name(), inlets, outlets)
759 }
760}
761
762#[derive(Clone, Debug)]
765pub struct Concat<T: 'static> {
766 inputs: usize,
767 _marker: PhantomData<fn() -> T>,
768}
769
770impl<T: 'static> Concat<T> {
771 #[must_use]
772 pub fn new(inputs: usize) -> Self {
773 assert!(inputs > 1, "concat input count must be greater than one");
774 Self {
775 inputs,
776 _marker: PhantomData,
777 }
778 }
779}
780
781impl<T> GraphStage for Concat<T>
782where
783 T: Clone + Send + 'static,
784{
785 type Shape = FanInShape<T, T>;
786
787 fn name(&self) -> &str {
788 "Concat"
789 }
790
791 fn allocate_shape(&self, allocator: &mut PortAllocator) -> Self::Shape {
792 let inlets = (0..self.inputs)
793 .map(|index| allocator.inlet(format!("Concat.in{index}")))
794 .collect();
795 FanInShape::new(inlets, allocator.outlet_arc(concat_outlet_name()))
796 }
797
798 fn stage_spec(&self, shape: &Self::Shape) -> StageSpec {
799 self.stage_spec_with_ports(shape, shape.inlets(), shape.outlets())
800 }
801
802 fn stage_spec_with_ports(
803 &self,
804 _shape: &Self::Shape,
805 inlets: Vec<AnyInlet>,
806 outlets: Vec<AnyOutlet>,
807 ) -> StageSpec {
808 StageSpec::concat(concat_stage_name(), inlets, outlets)
809 }
810}
811
812#[derive(Clone, Debug)]
815pub struct OrElse<T: 'static> {
816 _marker: PhantomData<fn() -> T>,
817}
818
819impl<T: 'static> OrElse<T> {
820 #[must_use]
821 pub fn new() -> Self {
822 Self {
823 _marker: PhantomData,
824 }
825 }
826}
827
828impl<T: 'static> Default for OrElse<T> {
829 fn default() -> Self {
830 Self::new()
831 }
832}
833
834impl<T> GraphStage for OrElse<T>
835where
836 T: Clone + Send + 'static,
837{
838 type Shape = FanInShape<T, T>;
839
840 fn name(&self) -> &str {
841 "OrElse"
842 }
843
844 fn allocate_shape(&self, allocator: &mut PortAllocator) -> Self::Shape {
845 let inlets = vec![
846 allocator.inlet_arc(or_else_primary_name()),
847 allocator.inlet_arc(or_else_secondary_name()),
848 ];
849 FanInShape::new(inlets, allocator.outlet_arc(or_else_outlet_name()))
850 }
851
852 fn stage_spec(&self, shape: &Self::Shape) -> StageSpec {
853 self.stage_spec_with_ports(shape, shape.inlets(), shape.outlets())
854 }
855
856 fn stage_spec_with_ports(
857 &self,
858 _shape: &Self::Shape,
859 inlets: Vec<AnyInlet>,
860 outlets: Vec<AnyOutlet>,
861 ) -> StageSpec {
862 StageSpec::or_else(or_else_stage_name(), inlets, outlets)
863 }
864}
865
866#[derive(Clone, Debug)]
869pub struct Interleave<T: 'static> {
870 inputs: usize,
871 segment_size: usize,
872 eager_close: bool,
873 _marker: PhantomData<fn() -> T>,
874}
875
876impl<T: 'static> Interleave<T> {
877 #[must_use]
878 pub fn new(inputs: usize, segment_size: usize) -> Self {
879 Self::new_with_eager_close(inputs, segment_size, false)
880 }
881
882 #[must_use]
883 pub fn new_with_eager_close(inputs: usize, segment_size: usize, eager_close: bool) -> Self {
884 assert!(
885 inputs > 1,
886 "interleave input count must be greater than one"
887 );
888 assert!(
889 segment_size > 0,
890 "interleave segment size must be greater than zero"
891 );
892 Self {
893 inputs,
894 segment_size,
895 eager_close,
896 _marker: PhantomData,
897 }
898 }
899}
900
901impl<T> GraphStage for Interleave<T>
902where
903 T: Clone + Send + 'static,
904{
905 type Shape = FanInShape<T, T>;
906
907 fn name(&self) -> &str {
908 "Interleave"
909 }
910
911 fn allocate_shape(&self, allocator: &mut PortAllocator) -> Self::Shape {
912 let inlets = (0..self.inputs)
913 .map(|index| allocator.inlet(format!("Interleave.in{index}")))
914 .collect();
915 FanInShape::new(inlets, allocator.outlet_arc(interleave_outlet_name()))
916 }
917
918 fn stage_spec(&self, shape: &Self::Shape) -> StageSpec {
919 self.stage_spec_with_ports(shape, shape.inlets(), shape.outlets())
920 }
921
922 fn stage_spec_with_ports(
923 &self,
924 _shape: &Self::Shape,
925 inlets: Vec<AnyInlet>,
926 outlets: Vec<AnyOutlet>,
927 ) -> StageSpec {
928 StageSpec::interleave(
929 interleave_stage_name(),
930 inlets,
931 outlets,
932 self.segment_size,
933 self.eager_close,
934 )
935 }
936}
937
938#[derive(Clone, Debug)]
941pub struct MergePreferred<T: 'static> {
942 secondary_ports: usize,
943 _marker: PhantomData<fn() -> T>,
944}
945
946impl<T: 'static> MergePreferred<T> {
947 #[must_use]
948 pub fn new(secondary_ports: usize) -> Self {
949 assert!(
950 secondary_ports > 0,
951 "merge-preferred secondary input count must be greater than zero"
952 );
953 Self {
954 secondary_ports,
955 _marker: PhantomData,
956 }
957 }
958}
959
960impl<T> GraphStage for MergePreferred<T>
961where
962 T: Clone + Send + 'static,
963{
964 type Shape = MergePreferredShape<T>;
965
966 fn name(&self) -> &str {
967 "MergePreferred"
968 }
969
970 fn allocate_shape(&self, allocator: &mut PortAllocator) -> Self::Shape {
971 let preferred = allocator.inlet_arc(merge_preferred_preferred_name());
972 let secondary = (0..self.secondary_ports)
973 .map(|index| allocator.inlet(format!("MergePreferred.in{index}")))
974 .collect();
975 MergePreferredShape::new(
976 preferred,
977 secondary,
978 allocator.outlet_arc(merge_preferred_outlet_name()),
979 )
980 }
981
982 fn stage_spec(&self, shape: &Self::Shape) -> StageSpec {
983 self.stage_spec_with_ports(shape, shape.inlets(), shape.outlets())
984 }
985
986 fn stage_spec_with_ports(
987 &self,
988 _shape: &Self::Shape,
989 inlets: Vec<AnyInlet>,
990 outlets: Vec<AnyOutlet>,
991 ) -> StageSpec {
992 StageSpec::merge_preferred(merge_preferred_stage_name(), inlets, outlets)
993 }
994}
995
996#[derive(Clone, Debug)]
1000pub struct MergePrioritized<T: 'static> {
1001 weights: Vec<usize>,
1002 _marker: PhantomData<fn() -> T>,
1003}
1004
1005impl<T: 'static> MergePrioritized<T> {
1006 #[must_use]
1007 pub fn new(weights: Vec<usize>) -> Self {
1008 assert!(!weights.is_empty(), "prioritized merge must have inputs");
1009 assert!(
1010 weights.iter().all(|weight| *weight > 0),
1011 "prioritized merge weights must be greater than zero"
1012 );
1013 Self {
1014 weights,
1015 _marker: PhantomData,
1016 }
1017 }
1018}
1019
1020impl<T> GraphStage for MergePrioritized<T>
1021where
1022 T: Clone + Send + 'static,
1023{
1024 type Shape = FanInShape<T, T>;
1025
1026 fn name(&self) -> &str {
1027 "MergePrioritized"
1028 }
1029
1030 fn allocate_shape(&self, allocator: &mut PortAllocator) -> Self::Shape {
1031 let inlets = (0..self.weights.len())
1032 .map(|index| allocator.inlet(format!("MergePrioritized.in{index}")))
1033 .collect();
1034 FanInShape::new(
1035 inlets,
1036 allocator.outlet_arc(merge_prioritized_outlet_name()),
1037 )
1038 }
1039
1040 fn stage_spec(&self, shape: &Self::Shape) -> StageSpec {
1041 self.stage_spec_with_ports(shape, shape.inlets(), shape.outlets())
1042 }
1043
1044 fn stage_spec_with_ports(
1045 &self,
1046 _shape: &Self::Shape,
1047 inlets: Vec<AnyInlet>,
1048 outlets: Vec<AnyOutlet>,
1049 ) -> StageSpec {
1050 StageSpec::merge_prioritized(
1051 merge_prioritized_stage_name(),
1052 inlets,
1053 outlets,
1054 self.weights.clone(),
1055 )
1056 }
1057}
1058
1059#[derive(Clone, Debug)]
1062pub struct Zip<Left: 'static, Right: 'static> {
1063 _marker: PhantomData<fn() -> (Left, Right)>,
1064}
1065
1066impl<Left: 'static, Right: 'static> Zip<Left, Right> {
1067 #[must_use]
1068 pub fn new() -> Self {
1069 Self {
1070 _marker: PhantomData,
1071 }
1072 }
1073}
1074
1075impl<Left: 'static, Right: 'static> Default for Zip<Left, Right> {
1076 fn default() -> Self {
1077 Self::new()
1078 }
1079}
1080
1081impl<Left, Right> GraphStage for Zip<Left, Right>
1082where
1083 Left: Clone + Send + 'static,
1084 Right: Clone + Send + 'static,
1085{
1086 type Shape = ZipShape<Left, Right>;
1087
1088 fn name(&self) -> &str {
1089 "Zip"
1090 }
1091
1092 fn allocate_shape(&self, _allocator: &mut PortAllocator) -> Self::Shape {
1093 let first_id = next_port_id_block(3);
1094 ZipShape::new(
1095 Inlet::with_arc_name(first_id, zip_in0_name()),
1096 Inlet::with_arc_name(first_id.offset(1), zip_in1_name()),
1097 Outlet::with_arc_name(first_id.offset(2), zip_outlet_name()),
1098 )
1099 }
1100
1101 fn stage_spec(&self, shape: &Self::Shape) -> StageSpec {
1102 self.stage_spec_with_ports(shape, shape.inlets(), shape.outlets())
1103 }
1104
1105 fn stage_spec_with_ports(
1106 &self,
1107 _shape: &Self::Shape,
1108 inlets: Vec<AnyInlet>,
1109 outlets: Vec<AnyOutlet>,
1110 ) -> StageSpec {
1111 let zip = Arc::new(move |left: DatumValue, right: DatumValue| {
1112 let left: Left = downcast_datum(left, "zip", || "Zip.in0")?;
1113 let right: Right = downcast_datum(right, "zip", || "Zip.in1")?;
1114 Ok(datum((left, right)))
1115 });
1116 StageSpec::zip(zip_stage_name(), inlets, outlets, zip)
1117 }
1118}
1119
1120#[derive(Clone, Debug)]
1123pub struct MergeSorted<T: 'static> {
1124 _marker: PhantomData<fn() -> T>,
1125}
1126
1127impl<T: 'static> MergeSorted<T> {
1128 #[must_use]
1129 pub fn new() -> Self {
1130 Self {
1131 _marker: PhantomData,
1132 }
1133 }
1134}
1135
1136impl<T: 'static> Default for MergeSorted<T> {
1137 fn default() -> Self {
1138 Self::new()
1139 }
1140}
1141
1142impl<T> GraphStage for MergeSorted<T>
1143where
1144 T: Clone + Ord + Send + 'static,
1145{
1146 type Shape = FanInShape<T, T>;
1147
1148 fn name(&self) -> &str {
1149 "MergeSorted"
1150 }
1151
1152 fn allocate_shape(&self, allocator: &mut PortAllocator) -> Self::Shape {
1153 let inlets = vec![
1154 allocator.inlet("MergeSorted.in0"),
1155 allocator.inlet("MergeSorted.in1"),
1156 ];
1157 FanInShape::new(inlets, allocator.outlet("MergeSorted.out"))
1158 }
1159
1160 fn stage_spec(&self, shape: &Self::Shape) -> StageSpec {
1161 let compare = Arc::new(
1162 move |a: &DatumValue, b: &DatumValue| -> std::cmp::Ordering {
1163 let a_t: &T = a
1164 .as_any_ref()
1165 .downcast_ref::<T>()
1166 .expect("merge-sorted compare: wrong element type");
1167 let b_t: &T = b
1168 .as_any_ref()
1169 .downcast_ref::<T>()
1170 .expect("merge-sorted compare: wrong element type");
1171 a_t.cmp(b_t)
1172 },
1173 );
1174 StageSpec::merge_sorted(
1175 Arc::from(self.name()),
1176 shape.inlets(),
1177 shape.outlets(),
1178 compare,
1179 )
1180 }
1181
1182 fn create_logic(&self, shape: &Self::Shape) -> GraphStageLogic {
1183 struct State<T> {
1184 left: VecDeque<T>,
1185 right: VecDeque<T>,
1186 left_closed: bool,
1187 right_closed: bool,
1188 pending: VecDeque<T>,
1189 }
1190
1191 impl<T> Default for State<T> {
1192 fn default() -> Self {
1193 Self {
1194 left: VecDeque::new(),
1195 right: VecDeque::new(),
1196 left_closed: false,
1197 right_closed: false,
1198 pending: VecDeque::new(),
1199 }
1200 }
1201 }
1202
1203 fn maybe_queue_output<T>(state: &mut State<T>) -> bool
1204 where
1205 T: Clone + Ord,
1206 {
1207 let next = match (state.left.front(), state.right.front()) {
1208 (Some(left), Some(right)) => {
1209 if left <= right {
1210 state.left.pop_front()
1211 } else {
1212 state.right.pop_front()
1213 }
1214 }
1215 (Some(_), None) if state.right_closed => state.left.pop_front(),
1216 (None, Some(_)) if state.left_closed => state.right.pop_front(),
1217 _ => None,
1218 };
1219 if let Some(value) = next {
1220 state.pending.push_back(value);
1221 true
1222 } else {
1223 false
1224 }
1225 }
1226
1227 fn maybe_complete<T>(
1228 logic: &mut GraphStageLogic,
1229 outlet: &Outlet<T>,
1230 state: &State<T>,
1231 ) -> StreamResult<()>
1232 where
1233 T: Clone + Send + 'static,
1234 {
1235 if state.left_closed
1236 && state.right_closed
1237 && state.left.is_empty()
1238 && state.right.is_empty()
1239 && state.pending.is_empty()
1240 && !logic.is_closed(outlet)
1241 {
1242 logic.complete(outlet)?;
1243 }
1244 Ok(())
1245 }
1246
1247 fn maybe_pull<T>(
1248 logic: &mut GraphStageLogic,
1249 left: &Inlet<T>,
1250 right: &Inlet<T>,
1251 state: &State<T>,
1252 ) -> StreamResult<()>
1253 where
1254 T: Clone + Send + 'static,
1255 {
1256 if state.left.is_empty() && !state.left_closed && !logic.has_been_pulled(left) {
1257 logic.pull(left)?;
1258 }
1259 if state.right.is_empty() && !state.right_closed && !logic.has_been_pulled(right) {
1260 logic.pull(right)?;
1261 }
1262 Ok(())
1263 }
1264
1265 fn maybe_drain<T>(
1266 logic: &mut GraphStageLogic,
1267 outlet: &Outlet<T>,
1268 state: &Arc<Mutex<State<T>>>,
1269 ) -> StreamResult<()>
1270 where
1271 T: Clone + Ord + Send + 'static,
1272 {
1273 let next = if logic.is_available(outlet) {
1274 state
1275 .lock()
1276 .expect("merge-sorted state poisoned")
1277 .pending
1278 .pop_front()
1279 } else {
1280 None
1281 };
1282 if let Some(value) = next {
1283 logic.push(outlet, value)?;
1284 }
1285 Ok(())
1286 }
1287
1288 struct In<T: 'static> {
1289 inlet_id: PortId,
1290 left: Inlet<T>,
1291 right: Inlet<T>,
1292 outlet: Outlet<T>,
1293 state: Arc<Mutex<State<T>>>,
1294 }
1295
1296 impl<T> InHandler for In<T>
1297 where
1298 T: Clone + Ord + Send + 'static,
1299 {
1300 fn on_push(
1301 &mut self,
1302 logic: &mut GraphStageLogic,
1303 _inlet: AnyInlet,
1304 ) -> StreamResult<()> {
1305 let value: T = logic.grab_datum(self.inlet_id).and_then(|value| {
1306 downcast_datum(value, "grab", || {
1307 format!("inlet#{}", self.inlet_id.as_usize())
1308 })
1309 })?;
1310 {
1311 let mut state = self.state.lock().expect("merge-sorted state poisoned");
1312 if self.inlet_id == self.left.id() {
1313 state.left.push_back(value);
1314 } else {
1315 state.right.push_back(value);
1316 }
1317 while maybe_queue_output(&mut state) {}
1318 }
1319 maybe_drain(logic, &self.outlet, &self.state)?;
1320 let state = self.state.lock().expect("merge-sorted state poisoned");
1321 maybe_complete(logic, &self.outlet, &state)?;
1322 maybe_pull(logic, &self.left, &self.right, &state)
1323 }
1324
1325 fn on_upstream_finish(
1326 &mut self,
1327 logic: &mut GraphStageLogic,
1328 _inlet: AnyInlet,
1329 ) -> StreamResult<()> {
1330 {
1331 let mut state = self.state.lock().expect("merge-sorted state poisoned");
1332 if self.inlet_id == self.left.id() {
1333 state.left_closed = true;
1334 } else {
1335 state.right_closed = true;
1336 }
1337 while maybe_queue_output(&mut state) {}
1338 }
1339 maybe_drain(logic, &self.outlet, &self.state)?;
1340 let state = self.state.lock().expect("merge-sorted state poisoned");
1341 maybe_complete(logic, &self.outlet, &state)?;
1342 maybe_pull(logic, &self.left, &self.right, &state)
1343 }
1344 }
1345
1346 struct Out<T: 'static> {
1347 left: Inlet<T>,
1348 right: Inlet<T>,
1349 outlet: Outlet<T>,
1350 state: Arc<Mutex<State<T>>>,
1351 }
1352
1353 impl<T> OutHandler for Out<T>
1354 where
1355 T: Clone + Ord + Send + 'static,
1356 {
1357 fn on_pull(
1358 &mut self,
1359 logic: &mut GraphStageLogic,
1360 _outlet: AnyOutlet,
1361 ) -> StreamResult<()> {
1362 maybe_drain(logic, &self.outlet, &self.state)?;
1363 let state = self.state.lock().expect("merge-sorted state poisoned");
1364 maybe_complete(logic, &self.outlet, &state)?;
1365 maybe_pull(logic, &self.left, &self.right, &state)
1366 }
1367 }
1368
1369 let state = Arc::new(Mutex::new(State::<T>::default()));
1370 let left = shape.inlet(0).expect("merge-sorted left inlet");
1371 let right = shape.inlet(1).expect("merge-sorted right inlet");
1372 let outlet = shape.outlet();
1373 let mut logic = GraphStageLogic::new(shape);
1374 logic
1375 .set_handler(
1376 &left,
1377 Box::new(In {
1378 inlet_id: left.id(),
1379 left: left.clone(),
1380 right: right.clone(),
1381 outlet: outlet.clone(),
1382 state: Arc::clone(&state),
1383 }),
1384 )
1385 .unwrap();
1386 logic
1387 .set_handler(
1388 &right,
1389 Box::new(In {
1390 inlet_id: right.id(),
1391 left: left.clone(),
1392 right: right.clone(),
1393 outlet: outlet.clone(),
1394 state: Arc::clone(&state),
1395 }),
1396 )
1397 .unwrap();
1398 logic
1399 .set_out_handler(
1400 &outlet.clone(),
1401 Box::new(Out {
1402 left,
1403 right,
1404 outlet: outlet.clone(),
1405 state,
1406 }),
1407 )
1408 .unwrap();
1409 logic
1410 }
1411}
1412
1413#[derive(Clone)]
1417pub struct MergeSequence<T: 'static> {
1418 inputs: usize,
1419 extract_sequence: Arc<dyn Fn(&T) -> u64 + Send + Sync>,
1420 _marker: PhantomData<fn() -> T>,
1421}
1422
1423impl<T: 'static> fmt::Debug for MergeSequence<T> {
1424 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1425 f.debug_struct("MergeSequence")
1426 .field("inputs", &self.inputs)
1427 .finish_non_exhaustive()
1428 }
1429}
1430
1431impl<T: 'static> MergeSequence<T> {
1432 #[must_use]
1433 pub fn new<F>(inputs: usize, extract_sequence: F) -> Self
1434 where
1435 F: Fn(&T) -> u64 + Send + Sync + 'static,
1436 {
1437 assert!(
1438 inputs > 1,
1439 "merge sequence input count must be greater than one"
1440 );
1441 Self {
1442 inputs,
1443 extract_sequence: Arc::new(extract_sequence),
1444 _marker: PhantomData,
1445 }
1446 }
1447}
1448
1449impl<T> GraphStage for MergeSequence<T>
1450where
1451 T: Clone + Send + 'static,
1452{
1453 type Shape = FanInShape<T, T>;
1454
1455 fn name(&self) -> &str {
1456 "MergeSequence"
1457 }
1458
1459 fn allocate_shape(&self, allocator: &mut PortAllocator) -> Self::Shape {
1460 let inlets = (0..self.inputs)
1461 .map(|index| allocator.inlet(format!("MergeSequence.in{index}")))
1462 .collect();
1463 FanInShape::new(inlets, allocator.outlet("MergeSequence.out"))
1464 }
1465
1466 fn stage_spec(&self, shape: &Self::Shape) -> StageSpec {
1467 let extract = Arc::clone(&self.extract_sequence);
1468 let extract_sequence = Arc::new(move |dv: &DatumValue| -> u64 {
1469 let t: &T = dv
1470 .as_any_ref()
1471 .downcast_ref::<T>()
1472 .expect("merge-sequence extract: wrong element type");
1473 extract(t)
1474 });
1475 let typed_extract_fn = Arc::clone(&self.extract_sequence);
1478 let typed_extract: Arc<dyn Fn(&T) -> u64 + Send + Sync> = typed_extract_fn;
1479 let typed_extract: Arc<StageTypedSequenceFn> = Arc::new(typed_extract);
1480 StageSpec::merge_sequence(
1481 Arc::from(self.name()),
1482 shape.inlets(),
1483 shape.outlets(),
1484 self.inputs,
1485 extract_sequence,
1486 typed_extract,
1487 )
1488 }
1489
1490 fn create_logic(&self, shape: &Self::Shape) -> GraphStageLogic {
1491 #[derive(Clone)]
1492 struct Pending<T> {
1493 sequence: u64,
1494 elem: T,
1495 }
1496
1497 struct State<T> {
1498 next_sequence: u64,
1499 pending: Vec<Pending<T>>,
1500 completed: usize,
1501 pending_output: VecDeque<T>,
1502 }
1503
1504 fn try_emit_pending<T>(state: &mut State<T>) -> StreamResult<()>
1505 where
1506 T: Clone + Send + 'static,
1507 {
1508 while let Some(index) = state
1509 .pending
1510 .iter()
1511 .position(|item| item.sequence == state.next_sequence)
1512 {
1513 let item = state.pending.remove(index);
1514 if state
1515 .pending
1516 .iter()
1517 .any(|other| other.sequence == state.next_sequence)
1518 {
1519 return Err(StreamError::Failed(format!(
1520 "duplicate sequence {} on merge sequence",
1521 state.next_sequence
1522 )));
1523 }
1524 state.pending_output.push_back(item.elem);
1525 state.next_sequence += 1;
1526 }
1527 Ok(())
1528 }
1529
1530 struct In<T: 'static> {
1531 inlet_id: PortId,
1532 inlet_index: usize,
1533 inlet: Inlet<T>,
1534 all_inlets: Vec<Inlet<T>>,
1535 outlet: Outlet<T>,
1536 extract_sequence: Arc<dyn Fn(&T) -> u64 + Send + Sync>,
1537 state: Arc<Mutex<State<T>>>,
1538 }
1539
1540 impl<T> InHandler for In<T>
1541 where
1542 T: Clone + Send + 'static,
1543 {
1544 fn on_push(
1545 &mut self,
1546 logic: &mut GraphStageLogic,
1547 _inlet: AnyInlet,
1548 ) -> StreamResult<()> {
1549 let elem: T = logic.grab_datum(self.inlet_id).and_then(|value| {
1550 downcast_datum(value, "grab", || {
1551 format!("inlet#{}", self.inlet_id.as_usize())
1552 })
1553 })?;
1554 let sequence = (self.extract_sequence)(&elem);
1555 {
1556 let mut state = self.state.lock().expect("merge-sequence state poisoned");
1557 if sequence < state.next_sequence {
1558 return Err(StreamError::Failed(format!(
1559 "sequence regression from {} to {} on port {}",
1560 state.next_sequence, sequence, self.inlet_index
1561 )));
1562 }
1563 state.pending.push(Pending { sequence, elem });
1564 try_emit_pending(&mut state)?;
1565 }
1566 let next = if logic.is_available(&self.outlet) {
1567 self.state
1568 .lock()
1569 .expect("merge-sequence state poisoned")
1570 .pending_output
1571 .pop_front()
1572 } else {
1573 None
1574 };
1575 if let Some(value) = next {
1576 logic.push(&self.outlet, value)?;
1577 }
1578 let state = self.state.lock().expect("merge-sequence state poisoned");
1579 if state.completed == self.all_inlets.len()
1580 && state.pending.is_empty()
1581 && state.pending_output.is_empty()
1582 {
1583 logic.complete(&self.outlet)?;
1584 } else if logic.is_available(&self.outlet)
1585 && state.pending_output.is_empty()
1586 && state.pending.len() + state.completed == self.all_inlets.len()
1587 {
1588 return Err(StreamError::Failed(format!(
1589 "expected sequence {}, but all input ports have pushed or are complete",
1590 state.next_sequence
1591 )));
1592 }
1593 if !logic.has_been_pulled(&self.inlet) {
1594 logic.pull(&self.inlet)?;
1595 }
1596 Ok(())
1597 }
1598
1599 fn on_upstream_finish(
1600 &mut self,
1601 logic: &mut GraphStageLogic,
1602 _inlet: AnyInlet,
1603 ) -> StreamResult<()> {
1604 {
1605 let mut state = self.state.lock().expect("merge-sequence state poisoned");
1606 state.completed += 1;
1607 }
1608 let state = self.state.lock().expect("merge-sequence state poisoned");
1609 if state.completed == self.all_inlets.len()
1610 && state.pending.is_empty()
1611 && state.pending_output.is_empty()
1612 {
1613 logic.complete(&self.outlet)?;
1614 } else if logic.is_available(&self.outlet)
1615 && state.pending_output.is_empty()
1616 && state.pending.len() + state.completed == self.all_inlets.len()
1617 {
1618 return Err(StreamError::Failed(format!(
1619 "expected sequence {}, but all input ports have pushed or are complete",
1620 state.next_sequence
1621 )));
1622 }
1623 Ok(())
1624 }
1625 }
1626
1627 struct Out<T: 'static> {
1628 inlets: Vec<Inlet<T>>,
1629 outlet: Outlet<T>,
1630 state: Arc<Mutex<State<T>>>,
1631 }
1632
1633 impl<T> OutHandler for Out<T>
1634 where
1635 T: Clone + Send + 'static,
1636 {
1637 fn on_pull(
1638 &mut self,
1639 logic: &mut GraphStageLogic,
1640 _outlet: AnyOutlet,
1641 ) -> StreamResult<()> {
1642 let next = self
1643 .state
1644 .lock()
1645 .expect("merge-sequence state poisoned")
1646 .pending_output
1647 .pop_front();
1648 if let Some(value) = next {
1649 logic.push(&self.outlet, value)?;
1650 } else {
1651 let state = self.state.lock().expect("merge-sequence state poisoned");
1652 if state.completed == self.inlets.len() && state.pending.is_empty() {
1653 logic.complete(&self.outlet)?;
1654 } else if state.pending.len() + state.completed == self.inlets.len() {
1655 return Err(StreamError::Failed(format!(
1656 "expected sequence {}, but all input ports have pushed or are complete",
1657 state.next_sequence
1658 )));
1659 }
1660 }
1661 for inlet in &self.inlets {
1662 if !logic.has_been_pulled(inlet) && !logic.is_closed(inlet) {
1663 logic.pull(inlet)?;
1664 }
1665 }
1666 Ok(())
1667 }
1668 }
1669
1670 let inlets = shape.inlets_vec();
1671 let outlet = shape.outlet();
1672 let state = Arc::new(Mutex::new(State {
1673 next_sequence: 0,
1674 pending: Vec::new(),
1675 completed: 0,
1676 pending_output: VecDeque::new(),
1677 }));
1678 let mut logic = GraphStageLogic::new(shape);
1679 for (index, inlet) in inlets.iter().cloned().enumerate() {
1680 logic
1681 .set_handler(
1682 &inlet.clone(),
1683 Box::new(In {
1684 inlet_id: inlet.id(),
1685 inlet_index: index,
1686 inlet: inlet.clone(),
1687 all_inlets: inlets.clone(),
1688 outlet: outlet.clone(),
1689 extract_sequence: Arc::clone(&self.extract_sequence),
1690 state: Arc::clone(&state),
1691 }),
1692 )
1693 .unwrap();
1694 }
1695 logic
1696 .set_out_handler(
1697 &outlet.clone(),
1698 Box::new(Out {
1699 inlets,
1700 outlet: outlet.clone(),
1701 state,
1702 }),
1703 )
1704 .unwrap();
1705 logic
1706 }
1707}
1708
1709#[derive(Clone, Debug)]
1713pub struct MergeLatest<T: 'static> {
1714 inputs: usize,
1715 eager_complete: bool,
1716 _marker: PhantomData<fn() -> T>,
1717}
1718
1719impl<T: 'static> MergeLatest<T> {
1720 #[must_use]
1721 pub fn new(inputs: usize, eager_complete: bool) -> Self {
1722 assert!(
1723 inputs > 0,
1724 "merge-latest input count must be greater than zero"
1725 );
1726 Self {
1727 inputs,
1728 eager_complete,
1729 _marker: PhantomData,
1730 }
1731 }
1732}
1733
1734impl<T> GraphStage for MergeLatest<T>
1735where
1736 T: Clone + Send + 'static,
1737{
1738 type Shape = FanInShape<T, Vec<T>>;
1739
1740 fn name(&self) -> &str {
1741 "MergeLatest"
1742 }
1743
1744 fn allocate_shape(&self, allocator: &mut PortAllocator) -> Self::Shape {
1745 let inlets = (0..self.inputs)
1746 .map(|index| allocator.inlet(format!("MergeLatest.in{index}")))
1747 .collect();
1748 FanInShape::new(inlets, allocator.outlet("MergeLatest.out"))
1749 }
1750
1751 fn stage_spec(&self, shape: &Self::Shape) -> StageSpec {
1752 let build_snapshot = Arc::new(move |values: &[&DatumValue]| -> DatumValue {
1753 let snapshot: Vec<T> = values
1754 .iter()
1755 .map(|dv| {
1756 dv.as_any_ref()
1757 .downcast_ref::<T>()
1758 .cloned()
1759 .expect("merge-latest snapshot: wrong element type")
1760 })
1761 .collect();
1762 datum(snapshot)
1763 });
1764 #[allow(clippy::type_complexity)]
1767 let typed_snapshot_fn: Arc<dyn Fn(&[Option<T>]) -> Vec<T> + Send + Sync> =
1768 Arc::new(move |slots: &[Option<T>]| {
1769 slots
1770 .iter()
1771 .map(|s| {
1772 s.clone()
1773 .expect("merge-latest typed snapshot: slot is None")
1774 })
1775 .collect()
1776 });
1777 let typed_snapshot: Arc<StageTypedSnapshotFn> = Arc::new(typed_snapshot_fn);
1778 StageSpec::merge_latest(
1779 Arc::from(self.name()),
1780 shape.inlets(),
1781 shape.outlets(),
1782 self.inputs,
1783 self.eager_complete,
1784 build_snapshot,
1785 typed_snapshot,
1786 )
1787 }
1788
1789 fn create_logic(&self, shape: &Self::Shape) -> GraphStageLogic {
1790 struct State<T> {
1791 latest: Vec<Option<T>>,
1792 seen: usize,
1793 completed: usize,
1794 pending: VecDeque<Vec<T>>,
1795 eager_complete: bool,
1796 }
1797
1798 struct In<T: 'static> {
1799 inlet_id: PortId,
1800 inlet_index: usize,
1801 inlet: Inlet<T>,
1802 all_inlets: Vec<Inlet<T>>,
1803 outlet: Outlet<Vec<T>>,
1804 state: Arc<Mutex<State<T>>>,
1805 }
1806
1807 impl<T> InHandler for In<T>
1808 where
1809 T: Clone + Send + 'static,
1810 {
1811 fn on_push(
1812 &mut self,
1813 logic: &mut GraphStageLogic,
1814 _inlet: AnyInlet,
1815 ) -> StreamResult<()> {
1816 let elem: T = logic.grab_datum(self.inlet_id).and_then(|value| {
1817 downcast_datum(value, "grab", || {
1818 format!("inlet#{}", self.inlet_id.as_usize())
1819 })
1820 })?;
1821 {
1822 let mut state = self.state.lock().expect("merge-latest state poisoned");
1823 if state.latest[self.inlet_index].is_none() {
1824 state.seen += 1;
1825 }
1826 state.latest[self.inlet_index] = Some(elem);
1827 if state.seen == state.latest.len() {
1828 let snapshot = state
1829 .latest
1830 .iter()
1831 .map(|item| item.clone().expect("merge-latest seen"))
1832 .collect();
1833 state.pending.push_back(snapshot);
1834 }
1835 }
1836 let next = if logic.is_available(&self.outlet) {
1837 self.state
1838 .lock()
1839 .expect("merge-latest state poisoned")
1840 .pending
1841 .pop_front()
1842 } else {
1843 None
1844 };
1845 if let Some(value) = next {
1846 logic.push(&self.outlet, value)?;
1847 }
1848 if !logic.has_been_pulled(&self.inlet) {
1849 logic.pull(&self.inlet)?;
1850 }
1851 Ok(())
1852 }
1853
1854 fn on_upstream_finish(
1855 &mut self,
1856 logic: &mut GraphStageLogic,
1857 _inlet: AnyInlet,
1858 ) -> StreamResult<()> {
1859 let state = {
1860 let mut state = self.state.lock().expect("merge-latest state poisoned");
1861 state.completed += 1;
1862 (
1863 state.completed == self.all_inlets.len(),
1864 state.eager_complete,
1865 state.pending.is_empty(),
1866 )
1867 };
1868 if state.0 || (state.1 && state.2) {
1869 logic.complete(&self.outlet)?;
1870 }
1871 Ok(())
1872 }
1873 }
1874
1875 struct Out<T: 'static> {
1876 inlets: Vec<Inlet<T>>,
1877 outlet: Outlet<Vec<T>>,
1878 state: Arc<Mutex<State<T>>>,
1879 }
1880
1881 impl<T> OutHandler for Out<T>
1882 where
1883 T: Clone + Send + 'static,
1884 {
1885 fn on_pull(
1886 &mut self,
1887 logic: &mut GraphStageLogic,
1888 _outlet: AnyOutlet,
1889 ) -> StreamResult<()> {
1890 let next = self
1891 .state
1892 .lock()
1893 .expect("merge-latest state poisoned")
1894 .pending
1895 .pop_front();
1896 if let Some(value) = next {
1897 logic.push(&self.outlet, value)?;
1898 } else {
1899 let state = self.state.lock().expect("merge-latest state poisoned");
1900 if state.completed == self.inlets.len()
1901 || (state.eager_complete && state.completed > 0)
1902 {
1903 logic.complete(&self.outlet)?;
1904 }
1905 }
1906 for inlet in &self.inlets {
1907 if !logic.has_been_pulled(inlet) && !logic.is_closed(inlet) {
1908 logic.pull(inlet)?;
1909 }
1910 }
1911 Ok(())
1912 }
1913 }
1914
1915 let inlets = shape.inlets_vec();
1916 let outlet = shape.outlet();
1917 let state = Arc::new(Mutex::new(State {
1918 latest: vec![None; inlets.len()],
1919 seen: 0,
1920 completed: 0,
1921 pending: VecDeque::new(),
1922 eager_complete: self.eager_complete,
1923 }));
1924 let mut logic = GraphStageLogic::new(shape);
1925 for (index, inlet) in inlets.iter().cloned().enumerate() {
1926 logic
1927 .set_handler(
1928 &inlet.clone(),
1929 Box::new(In {
1930 inlet_id: inlet.id(),
1931 inlet_index: index,
1932 inlet: inlet.clone(),
1933 all_inlets: inlets.clone(),
1934 outlet: outlet.clone(),
1935 state: Arc::clone(&state),
1936 }),
1937 )
1938 .unwrap();
1939 }
1940 logic
1941 .set_out_handler(
1942 &outlet.clone(),
1943 Box::new(Out {
1944 inlets,
1945 outlet: outlet.clone(),
1946 state,
1947 }),
1948 )
1949 .unwrap();
1950 logic
1951 }
1952}
1953
1954#[derive(Clone)]
1958pub struct Partition<T: 'static> {
1959 outputs: usize,
1960 partitioner: Arc<dyn Fn(&T) -> usize + Send + Sync>,
1961 eager_cancel: bool,
1962 _marker: PhantomData<fn() -> T>,
1963}
1964
1965impl<T: 'static> fmt::Debug for Partition<T> {
1966 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1967 f.debug_struct("Partition")
1968 .field("outputs", &self.outputs)
1969 .field("eager_cancel", &self.eager_cancel)
1970 .finish_non_exhaustive()
1971 }
1972}
1973
1974impl<T: 'static> Partition<T> {
1975 #[must_use]
1976 pub fn new<F>(outputs: usize, partitioner: F) -> Self
1977 where
1978 F: Fn(&T) -> usize + Send + Sync + 'static,
1979 {
1980 Self::new_with_eager_cancel(outputs, partitioner, false)
1981 }
1982
1983 #[must_use]
1984 pub fn new_with_eager_cancel<F>(outputs: usize, partitioner: F, eager_cancel: bool) -> Self
1985 where
1986 F: Fn(&T) -> usize + Send + Sync + 'static,
1987 {
1988 assert!(
1989 outputs > 0,
1990 "partition output count must be greater than zero"
1991 );
1992 Self {
1993 outputs,
1994 partitioner: Arc::new(partitioner),
1995 eager_cancel,
1996 _marker: PhantomData,
1997 }
1998 }
1999}
2000
2001impl<T> GraphStage for Partition<T>
2002where
2003 T: Clone + Send + 'static,
2004{
2005 type Shape = FanOutShape<T, T>;
2006
2007 fn name(&self) -> &str {
2008 "Partition"
2009 }
2010
2011 fn allocate_shape(&self, allocator: &mut PortAllocator) -> Self::Shape {
2012 let inlet = allocator.inlet("Partition.in");
2013 let outlets = (0..self.outputs)
2014 .map(|index| allocator.outlet(format!("Partition.out{index}")))
2015 .collect();
2016 FanOutShape::new(inlet, outlets)
2017 }
2018
2019 fn stage_spec(&self, shape: &Self::Shape) -> StageSpec {
2020 let partitioner_clone = Arc::clone(&self.partitioner);
2021 let partitioner = Arc::new(move |dv: &DatumValue| -> usize {
2022 let t: &T = dv
2023 .as_any_ref()
2024 .downcast_ref::<T>()
2025 .expect("partition: wrong element type");
2026 partitioner_clone(t)
2027 });
2028 let typed_partitioner_fn: Arc<dyn Fn(&T) -> usize + Send + Sync> =
2029 Arc::clone(&self.partitioner);
2030 let typed_partitioner: Arc<StageTypedPartitionFn> = Arc::new(typed_partitioner_fn);
2031 StageSpec::partition(
2032 Arc::from(self.name()),
2033 shape.inlets(),
2034 shape.outlets(),
2035 self.outputs,
2036 partitioner,
2037 typed_partitioner,
2038 self.eager_cancel,
2039 )
2040 }
2041
2042 fn create_logic(&self, shape: &Self::Shape) -> GraphStageLogic {
2043 struct State<T> {
2044 pending: Option<(usize, T)>,
2045 upstream_closed: bool,
2046 live_outlets: usize,
2047 cancelled: Vec<bool>,
2048 eager_cancel: bool,
2049 }
2050
2051 fn any_live_demand<T>(
2052 logic: &GraphStageLogic,
2053 outlets: &[Outlet<T>],
2054 cancelled: &[bool],
2055 ) -> bool
2056 where
2057 T: Clone + Send + 'static,
2058 {
2059 outlets
2060 .iter()
2061 .enumerate()
2062 .any(|(index, outlet)| !cancelled[index] && logic.is_available(outlet))
2063 }
2064
2065 struct In<T: 'static> {
2066 inlet_id: PortId,
2067 inlet: Inlet<T>,
2068 outlets: Vec<Outlet<T>>,
2069 partitioner: Arc<dyn Fn(&T) -> usize + Send + Sync>,
2070 state: Arc<Mutex<State<T>>>,
2071 }
2072
2073 impl<T> InHandler for In<T>
2074 where
2075 T: Clone + Send + 'static,
2076 {
2077 fn on_push(
2078 &mut self,
2079 logic: &mut GraphStageLogic,
2080 _inlet: AnyInlet,
2081 ) -> StreamResult<()> {
2082 let item: T = logic.grab_datum(self.inlet_id).and_then(|value| {
2083 downcast_datum(value, "grab", || {
2084 format!("inlet#{}", self.inlet_id.as_usize())
2085 })
2086 })?;
2087 let idx = (self.partitioner)(&item);
2088 if idx >= self.outlets.len() {
2089 return Err(StreamError::Failed(format!(
2090 "partitioner returned out-of-bounds index {idx} for {} outputs",
2091 self.outlets.len()
2092 )));
2093 }
2094 let mut pull_again = false;
2095 {
2096 let mut state = self.state.lock().expect("partition state poisoned");
2097 if state.cancelled[idx] {
2098 pull_again = !state.upstream_closed
2099 && any_live_demand(logic, &self.outlets, &state.cancelled);
2100 } else if logic.is_available(&self.outlets[idx]) {
2101 logic.push(&self.outlets[idx], item)?;
2102 pull_again = !state.upstream_closed
2103 && any_live_demand(logic, &self.outlets, &state.cancelled);
2104 } else {
2105 state.pending = Some((idx, item));
2106 }
2107 }
2108 if pull_again && !logic.has_been_pulled(&self.inlet) {
2109 logic.pull(&self.inlet)?;
2110 }
2111 Ok(())
2112 }
2113
2114 fn on_upstream_finish(
2115 &mut self,
2116 logic: &mut GraphStageLogic,
2117 _inlet: AnyInlet,
2118 ) -> StreamResult<()> {
2119 let complete_now = {
2120 let mut state = self.state.lock().expect("partition state poisoned");
2121 state.upstream_closed = true;
2122 state.pending.is_none()
2123 };
2124 if complete_now {
2125 for outlet in &self.outlets {
2126 if !logic.is_closed(outlet) {
2127 logic.complete(outlet)?;
2128 }
2129 }
2130 }
2131 Ok(())
2132 }
2133 }
2134
2135 struct Out<T: 'static> {
2136 index: usize,
2137 inlet: Inlet<T>,
2138 outlets: Vec<Outlet<T>>,
2139 state: Arc<Mutex<State<T>>>,
2140 }
2141
2142 impl<T> OutHandler for Out<T>
2143 where
2144 T: Clone + Send + 'static,
2145 {
2146 fn on_pull(
2147 &mut self,
2148 logic: &mut GraphStageLogic,
2149 _outlet: AnyOutlet,
2150 ) -> StreamResult<()> {
2151 let mut complete_now = false;
2152 let pending = {
2153 let mut state = self.state.lock().expect("partition state poisoned");
2154 if let Some((idx, _)) = &state.pending
2155 && *idx == self.index
2156 {
2157 state.pending.take()
2158 } else {
2159 None
2160 }
2161 };
2162 if let Some((_, item)) = pending {
2163 logic.push(&self.outlets[self.index], item)?;
2164 let state = self.state.lock().expect("partition state poisoned");
2165 if state.upstream_closed {
2166 complete_now = true;
2167 } else if any_live_demand(logic, &self.outlets, &state.cancelled)
2168 && !logic.has_been_pulled(&self.inlet)
2169 {
2170 logic.pull(&self.inlet)?;
2171 }
2172 } else {
2173 let state = self.state.lock().expect("partition state poisoned");
2174 if state.upstream_closed {
2175 complete_now = true;
2176 } else if any_live_demand(logic, &self.outlets, &state.cancelled)
2177 && !logic.has_been_pulled(&self.inlet)
2178 {
2179 logic.pull(&self.inlet)?;
2180 }
2181 }
2182 if complete_now {
2183 for outlet in &self.outlets {
2184 if !logic.is_closed(outlet) {
2185 logic.complete(outlet)?;
2186 }
2187 }
2188 }
2189 Ok(())
2190 }
2191
2192 fn on_downstream_finish(
2193 &mut self,
2194 logic: &mut GraphStageLogic,
2195 _outlet: AnyOutlet,
2196 ) -> StreamResult<()> {
2197 let (cancel_stage, clear_pending) = {
2198 let mut state = self.state.lock().expect("partition state poisoned");
2199 if state.cancelled[self.index] {
2200 return Ok(());
2201 }
2202 state.cancelled[self.index] = true;
2203 state.live_outlets -= 1;
2204 let clear_pending = state
2205 .pending
2206 .as_ref()
2207 .is_some_and(|(idx, _)| *idx == self.index);
2208 let cancel_stage = state.eager_cancel || state.live_outlets == 0;
2209 if clear_pending {
2210 state.pending = None;
2211 }
2212 (cancel_stage, clear_pending)
2213 };
2214 if cancel_stage {
2215 logic.complete_stage()?;
2216 } else if clear_pending
2217 && !logic.has_been_pulled(&self.inlet)
2218 && !logic.is_closed(&self.inlet)
2219 {
2220 let state = self.state.lock().expect("partition state poisoned");
2221 if any_live_demand(logic, &self.outlets, &state.cancelled) {
2222 logic.pull(&self.inlet)?;
2223 }
2224 }
2225 Ok(())
2226 }
2227 }
2228
2229 let inlet = shape.inlet();
2230 let outlets = shape.outlets_vec();
2231 let state = Arc::new(Mutex::new(State {
2232 pending: None,
2233 upstream_closed: false,
2234 live_outlets: outlets.len(),
2235 cancelled: vec![false; outlets.len()],
2236 eager_cancel: self.eager_cancel,
2237 }));
2238 let mut logic = GraphStageLogic::new(shape);
2239 logic
2240 .set_handler(
2241 &inlet,
2242 Box::new(In {
2243 inlet_id: inlet.id(),
2244 inlet: inlet.clone(),
2245 outlets: outlets.clone(),
2246 partitioner: Arc::clone(&self.partitioner),
2247 state: Arc::clone(&state),
2248 }),
2249 )
2250 .unwrap();
2251 for (index, outlet) in outlets.iter().cloned().enumerate() {
2252 logic
2253 .set_out_handler(
2254 &outlet,
2255 Box::new(Out {
2256 index,
2257 inlet: inlet.clone(),
2258 outlets: outlets.clone(),
2259 state: Arc::clone(&state),
2260 }),
2261 )
2262 .unwrap();
2263 }
2264 logic
2265 }
2266}
2267
2268#[derive(Clone, Debug)]
2271pub struct Unzip<A: 'static, B: 'static> {
2272 _marker: PhantomData<fn() -> (A, B)>,
2273}
2274
2275impl<A: 'static, B: 'static> Unzip<A, B> {
2276 #[must_use]
2277 pub fn new() -> Self {
2278 Self {
2279 _marker: PhantomData,
2280 }
2281 }
2282}
2283
2284impl<A: 'static, B: 'static> Default for Unzip<A, B> {
2285 fn default() -> Self {
2286 Self::new()
2287 }
2288}
2289
2290impl<A, B> GraphStage for Unzip<A, B>
2291where
2292 A: Clone + Send + 'static,
2293 B: Clone + Send + 'static,
2294{
2295 type Shape = FanOutShape2<(A, B), A, B>;
2296
2297 fn name(&self) -> &str {
2298 "Unzip"
2299 }
2300
2301 fn allocate_shape(&self, allocator: &mut PortAllocator) -> Self::Shape {
2302 FanOutShape2::new(
2303 allocator.inlet("Unzip.in"),
2304 allocator.outlet("Unzip.out0"),
2305 allocator.outlet("Unzip.out1"),
2306 )
2307 }
2308
2309 fn stage_spec(&self, shape: &Self::Shape) -> StageSpec {
2310 let split = Arc::new(|dv: DatumValue| -> (DatumValue, DatumValue) {
2311 let pair: (A, B) =
2312 downcast_datum(dv, "unzip", || "Unzip.in").expect("unzip: wrong element type");
2313 (datum(pair.0), datum(pair.1))
2314 });
2315 #[allow(clippy::type_complexity)]
2320 let typed_split_fn: Arc<dyn Fn((A, B)) -> (A, B) + Send + Sync> =
2321 Arc::new(|pair: (A, B)| pair);
2322 let typed_split: Arc<StageTypedUnzipFn> = Arc::new(typed_split_fn);
2323 StageSpec::unzip(
2324 Arc::from(self.name()),
2325 shape.inlets(),
2326 shape.outlets(),
2327 split,
2328 typed_split,
2329 )
2330 }
2331
2332 fn create_logic(&self, shape: &Self::Shape) -> GraphStageLogic {
2333 UnzipWith::new(|pair: (A, B)| pair).create_logic(shape)
2334 }
2335}
2336
2337#[derive(Clone)]
2340pub struct UnzipWith<In: 'static, Out0: 'static, Out1: 'static> {
2341 split: Arc<dyn Fn(In) -> (Out0, Out1) + Send + Sync>,
2342 _marker: PhantomData<fn(In) -> (Out0, Out1)>,
2343}
2344
2345impl<In: 'static, Out0: 'static, Out1: 'static> fmt::Debug for UnzipWith<In, Out0, Out1> {
2346 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2347 f.debug_struct("UnzipWith").finish_non_exhaustive()
2348 }
2349}
2350
2351impl<In: 'static, Out0: 'static, Out1: 'static> UnzipWith<In, Out0, Out1> {
2352 #[must_use]
2353 pub fn new<F>(split: F) -> Self
2354 where
2355 F: Fn(In) -> (Out0, Out1) + Send + Sync + 'static,
2356 {
2357 Self {
2358 split: Arc::new(split),
2359 _marker: PhantomData,
2360 }
2361 }
2362}
2363
2364impl<In, Out0, Out1> GraphStage for UnzipWith<In, Out0, Out1>
2365where
2366 In: Clone + Send + 'static,
2367 Out0: Clone + Send + 'static,
2368 Out1: Clone + Send + 'static,
2369{
2370 type Shape = FanOutShape2<In, Out0, Out1>;
2371
2372 fn name(&self) -> &str {
2373 "UnzipWith"
2374 }
2375
2376 fn allocate_shape(&self, allocator: &mut PortAllocator) -> Self::Shape {
2377 FanOutShape2::new(
2378 allocator.inlet("UnzipWith.in"),
2379 allocator.outlet("UnzipWith.out0"),
2380 allocator.outlet("UnzipWith.out1"),
2381 )
2382 }
2383
2384 fn stage_spec(&self, shape: &Self::Shape) -> StageSpec {
2385 let split_fn = Arc::clone(&self.split);
2386 let split = Arc::new(move |dv: DatumValue| -> (DatumValue, DatumValue) {
2387 let value: In = downcast_datum(dv, "unzip_with", || "UnzipWith.in")
2388 .expect("unzip-with: wrong element type");
2389 let (out0, out1) = split_fn(value);
2390 (datum(out0), datum(out1))
2391 });
2392 let typed_split_fn: Arc<dyn Fn(In) -> (Out0, Out1) + Send + Sync> = Arc::clone(&self.split);
2395 let typed_split: Arc<StageTypedUnzipFn> = Arc::new(typed_split_fn);
2396 StageSpec::unzip(
2397 Arc::from(self.name()),
2398 shape.inlets(),
2399 shape.outlets(),
2400 split,
2401 typed_split,
2402 )
2403 }
2404
2405 fn create_logic(&self, shape: &Self::Shape) -> GraphStageLogic {
2406 struct State {
2407 left_open: bool,
2408 right_open: bool,
2409 upstream_closed: bool,
2410 }
2411
2412 struct InHandlerState<In: 'static, Out0: 'static, Out1: 'static> {
2413 inlet_id: PortId,
2414 inlet: Inlet<In>,
2415 out0: Outlet<Out0>,
2416 out1: Outlet<Out1>,
2417 split: Arc<dyn Fn(In) -> (Out0, Out1) + Send + Sync>,
2418 state: Arc<Mutex<State>>,
2419 }
2420
2421 impl<In, Out0, Out1> InHandler for InHandlerState<In, Out0, Out1>
2422 where
2423 In: Clone + Send + 'static,
2424 Out0: Clone + Send + 'static,
2425 Out1: Clone + Send + 'static,
2426 {
2427 fn on_push(
2428 &mut self,
2429 logic: &mut GraphStageLogic,
2430 _inlet: AnyInlet,
2431 ) -> StreamResult<()> {
2432 let value: In = logic.grab_datum(self.inlet_id).and_then(|value| {
2433 downcast_datum(value, "grab", || {
2434 format!("inlet#{}", self.inlet_id.as_usize())
2435 })
2436 })?;
2437 let (left, right) = (self.split)(value);
2438 let state = self.state.lock().expect("unzip-with state poisoned");
2439 if state.left_open {
2440 logic.push(&self.out0, left)?;
2441 }
2442 if state.right_open {
2443 logic.push(&self.out1, right)?;
2444 }
2445 drop(state);
2446 let state = self.state.lock().expect("unzip-with state poisoned");
2447 let left_ready = !state.left_open || logic.is_available(&self.out0);
2448 let right_ready = !state.right_open || logic.is_available(&self.out1);
2449 if (state.left_open || state.right_open)
2450 && left_ready
2451 && right_ready
2452 && !logic.has_been_pulled(&self.inlet)
2453 {
2454 logic.pull(&self.inlet)?;
2455 }
2456 Ok(())
2457 }
2458
2459 fn on_upstream_finish(
2460 &mut self,
2461 logic: &mut GraphStageLogic,
2462 _inlet: AnyInlet,
2463 ) -> StreamResult<()> {
2464 self.state
2465 .lock()
2466 .expect("unzip-with state poisoned")
2467 .upstream_closed = true;
2468 if !logic.is_closed(&self.out0) {
2469 logic.complete(&self.out0)?;
2470 }
2471 if !logic.is_closed(&self.out1) {
2472 logic.complete(&self.out1)?;
2473 }
2474 Ok(())
2475 }
2476 }
2477
2478 struct Out<In: 'static, Out0: 'static, Out1: 'static> {
2479 is_left: bool,
2480 inlet: Inlet<In>,
2481 out0: Outlet<Out0>,
2482 out1: Outlet<Out1>,
2483 state: Arc<Mutex<State>>,
2484 }
2485
2486 impl<In, Out0, Out1> OutHandler for Out<In, Out0, Out1>
2487 where
2488 In: Clone + Send + 'static,
2489 Out0: Clone + Send + 'static,
2490 Out1: Clone + Send + 'static,
2491 {
2492 fn on_pull(
2493 &mut self,
2494 logic: &mut GraphStageLogic,
2495 _outlet: AnyOutlet,
2496 ) -> StreamResult<()> {
2497 let state = self.state.lock().expect("unzip-with state poisoned");
2498 let left_ready = !state.left_open || logic.is_available(&self.out0);
2499 let right_ready = !state.right_open || logic.is_available(&self.out1);
2500 if state.upstream_closed {
2501 drop(state);
2502 if !logic.is_closed(&self.out0) {
2503 logic.complete(&self.out0)?;
2504 }
2505 if !logic.is_closed(&self.out1) {
2506 logic.complete(&self.out1)?;
2507 }
2508 } else if (state.left_open || state.right_open)
2509 && left_ready
2510 && right_ready
2511 && !logic.has_been_pulled(&self.inlet)
2512 {
2513 drop(state);
2514 logic.pull(&self.inlet)?;
2515 }
2516 Ok(())
2517 }
2518
2519 fn on_downstream_finish(
2520 &mut self,
2521 logic: &mut GraphStageLogic,
2522 _outlet: AnyOutlet,
2523 ) -> StreamResult<()> {
2524 let mut state = self.state.lock().expect("unzip-with state poisoned");
2525 if self.is_left {
2526 state.left_open = false;
2527 } else {
2528 state.right_open = false;
2529 }
2530 if !state.left_open && !state.right_open {
2531 logic.complete_stage()?;
2532 return Ok(());
2533 }
2534 let left_ready = !state.left_open || logic.is_available(&self.out0);
2535 let right_ready = !state.right_open || logic.is_available(&self.out1);
2536 if !state.upstream_closed
2537 && (state.left_open || state.right_open)
2538 && left_ready
2539 && right_ready
2540 && !logic.has_been_pulled(&self.inlet)
2541 {
2542 logic.pull(&self.inlet)?;
2543 }
2544 Ok(())
2545 }
2546 }
2547
2548 let inlet = shape.inlet();
2549 let out0 = shape.out0();
2550 let out1 = shape.out1();
2551 let state = Arc::new(Mutex::new(State {
2552 left_open: true,
2553 right_open: true,
2554 upstream_closed: false,
2555 }));
2556 let mut logic = GraphStageLogic::new(shape);
2557 logic
2558 .set_handler(
2559 &inlet,
2560 Box::new(InHandlerState {
2561 inlet_id: inlet.id(),
2562 inlet: inlet.clone(),
2563 out0: out0.clone(),
2564 out1: out1.clone(),
2565 split: Arc::clone(&self.split),
2566 state: Arc::clone(&state),
2567 }),
2568 )
2569 .unwrap();
2570 logic
2571 .set_out_handler(
2572 &out0,
2573 Box::new(Out {
2574 is_left: true,
2575 inlet: inlet.clone(),
2576 out0: out0.clone(),
2577 out1: out1.clone(),
2578 state: Arc::clone(&state),
2579 }),
2580 )
2581 .unwrap();
2582 logic
2583 .set_out_handler(
2584 &out1.clone(),
2585 Box::new(Out {
2586 is_left: false,
2587 inlet: inlet.clone(),
2588 out0: out0.clone(),
2589 out1: out1.clone(),
2590 state,
2591 }),
2592 )
2593 .unwrap();
2594 logic
2595 }
2596}
2597
2598#[derive(Clone, Debug)]
2601pub struct AsyncBoundary<T: 'static> {
2602 _marker: PhantomData<fn() -> T>,
2603}
2604
2605impl<T: 'static> AsyncBoundary<T> {
2606 #[must_use]
2607 pub fn new() -> Self {
2608 Self {
2609 _marker: PhantomData,
2610 }
2611 }
2612}
2613
2614impl<T: 'static> Default for AsyncBoundary<T> {
2615 fn default() -> Self {
2616 Self::new()
2617 }
2618}
2619
2620impl<T> GraphStage for AsyncBoundary<T>
2621where
2622 T: Clone + Send + 'static,
2623{
2624 type Shape = FlowShape<T, T>;
2625
2626 fn name(&self) -> &str {
2627 "AsyncBoundary"
2628 }
2629
2630 fn allocate_shape(&self, _allocator: &mut PortAllocator) -> Self::Shape {
2631 let first_id = next_port_id_block(2);
2632 FlowShape::new(
2633 Inlet::with_arc_name(first_id, async_boundary_inlet_name()),
2634 Outlet::with_arc_name(first_id.offset(1), async_boundary_outlet_name()),
2635 )
2636 }
2637
2638 fn stage_spec(&self, shape: &Self::Shape) -> StageSpec {
2639 self.stage_spec_with_ports(shape, shape.inlets(), shape.outlets())
2640 }
2641
2642 fn stage_spec_with_ports(
2643 &self,
2644 _shape: &Self::Shape,
2645 inlets: Vec<AnyInlet>,
2646 outlets: Vec<AnyOutlet>,
2647 ) -> StageSpec {
2648 StageSpec::async_boundary(async_boundary_stage_name(), inlets, outlets)
2649 }
2650}