I am implementing a library "B" that will be used by another library "A", which will be used in the final program. B implements a hardware protocol, for which I need some quirks on certain chips.
My question is, how do I implement those quirks.
Use bitflags to allow runtime configuration
Use features to allow compile-time configuration
Something else...?
I currently tend towards #2, since it can be implemented most easily and would be more performant, since I won't need to branch if quirks.contains(...) in the code.
However, because of the dependency tree, I then will run into this issue.
Is there any established best practice in Rust how to deal with hardware quirks?
If it's just on certain chips, I think switching on target_arch or target_feature should make the most sense. I don't see a reason to set it via some externally configurable parameter, like crate features, since it should be unconditionally determined by your compilation target.
"Chip" in this context refers to a certain line of Zigbee chips. All of them can be used on any architecture (we currently use ARMv7 but as well may use them on x86_64).
B implements a low-level communication protocol via a serial port, which needs some quirks on certain models of that Zigbee chip line.
Rust features should be additive and should not change behavior, they should only enable the use of additional options. The options should be configured at runtime.
The reason is that two libraries that A depends on (C and D) may also depend on B, and may enable different features in B. All of these features will be enabled when compiling.
I'm not familiar with Zigbee chips, but I'd expect the best option to be runtime feature detection. Otherwise it seems that choosing the correct build configuration could be a pain. A runtime config would probably be the second-best option.
If you want to go the compile-time route, it certainly shouldn't be a cargo feature, since features should be additive. Perhaps an environment variable or a cargo.metadata field which is read in a build script? Or a separate build-time configuration file (which is also handled via build script)?