yield_return/
local_iter.rs1use std::{
2 cell::RefCell,
3 future::Future,
4 iter::FusedIterator,
5 ops::{Deref, DerefMut},
6 pin::Pin,
7 rc::Rc,
8 task::{Context, Poll},
9};
10
11use futures_core::{FusedStream, Stream};
12
13use crate::utils::noop_waker;
14
15struct Sender<T>(Rc<RefCell<Option<T>>>);
16
17impl<T> Sender<T> {
18 #[track_caller]
19 fn set(&self, value: T) {
20 let mut data = self.0.borrow_mut();
21 assert!(data.is_none(), "The result of `ret` is not await.");
22 *data = Some(value);
23 }
24}
25
26impl<T> Future for Sender<T> {
27 type Output = ();
28 fn poll(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Self::Output> {
29 if self.0.borrow().is_some() {
30 Poll::Pending
31 } else {
32 Poll::Ready(())
33 }
34 }
35}
36
37pub struct LocalIterContext<T>(Sender<T>);
41
42impl<T> LocalIterContext<T> {
43 #[track_caller]
45 pub fn ret(&mut self, value: T) -> impl Future<Output = ()> + '_ {
46 self.0.set(value);
47 &mut self.0
48 }
49
50 pub async fn ret_iter(&mut self, iter: impl IntoIterator<Item = T>) {
52 for value in iter {
53 self.ret(value).await;
54 }
55 }
56}
57
58struct Data<'a, T> {
59 value: Rc<RefCell<Option<T>>>,
60 fut: Option<Pin<Box<dyn Future<Output = ()> + 'a>>>,
61}
62impl<T> Data<'_, T> {
63 fn poll_next(&mut self, cx: &mut Context) -> Poll<Option<T>> {
64 let Some(fut) = &mut self.fut else {
65 return Poll::Ready(None);
66 };
67 let poll = fut.as_mut().poll(cx);
68 match poll {
69 Poll::Ready(_) => {
70 assert!(
71 self.value.borrow().is_none(),
72 "The result of `ret` is not await."
73 );
74 self.fut = None;
75 Poll::Ready(None)
76 }
77 Poll::Pending => {
78 if let Some(value) = self.value.borrow_mut().take() {
79 Poll::Ready(Some(value))
80 } else {
81 Poll::Pending
82 }
83 }
84 }
85 }
86}
87
88pub struct LocalIter<'a, T>(Data<'a, T>);
92
93impl<'a, T: 'a> LocalIter<'a, T> {
94 pub fn new<Fut: Future<Output = ()> + 'a>(f: impl FnOnce(LocalIterContext<T>) -> Fut) -> Self {
107 let value = Rc::new(RefCell::new(None));
108 let cx = LocalIterContext(Sender(value.clone()));
109 let fut: Pin<Box<dyn Future<Output = ()> + 'a>> = Box::pin(f(cx));
110 let fut = Some(fut);
111 Self(Data { value, fut })
112 }
113}
114
115impl<T> Iterator for LocalIter<'_, T> {
116 type Item = T;
117 #[track_caller]
118 fn next(&mut self) -> Option<Self::Item> {
119 match self.0.poll_next(&mut Context::from_waker(&noop_waker())) {
120 Poll::Ready(value) => value,
121 Poll::Pending => panic!("`YieldContext::ret` is not called."),
122 }
123 }
124}
125impl<T> FusedIterator for LocalIter<'_, T> {}
126
127pub struct LocalAsyncIterContext<T>(LocalIterContext<T>);
131impl<T> Deref for LocalAsyncIterContext<T> {
132 type Target = LocalIterContext<T>;
133 fn deref(&self) -> &Self::Target {
134 &self.0
135 }
136}
137impl<T> DerefMut for LocalAsyncIterContext<T> {
138 fn deref_mut(&mut self) -> &mut Self::Target {
139 &mut self.0
140 }
141}
142
143pub struct LocalAsyncIter<'a, T>(LocalIter<'a, T>);
147
148impl<'a, T: 'a> LocalAsyncIter<'a, T> {
149 pub fn new<Fut: Future<Output = ()> + 'a>(
164 f: impl FnOnce(LocalAsyncIterContext<T>) -> Fut,
165 ) -> Self {
166 Self(LocalIter::new(|cx| f(LocalAsyncIterContext(cx))))
167 }
168}
169
170impl<T> Stream for LocalAsyncIter<'_, T> {
171 type Item = T;
172
173 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
174 self.0 .0.poll_next(cx)
175 }
176}
177impl<T> FusedStream for LocalAsyncIter<'_, T> {
178 fn is_terminated(&self) -> bool {
179 self.0 .0.fut.is_none()
180 }
181}