Unless I’m missing something, there’s an example of this sort of thing in the GeneralPurposeAllocator:
here’s how it’s allocated:
and here’s how it’s freed:
There are accessor functions in BucketHeader that calculate the offset to particular trailing sections, like this:
If you make the Header struct extern then you’d get guaranteed field order, but the idea would be the same: allocate @sizeOf(Header) + trailing_size bytes with alignment @alignOf(Header), cast it to *Header, and then make sure that you can still free the entire allocated slice (so either store the size of the trailing data in the header, or make it so the size of the trailing data can be calculated when it’s time to free).
EDIT: Also worth looking at how the bucket size is calculated to see how it deals with ensuring alignment of the trailing data: