Remove repetition of calling generic function on enum variants?

When I have an enum where every variant's data has a different type, but implements the same trait, how can I call a generic function on this data without repeating the call n times?

I'm specifically looking for a solution that still uses monophonic versions (no trait objects).

enum Image {
    RGB(Vec<RGB>),
    RGBA(Vec<RGBA>),
    BGR(Vec<BGR>),
    Gray(Vec<u8>),
}

fn process_pixels<T: Pixel>(image: &[T]) {}

match image {
   RGB(image) => process_pixels(&image), // how to eliminate this repetition?
   RGBA(image) => process_pixels(&image),
   BGR(image) => process_pixels(&image),
   Gray(image) => process_pixels(&image),
}

I think I've asked about it before, and there was some fancy macro crate for this, but I can't find it now.

enum_dispatch?

2 Likes

Thanks! That may be the crate I've seen before.

It looks very hacky (keeps global state between proc macro invocations) and is limited to trait methods (can't directly do expressions or freestanding functions), which may be why I haven't used it last time.

My search also yielded enumerate, which has a slightly different API, but seems to suffer from the same limitation regarding associated functions. I didn't have a look at the implementation though.

This is a bit unfortunate, I think having a go-to answer to this particular problem would be good for the ecosystem, as the "enum implements a trait by delegating to each of its variant that also implement the trait" looks like a common, useful pattern to me.

Maybe also optionally adding to this pattern a last variant Dyn(Box<dyn Trait>) that allows extending the closed set of types (at the price of virtual calls) when this makes sense.