Hi all, this is a method that I've wished for a long time that Result
had on it, and I thought I might bring this up here to see if anyone has thoughts, to see if there's maybe something obvious I'm missing. If people think this seems like a really good idea I might make an RFC for it.
Sometimes you have a task that ends up with Result<(), Error>
, wherein sometimes the error indicates an actual problem that should be logged as an error, but sometimes it just represents something normal. For example, in quinn
, accepting a stream on a connection returns Result<Stream, ConnectionError>
--but if the client closes the connection intentionally then the accept method will return Err(ConnectionError::ApplicationClose)
, which is not actually an error and shouldn't be logged as an error.
This means that a sub-task that accepts streams on a connection will naturally have a return signature Result<(), ConnectionError>
, and when it returns you want to pattern match on the error and log the error unless the error is ApplicationClose
.
If there was some method on Result<I, E>
that worked sort of like and_then
but in "reverse" (it has the ability to turn an Err
variant into an Ok
variant) this could be done without pattern matching:
impl<I, E> Result<I, E> {
fn recover_err<F: FnOnce(E) -> Result<I, E>>(self, f: F) -> Result<I, E> {
match self {
Ok(i) => Ok(i),
Err(e) => f(e),
}
}
}
async fn accept_streams(conn: &Connection) -> Result<(), ConnectionError> { ... }
...
accept_streams(&conn).await
.recover_err(|e| if matches!(e, ConnectionError::ApplicationClose) { Ok(()) } else { Err(e) })?;
Thoughts?