Matching against discriminants of enums with fields

Hey folks, I have what I thought was a relatively simple situation, but is proving to have rougher edges than I initially anticipated.

I have an enum that looks like this - it's used as part of sending requests to and receiving requests from other systems:

enum Request {
  RequestOne(String) = 1,
  RequestTwo(String, Option<String>) = 2,
  RequestThree(u8, Option<String>) = 3,

impl Request {
  pub(crate) fn message_type(&self) -> u8 {
    unsafe { *(self as *const Self as *const u8) }

This works fine for getting the discriminant out of an enum, but I would also like to be able to match against it, when I'm converting raw binary data back into types. Something like this:

match message_type => {
  Request::RequestOne(_).message_type() => Request::RequestOne(data.to_string()),
  Request::RequestTwo(_, _).message_type() => Request::RequestTwo(data.to_string(), None)
  Request::RequestThree(_, _).message_type() => Request::RequestOne(other_data, Some(data.to_string())),

This code very definitely doesn't compile, but I'm wondering if there's a sane way to do basically the same thing? Or should I abandon this approach completely? I realise this might be using enums in ways they really weren't designed for.

You can do something like:

const REQUEST_ONE: u8 = 1;
const REQUEST_TWO: u8 = 2;
const REQUEST_THREE: u8 = 3;

enum Request {
  RequestOne(String) = REQUEST_ONE,
  RequestTwo(String, Option<String>) = REQUEST_TWO,
  RequestThree(u8, Option<String>) = REQUEST_THREE,

You can use the const's to find the enum type.


Nah, you are, kinda, sorta, using it for what it was designed for. Just the usual trouble with bleeding edge features.

When you are using something which is less than one week old rough edges are expected.

The expectation was that you would always have two sibling enums and use #[repr(𝓲𝓷𝓽𝓮𝓰𝓮𝓻)].


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.