Custom offset for Struct fields

Is there a way to specify the offset of each of the fields in a rust struct?

For background, I am working on a project that needs to read structs from the memory of other processes. There are large parts of these structs that contain unknown data, so I want to be able to specify the offset of each field I do know so that I can just directly copy bytes from the target process to the relevant struct, which would be much easier to maintain and read than having to manually convert from a byte array to the final format.

I have tried inserting private _pad: [u8; x] fields but this prevents me from deriving pretty much any traits on the struct and is really likely to cause errors if eg. I need to add a field.

I'm basically looking for something along the lines of C#'s FieldOffset [https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.fieldoffsetattribute?view=netcore-3.1](docs page) feature.

1 Like

There is nothing exactly like that, but you can use #[repr(C)] to ensure that the fields end up in the order you expect. You can read more here. Which derives do you have trouble with regarding your _pad fields?

I see, thanks. I can't derive Debug or Default on my structs because some of the _pad fields are quite large (the largest so far is 249 u8s) and arrays "only have std trait implementations for lengths 0..=32".

If they are _pad fields, presumably you don't reference them in your code (due to the initial _) so you shouldn't care how they are substructured; you only need them to reserve the required amount of unaligned memory. Can't you use a procedural macro to generate these in a way where derive would work, either as a tuple substruct
(e.g., _pad_N: { [u8; 32], [u8; 32], … , [u8; 32], [u8; 25] } or
as a sequence of shorter pads
(e.g., _pad_N_0: [u8; 32], _pad_N_32: [u8; 32], … , _pad_N_192: [u8; 32], _pad_N_224: [u8; 25] ),
where both approaches allocate 249 contiguous u8s?

Edit: I just realized that the tuple substruct might itself force an unwanted alignment. If that's the case, only the second alternative works.

1 Like

Thanks for the suggestion. I've had a couple of goes at it but I'm pretty sure that procedural macros aren't allowed inside struct definitions. Using an attribute macro causes a compiler error expected an inert attribute, found an attribute macro which when checking the docs appears to be because attribute macros are only allowed on the struct itself, not on fields. Plain procedural macros produce syntax errors (expected COLON).

I'm currently looking at trying to use an attribute macro on the whole struct with inert attributes on individual fields, will post an update once I've had a go.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.