oxidecomputer / humility

Debugger for Hubris
Mozilla Public License 2.0
526 stars 50 forks source link

reflect: best-effort binary format for `bitflags` #461

Closed hawkw closed 6 months ago

hawkw commented 6 months ago

Hubris uses the bitflags crate in several places. Currently, humility's reflection module treats types generated using bitflags the same as all other integers; in output from commands like `humility ringbuf, they are formatted as hexadecimal.

This is not the worst, but it would be nicer if we could format bitflags types as binary, instead. That way, a reader need not convert hex to binary to determine which bits are set in a bitflags type.

As of bitflags 2.0, types generated using the "struct style" bitflags! macro always contain a single field whose type is InternalBitFlags. This means that humility's reflection module can detect bitflag types generated using this style of the macro, and format them as binary instead of hex. This PR implements that behavior. For example, in the task_thermal ringbuf, we used to see:

PowerModeChanged(PowerBitmask(InternalBitFlags(0x1)))
...
PowerModeChanged(PowerBitmask(InternalBitFlags(0x2)))

but now we see:

PowerModeChanged(PowerBitmask(0b1))
...
PowerModeChanged(PowerBitmask(0b10))

which is IMO quite a bit nicer!

It is worth noting that when the "impl style" of the bitflags! macro is used, there is no InternalBitFlags struct, as the user declares the struct type directly. In this case, we cannot currently detect that the type would like to be formatted as bits. For example:

// This *will* generate an `InternalBitFlags` struct
bitflags::bitflags! {
    pub struct MyBitflags: u8 {
       const FOO = 1 << 1;
       const BAR = 1 << 2;
   }
}

// This *will NOT* generate an `InternalBitFlags` struct
pub struct MyOtherBitflags(u8);
bitflags::bitflags! {
    impl MyOtherBitflags: u8 {
       const FOO = 1 << 1;
       const BAR = 1 << 2;
   }
}

However, I think this is still better than the current state of things, as we currently format bitflags types as hex with both styles of macro invocation.

Closes #460