Patterns for choosing only one implementation out of many

I have a project that uses a special communication crate. This is somewhat cumbersome to use; it's basically only for use in final tests and actual production environments. I'm working on a few different "simulator implementations" -- but it only makes sense to have one enabled at a time.

How would you go about expressing this?

The obvious solution is to use features, but I find that expressing "exactly one from a set of N features" is a little cumbersome; the C implementation has 5 different simulators, and I intend to port all of them to Rust.

On the other hand, using features automatically unlocks the ability to enable dependencies.

Hm... Is there something that can help express this:

#[cfg(not(exactly_one_of_features(foo, bar, baz)))]
compile_error!("Must specify exactly one comms backend implementation");

It gets a little annoying, because there are actually two different "production" backends (one for non-Windows and one for Windows), and it would be super neat if these were default (on respective platform type), while setting any of the other would disable the default ones and enable the selected one.

Are there any crates that help make these kinds of feature selections a little easier?

Unfortunately, such pattern isn't officially supported in Cargo. Features are supposed to be purely additive, and libraries are expected to work when all features are enabled at once.

There's cfg-if crate that helps a bit dealing with many alternatives, but ultimately there's no good solution.

1 Like

The fully supported, but sometimes tedious or infeasible, solution is to define a trait and use generics to allow picking an implementation without picking exactly one for the whole build.

3 Likes