15

I would like to implement this C code which uses a flexible array member (sometimes called the struct hack) in Rust:

struct test {
  int key;
  int dataSize;
  int data[];
};
struct test* t = malloc(sizeof(struct test) + sizeOfData)

The empty array at the end of structure allows you to allocate your meta fields and data all at once. Unfortunately, I can't figure out how to do such thing in Rust.

hippietrail
  • 15,848
  • 18
  • 99
  • 158
kirugan
  • 2,514
  • 2
  • 22
  • 41
  • 4
    https://users.rust-lang.org/t/emulating-c-flexible-array-members-in-rust/6262 – Stargateur Jun 23 '18 at 23:17
  • 2
    I think you could achieve this on nightly with the allocator API and a decent amount of `unsafe`. But I'm not familiar enough with how it works in C. What if the alignment of the `data` array is bigger than the size of the header -- are padding bytes counted in the `sizeof`, or do we just rely on `malloc` allocating more than necessary to satisfy the maximum possible alignment? – trent Jun 24 '18 at 00:14
  • @MatthieuM. Probably my fault because you can't avoid padding bytes like I said, both sizeof and offsetof must produce the same size for FAM. – Stargateur Oct 30 '18 at 08:33

1 Answers1

1

The Rust equivalent of this struct would use a slice:

struct test {
  key: i32,
  dataSize: i32,
  data: [i32],
}

however, these types are not really convenient to use at the moment as there is no safe way to construct them.

A more practical way to do this is to use a generic:

struct test<T: ?Sized> {
  key: i32,
  dataSize: i32,
  data: T,
}

and then to make sure that you only use test when T is an array or a slice (which you could only create through coercion).

See also:

mcarton
  • 27,633
  • 5
  • 85
  • 95
  • 1
    no it's wrong, slice contains their len, FAM doesn't. There is no equivalent of FAM in Rust ATM. – Stargateur Sep 01 '19 at 21:53
  • 1
    @Stargateur `[T]` does not contain the length. You are talking about `&[T]` which is a fat pointer to a slice: that contains the length. But not the unsized `[T]` itself. – Lukas Kalbertodt Sep 01 '19 at 21:55
  • 3
    @JL2210 A fat pointer is a pointer + some extra data, for example `&[T]` is a fat pointer, as it contains the address to the first element + the size, and `&dyn Trait` is a fat pointer as it contains a pointer to the data + a pointer to the vtable. – mcarton Sep 01 '19 at 22:27
  • @LukasKalbertodt but this would not make sense in Rust, `[T]` need to know its size somehow, if you need unsafe this would not be Rust for me. Say [T] is the equivalent of FAM is wrong for me, at least for now. – Stargateur Sep 01 '19 at 22:31
  • Hoi! Could [this](https://github.com/rust-lang/rfcs/blob/master/text/1861-extern-types.md#detailed-design) be the correct solution to all of this? At least pointers to structs with an extern type as last field are not fat pointers. – Lukas Kalbertodt Sep 02 '19 at 14:29