Bitflags in Rust
While working on Rust bindings for KConfig as a part of Season of KDE 2022, I came across a few problems while trying to represent QFlags
in Rust:
- Most
QFlags
are defined as C++ enums in which multiple members can have the same value. This is not possible in Rust enum. - It is possible to enable multiple flags using BitwiseOr. Rust enums cannot do bitwise operations.
This post will guide you through the various implementations I came up with and their tradeoffs.
The C++ enum
The enum I was trying to implement was KConfig::OpenFlags
. The enum is given below:
;
Implementation 1: Using Rust modules
This method uses a combination of Rust modules and consants. The sample implementation is as follow:
Advantages
Const is replaced at compile time, so no performance cost.
All values can be documented in the same way using Rust comments.
Multiple flags can be activated.
Drawbacks
- Not an enum. Just a collection of constants.
Implementation 2: Using const in Impl
This method defines the problematic members as const
in impl
. The sample implementation is as follows:
Advantages
- Enum, for the most part.
Drawbacks
- Inconsistent documentation. The constants don’t show up as enum variants.
- Multiple flags cannot be activated
Implementation 3: Converting standard Rust enums when passing to C++
This method uses standard rust enums. The sample implementation is as follows:
Advantages
Completely Enum.
Documentation works as expected.
Drawbacks
Function call every time passing from Rust to C++. I don’t think this will have much performance penalty, but still worth mentioning.
Cannot set multiple flags at once. Eg
OpenFlag::IncludeGlobal | OpenFlag::CascadeConfig
not possible
Implementation 4: use bitflags crate
This is the implementation that I finally settled on. The implementation is as follows:
use bitflags
bitflags!
Advantages
Multiple flags can be used together.
Documentation is consistent.
Drawbacks
- Not enum. Shows up as
struct
in docs.
Documentation Screenshot
Conclusion
I think I will be using bitflags for representing all QFlags
in kconfig for the foreseeable future.