Dealing with very long permutations of enum

I have an enum encapsulating a set of limited types that I would like implementors of a trait Op to accept as a possible method argument. The enum wrapping should be done away with once Op gets it's contents. I implement the trait Op for a bunch of structs, then at runtime, I want to dynamically determine which objects get which argument of the possible types using an enum. This sounds confusing so here's some code

enum AllTypes {
    U32s(Vec<u32>),
    U8s(Vec<u8>),
    Dates(Vec<Date>),
    ...
}

trait Op<T> {
    fn op(&self, _: T) {}
}

// at runtime something like this might happen
if arglist == ("u32", "u8") {
    let op: &dyn Op<(u32, u8)> = ...;
    args = Arg::U32ThenU8(op);
} else { ... }

// some time later with alltypes variable defined in scope
match args {
                     // OurMap basically maps it's closure's output to the ops input using generics
    Arg::U32ThenU8(op) => OurMap(op, move |alltypes| (alltypes.get_u32s()[0], alltypes.get_u8s()[0])),
    ... // all the other possible permutations of Arg variants.. this is the daunting part
}

I'm pretty sure this will work, ignoring the unboxed pseducode closure above. The point is, I can map Arg type to an implementors of Op<T>. The daunting part is the Arg enum. I have 12 possible variants for the AllTypes enum. And because I don't see any other way to do this but to define a maximum number of types that can be mixed together (arity) THEN write each possible permutation of those types mixed together, I am stuck simply because hand writing this is extremely tedious.

enum Arg {
U32(&dyn Op<u32>),
U8(&dyn Op<u8>),
Usize(...)
Date(...)
U32ThenU8(...)
U8ThenU32(...)
U32ThenUsize(...)
... // not even close to done
}

Not to mention the match statements for Arg.. I know in rust there are macros like println! that are somewhat variadic. I can do this with C++ variadic templates. How do I do this kind of thing in Rust? Macros?

The code above is completely contrived and only for demonstration purposes. The program is basically an interpreter.

Yes.

Is this really all permutations? Or is there a limited set?

Because if it's really everything, why not have one variant of Arg that holds a Vec<Arg>, and maybe another with a HashMap<String, Arg>? That's basically what Unityped programming languages (like Python, often called "dynamic") do in their interpreters.

2 Likes