How to write a function to select a specific enum variant?

// prost-build, so not really changeable
mod generated_from_protobuf {
  struct MessageOneT {
    // something
  }
  struct MessageTwoT {
    // something
  }

  enum Messages {
    MessageOne(MessageOneT),
    MessageTwo(MessageTwoT),
    //100+ variants
  }
}

/// Waits for `Messages::MessageOne`, ignoring other variants of `Messages`
fn wait_for_msg_one() -> MessageOneT {
    loop {
        // would be received from a channel
        let incoming: Messages = Messages::MessageOne(MessageOneT {});

        // will have boilerplate for timeouts, etc.
        if let Messages::MessageOne(t) = incoming {
            return t;
        }
    }
}

// Any way to avoid writing one function per enum variant, but still having an easy way to wait for whatever variant is needed?

How can I make wait_for_msg_one work for all variants of the enum? Is there a way to write it so I can just say wait for the next MessageThree and it figures out that means it will return MessageThreeT? Ideally without writing something for each variant, as there's 100+ of them, and they will be added over time. Or is this something where macros would have to be used? (I've never written one)

You probably do want some sort of macro. Perhaps this one (but I didn't try it out or know the nuances around overlapping variant-wrapped types). Then you could

fn wait_for_msg<T: TryFrom<Messages>>() -> T {
    loop {
        let incoming: Messages = todo!();
        if let Ok(msg) = T::try_from(incoming) {
            return msg;
        }
    }
}
1 Like