Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scripting RFC: Custom layouts #21

Open
eira-fransham opened this issue Apr 19, 2019 · 0 comments
Open

Scripting RFC: Custom layouts #21

eira-fransham opened this issue Apr 19, 2019 · 0 comments

Comments

@eira-fransham
Copy link

eira-fransham commented Apr 19, 2019

This came up on the #scripting discord chat, but for many structs it should be possible to remove the requirement for #[repr(C)]. Since we're generating the struct definitions at runtime - at least, certainly for Lua - we can just have a struct that lets you specify offsets like so:

enum FieldsDef<'a> {
    Named(&'a [(&'a str, usize)]),
    Unnamed(&'a [usize]),
}

struct MyStruct {
    a: Foo,
    b: Bar,
}

impl GetFields for MyStruct {
    const FIELDS: FieldsDef<'static> = FieldsDef::Named(&[
        ("a", offset_of!(MyStruct, a)),
        ("b", offset_of!(MyStruct, b)),
    ]);
}

Then the backend can use this to generate a C-compatible struct definition on the fly, reordering fields and generating explicit padding bytes where necessary. This allows Rust to reorder fields and do whatever else but without sacrificing the ability to access those fields in the scripting layer.

This also allows us to support tuples and external types. For tuples, we can do something like so:

impl<A, B> GetFields for (A, B) {
    const FIELDS: FieldsDef<'static> = FieldsDef::Unnamed(&[
        (offset_of!(Self, 0)),
        (offset_of!(Self, 1)),
    ]);
}

Then for external structs we can do something like so:

pub struct MyStruct {
    pub a: Foo,
    pub b: Bar,
}

// ... in another crate ...

struct MyWrapper(MyStruct);

impl GetFields for MyWrapper {
    const FIELDS: FieldsDef<'static> = FieldsDef::Named(&[
        ("a", offset_of!(MyStruct, 0.a)),
        ("b", offset_of!(MyStruct, 0.b)),
    ]);
}

I've used an associated const in this, but it's worth noting that you could also support structs with runtime-defined layouts if you made it a fn. The only example I can think of is wasmtime's VMCtx, which isn't something that you'd be likely to pass to a script, but it's worth thinking about.

This could be very simply wrapped in a derive macro - if Rust supported macro_rules macros as annotations it'd even be simple enough to be implement using that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant