| Crates.io | option_into_controlflow |
| lib.rs | option_into_controlflow |
| version | 1.0.0 |
| created_at | 2024-12-31 18:32:43.365288+00 |
| updated_at | 2024-12-31 18:32:43.365288+00 |
| description | Option into ControlFlow conversion |
| homepage | |
| repository | https://github.com/komar007/option_into_controlflow |
| max_upload_size | |
| id | 1500279 |
| size | 27,683 |
option_into_controlflowConvert Option<T> into ControlFlow<T, _> or ControlFlow<_, T>.
Analogically to ok_or and ok_or_else for converting into Result, this crate introduces:
break_or/continue_or,break_or_else/continue_or_else andbreak_or_default/continue_or_default for converting into ControlFlow.Since ControlFlow is more symmetrical than Result, functions exist for converting the Some
variant both into Break and Continue.
Suppose you are receiving some messages:
async fn process_messages(mut msgs: mpsc::Receiver<i32>) {
while let Some(msg) = msgs.recv().await {
println!("msg = {}", msg)
}
}
but now you need to support cancellation, so you do this:
async fn process_messages(mut msgs: mpsc::Receiver<i32>, token: CancellationToken) {
while let Some(msg) = select! { biased;
_ = token.cancelled() => None,
m = msgs.recv() => m,
} {
println!("msg = {}", msg)
}
}
and that's fine, but now you're using Option for controlling flow. None used to mean there will
be no more messages. This is semantically correct for a receiver and it's fine to pattern-match on
it in a loop condition. But now, None means "there will be no more messages OR processing is
cancelled". As the logic becomes more complicated, you might want to pattern-match on
ControlFlow::Continue instead, which is there for a reason - it conveys whether to continue or to
break.
So you can do this:
async fn process_messages(mut msgs: mpsc::Receiver<i32>, token: CancellationToken) {
while let ControlFlow::Continue(msg) = select! { biased;
_ = token.cancelled() => ControlFlow::Break(()),
m = msgs.recv() => {
if let Some(m) = m {
ControlFlow::Continue(m)
} else {
ControlFlow::Break(())
}
},
} {
println!("msg = {}", msg)
}
}
but it's so verbose, so, of course, you use option_into_controlflow:
async fn process_messages(mut msgs: mpsc::Receiver<i32>, token: CancellationToken) {
while let ControlFlow::Continue(msg) = select! { biased;
_ = token.cancelled() => ControlFlow::Break(()),
m = msgs.recv() => m.continue_or(()),
} {
println!("msg = {}", msg)
}
}
which is the best of both worlds - you no longer use Option for controlling the loop, but your
code becomes semantic, idiomatic and understandable.