Accessing enum struct data by name

I am trying to build a sort of DSL that needs to access data from different variants of an enum. In continuation to my previous question, I would like to do something like this:

enum Sample {
    Var1 {data: i32},
    Var2 {data1: i32, data2: i32},
    Var3 {data1: f32, data2:f32},
    Var4,
}

macro_rules! test_member {
    ($val:ident, $var:path, $member_name:ident, $member_val:expr) => {
        if let $var(s) = $val {  // <== some magic happens here
            s.$member_name == $member_val
        } else {
            false
        }
    }
}

// use
let s = Sample::Var2{data1: 1, data2: 2};
let is_val = test_member!(s, Sample::Var2, data2, 2);

Is this even possible? Is there a syntax that allows getting the "inner" struct from the enum variation?

Thanks!

macro_rules! test_member {
    ($val:expr, $var:path, $member_name:ident, $member_val:expr) => {
        if let $var{$member_name, ..} = &$val {
            *$member_name == $member_val
        } else {
            false
        }
    }
}

(playground)

Edit: Even shorter:

macro_rules! test_member {
    ($val:expr, $var:path, $member_name:ident, $member_val:expr) => {
        matches!(&$val, $var{$member_name, ..} if *$member_name == $member_val)
    }
}
1 Like

I don't think it's directly possible to get the entire struct of an enum variant.

enum Sample {
// --snip--
    Var2 {data1: i32, data2: i32},
// --snip--
}

The struct associated with the Var2 variant is anonymous. You can access and store all of its fields, but can't access/use the anonymous struct itself.
It is a bit limiting that you can't do something like having a function take a specific variant as an input when you know you have a specific variant.


Boilerplate-y workaround is to "extract" the enum variants into dedicated structs:

struct Var1{ pub data: i32 }
struct Var2{ pub data1: i32, pub data2: i32 }
struct Var3{ pub data1: f32, pub data2: f32 }
enum Sample {
    Var1(Var1),
    Var2(Var2),
    Var3(Var3),
    Var4,
}

(Shout outs to rust-analyzer which has a code action that does this for you!)


As for more built-in solutions, I'm pretty sure there's an RFC for this. I don't remember what it was called or if it was merged.

Wow! This is so cool and simple. Thanks.