std_mel/flow/mod.rs
1use futures::{pin_mut, select, FutureExt};
2use melodium_core::common::executive::{InputExt, OutputExt, Value};
3use melodium_macro::{check, mel_treatment};
4use std::collections::VecDeque;
5
6pub mod concentrate;
7pub mod vec;
8
9/// Chain two streams.
10///
11///
12/// ```mermaid
13/// graph LR
14/// T("chain()")
15/// A["🟨 🟨 🟨 🟨 🟨 🟨"] -->|first| T
16/// B["… 🟪 🟪 🟪"] -->|second| T
17///
18/// T -->|chained| O["… 🟪 🟪 🟪 🟨 🟨 🟨 🟨 🟨 🟨"]
19///
20/// style A fill:#ffffff,stroke:#ffffff
21/// style B fill:#ffffff,stroke:#ffffff
22/// style O fill:#ffffff,stroke:#ffffff
23/// ```
24#[mel_treatment(
25 generic T ()
26 input first Stream<T>
27 input second Stream<T>
28 output chained Stream<T>
29)]
30pub async fn chain() {
31 while let Ok(values) = first.recv_many().await {
32 check!(chained.send_many(values).await)
33 }
34
35 while let Ok(values) = second.recv_many().await {
36 check!(chained.send_many(values).await)
37 }
38}
39
40/// Trigger on a stream start and end.
41///
42/// Emit `start` when a first value is send through the stream.
43/// Emit `end` when stream is finally over.
44///
45/// Emit `first` with the first value coming in the stream.
46/// Emit `last` with the last value coming in the stream.
47///
48/// ℹ️ `start` and `first` are always emitted together.
49/// If the stream only contains one element, `first` and `last` both contains it.
50/// If the stream never transmit any data before being ended, only `end` is emitted.
51///
52/// ```mermaid
53/// graph LR
54/// T("trigger()")
55/// B["🟥 … 🟨 🟨 🟨 🟨 🟨 🟨 … 🟩"] -->|stream| T
56///
57/// T -->|start| S["〈🟦〉"]
58/// T -->|first| F["〈🟩〉"]
59/// T -->|last| L["〈🟥〉"]
60/// T -->|end| E["〈🟦〉"]
61///
62/// style B fill:#ffffff,stroke:#ffffff
63/// style S fill:#ffffff,stroke:#ffffff
64/// style F fill:#ffffff,stroke:#ffffff
65/// style L fill:#ffffff,stroke:#ffffff
66/// style E fill:#ffffff,stroke:#ffffff
67/// ```
68#[mel_treatment(
69 generic T ()
70 input stream Stream<T>
71 output start Block<void>
72 output end Block<void>
73 output first Block<T>
74 output last Block<T>
75)]
76pub async fn trigger() {
77 let mut last_value = None;
78
79 if let Ok(mut values) = stream.recv_many().await {
80 let _ = start.send_one_as(()).await;
81 if let Some(val) = values.pop_front() {
82 let _ = first.send_one(val.clone()).await;
83 last_value = Some(val);
84 }
85 if let Some(val) = Into::<VecDeque<Value>>::into(values).pop_back() {
86 last_value = Some(val);
87 }
88
89 let _ = futures::join!(start.close(), first.close());
90 }
91
92 while let Ok(values) = stream.recv_many().await {
93 last_value = Into::<VecDeque<Value>>::into(values).pop_back();
94 }
95
96 let _ = end.send_one_as(()).await;
97 if let Some(val) = last_value {
98 let _ = last.send_one(val).await;
99 }
100
101 // We don't close `end` and `last` explicitly here,
102 // because it would be redundant with boilerplate
103 // implementation of treatments.
104}
105
106/// Check a blocking value.
107///
108/// When `value` block is received, `check` is emitted.
109///
110/// ```mermaid
111/// graph LR
112/// T("check()")
113/// B["〈🟨〉"] -->|value| T
114///
115/// T -->|check| S["〈🟦〉"]
116///
117/// style B fill:#ffffff,stroke:#ffffff
118/// style S fill:#ffffff,stroke:#ffffff
119/// ```
120#[mel_treatment(
121 generic T ()
122 input value Block<T>
123 output check Block<void>
124)]
125pub async fn check() {
126 if let Ok(_) = value.recv_one().await {
127 let _ = check.send_one_as(()).await;
128 }
129}
130
131/// Uncheck a blocking value.
132///
133/// When `value` block stream is closed without receiving anything, `uncheck` is emitted.
134///
135/// ```mermaid
136/// graph LR
137/// T("uncheck()")
138/// B["〈🟨〉"] -->|value| T
139///
140/// T -->|uncheck| S["〈🟦〉"]
141///
142/// style B fill:#ffffff,stroke:#ffffff
143/// style S fill:#ffffff,stroke:#ffffff
144/// ```
145#[mel_treatment(
146 generic T ()
147 input value Block<T>
148 output uncheck Block<void>
149)]
150pub async fn uncheck() {
151 if let Err(_) = value.recv_one().await {
152 let _ = uncheck.send_one_as(()).await;
153 }
154}
155
156/// Emit a blocking value.
157///
158/// When `trigger` is enabled, `value` is emitted as block.
159///
160/// ```mermaid
161/// graph LR
162/// T("emit(value=🟨)")
163/// B["〈🟦〉"] -->|trigger| T
164///
165/// T -->|emit| S["〈🟨〉"]
166///
167/// style B fill:#ffffff,stroke:#ffffff
168/// style S fill:#ffffff,stroke:#ffffff
169/// ```
170#[mel_treatment(
171 generic T ()
172 input trigger Block<void>
173 output emit Block<T>
174)]
175pub async fn emit(value: T) {
176 if let Ok(_) = trigger.recv_one().await {
177 let _ = emit.send_one(value).await;
178 }
179}
180
181/// Stream a blocking value.
182///
183/// ```mermaid
184/// graph LR
185/// T("stream()")
186/// B["〈🟦〉"] -->|block| T
187///
188/// T -->|stream| S["🟦"]
189///
190///
191/// style B fill:#ffffff,stroke:#ffffff
192/// style S fill:#ffffff,stroke:#ffffff
193/// ```
194#[mel_treatment(
195 generic T ()
196 input block Block<T>
197 output stream Stream<T>
198)]
199pub async fn stream() {
200 if let Ok(val) = block.recv_one().await {
201 let _ = stream.send_one(val).await;
202 }
203}
204
205/// Merge two streams.
206///
207/// The two streams are merged without predictible order.
208///
209/// ℹ️ Merge continues as long as `a` or `b` continues too, while the other can be ended.
210///
211/// ```mermaid
212/// graph LR
213/// T("merge()")
214/// A["… 🟦 🟫 …"] -->|a| T
215/// B["… 🟧 🟪 🟨 …"] -->|b| T
216///
217///
218/// T -->|value| V["… 🟦 🟧 🟪 🟫 🟨 …"]
219///
220/// style V fill:#ffffff,stroke:#ffffff
221/// style A fill:#ffffff,stroke:#ffffff
222/// style B fill:#ffffff,stroke:#ffffff
223/// ```
224#[mel_treatment(
225 generic T ()
226 input a Stream<T>
227 input b Stream<T>
228 output value Stream<T>
229)]
230pub async fn merge() {
231 let xa = async {
232 while let Ok(a) = (&a).recv_many().await {
233 check!(value.send_many(a).await);
234 }
235 }
236 .fuse();
237 let xb = async {
238 while let Ok(b) = (&b).recv_many().await {
239 check!(value.send_many(b).await);
240 }
241 }
242 .fuse();
243
244 pin_mut!(xa, xb);
245
246 loop {
247 select! {
248 () = xa => {},
249 () = xb => {},
250 complete => break,
251 };
252 }
253}
254
255/// Arrange two streams as one.
256///
257/// The two streams are merged using the `select` stream:
258/// - when `true`, value from `a` is used;
259/// - when `false`, value from `b` is used.
260///
261/// ℹ️ No value from either `a` or `b` are discarded, they are used when `select` give turn.
262///
263/// ⚠️ When `select` ends merge terminates without treating the remaining values from `a` and `b`.
264/// When `select` give turn to `a` or `b` while the concerned stream is ended, the merge terminates.
265/// Merge continues as long as `select` and concerned stream does, while the other can be ended.
266///
267/// ```mermaid
268/// graph LR
269/// T("arrange()")
270/// A["… 🟦 🟫 …"] -->|a| T
271/// B["… 🟧 🟪 🟨 …"] -->|b| T
272/// O["… 🟩 🟥 🟥 🟩 🟥 …"] -->|select|T
273///
274///
275/// T -->|value| V["… 🟦 🟧 🟪 🟫 🟨 …"]
276///
277/// style V fill:#ffffff,stroke:#ffffff
278/// style O fill:#ffffff,stroke:#ffffff
279/// style A fill:#ffffff,stroke:#ffffff
280/// style B fill:#ffffff,stroke:#ffffff
281/// ```
282#[mel_treatment(
283 generic T ()
284 input a Stream<T>
285 input b Stream<T>
286 input select Stream<bool>
287 output value Stream<T>
288)]
289pub async fn arrange() {
290 while let Ok(select) = select.recv_one_as::<bool>().await {
291 let val;
292 if select {
293 if let Ok(v) = a.recv_one().await {
294 val = v;
295 } else {
296 break;
297 }
298 } else {
299 if let Ok(v) = b.recv_one().await {
300 val = v;
301 } else {
302 break;
303 }
304 }
305
306 check!(value.send_one(val).await)
307 }
308}
309
310/// Fill a pattern stream with a `value.
311///
312/// ```mermaid
313/// graph LR
314/// T("fill(value=🟧)")
315/// B["… 🟦 🟦 🟦 …"] -->|pattern| T
316///
317/// T -->|filled| O["… 🟧 🟧 🟧 …"]
318///
319/// style B fill:#ffffff,stroke:#ffffff
320/// style O fill:#ffffff,stroke:#ffffff
321/// ```
322#[mel_treatment(
323 generic T ()
324 input pattern Stream<void>
325 output filled Stream<T>
326)]
327pub async fn fill(value: T) {
328 while let Ok(pat) = pattern.recv_many().await {
329 let mut transmission = melodium_core::TransmissionValue::new(value.clone());
330 for _ in 1..pat.len() {
331 transmission.push(value.clone());
332 }
333 check!(filled.send_many(transmission).await)
334 }
335}
336
337/// Filter a stream according to `bool` stream.
338///
339/// ℹ️ If both streams are not the same size nothing is sent through accepted nor rejected.
340///
341/// ```mermaid
342/// graph LR
343/// T("filter()")
344/// V["… 🟦 🟧 🟪 🟫 🟨 …"] -->|value| T
345/// D["… 🟩 🟥 🟥 🟩 🟥 …"] -->|select|T
346///
347/// T -->|accepted| A["… 🟦 🟫 …"]
348/// T -->|rejected| R["… 🟧 🟪 🟨 …"]
349///
350/// style V fill:#ffffff,stroke:#ffffff
351/// style D fill:#ffffff,stroke:#ffffff
352/// style A fill:#ffffff,stroke:#ffffff
353/// style R fill:#ffffff,stroke:#ffffff
354/// ```
355#[mel_treatment(
356 generic T ()
357 input value Stream<T>
358 input select Stream<bool>
359 output accepted Stream<T>
360 output rejected Stream<T>
361)]
362pub async fn filter() {
363 let mut accepted_op = true;
364 let mut rejected_op = true;
365
366 while let (Ok(value), Ok(select)) = futures::join!(value.recv_one(), select.recv_one()) {
367 let select = select.try_data::<bool>().unwrap();
368 if select {
369 if let Err(_) = accepted.send_one(value).await {
370 // If we cannot send anymore on accepted, we note it,
371 // and check if rejected is still valid, else just terminate.
372 accepted_op = false;
373 if !rejected_op {
374 break;
375 }
376 }
377 } else {
378 if let Err(_) = rejected.send_one(value).await {
379 // If we cannot send anymore on rejected, we note it,
380 // and check if accepted is still valid, else just terminate.
381 rejected_op = false;
382 if !accepted_op {
383 break;
384 }
385 }
386 }
387 }
388}
389
390/// Filter a block according to `bool` value.
391///
392/// ℹ️ If `select` is never received nothing is emitted.
393///
394/// ```mermaid
395/// graph LR
396/// T("filterBlock()")
397/// V["〈🟦〉"] -->|value| T
398/// D["〈🟩〉"] -->|select|T
399///
400/// T -->|accepted| A["〈🟦〉"]
401/// T -->|rejected| R[" "]
402///
403/// style V fill:#ffffff,stroke:#ffffff
404/// style D fill:#ffffff,stroke:#ffffff
405/// style A fill:#ffffff,stroke:#ffffff
406/// style R fill:#ffffff,stroke:#ffffff
407/// ```
408#[mel_treatment(
409 generic T ()
410 input value Block<T>
411 input select Block<bool>
412 output accepted Block<T>
413 output rejected Block<T>
414)]
415pub async fn filterBlock() {
416 if let (Ok(value), Ok(select)) = futures::join!(value.recv_one(), select.recv_one()) {
417 let select = select.try_data::<bool>().unwrap();
418 if select {
419 let _ = accepted.send_one(value).await;
420 } else {
421 let _ = rejected.send_one(value).await;
422 }
423 }
424}
425
426/// Fit a stream into a pattern.
427///
428/// ℹ️ If some remaining values doesn't fit into the pattern, they are trashed.
429///
430/// ```mermaid
431/// graph LR
432/// T("fit()")
433/// A["… 🟨 🟨 🟨 🟨 🟨 🟨"] -->|value| T
434/// B["🟦 🟦 🟦 🟦"] -->|pattern| T
435///
436/// T -->|fitted| O["🟨 🟨 🟨 🟨"]
437///
438/// style A fill:#ffffff,stroke:#ffffff
439/// style B fill:#ffffff,stroke:#ffffff
440/// style O fill:#ffffff,stroke:#ffffff
441/// ```
442#[mel_treatment(
443 generic T ()
444 input value Stream<T>
445 input pattern Stream<void>
446 output fitted Stream<T>
447)]
448pub async fn fit() {
449 'main: while let Ok(pattern) = pattern.recv_many_as::<()>().await {
450 for _ in pattern {
451 if let Ok(val) = value.recv_one().await {
452 check!('main, fitted.send_one(val).await)
453 } else {
454 break 'main;
455 }
456 }
457 }
458}
459
460/// Gives count of elements passing through stream.
461///
462/// This count increment one for each element within the stream, starting at 1.
463///
464/// ```mermaid
465/// graph LR
466/// T("count()")
467/// V["🟦 🟦 🟦 …"] -->|iter| T
468///
469/// T -->|count| P["1️⃣ 2️⃣ 3️⃣ …"]
470///
471/// style V fill:#ffffff,stroke:#ffffff
472/// style P fill:#ffffff,stroke:#ffffff
473/// ```
474#[mel_treatment(
475 generic T ()
476 input stream Stream<T>
477 output count Stream<u128>
478)]
479pub async fn count() {
480 let mut i: u128 = 1;
481 while let Ok(iter) = stream.recv_many().await {
482 let next_i = i + iter.len() as u128;
483 check!(count.send_many_as((i..next_i).collect::<Vec<_>>()).await);
484 i = next_i;
485 }
486}
487
488/// Generate a stream with a given length.
489///
490/// ```mermaid
491/// graph LR
492/// T("generate()")
493/// B["〈🟨〉"] -->|length| T
494///
495/// T -->|stream| S["… 🟦 🟦 🟦 🟦 🟦 🟦"]
496///
497///
498/// style B fill:#ffffff,stroke:#ffffff
499/// style S fill:#ffffff,stroke:#ffffff
500/// ```
501#[mel_treatment(
502 generic T ()
503 input length Block<u128>
504 output stream Stream<T>
505)]
506pub async fn generate(data: T) {
507 if let Ok(length) = length.recv_one_as::<u128>().await {
508 const CHUNK: u128 = 2u128.pow(20);
509 let mut total = 0u128;
510 while total < length {
511 let chunk = u128::min(CHUNK, length - total) as usize;
512 let mut transmission = melodium_core::TransmissionValue::new(data.clone());
513 for _ in 1..chunk {
514 transmission.push(data.clone());
515 }
516 check!(stream.send_many(transmission).await);
517 total += chunk as u128;
518 }
519 }
520}
521
522/// Generate a stream indefinitely.
523///
524/// This generates a continuous stream, until stream consumers closes it.
525///
526/// ```mermaid
527/// graph LR
528/// T("generateIndefinitely()")
529/// B["〈🟦〉"] -->|trigger| T
530///
531/// T -->|stream| S["… 🟦 🟦 🟦 🟦 🟦 🟦"]
532///
533///
534/// style B fill:#ffffff,stroke:#ffffff
535/// style S fill:#ffffff,stroke:#ffffff
536/// ```
537#[mel_treatment(
538 generic T ()
539 input trigger Block<void>
540 output stream Stream<T>
541)]
542pub async fn generate_indefinitely(data: T) {
543 if let Ok(_) = trigger.recv_one().await {
544 const CHUNK: usize = 2usize.pow(20);
545 loop {
546 let mut transmission = melodium_core::TransmissionValue::new(data.clone());
547 for _ in 1..CHUNK {
548 transmission.push(data.clone());
549 }
550 check!(stream.send_many(transmission).await);
551 }
552 }
553}
554
555/// Insert a block into a stream.
556///
557/// `block` is inserted into `stream` when it comes and everything is streamed to `output`.
558///
559/// ℹ️ No assumption on block insertion position in stream can be made.
560///
561/// ```mermaid
562/// graph LR
563/// T("insert()")
564/// A["… 🟦 🟦 🟦 🟦 …"] -->|stream| T
565/// B["〈🟧〉"] -->|block| T
566///
567///
568/// T -->|output| V["… 🟦 🟧 🟦 🟦 🟦 …"]
569///
570/// style V fill:#ffffff,stroke:#ffffff
571/// style A fill:#ffffff,stroke:#ffffff
572/// style B fill:#ffffff,stroke:#ffffff
573/// ```
574#[mel_treatment(
575 generic T ()
576 input stream Stream<T>
577 input block Block<T>
578 output output Stream<T>
579)]
580pub async fn insert() {
581 let streaming = async {
582 while let Ok(values) = (&stream).recv_many().await {
583 check!(output.send_many(values).await);
584 }
585 }
586 .fuse();
587 let insert_block = async {
588 if let Ok(val) = (&block).recv_one().await {
589 let _ = output.send_one(val).await;
590 }
591 }
592 .fuse();
593
594 pin_mut!(streaming, insert_block);
595
596 loop {
597 select! {
598 () = streaming => {},
599 () = insert_block => {},
600 complete => break,
601 };
602 }
603}
604
605/// Merge two incoming blocks as a stream.
606///
607/// Each block is taken when it arrives and send through `stream`.
608///
609/// ℹ️ No priority on blocks order in stream can be assumed.
610///
611/// ```mermaid
612/// graph LR
613/// T("flock()")
614/// A["〈🟦〉"] -->|a| T
615/// B["〈🟧〉"] -->|b| T
616///
617///
618/// T -->|stream| V["🟧 🟦"]
619///
620/// style V fill:#ffffff,stroke:#ffffff
621/// style A fill:#ffffff,stroke:#ffffff
622/// style B fill:#ffffff,stroke:#ffffff
623/// ```
624#[mel_treatment(
625 generic T ()
626 input a Block<T>
627 input b Block<T>
628 output stream Stream<T>
629)]
630pub async fn flock() {
631 let xa = async {
632 if let Ok(a) = (&a).recv_one().await {
633 let _ = stream.send_one(a).await;
634 }
635 }
636 .fuse();
637 let xb = async {
638 if let Ok(b) = (&b).recv_one().await {
639 let _ = stream.send_one(b).await;
640 }
641 }
642 .fuse();
643
644 pin_mut!(xa, xb);
645
646 loop {
647 select! {
648 () = xa => {},
649 () = xb => {},
650 complete => break,
651 };
652 }
653}
654
655/// Emit one block.
656///
657/// Take first block coming among `a` or `b` and emit it in `value`, ignoring the remaining one.
658///
659/// ℹ️ No priority between blocks can be assumed if they are ready at same moment.
660///
661/// ```mermaid
662/// graph LR
663/// T("one()")
664/// A["〈〉"] -->|a| T
665/// B["〈🟧〉"] -->|b| T
666///
667///
668/// T -->|value| V["〈🟧〉"]
669///
670/// style V fill:#ffffff,stroke:#ffffff
671/// style A fill:#ffffff,stroke:#ffffff
672/// style B fill:#ffffff,stroke:#ffffff
673/// ```
674#[mel_treatment(
675 generic T ()
676 input a Block<T>
677 input b Block<T>
678 output value Block<T>
679)]
680pub async fn one() {
681 let xa = async { (&a).recv_one().await.ok() }.fuse();
682 let xb = async { (&b).recv_one().await.ok() }.fuse();
683
684 pin_mut!(xa, xb);
685
686 loop {
687 let val = select! {
688 val = xa => val,
689 val = xb => val,
690 complete => break,
691 };
692
693 if let Some(val) = val {
694 let _ = value.send_one(val).await;
695 break;
696 }
697 }
698}
699
700/// Never send any value.
701///
702/// No value is ever sent on `closed` output, which is immediately closed.
703///
704#[mel_treatment(
705 generic T ()
706 input trigger Block<void>
707 output closed Stream<T>
708)]
709pub async fn close() {
710 // Nothing to do
711}
712
713/// Never send any value.
714///
715/// No value is ever sent on `closed` output, which is immediately closed.
716///
717#[mel_treatment(
718 generic T ()
719 input trigger Block<void>
720 output closed Block<T>
721)]
722pub async fn close_block() {
723 // Nothing to do
724}
725
726/// Consume stream indefinitely.
727///
728/// Input `stream` is consumed indefinitely until it becomes closed by previous treatment.
729///
730#[mel_treatment(
731 generic T ()
732 input stream Stream<T>
733)]
734pub async fn consume() {
735 while let Ok(_) = stream.recv_many().await {
736 // Nothing to do.
737 }
738}
739
740/// Pass stream under condition.
741///
742/// If `if` is `true`, pass the stream, else closes it.
743///
744#[mel_treatment(
745 generic T ()
746 input stream Stream<T>
747 output passed Stream<T>
748)]
749pub async fn pass(cond: bool) {
750 if cond {
751 while let Ok(data) = stream.recv_many().await {
752 check!(passed.send_many(data).await)
753 }
754 }
755}
756
757/// Pass block under condition.
758///
759/// If `if` is `true`, pass the block, else nothing.
760///
761#[mel_treatment(
762 generic T ()
763 input block Block<T>
764 output passed Block<T>
765)]
766pub async fn passBlock(cond: bool) {
767 if cond {
768 if let Ok(data) = block.recv_one().await {
769 let _ = passed.send_one(data).await;
770 }
771 }
772}
773
774/// Barrier stream under condition.
775///
776/// Awaits `leverage` to let stream pass if it is `true`, else closes the stream.
777///
778#[mel_treatment(
779 generic T ()
780 input leverage Block<bool>
781 input stream Stream<T>
782 output passed Stream<T>
783)]
784pub async fn barrier() {
785 if let Ok(true) = leverage.recv_one_as::<bool>().await {
786 while let Ok(data) = stream.recv_many().await {
787 check!(passed.send_many(data).await)
788 }
789 }
790}
791
792/// Pass stream until cut signal.
793///
794/// Let stream pass until `cut` signal si received.
795///
796#[mel_treatment(
797 generic T ()
798 input cut Block<void>
799 input stream Stream<T>
800 output passed Stream<T>
801)]
802pub async fn cut() {
803 let cut = async { cut.recv_one().await.is_ok() }.fuse();
804 let pass = async {
805 while let Ok(values) = stream.recv_many().await {
806 check!(passed.send_many(values).await)
807 }
808 }
809 .fuse();
810
811 pin_mut!(cut, pass);
812
813 loop {
814 select! {
815 () = pass => break,
816 do_cut = cut => if do_cut {
817 break
818 },
819 complete => break,
820 }
821 }
822}
823
824/// Release stream once signal is received.
825///
826/// Awaits `leverage` to let stream pass, else closes the stream.
827///
828#[mel_treatment(
829 generic T ()
830 input leverage Block<void>
831 input data Stream<T>
832 output released Stream<T>
833)]
834pub async fn release() {
835 if let Ok(_) = leverage.recv_one().await {
836 while let Ok(data) = data.recv_many().await {
837 check!(released.send_many(data).await)
838 }
839 }
840}
841
842/// Release block once signal is received.
843///
844/// Awaits `leverage` to let block pass, else closes the flow.
845///
846#[mel_treatment(
847 generic T ()
848 input leverage Block<void>
849 input data Block<T>
850 output released Block<T>
851)]
852pub async fn releaseBlock() {
853 if let Ok(_) = leverage.recv_one().await {
854 if let Ok(data) = data.recv_one().await {
855 let _ = released.send_one(data).await;
856 }
857 }
858}
859
860/// Await blocks.
861///
862/// Wait for two blocks and send `awaited` once both are received.
863///
864/// ℹ️ If one block is never received, `awaited` is never emitted.
865#[mel_treatment(
866 generic T ()
867 input a Block<T>
868 input b Block<T>
869 output awaited Block<void>
870)]
871pub async fn waitBlock() {
872 let (a, b) = futures::join!(async { a.recv_one().await.is_ok() }, async {
873 b.recv_one().await.is_ok()
874 });
875
876 if a && b {
877 let _ = awaited.send_one_as(()).await;
878 }
879}