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.

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.