I have a match block that determines who needs to send a message
match text.to_id {
Some(id) => {
if let Some(tx) = state.read().unwrap().get(&id){
tx.send(message.clone()).unwrap();
} else {continue;}
}
None => {
for (_id, send) in state.read().unwrap().iter(){
send.send(message.clone()).unwrap();
}
}
}
but if id == 0, this should send the message to everyone the same way. if I try:
None | Some(0)=>
None | Some(id) if id == 0=>
or
Some(id) if id !=0 =>
it doesn't work or send me a error:
`Some(_)` not covered
how can use pattern None too, if id==0?
Patterns are traversed top-to-bottom. So if you add alternates to the None
clause (overlapping with the Some()
clause) you need to move the pattern to the top:
match text.to_id {
None | Some(0) => {
for (_id, send) in state.read().unwrap().iter(){
send.send(message.clone()).unwrap();
}
}
Some(id) => {
if let Some(tx) = state.read().unwrap().get(&id){
tx.send(message.clone()).unwrap();
} else {continue;}
}
}
If you add a guard to the original Some
clause, then you still need to match Some(_)
in the bottom clause for Some(0)
and Rust does not have refinement types so it does not understand that the complement of Some(id) if id != 0
is Some(0)
, which is why it's telling you that Some(_)
is not covered. In that case the easiest is to just use a wildcard for the second branch
match text.to_id {
Some(id) if id != 0 => {
if let Some(tx) = state.read().unwrap().get(&id){
tx.send(message.clone()).unwrap();
} else {continue;}
}
_ => {
for (_id, send) in state.read().unwrap().iter(){
send.send(message.clone()).unwrap();
}
}
}
An other alternative is to fold the Some(0)
case into a None
via Option::filter
, such that the case does not "infect" the match:
match text.to_id.filter(|id| *id != 0) {
Some(id) => {
if let Some(tx) = state.read().unwrap().get(&id){
tx.send(message.clone()).unwrap();
} else {continue;}
}
None => {
for (_id, send) in state.read().unwrap().iter(){
send.send(message.clone()).unwrap();
}
}
}