phip1611
phip1611

Reputation: 6170

How to align a packed struct with no padding between fields in Rust?

I'm working with an ABI where I need exact control over the data layout of the payload on both ends. Furthermore, there should be no padding between fields at all, ever. Additionally, the beginning of the payload should be page-aligned.

#[repr(C)] helps a lot. The modifiers #[repr(packed(N))] and #[repr(align(N))] are compatible with repr(C) but they can't be used together. I can't achieve what I want with #[repr(C, packed(4096))].

How to solve this?

Upvotes: 4

Views: 1282

Answers (1)

phip1611
phip1611

Reputation: 6170

The packed(N) type layout modifier does not guarantee that there will be never padding at all. This is only the case for packed / packed(1) because packed(N) can only lower the alignment of each field to min(N, default alignment). packed(N) doesn't mean that the struct is "packed", i.e. no padding at all between fields, or the alignment of the struct is 4096 byte.

If you want a page-aligned struct with no padding at all, you want to do the following:

#[repr(align(4096))]
struct Aligned4096<T>(T);
// plus impl convenient methods

#[repr(C, packed)]
struct Foo {
    a: u8,
    b: u64,
    c: u16,
    d: u8,
}
// plus impl convenient methods

fn main() {
    let aligned_foo = Aligned4096(Foo::new());
}

A more detailed view of how different N in packed(N) change the type layout is shown in this table on GitHub. More information about the type layout modifiers in general is provided in the official language documentation.

Upvotes: 5

Related Questions