Please think about bit-flag enumerations when designing this. Bit-flag enumerations have some constants given explicit names and values with disjoint bit patterns, and then programs may use the logical OR of any set of the named constants, possibly with some exceptions (which, of course, C does not check for). They are very common in C low-level interfaces, for instance the second argument to the POSIX open primitive on Linux can be any combination of
enum OpenFlags {
O_RDONLY = 0x00000000,
O_WRONLY = 0x00000001,
O_RDWR = 0x00000002,
O_ACCMODE = 0x00000003,
O_CREAT = 0x00000040,
O_EXCL = 0x00000080,
O_NOCTTY = 0x00000100,
O_TRUNC = 0x00000200,
O_APPEND = 0x00000400,
O_NONBLOCK = 0x00000800,
O_DSYNC = 0x00001000,
O_ASYNC = 0x00002000,
O_DIRECT = 0x00004000,
O_LARGEFILE = 0x00008000,
O_DIRECTORY = 0x00010000,
O_NOFOLLOW = 0x00020000,
O_NOATIME = 0x00040000,
O_CLOEXEC = 0x00080000,
O_SYNC = 0x00101000,
O_PATH = 0x00200000,
O_TMPFILE = 0x00410000,
O_NDELAY = O_NONBLOCK,
O_FSYNC = O_SYNC
}
except that you must use exactly one of O_RDONLY, O_WRONLY, and O_RDWR, and some of the combinations of the others might not make a whole lot of sense.
Rust’s insistence that variables with a numeric-enum type can only have values equal to one of the named constants means that this kind of foreign interface is poorly handled.