Getting common value out of enum variations

I have a structure, as follows:

enum Message {
    CONNECT { id: PlayerID, address: Option<SocketAddr>},
    MOVE { id: PlayerID, delta: Vec2D },
    DISCONNECT { id: PlayerID },
}

In a method, broadcast, I am attempting to send this message to multiple clients. In order to avoid sending a client it's own message, I am checking to see if the id of the sender is the same as who will receive the packet in the loop. However, I need to pull the id field out of the enum, and I must do this without consuming the value. Here is my current code:

let id = match &message {
    Message::CONNECT { id, address } => id,
    Message::DISCONNECT { id } => id,
    Message::MOVE { id , delta} => id
};
for (client, mailbox) in self.clients.iter() {
    if id == client {continue;}
    mailbox.send(message);
}

The error I get from the compiler is as follows: cannot move out of message because it is borrowed, and the line mailbox.send(message) is highlighted.

How can I retrieve the common id field from the enum, without consuming the value of message?

You are no consuming message at match &message. You are consuming message at mailbox.send(message), where is highlighted.

You either should send message.clone(), or change mailbox.send's signature to not consume the message.

If PlayerID is Copy, then the following would work:

let Message::CONNECT { id, .. }
    | Message::DISCONNECT { id }
    | Message::MOVE { id , .. } = message;
for (client, mailbox) in self.clients.iter() {
    if id == client {continue;}
    mailbox.send(message);
}

If it's Clone, then borrow message and then do let id = id.clone();.

I'm also showing that you can merge multiple patterns using or-patterns with the |, and because every possible variant has the field id, then it becomes an irrefutable pattern, meaning you no longer need the match.

It is currently not working because of "match ergonomics" which makes the compiler notice that you have a &Message, so it infers that id should actually be a &PlayerID.

1 Like

This doesn't work. message is consumed in previous for cycle, and original code doesn't work for the exact same reason. The title and the question are red herrings, OP's method of extracting id is fine.

Then one way to solve OP's problem would be to search the client first, and then use it to send the message outside of the loop.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.