|
1 | 1 | use futures::future::Future;
|
| 2 | +use futures::stream::Stream; |
2 | 3 |
|
3 | 4 | pub async fn ready<T>(value: T) -> T {
|
4 | 5 | value
|
@@ -101,6 +102,28 @@ pub async fn unwrap_or_else<Fut, T, E, F>(future: Fut, f: F) -> T
|
101 | 102 | future_result.unwrap_or_else(f)
|
102 | 103 | }
|
103 | 104 |
|
| 105 | +pub fn flatten_stream<Fut, St, T>(future: Fut) -> impl Stream<Item = T> |
| 106 | + where Fut: Future<Output = St>, |
| 107 | + St: Stream<Item = T>, |
| 108 | +{ |
| 109 | + use crate::stream::next; |
| 110 | + futures::stream::unfold((Some(future), None), async move | (future, stream)| { |
| 111 | + match (future, stream) { |
| 112 | + (Some(future), None) => { |
| 113 | + let stream = await!(future); |
| 114 | + let mut stream = Box::pin(stream); |
| 115 | + let item = await!(next(&mut stream)); |
| 116 | + item.map(|item| (item, (None, Some(stream)))) |
| 117 | + }, |
| 118 | + (None, Some(mut stream)) => { |
| 119 | + let item = await!(next(&mut stream)); |
| 120 | + item.map(|item| (item, (None, Some(stream)))) |
| 121 | + }, |
| 122 | + _ => unreachable!() |
| 123 | + } |
| 124 | + }) |
| 125 | +} |
| 126 | + |
104 | 127 | #[cfg(test)]
|
105 | 128 | mod tests {
|
106 | 129 | use futures::executor;
|
@@ -204,4 +227,18 @@ mod tests {
|
204 | 227 | assert_eq!(await!(new_future), ());
|
205 | 228 | });
|
206 | 229 | }
|
| 230 | + |
| 231 | + #[test] |
| 232 | + fn test_flatten_stream() { |
| 233 | + use futures::stream; |
| 234 | + use crate::stream::collect; |
| 235 | + executor::block_on(async { |
| 236 | + let stream_items = vec![17, 18, 19]; |
| 237 | + let future_of_a_stream = ready(stream::iter(stream_items)); |
| 238 | + |
| 239 | + let stream = flatten_stream(future_of_a_stream); |
| 240 | + let list: Vec<_> = await!(collect(stream)); |
| 241 | + assert_eq!(list, vec![17, 18, 19]); |
| 242 | + }); |
| 243 | + } |
207 | 244 | }
|
0 commit comments