So, I'm trying to get around the fact that Rust (still) doesn't have anything like a bitfield construct in the language yet.
I'm writing a small module that parses bits for the real-time clock in older x86 systems (and sometimes newer ones). The RTC has four "status" registers laid out as follows:
Status A:
Bit | Description |
---|---|
0:6 | Unspecified |
7 | Update-in-progress (UIP) |
Status B:
Bit | Description |
---|---|
0 | Enable daylight savings time |
1 | Time mode (12 hour or 24 hour) |
2 | Data mode (1 = binary, 0 = BCD) |
3 | Enable square-wave output |
4 | Enable update-ended interrupt |
5 | Enable alarm interrupt |
6 | Enable periodic interrupt |
7 | Enable setting of the clock by freezing updates |
Status C:
Bit | Description |
---|---|
0:3 | Unspecified |
4 | Update has ended |
5 | Alarm interrupt has triggered |
6 | Periodic interrupt has triggered |
7 | General interrupt has triggered, is set if any of bits 4-6 are set |
Status D:
Bit | Description |
---|---|
0:6 | Unspecified |
7 | Valid RAM for CMOS |
Currently I specify these using modular-bitfield. However, the bitfield proc-macro does not appear to be respecting my visibility modifiers, and that is causing the unreachable_pub
lint to wine. Its also emitting dead code, and even explicitly tries to allow it, despite the fact that I have it set to forbid. I cannot seem to find any way to change this behavior, and I'm completely unexperienced with modifying or understanding the internals of proc-macros. I describe the bitfields, however, using this code:
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, BitfieldSpecifier)]
pub(crate) enum DataMode {
Bcd,
Binary,
}
#[bitfield(bits = 8)]
#[repr(C)]
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
pub(crate) struct StatusA {
#[skip]
#[bits = 7]
_rsvd: B7,
/// Update in progress
#[skip(setters)]
#[bits = 1]
pub(crate) update_in_progress: bool,
}
#[bitfield(bits = 8)]
#[repr(C)]
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
pub(crate) struct StatusB {
/// Daylight Savings Enable
#[bits = 1]
pub(crate) enable_dst: bool,
/// 24-hour time
#[bits = 1]
pub(crate) hr24: bool,
/// Data Mode - 0: BCD, 1: Binary
#[bits = 1]
pub(crate) data_mode: DataMode,
/// enable square wave output
#[bits = 1]
pub(crate) enable_square_wave_output: bool,
/// enable update-ended interrupt
#[bits = 1]
pub(crate) enable_update_ended_interrupt: bool,
/// enable alarm interrupt
#[bits = 1]
pub(crate) enable_alarm_interrupt: bool,
/// enable periodic interrupt
#[bits = 1]
pub(crate) enable_periodic_interrupt: bool,
/// enable clock setting by freezing updates
#[bits = 1]
pub(crate) enable_clock_setting: bool,
}
#[bitfield(bits = 8)]
#[repr(C)]
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
pub(crate) struct StatusC {
#[skip]
#[bits = 4]
_rsvd: B4,
/// Update-Ended Interrupt Flag
#[skip(setters)]
#[bits = 1]
pub(crate) update_ended: bool,
/// Alarm Interrupt flag
#[skip(setters)]
#[bits = 1]
pub(crate) alarm_interrupt: bool,
/// Periodic Interrupt flag
#[skip(setters)]
#[bits = 1]
pub(crate) periodic_interrupt: bool,
/// Interrupt request flag =1 when any or all of bits 6-4 are 1 and appropriate enables
/// (Register B) are set to 1. Generates IRQ 8 when triggered.
#[skip(setters)]
#[bits = 1]
pub(crate) irq: bool,
}
#[bitfield(bits = 8)]
#[repr(C)]
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
pub(crate) struct StatusD {
#[skip]
#[bits = 7]
_rsvd: B7,
/// Valid RAM - 1 indicates battery power good, 0 if dead or disconnected.
#[skip(setters)]
#[bits = 1]
pub(crate) valid_ram: bool,
}
How can I make this work with bitvec? I could always just read the bits manually, too, but I'd like to use something like Bitvec if at all possible. (Or somebody might know a way around this problem -- other than disabling unreachable_pub
-- unless there's a good reason for doing so, that is.)