use futures::{StreamExt, stream::Map, Stream};
pub trait TryEnumerateExt<Ok, Err>: Stream<Item=Result<Ok, Err>> + Sized {
#[allow(clippy::type_complexity)]
fn try_enumerate(
self
) -> Map<
futures::stream::Enumerate<Self>,
fn((usize, Result<Ok, Err>)) -> Result<(usize, Ok), Err>,
> {
self.enumerate().map(|(i, res)| res.map(|v| (i, v)))
}
}
impl<S, Ok, Err> TryEnumerateExt<Ok, Err> for S where S: Stream<Item=Result<Ok, Err>> + Sized {}
pub trait TryEnumerateAllExt<Ok, Err>: Stream<Item=Result<Ok, Err>> + Sized {
#[allow(clippy::type_complexity)]
fn try_enumerate_all(
self
) -> Map<
futures::stream::Enumerate<Self>,
fn((usize, Result<Ok, Err>)) -> Result<(usize, Ok), (usize, Err)>,
> {
self.enumerate().map(|(i, res)| res.map(|v| (i, v)).map_err(|err| (i, err)))
}
}
impl<S, Ok, Err> TryEnumerateAllExt<Ok, Err> for S where S: Stream<Item=Result<Ok, Err>> + Sized {}
#[cfg(test)]
mod tests {
use super::*;
use std::future;
use futures::stream;
use tokio::pin;
#[tokio::test]
async fn enumerate_yielded_regardless_of_errors() {
let stream = stream::iter([Ok(0), Err(1), Ok(2)])
.try_enumerate()
.filter_map(|res| future::ready(res.ok()));
pin!(stream);
for i in 0..2 {
let (enumerate_idx, value) = stream.next().await.expect("Stream ended prematurely");
assert_eq!(enumerate_idx, value, "Enumeration index mismatch for item #{i}")
}
}
}