1use futures::Stream;
19use futures::future::FusedFuture;
20use futures::stream::FusedStream;
21use parking_lot::Mutex;
22use pin_project_lite::pin_project;
23use std::ops::DerefMut;
24use std::pin::Pin;
25use std::sync::Arc;
26use std::task::{Context, Poll};
27
28pub fn async_stream<T, F: Future<Output = ()>>(
54 generator: impl FnOnce(Emitter<T>) -> F,
55) -> impl FusedStream<Item = T> {
56 let (emitter, receiver) = tx_rx();
57 AsyncStream::new(receiver, generator(emitter))
58}
59
60pub fn async_try_stream<T, E, F: Future<Output = Result<(), E>>>(
90 generator: impl FnOnce(TryEmitter<T, E>) -> F,
91) -> impl FusedStream<Item = Result<T, E>> {
92 let (try_emitter, mut emitter, receiver) = try_tx_rx::<T, E>();
93 AsyncStream::new(receiver, async move {
94 if let Err(e) = generator(try_emitter).await {
95 emitter.set(Err(e));
100 }
101 })
102}
103
104fn tx_rx<T>() -> (Emitter<T>, Receiver<T>) {
106 let slot = Arc::new(Mutex::new(None));
107 (
108 Emitter {
109 slot: Arc::clone(&slot),
110 },
111 Receiver { slot },
112 )
113}
114
115#[expect(
117 clippy::type_complexity,
118 reason = "three-element tuple is clearer than an alias here"
119)]
120fn try_tx_rx<T, E>() -> (
121 TryEmitter<T, E>,
122 Emitter<Result<T, E>>,
123 Receiver<Result<T, E>>,
124) {
125 let slot = Arc::new(Mutex::new(None));
126 (
127 TryEmitter {
128 slot: Arc::clone(&slot),
129 },
130 Emitter {
131 slot: Arc::clone(&slot),
132 },
133 Receiver { slot },
134 )
135}
136
137type SlotRef<T> = Arc<Mutex<Option<T>>>;
141
142pub struct Emitter<T> {
146 slot: SlotRef<T>,
147}
148
149pub struct TryEmitter<T, E> {
153 slot: SlotRef<Result<T, E>>,
154}
155
156struct Receiver<T> {
157 slot: SlotRef<T>,
158}
159
160impl<T> Emitter<T> {
161 pub fn emit(&mut self, value: T) -> impl FusedFuture<Output = ()> {
175 self.set(value);
176 Emit { done: false }
177 }
178
179 fn set(&mut self, value: T) {
183 let mut guard = self.slot.lock();
184 match guard.deref_mut() {
185 Some(_) => panic!("Misuse: await was not called after calling emit"),
186 slot => *slot = Some(value),
187 }
188 }
189}
190
191impl<T, E> TryEmitter<T, E> {
192 pub fn emit(&mut self, value: T) -> impl FusedFuture<Output = ()> {
202 let mut guard = self.slot.lock();
203 match guard.deref_mut() {
204 Some(_) => panic!("Misuse: await was not called after calling emit"),
205 slot => *slot = Some(Ok::<T, E>(value)),
206 }
207
208 Emit { done: false }
209 }
210}
211
212struct Emit {
213 done: bool,
214}
215
216impl FusedFuture for Emit {
217 fn is_terminated(&self) -> bool {
218 self.done
219 }
220}
221
222impl Future for Emit {
223 type Output = ();
224
225 fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> {
226 if !self.done {
227 self.done = true;
228 Poll::Pending
231 } else {
232 Poll::Ready(())
233 }
234 }
235}
236
237pin_project! {
238 struct AsyncStream<T, U> {
239 rx: Receiver<T>,
240 done: bool,
241 #[pin]
242 generator: U,
243 }
244}
245
246impl<T, U> AsyncStream<T, U> {
247 fn new(rx: Receiver<T>, generator: U) -> AsyncStream<T, U> {
248 AsyncStream {
249 rx,
250 done: false,
251 generator,
252 }
253 }
254}
255
256impl<T, U> FusedStream for AsyncStream<T, U>
257where
258 U: Future<Output = ()>,
259{
260 fn is_terminated(&self) -> bool {
261 self.done
262 }
263}
264
265impl<T, U> Stream for AsyncStream<T, U>
266where
267 U: Future<Output = ()>,
268{
269 type Item = T;
270
271 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
272 let this = self.project();
273
274 if *this.done {
275 return Poll::Ready(None);
276 }
277
278 debug_assert!(this.rx.slot.lock().is_none());
281 let res = this.generator.poll(cx);
282 *this.done = res.is_ready();
283
284 match this.rx.slot.lock().take() {
285 Some(v) => Poll::Ready(Some(v)),
287 None if *this.done => Poll::Ready(None),
289 None => Poll::Pending,
292 }
293 }
294
295 fn size_hint(&self) -> (usize, Option<usize>) {
296 if self.done { (0, Some(0)) } else { (0, None) }
297 }
298}
299
300#[cfg(test)]
301mod test {
302 use crate::async_stream::Emitter;
303 use crate::{async_stream, async_try_stream};
304 use futures::stream::FusedStream;
305 use futures::{Stream, StreamExt, pin_mut};
306 use std::assert_matches;
307 use std::pin::Pin;
308 use std::sync::Arc;
309 use std::sync::atomic::{AtomicUsize, Ordering};
310 use std::task::{Context, Poll};
311 use tokio::sync::mpsc;
312
313 #[tokio::test]
314 async fn noop_stream() {
315 let s = async_stream(|_: Emitter<()>| async {});
316 pin_mut!(s);
317
318 assert_eq!(s.next().await, None);
319 }
320
321 #[tokio::test]
322 async fn empty_stream() {
323 let mut ran = false;
324
325 {
326 let r = &mut ran;
327 let s = async_stream(|_: Emitter<()>| async {
328 *r = true;
329 println!("hello world!");
330 });
331 pin_mut!(s);
332
333 assert_eq!(s.next().await, None);
334 }
335
336 assert!(ran);
337 }
338
339 #[tokio::test]
340 async fn emit_single_value() {
341 let s = async_stream(|mut emitter| async move {
342 emitter.emit("hello").await;
343 });
344
345 let values: Vec<_> = s.collect().await;
346
347 assert_eq!(1, values.len());
348 assert_eq!("hello", values[0]);
349 }
350
351 #[tokio::test]
352 async fn fused() {
353 let s = async_stream(|mut emitter| async move {
354 emitter.emit("hello").await;
355 });
356 pin_mut!(s);
357
358 assert!(!s.is_terminated());
359 assert_eq!(s.next().await, Some("hello"));
360 assert_eq!(s.next().await, None);
361
362 assert!(s.is_terminated());
363 assert_eq!(s.next().await, None);
365 }
366
367 #[tokio::test]
368 async fn emit_multi_value() {
369 let s = async_stream(|mut emitter| async move {
370 emitter.emit("hello").await;
371 emitter.emit("world").await;
372 emitter.emit("dizzy").await;
373 });
374
375 let values: Vec<_> = s.collect().await;
376
377 assert_eq!(3, values.len());
378 assert_eq!("hello", values[0]);
379 assert_eq!("world", values[1]);
380 assert_eq!("dizzy", values[2]);
381 }
382
383 #[tokio::test]
384 #[should_panic = "await was not called after calling emit"]
385 async fn emit_without_await() {
386 let s = async_stream(|mut emitter| async move {
387 #[expect(clippy::let_underscore_future)]
388 {
389 let _ = emitter.emit("hello");
390 let _ = emitter.emit("world");
391 }
392 });
393
394 let _: Vec<_> = s.collect().await;
395 }
396
397 #[tokio::test]
398 async fn unit_emit_in_select() {
399 use tokio::select;
400
401 #[expect(clippy::unused_async)]
402 async fn do_stuff_async() {}
403
404 let s = async_stream(|mut emitter| async move {
405 select! {
406 _ = do_stuff_async() => emitter.emit(()).await,
407 else => emitter.emit(()).await,
408 }
409 });
410
411 let values: Vec<_> = s.collect().await;
412 assert_eq!(values.len(), 1);
413 }
414
415 #[tokio::test]
416 async fn emit_with_select() {
417 use tokio::select;
418
419 #[expect(clippy::unused_async)]
420 async fn do_stuff_async() {}
421 #[expect(clippy::unused_async)]
422 async fn more_async_work() {}
423
424 let s = async_stream(|mut emitter| async move {
425 select! {
426 _ = do_stuff_async() => emitter.emit("hey").await,
427 _ = more_async_work() => emitter.emit("hey").await,
428 else => emitter.emit("hey").await,
429 }
430 });
431
432 let values: Vec<_> = s.collect().await;
433 assert_eq!(values, vec!["hey"]);
434 }
435
436 #[tokio::test]
437 async fn return_stream() {
438 fn build_stream() -> impl Stream<Item = u32> {
439 async_stream(|mut emitter| async move {
440 emitter.emit(1).await;
441 emitter.emit(2).await;
442 emitter.emit(3).await;
443 })
444 }
445
446 let s = build_stream();
447
448 let values: Vec<_> = s.collect().await;
449 assert_eq!(3, values.len());
450 assert_eq!(1, values[0]);
451 assert_eq!(2, values[1]);
452 assert_eq!(3, values[2]);
453 }
454
455 #[tokio::test]
456 async fn consume_channel() {
457 let (tx, mut rx) = mpsc::channel(10);
458
459 let s = async_stream(|mut emitter| async move {
460 while let Some(v) = rx.recv().await {
461 emitter.emit(v).await;
462 }
463 });
464
465 pin_mut!(s);
466
467 for i in 0..3 {
468 assert_matches!(tx.send(i).await, Ok(_));
469 assert_eq!(Some(i), s.next().await);
470 }
471
472 drop(tx);
473 assert_eq!(None, s.next().await);
474 }
475
476 #[tokio::test]
477 async fn borrow_self() {
478 struct Data(String);
479
480 impl Data {
481 fn stream(&self) -> impl Stream<Item = &str> + '_ {
482 async_stream(move |mut emitter| async move {
483 emitter.emit(&self.0[..]).await;
484 })
485 }
486 }
487
488 let data = Data("hello".to_string());
489 let s = data.stream();
490 pin_mut!(s);
491
492 assert_eq!(Some("hello"), s.next().await);
493 }
494
495 #[tokio::test]
496 async fn stream_in_stream() {
497 let s = async_stream(|mut emitter| async move {
498 let s = async_stream(|mut inner_emitter| async move {
499 for i in 0..3 {
500 inner_emitter.emit(i).await;
501 }
502 });
503
504 pin_mut!(s);
505 while let Some(v) = s.next().await {
506 emitter.emit(v).await;
507 }
508 });
509
510 let values: Vec<_> = s.collect().await;
511 assert_eq!(3, values.len());
512 }
513
514 #[tokio::test]
519 async fn stream_in_stream_misuse() {
520 let s = async_stream(|mut emitter| async move {
521 let s = async_stream(|_inner_emitter: Emitter<i32>| async move {
522 for _i in 0..3 {
523 emitter.emit("foo").await;
524 }
525 });
526
527 pin_mut!(s);
528 while let Some(v) = s.next().await {
529 println!("{v}");
530 }
531 });
532
533 let values: Vec<_> = s.collect().await;
534 assert_eq!(3, values.len());
535 }
536
537 #[tokio::test]
538 async fn emit_non_unpin_value() {
539 let s: Vec<_> = async_stream(|mut emitter| async move {
540 for i in 0..3 {
541 emitter.emit(async move { i }).await;
542 }
543 })
544 .buffered(1)
545 .collect()
546 .await;
547
548 assert_eq!(s, vec![0, 1, 2]);
549 }
550
551 #[tokio::test]
552 async fn should_not_call_handler_function_if_not_polled() {
553 let _ = async_stream(|_: Emitter<()>| async move {
554 panic!("should not be called");
555 });
556 }
557
558 #[tokio::test]
559 async fn should_not_continue_until_next_poll() {
560 let s = async_stream(|mut emitter| async move {
561 emitter.emit("hey").await;
562 panic!("make sure poll based and not push based");
563 });
564 pin_mut!(s);
565 let _ = s.next().await;
566 }
567
568 #[test]
569 fn inner_try_stream() {
570 use tokio::select;
571
572 #[expect(clippy::unused_async)]
573 async fn do_stuff_async() {}
574
575 let _ = async_stream(|mut emitter| async move {
576 select! {
577 _ = do_stuff_async() => {
578 let another_s = async_try_stream(|mut inner_emitter| async move {
579 inner_emitter.emit(()).await;
580 Ok(())
581 });
582 let _: Result<(), ()> = Box::pin(another_s).next().await.unwrap();
583 },
584 else => {},
585 }
586 emitter.emit(()).await;
587 });
588 }
589
590 #[tokio::test]
591 async fn single_err() {
592 let s = async_try_stream(|mut emitter| async move {
593 if true {
594 Err("hello")?;
595 } else {
596 emitter.emit("world").await;
597 }
598
599 unreachable!();
600 });
601
602 let values: Vec<_> = s.collect().await;
603 assert_eq!(1, values.len());
604 assert_eq!(Err("hello"), values[0]);
605 }
606
607 #[tokio::test]
608 async fn emit_then_err() {
609 let s = async_try_stream(|mut emitter| async move {
610 emitter.emit("hello").await;
611 Err("world")?;
612 unreachable!();
613 });
614
615 let values: Vec<_> = s.collect().await;
616 assert_eq!(2, values.len());
617 assert_eq!(Ok("hello"), values[0]);
618 assert_eq!(Err("world"), values[1]);
619 }
620
621 #[tokio::test]
622 async fn convert_err() {
623 struct ErrorA(u8);
624 #[derive(PartialEq, Debug)]
625 struct ErrorB(u8);
626 impl From<ErrorA> for ErrorB {
627 fn from(a: ErrorA) -> ErrorB {
628 ErrorB(a.0)
629 }
630 }
631
632 fn test() -> impl Stream<Item = Result<&'static str, ErrorB>> {
633 async_try_stream(|mut emitter| async move {
634 if true {
635 Err(ErrorA(1))?;
636 } else {
637 Err(ErrorB(2))?;
638 }
639 emitter.emit("unreachable").await;
640 Ok(())
641 })
642 }
643
644 let values: Vec<_> = test().collect().await;
645 assert_eq!(1, values.len());
646 assert_eq!(Err(ErrorB(1)), values[0]);
647 }
648
649 #[tokio::test]
650 async fn multi_try() {
651 fn test() -> impl Stream<Item = Result<i32, String>> {
652 async_try_stream(|mut emitter| async move {
653 let a = Ok::<_, String>(Ok::<_, String>(123))??;
654 for _ in 1..10 {
655 emitter.emit(a).await;
656 }
657 Ok(())
658 })
659 }
660 let values: Vec<_> = test().collect().await;
661 assert_eq!(9, values.len());
662 assert_eq!(
663 std::iter::repeat_n(123, 9).map(Ok).collect::<Vec<_>>(),
664 values
665 );
666 }
667
668 struct DropGuard(Arc<AtomicUsize>);
669
670 impl Drop for DropGuard {
671 fn drop(&mut self) {
672 self.0.fetch_add(1, Ordering::SeqCst);
673 }
674 }
675
676 #[tokio::test]
677 async fn generator_freed_on_done() {
678 let drops = Arc::new(AtomicUsize::new(0));
679 let guard = DropGuard(Arc::clone(&drops));
680
681 let s = async_stream(|mut emitter| async move {
682 let _guard = guard;
683 emitter.emit(1).await;
684 });
685 pin_mut!(s);
686
687 assert_eq!(s.next().await, Some(1));
688 assert_eq!(s.next().await, None);
689
690 assert_eq!(drops.load(Ordering::SeqCst), 1);
694 assert_eq!(s.next().await, None);
695 }
696
697 #[tokio::test]
698 async fn generator_freed_on_emitted_error() {
699 let drops = Arc::new(AtomicUsize::new(0));
700 let guard = DropGuard(Arc::clone(&drops));
701
702 let s = async_try_stream(|mut emitter| async move {
703 let _guard = guard;
704 emitter.emit(1).await;
705 Err("boom")
706 });
707 pin_mut!(s);
708
709 assert_eq!(s.next().await, Some(Ok(1)));
710 assert_eq!(s.next().await, Some(Err("boom")));
711
712 assert!(s.is_terminated());
715 assert_eq!(drops.load(Ordering::SeqCst), 1);
716
717 assert_eq!(s.next().await, None);
719 }
720
721 use pin_project_lite::pin_project;
722
723 pin_project! {
724 struct MyStream<T: Stream> {
725 #[pin]
726 input: T,
727 }
728 }
729
730 impl<T: Stream> Stream for MyStream<T> {
731 type Item = T::Item;
732
733 fn poll_next(
734 self: Pin<&mut Self>,
735 cx: &mut Context<'_>,
736 ) -> Poll<Option<Self::Item>> {
737 let this = self.project();
738 this.input.poll_next(cx)
739 }
740 }
741
742 #[tokio::test]
743 async fn emit_does_not_hold_on_value() {
744 let waker = futures::task::noop_waker_ref();
745 let mut cx = Context::from_waker(waker);
746
747 let run = Arc::<AtomicUsize>::new(AtomicUsize::new(0));
748 let moved = Arc::clone(&run);
749 let s = async_stream(|mut emitter| async move {
750 for _ in 0..2 {
751 let before = moved.fetch_add(1, Ordering::SeqCst);
752 emitter.emit(before).await;
753 }
754 });
755
756 let mut my_stream = Box::pin(MyStream { input: s });
757
758 #[derive(Debug, PartialEq)]
759 struct Item {
760 before: usize,
761 result: Poll<Option<usize>>,
762 after: usize,
763 }
764
765 let mut results = vec![];
766
767 assert_eq!(run.load(Ordering::SeqCst), 0);
768
769 while run.load(Ordering::SeqCst) < 2 {
770 let before = run.load(Ordering::SeqCst);
771 let result = my_stream.poll_next_unpin(&mut cx);
772 let after = run.load(Ordering::SeqCst);
773 results.push(Item {
774 before,
775 result,
776 after,
777 });
778 }
779
780 assert_eq!(
781 results,
782 vec![
783 Item {
784 before: 0,
785 result: Poll::Ready(Some(0)),
786 after: 1,
787 },
788 Item {
789 before: 1,
790 result: Poll::Ready(Some(1)),
791 after: 2,
792 }
793 ]
794 );
795 }
796}