Support for explicit endianness #455

Open
opened 2025-08-12 08:57:42 -05:00 by qwandor · 4 comments
qwandor commented 2025-08-12 08:57:42 -05:00 (Migrated from github.com)

When working with hardware or network packets it is sometimes necessary to access bitfields which may have a defined endianness which doesn't match the host's endianness. It would be useful if bitflags could be used to define a bitflags type with an explicit endianness.

I'm not sure what the best way to achieve this would be. If working with zerocopy, one approach would be to use e.g. zerocopy::byteorder::little_endian::U32 as the representation for a bitflags type.

#451 might also be related.

When working with hardware or network packets it is sometimes necessary to access bitfields which may have a defined endianness which doesn't match the host's endianness. It would be useful if `bitflags` could be used to define a bitflags type with an explicit endianness. I'm not sure what the best way to achieve this would be. If working with `zerocopy`, one approach would be to use e.g. `zerocopy::byteorder::little_endian::U32` as the representation for a bitflags type. #451 might also be related.
KodrAus commented 2025-08-12 18:05:51 -05:00 (Migrated from github.com)

Ah I see the issue here is that you're re-interpreting memory-mapped data as some flags type? If that wasn't the case then I'd expect you'd be able to use from_bits(u32::from_le_bytes(..)) to handle endianness.

The only thing stopping us from supporting something like zerocopy::byteorder::little_endian::U32 in the bitflags! macro today is the lack const support in trait implementations. I've been against inventing attributes like #[no_const] that alter the behavior of bitflags!, because complex macro_rules macros are difficult to maintain. If we were to cook up a proc-macro based version of the macro though with more configurability that could cover this is that something you'd consider using?

Ah I see the issue here is that you're re-interpreting memory-mapped data as some flags type? If that wasn't the case then I'd expect you'd be able to use `from_bits(u32::from_le_bytes(..))` to handle endianness. The only thing stopping us from supporting something like `zerocopy::byteorder::little_endian::U32` in the `bitflags!` macro today is the lack const support in trait implementations. I've been against inventing attributes like `#[no_const]` that alter the behavior of `bitflags!`, because complex `macro_rules` macros are difficult to maintain. If we were to cook up a proc-macro based version of the macro though with more configurability that could cover this is that something you'd consider using?
qwandor commented 2025-08-15 11:05:36 -05:00 (Migrated from github.com)

The case I'm actually looking at right now is with MMIO registers for a hardware peripheral, but it's equivalent to memory-mapped data.

A proc-macro based version of bitflags sounds workable to me.

The case I'm actually looking at right now is with MMIO registers for a hardware peripheral, but it's equivalent to memory-mapped data. A proc-macro based version of `bitflags` sounds workable to me.
mkroening commented 2025-08-26 06:49:20 -05:00 (Migrated from github.com)

Just as another data point: I created endian-num as a endian-aware version of core's integer primitives for MMIO purposes (zerocopy's types have no alignment requirement). In virtio-spec-rs/src/bitflags.rs, I adapted bitflag's macro to allow creating bitflags via const conversions to integer primitives and then doing the const operation on these primitives before converting back.

This is similar to how endian-awareness was allowed in https://github.com/wrenger/bitfield-struct-rs/pull/39.

No objections to a flexible proc-macro-based version of bitflags, but maybe allowing this via conversions might be comparatively easy?

Just as another data point: I created [endian-num](https://github.com/rust-osdev/endian-num) as a endian-aware version of `core`'s integer primitives for MMIO purposes (`zerocopy`'s types have no alignment requirement). In [virtio-spec-rs/src/bitflags.rs](https://github.com/rust-osdev/virtio-spec-rs/blob/v0.3.0/src/bitflags.rs), I adapted `bitflag`'s macro to allow creating bitflags via const conversions to integer primitives and then doing the const operation on these primitives before converting back. This is similar to how endian-awareness was allowed in https://github.com/wrenger/bitfield-struct-rs/pull/39. No objections to a flexible proc-macro-based version of `bitflags`, but maybe allowing this via conversions might be comparatively easy?
KodrAus commented 2025-08-26 17:28:45 -05:00 (Migrated from github.com)

Thanks for pointing this out @mkroening. It looks like that bitfields library is already using proc macros, where adding attributes like this is more straightforward.

Thanks for pointing this out @mkroening. It looks like that bitfields library is already using proc macros, where adding attributes like this is more straightforward.
Sign in to join this conversation.
No labels
bug
good first issue
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-bitflags/bitflags#455
No description provided.