Skip to content

rust: Support custom list types #1441

@azdle

Description

@azdle

It would be very helpful for me to be able to use a custom type for a list<T> type, but this crate seems to assume that list<T> always maps directly to Vec<T>.

Ex:

wit_bindgen::generate!({
    inline: r#"
        package foo:bar;

        interface baz {
            type bytes = list<u8>;
            read: func() -> bytes;
        }

        world bzt {
            use baz.{bytes};
        }
    "#,
    with: {
        "foo:bar/baz/bytes": crate::Bytes,
    }
});

struct Bytes(Vec<u8>);
error[E0308]: mismatched types
  --> ~/Projects/wit-bindgen-custom-list-type/target/debug/build/wit-bindgen-rust-macro-4f3b8d44afc291c2/out/bzt0.rs:43:21
   |
12 |             pub fn read() -> crate::Bytes {
   |                              ------------ expected `Bytes` because of return type
...
43 |                     result5
   |                     ^^^^^^^ expected `Bytes`, found `Vec<_>`
   |
   = note: expected struct `Bytes`
              found struct `Vec<_>`
help: try wrapping the expression in `Bytes`
   |
43 |                     Bytes(result5)
   |                     ++++++       +

My usecase is a wasm component that runs Lua scripts where I want to be able pass wit-bindgen's generated structs directly to mlua using its support of serde::{Serialize, Deserialize}. This works great for everything except list<u8> which would most logically map to a lua string (which hold arbitrary binary data), but it is being pulled in as an array like any other Vec<T> would. The way to solve this on the mlua side is to wrap it in a newtype with a different IntoLua implementation. I would really like to avoid having to have a full set of parallel types and conversions for everything that uses my type bytes = list<u8>;.

I think a reasonable way to implement this would be to just require that the type implements Into<Vec<T>>, From<Vec<T>>, and Deref<Target = T> insert some .into()s if the list type has a type defined in the with section. Though I haven't figured out how well that would fit into how wit-bindgen currently works. Thoughts on if that is a good approach or if there's a better option? I'm happy to do the implementation if this is something you'd accept.

Here's a quick hack just to prove to myself that this could reasonably work: azdle@4a5b8d1

Metadata

Metadata

Assignees

No one assigned

    Labels

    gen-rustRelated to bindings for Rust-compiled-to-WebAssembly

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions