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

Support custom conversions #787

Open
Manishearth opened this issue Feb 13, 2025 · 7 comments
Open

Support custom conversions #787

Manishearth opened this issue Feb 13, 2025 · 7 comments
Labels
A-attributes Area: configurability via attributes A-bridge-UX Area: UX improvements for people writing bridge modules

Comments

@Manishearth
Copy link
Contributor

The motivating example for this is protobufs, but this design should be generally useable for any kind of convenience wrappers

This feature is really in two parts. The goal is to support APIs like this:

impl Opaque {
  fn foo(proto: ProtoBuf<MyType>) {..}
  fn bar() -> ProtoBuf<MyType> {..}
}

where ProtoBuf<MyType> is not a diplomat-safe type, but it can be converted to/from a Diplomat-safe type (here, it would be &[u8]/DiplomatSlice<u8>)

Optionally, on the codegen side, it would be nice if these types could also be converted into something better, e.g. in Kotlin perhaps they get converted into MyTypeProto or something.

@Manishearth Manishearth added A-attributes Area: configurability via attributes A-bridge-UX Area: UX improvements for people writing bridge modules labels Feb 13, 2025
@Manishearth
Copy link
Contributor Author

The vague design I have is something like this, which is in two parts:

fn foo(#[diplomat::convert_custom(&[u8], conversion=convert_proto)] proto: ProtoBuf<MyType>) {
    
   let my: &MyType = proto.get(); // potentially fallible

}

In the diplomat macro, this performs conversion-to-&[u8] (and subsequent conversion-to-DiplomatSlice) in the generated C code, using the param_conversion path.

Then, we have some callback convert_proto that takes the ProtoBuf<MyType> token stream

This callback can be specified in the config.toml as a jinja template1, or as a custom function passed in by people calling diplomat-tool as a library.

One thing to note is that attributes on parameters are not yet stable, and this doesn't work for return types. We may instead wish to do something like:

#[diplomat::convert_custom(&[u8], arg=proto, conversion=convert_proto)] 
fn foo(proto: ProtoBuf<MyType>)

or even

#[diplomat::bridge]
#[diplomat::abi_rename = "foobar_{0}"]
#[diplomat::custom_conversion(pattern = "ProtoBuf<.*>", conversion=convert_proto)]
mod ffi {
  // ..
}

That may be convenient anyway.

Footnotes

  1. For a jinja template to work with generics we may need to provide functions for getting the generic arguments.

@Manishearth
Copy link
Contributor Author

cc @emarteca @maurer @mgeisler

@aabizri

This comment has been minimized.

@Manishearth

This comment has been minimized.

@aabizri

This comment has been minimized.

@Manishearth

This comment has been minimized.

@Manishearth
Copy link
Contributor Author

Manishearth commented Feb 18, 2025

Discussion about custom allocators can move to #792

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-attributes Area: configurability via attributes A-bridge-UX Area: UX improvements for people writing bridge modules
Projects
None yet
Development

No branches or pull requests

2 participants