async fn maximum(default: Thing, responses: Vec<Result<Response, ThingError>>) -> Result<Thing, reqwest::Error> {
let resps : (u8, Thing) = responses.into_iter()
.filter_map(|result| result.ok())
.filter(|result | result.status() == StatusCode::OK)
.map( |resp| Thing::try_parse_response(resp.bytes())) // <<<<< resp.bytes() is `async`
.filter_map(|result : Result<Thing, ThingError> | result.ok())
.fold((0, default), |(num, a):(u8,Thing), b| (num + 1, if a < b { b } else { a }));
match resps {
(num_responses, max) if num_responses < 2 => Err(NotEnoughResponses(num_responses, max)),
(num_responses, max) if num_responses >= 2 => Ok(max),
_ => panic!("How is x < 2 || x >= 2 not exhaustive?")
}
}
In the above snippet, several HTTP requests were made and this function is being used to parse the results and find the maximum Thing
. This is being called from an async
function already, but it's not clear to me how to pass an async
function to Iterator::map
.
I figured that if it's not possible to pass an async
function in where Iterator
is not expecting one, then the next best thing would be to try to await
the response bytes prior to forming an iterator. However, given the variable number of responses, I'd have to do something pretty ugly to resolve them.
let mut bodies = Vec::with_capacity(responses.len());
for i in 0..responses.len() {
bodies.push(responses[i].await);
}
And then zip the two into an iterator of (Response, Body)
or something like that.