Name Description Size
ffi
ffi_converter_impls.rs 20521
ffi_converter_traits.rs Traits that define how to transfer values via the FFI layer. These traits define how to pass values over the FFI in various ways: as arguments or as return values, from Rust to the foreign side and vice-versa. These traits are mainly used by the proc-macro generated code. The goal is to allow the proc-macros to go from a type name to the correct function for a given FFI operation. The main traits form a sort-of tree structure from general to specific: ```ignore [FfiConverter] | ----------------------------------------- | | [Lower] [Lift] | | ----------------- -------------- | | | | [LowerReturn] [LowerError] [LiftRef] [LiftReturn] ``` There's also: - [TypeId], which is implemented for all types that implement any of the above traits. - [ConvertError], which is implement for errors that can be used in callback interfaces. The `derive_ffi_traits` macro can be used to derive the specific traits from the general ones. Here's the main ways we implement these traits: * For most types we implement [FfiConverter] and use [derive_ffi_traits] to implement the rest * If a type can only be lifted/lowered, then we implement [Lift] or [Lower] and use [derive_ffi_traits] to implement the rest * If a type needs special-case handling, like `Result<>` and `()`, we implement the traits directly. FfiConverter has a generic parameter, that's filled in with a type local to the UniFFI consumer crate. This allows us to work around the Rust orphan rules for remote types. See `https://mozilla.github.io/uniffi-rs/internals/lifting_and_lowering.html#code-generation-and-the-fficonverter-trait` for details. ## Safety Most traits are unsafe (implementing it requires `unsafe impl`) because we can't guarantee that it's safe to pass your type out to foreign-language code and back again. Buggy implementations of this trait might violate some assumptions made by the generated code, or might not match with the corresponding code in the generated foreign-language bindings. These traits should not be used directly, only in generated code, and the generated code should have fixture tests to test that everything works correctly together. 29656
lib.rs # Runtime support code for uniffi This crate provides the small amount of runtime code that is required by the generated uniffi component scaffolding in order to transfer data back and forth across the C-style FFI layer, as well as some utilities for testing the generated bindings. The key concept here is the [`FfiConverter`] trait, which is responsible for converting between a Rust type and a low-level C-style type that can be passed across the FFI: * How to [represent](FfiConverter::FfiType) values of the Rust type in the low-level C-style type system of the FFI layer. * How to ["lower"](FfiConverter::lower) values of the Rust type into an appropriate low-level FFI value. * How to ["lift"](FfiConverter::try_lift) low-level FFI values back into values of the Rust type. * How to [write](FfiConverter::write) values of the Rust type into a buffer, for cases where they are part of a compound data structure that is serialized for transfer. * How to [read](FfiConverter::try_read) values of the Rust type from buffer, for cases where they are received as part of a compound data structure that was serialized for transfer. * How to [return](FfiConverter::lower_return) values of the Rust type from scaffolding functions. This logic encapsulates the Rust-side handling of data transfer. Each foreign-language binding must also implement a matching set of data-handling rules for each data type. In addition to the core `FfiConverter` trait, we provide a handful of struct definitions useful for passing core rust types over the FFI, such as [`RustBuffer`]. 12623
metadata.rs Pack UniFFI interface metadata into byte arrays In order to generate foreign bindings, we store interface metadata inside the library file using exported static byte arrays. The foreign bindings code reads that metadata from the library files and generates bindings based on that. The metadata static variables are generated by the proc-macros, which is an issue because the proc-macros don't have knowledge of the entire interface -- they can only see the item they're wrapping. For example, when a proc-macro sees a type name, it doesn't know anything about the actual type: it could be a Record, an Enum, or even a type alias for a `Vec<>`/`Result<>`. This module helps bridge the gap by providing tools that allow the proc-macros to generate code to encode the interface metadata: - A set of const functions to build up metadata buffers with const expressions - The `export_static_metadata_var!` macro, which creates the static variable from a const metadata buffer. - The `FfiConverter::TYPE_ID_META` const which encodes an identifier for that type in a metadata buffer. `uniffi_bindgen::macro_metadata` contains the code to read the metadata from a library file. `fixtures/metadata` has the tests. 10020
oneshot.rs Implements a simple oneshot channel. We used to use the `oneshot` crate for this, but the dependency was hard to manage (https://github.com/mozilla/uniffi-rs/issues/1736) This implementation is less efficient, but the difference is probably negligible for most use-cases involving UniFFI. 2235