mozilla / uniffi-rs

a multi-language bindings generator for rust
https://mozilla.github.io/uniffi-rs/
Mozilla Public License 2.0
2.89k stars 232 forks source link

Generic UniffiRustCallStatus #2299

Open Hinton opened 3 weeks ago

Hinton commented 3 weeks ago

While working on https://github.com/mozilla/uniffi-rs/pull/2265 I would like to use errors defined in external crates. Currently errors in UniFFI for kotlin are defined as with an ErrorHandler returning an instance of UniffiRustCallStatusErrorHandler. However since each crate currently define their own types for everything we have multiple implementations of UniffiRustCallStatusErrorHandler.

This is further complicated by the fact that uniffiRustCallWithError accepts a callback which uses UniffiRustCallStatus. UniffiRustCallStatus defines an error_buf as an instance of RustBuffer. As RustBuffer also have different implementations for each crate it's not easy to share these.

The most straightforward solution to this problem would be to make UniffiRustCallStatus, uniffiRustCallWithError and uniffiCheckCallStatus public. After which you could use uniffiRustCallWithError from the crate that defines the error (and also the RustBuffer implementation. However this diverges fairly significantly from the current design patterns used in UniFFI and feels like a sub-optimal approach.

Details The generated code for function definitions would look something like this: ```patch - fun uniffi_uniffi_ext_types_proc_macro_lib_fn_func_throw_external_error(uniffi_out_err: UniffiRustCallStatus, + fun uniffi_uniffi_ext_types_proc_macro_lib_fn_func_throw_external_error(uniffi_out_err: uniffi.uniffi_one_ns.UniffiRustCallStatus, ): Unit @Throws(UniffiOneException::class) fun `throwExternalError`() = - uniffiRustCallWithError(UniffiOneException) { _status -> + uniffi.uniffi_one_ns.uniffiRustCallWithError(UniffiOneException) { _status -> UniffiLib.INSTANCE.uniffi_uniffi_ext_types_proc_macro_lib_fn_func_throw_external_error( _status) ```

After raising the issue in matrix the ideal solution would most likely be to define the common types once, and be able to re-use them across all crates. This would ensure only a single implementation of RustBuffer exists, and potentially also only a single UniffiRustCallStatus removing the need for a workaround.