Skip to content
This repository has been archived by the owner on Dec 4, 2023. It is now read-only.

Commit

Permalink
Merge pull request #16 from eigerco/merge-upstream
Browse files Browse the repository at this point in the history
Merge upstream
  • Loading branch information
MeerKatDev authored Nov 13, 2023
2 parents 74fc05c + 2e7a9ae commit 2e22cb2
Show file tree
Hide file tree
Showing 73 changed files with 644 additions and 271 deletions.
7 changes: 5 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ commands:
command: |
mkdir -p $HOME/.bin
pushd $HOME/.bin
curl -sfSL --retry 5 --retry-delay 10 https://github.com/rust-lang-nursery/mdBook/releases/download/v0.4.2/mdbook-v0.4.2-x86_64-unknown-linux-gnu.tar.gz | tar xz
# mdbook
curl -sfSL --retry 5 --retry-delay 10 https://github.com/rust-lang-nursery/mdBook/releases/download/v0.4.35/mdbook-v0.4.35-x86_64-unknown-linux-gnu.tar.gz | tar xz
# mdbook-link-check
curl -sfSL --retry 5 --retry-delay 10 https://github.com/Michael-F-Bryan/mdbook-linkcheck/releases/download/v0.7.7/mdbook-linkcheck.x86_64-unknown-linux-gnu.zip -o mdbook-linkcheck.zip && unzip mdbook-linkcheck.zip && chmod +x mdbook-linkcheck
echo 'export PATH="$HOME/.bin:$PATH"' >> $BASH_ENV
popd
# Our policy for updating rust versions is at https://github.com/mozilla/uniffi-rs/tree/main/docs/policies/rust-versions.md
Expand Down Expand Up @@ -127,7 +130,7 @@ jobs:
- install-mdbook
- run: mdbook build docs/manual
- gh-pages/deploy:
build-dir: docs/manual/book
build-dir: docs/manual/book/html
ssh-fingerprints: "ac:68:a3:78:ea:ee:00:05:30:e1:dc:1f:2e:2f:7c:81"

Deploy Docker:
Expand Down
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,25 @@

[All changes in [[UnreleasedUniFFIVersion]]](https://github.com/mozilla/uniffi-rs/compare/v0.25.0...HEAD).

### What's changed?

- The `rust_future_continuation_callback_set` FFI function was removed. `rust_future_poll` now
inputs the callback pointer. External bindings authors will need to update their code.

### What's new?

- Rust traits `Display`, `Hash` and `Eq` exposed to Kotlin and Swift.

[All changes in [[UnreleasedUniFFIVersion]]](https://github.com/mozilla/uniffi-rs/compare/v0.25.1...HEAD).

## v0.25.1 (backend crates: v0.25.1) - (_2023-11-09_)

[All changes in v0.25.1](https://github.com/mozilla/uniffi-rs/compare/v0.25.0...v0.25.1).

### What's fixed?

- Fixed several bugs with async functions were defined in multiple crates that get built together.

## v0.25.0 (backend crates: v0.25.0) - (_2023-10-18_)

[All changes in v0.25.0](https://github.com/mozilla/uniffi-rs/compare/v0.24.3...v0.25.0).
Expand Down Expand Up @@ -46,6 +65,7 @@

- Updated the async functionality to correctly handle cancellation (#1669)
- Kotlin: Fixed low-level issue with exported async APIs
- Kotlin: Fixed empty records being exported as empty data classes in Kotlin. A class with a proper `equals` function should be used instead.

### What's changed?

Expand Down
18 changes: 9 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 15 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,33 @@

UniFFI is a toolkit for building cross-platform software components in Rust.

By writing your core business logic in Rust and describing its interface in a special
[interface definition file](https://mozilla.github.io/uniffi-rs/udl_file_spec.html),
For the impatient, see [**the UniFFI user guide**](https://mozilla.github.io/uniffi-rs/)
or [**the UniFFI examples**](https://github.com/mozilla/uniffi-rs/tree/main/examples#example-uniffi-components).

By writing your core business logic in Rust and describing its interface in an "object model",
you can use UniFFI to help you:

* Compile your Rust code into a shared library for use on different target platforms.
* Generate bindings to load and use the library from different target languages.

For example, UniFFI is currently used in the [mozilla/application-services](https://github.com/mozilla/application-services)
project to build browser storage and syncing functionality for Firefox mobile browsers. Core functionality is
written once in Rust, and auto-generated bindings allow that functionality to be called from both Kotlin (for Android apps)
and Swift (for iOS apps).
You can describe your object model in an [interface definition file](https://mozilla.github.io/uniffi-rs/udl_file_spec.html)
or [by using proc-macros](https://mozilla.github.io/uniffi-rs/proc_macro/index.html).

UniFFI is currently extensively by Mozilla in Firefox mobile and desktop browsers;
written once in Rust, auto-generated bindings allow that functionality to be called
from both Kotlin (for Android apps) and Swift (for iOS apps).
It also has a growing community of users shipping various cool things to many users.

Currently first-party supported foreign languages include Kotlin, Swift, Python and Ruby.
UniFII comes with support for **Kotlin**, **Swift**, **Python** and **Ruby** with 3rd party bindings available for **C#** and **Golang**.
Additional foreign language bindings can be developed externally and we welcome contributions to list them here.
See [Third-party foreign language bindings](#third-party-foreign-language-bindings).

## User Guide

You can read more about using the tool in [**the UniFFI user guide**](https://mozilla.github.io/uniffi-rs/).

Please be aware that UniFFI is being developed concurrently with its initial consumers, so it is changing rapidly and there
are a number of sharp edges to the user experience. Still, we consider is developed enough for production use in Mozilla
products and we welcome any feedback you may have about making it more broadly useful.
We consider it ready for production use, but UniFFI is a long way from a 1.0 release with lots of internal work still going on.
We try hard to avoid breaking simple consumers, but more advanced things might break as you upgrade over time.

### Etymology and Pronunciation

Expand All @@ -50,6 +54,7 @@ Other tools we know of which try and solve a similarly shaped problem are:
* [Kotlin Multiplatform support](https://gitlab.com/trixnity/uniffi-kotlin-multiplatform-bindings). The repository contains Kotlin Multiplatform bindings generation for UniFFI, letting you target both JVM and Native.
* [Go bindings](https://github.com/NordSecurity/uniffi-bindgen-go)
* [C# bindings](https://github.com/NordSecurity/uniffi-bindgen-cs)
* [Dart bindings](https://github.com/NiallBunting/uniffi-rs-dart)

### External resources

Expand Down
7 changes: 7 additions & 0 deletions docs/manual/book.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,10 @@ title = "The UniFFI user guide"

[output.html.playground]
runnable = false

[output.linkcheck]
exclude = [
# To get this `api` directory, CI does, roughly , `cargo doc && cp -r ./target/doc ./docs/manual/src/internals/api`
# so at the time we build the mdBook this isn't available.
'./api' # Used for rustdoc links to the source.
]
6 changes: 3 additions & 3 deletions docs/manual/src/Overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

UniFFI is a tool that automatically generates foreign-language bindings targeting Rust libraries.
The repository can be found on [github](https://github.com/mozilla/uniffi-rs/).
It fits in the practice of consolidating business logic in a single Rust library while targeting multiple platforms, making it simpler to develop and maintain a cross-platform codebase.
Note that this tool will not help you ship a Rust library to these platforms, but simply not have to write bindings code by hand [[0]](https://i.kym-cdn.com/photos/images/newsfeed/000/572/078/d6d.jpg).
It fits in the practice of consolidating business logic in a single Rust library while targeting multiple platforms, making it simpler to develop and maintain a cross-platform codebase.
Note that this tool will not help you ship a Rust library to these platforms, but simply not have to write bindings code by hand. [Related](https://i.kym-cdn.com/photos/images/newsfeed/000/572/078/d6d.jpg).

## Design

UniFFI requires to write an Interface Definition Language (based on [WebIDL](https://heycam.github.io/webidl/)) file describing the methods and data structures available to the targeted languages.
UniFFI requires to write an Interface Definition Language (based on [WebIDL](https://heycam.github.io/webidl/)) file describing the methods and data structures available to the targeted languages.
This .udl (UniFFI Definition Language) file, whose definitions must match with the exposed Rust code, is then used to generate Rust *scaffolding* code and foreign-languages *bindings*. This process can take place either during the build process or be manually initiated by the developer.

![uniffi diagram](./uniffi_diagram.png)
Expand Down
29 changes: 11 additions & 18 deletions docs/manual/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,20 @@
- [Procedural Macros: Attributes and Derives](./proc_macro/index.md)
- [Futures and async support](./futures.md)

# Bindings
- [Bindings](./bindings.md)
- [Customizing binding generation](./bindings.md)
- [Implementing Rust traits in foreign bindings](./foreign_traits.md)

- [Generating bindings](./bindings)
- [Customizing binding generation](./bindings#customizing-the-binding-generation)
- [Implementing Rust traits in foreign bindings](./foreign_traits)
- [Kotlin](./kotlin/configuration.md)
- [Integrating with Gradle](./kotlin/gradle.md)
- [Kotlin Lifetimes](./kotlin/lifetimes.md)

## Kotlin
- [Swift](./swift/overview.md)
- [Configuration](./swift/configuration.md)
- [Building a Swift module](./swift/module.md)
- [Integrating with Xcode](./swift/xcode.md)

- [Configuration](./kotlin/configuration)
- [Integrating with Gradle](./kotlin/gradle.md)
- [Kotlin Lifetimes](./kotlin/lifetimes.md)

## Swift

- [Overview](./swift/overview.md)
- [Configuration](./swift/configuration.md)
- [Building a Swift module](./swift/module.md)
- [Integrating with Xcode](./swift/xcode.md)

## Python
- [Configuration](./python/configuration)
- [Python](./python/configuration.md)

# Internals
- [Design Principles](./internals/design_principles.md)
Expand Down
3 changes: 3 additions & 0 deletions docs/manual/src/bindings.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@ Each of the bindings reads a file `uniffi.toml` in the root of a crate which sup
various options which influence how the bindings are generated. Default options will be used
if this file is missing.

`--config` option can be used to specify additional uniffi config file. This config is merged with
the `uniffi.toml` config present in each crate, with its values taking precedence.

Each binding supports different options, so please see the documentation for each binding language.
10 changes: 8 additions & 2 deletions docs/manual/src/futures.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ UniFFI supports exposing async Rust functions over the FFI. It can convert a Rus

Check out the [examples](https://github.com/mozilla/uniffi-rs/tree/main/examples/futures) or the more terse and thorough [fixtures](https://github.com/mozilla/uniffi-rs/tree/main/fixtures/futures).

Note that currently async functions are only supported by proc-macros, UDL support is being planned in https://github.com/mozilla/uniffi-rs/issues/1716.

## Example

This is a short "async sleep()" example:
Expand Down Expand Up @@ -34,6 +32,14 @@ if __name__ == '__main__':
asyncio.run(main())
```

Async functions can also be defined in UDL:
```idl
namespace example {
[Async]
string say_after(u64 ms, string who);
}
```

This code uses `asyncio` to drive the future to completion, while our exposed function is used with `await`.

In Rust `Future` terminology this means the foreign bindings supply the "executor" - think event-loop, or async runtime. In this example it's `asyncio`. There's no requirement for a Rust event loop.
Expand Down
2 changes: 1 addition & 1 deletion docs/manual/src/internals/lifting_and_lowering.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Lifting and lowering simple types such as integers is done by directly casting t
value to and from an appropriate type. For complex types such as optionals and
records we currently implement lifting and lowering by serializing into a byte
buffer, but this is an implementation detail that may change in future. (See
[ADR-0002](/docs/adr/0002-serialize-complex-datatypes.md) for the reasoning
[ADR-0002](https://github.com/mozilla/uniffi-rs/blob/main/docs/adr/0002-serialize-complex-datatypes.md) for the reasoning
behind this choice.)

As a concrete example, consider this interface for accumulating a list of integers:
Expand Down
4 changes: 2 additions & 2 deletions docs/manual/src/kotlin/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ The generated Kotlin modules can be configured using a `uniffi.toml` configurati
| ------------------ | ------- |------------ |
| `package_name` | `uniffi` | The Kotlin package name - ie, the value used in the `package` statement at the top of generated files. |
| `cdylib_name` | `uniffi_{namespace}`[^1] | The name of the compiled Rust library containing the FFI implementation (not needed when using `generate --library`). |
| `custom_types` | | A map which controls how custom types are exposed to Kotlin. See the [custom types section of the manual](../udl/custom_types#custom-types-in-the-bindings-code)|
| `external_packages` | | A map of packages to be used for the specified external crates. The key is the Rust crate name, the value is the Kotlin package which will be used referring to types in that crate. See the [external types section of the manual](../udl/ext_types_external#kotlin)
| `custom_types` | | A map which controls how custom types are exposed to Kotlin. See the [custom types section of the manual](../udl/custom_types.md#custom-types-in-the-bindings-code)|
| `external_packages` | | A map of packages to be used for the specified external crates. The key is the Rust crate name, the value is the Kotlin package which will be used referring to types in that crate. See the [external types section of the manual](../udl/ext_types_external.md#kotlin)


## Example
Expand Down
2 changes: 1 addition & 1 deletion docs/manual/src/proc_macro/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ fn do_http_request() -> Result<(), MyApiError> {

## The `#[uniffi::export(callback_interface)]` attribute

`#[uniffi::export(callback_interface)]` can be used to export a [callback interface](../udl/callback_interfaces.html) definition.
`#[uniffi::export(callback_interface)]` can be used to export a [callback interface](../udl/callback_interfaces.md) definition.
This allows the foreign bindings to implement the interface and pass an instance to the Rust code.

```rust
Expand Down
2 changes: 1 addition & 1 deletion docs/manual/src/python/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ The generated Python modules can be configured using a `uniffi.toml` configurati
| Configuration name | Default | Description |
| ------------------ | ------- |------------ |
| `cdylib_name` | `uniffi_{namespace}`[^1] | The name of the compiled Rust library containing the FFI implementation (not needed when using `generate --library`). |
| `custom_types` | | A map which controls how custom types are exposed to Python. See the [custom types section of the manual](../udl/custom_types#custom-types-in-the-bindings-code)|
| `custom_types` | | A map which controls how custom types are exposed to Python. See the [custom types section of the manual](../udl/custom_types.md#custom-types-in-the-bindings-code)|
| `external_packages` | | A map which controls the package name used by external packages. See below for more.

## External Packages
Expand Down
2 changes: 1 addition & 1 deletion docs/manual/src/swift/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The generated Swift module can be configured using a `uniffi.toml` configuration
| `ffi_module_filename` | `{ffi_module_name}` | The filename stem for the lower-level C module containing the FFI declarations. |
| `generate_module_map` | `true` | Whether to generate a `.modulemap` file for the lower-level C module with FFI declarations. |
| `omit_argument_labels` | `false` | Whether to omit argument labels in Swift function definitions. |
| `custom_types` | | A map which controls how custom types are exposed to Swift. See the [custom types section of the manual](../udl/custom_types#custom-types-in-the-bindings-code)|
| `custom_types` | | A map which controls how custom types are exposed to Swift. See the [custom types section of the manual](../udl/custom_types.md#custom-types-in-the-bindings-code)|


[^1]: `namespace` is the top-level namespace from your UDL file.
Expand Down
2 changes: 1 addition & 1 deletion docs/manual/src/tutorial/Prerequisites.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ uniffi = { version = "[latest-version]" }
uniffi = { version = "[latest-version]", features = [ "build" ] }
```

UniFFI has not reached version `1.0` yet. Versions are typically specified as "0.[minor-version]".
UniFFI has not reached version `1.0` yet. Versions are typically specified as `0.[minor-version]`.

## Build your crate as a cdylib

Expand Down
4 changes: 4 additions & 0 deletions docs/manual/src/tutorial/udl_file.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@ Here you can note multiple things:
- Rust's `u32` is also UDL's `u32`, but it is not always true! (TODO table correspondence)

**Note:** If any of the things you expose in the `udl` file do not have an equivalent in your Rust crate, you will get a hard error. Try changing the `u32` result type to `u64` and see what happens!

**Note** It's also possible to use [Rust procmacros](../proc_macro/index.md) to describe your interface and you can avoid
UDL files entirely if you choose.
Unfortunately the docs aren't quite as good for that yet though.
4 changes: 2 additions & 2 deletions docs/manual/src/udl/callback_interfaces.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Callback interfaces

Callback interfaces are a special implementation of
[Rust traits implemented by foreign languages](../foreign_traits).
[Rust traits implemented by foreign languages](../foreign_traits.md).

These are described in both UDL and proc-macros as an explict "callback interface".
They are (soft) deprecated, remain now for backwards compatibility, but probably
Expand Down Expand Up @@ -29,7 +29,7 @@ from multiple threads at once, but Rust can not enforce this in the foreign code

## Rust signature differences

Consider the examples in [Rust traits implemented by foreign languages](../foreign_traits).
Consider the examples in [Rust traits implemented by foreign languages](../foreign_traits.md).

If the traits in question are defined as a "callback" interface, the `Arc<dyn Keychain>` types
would actually be `Box<dyn Keychain>` - eg, the Rust implementation of the `Authenticator`
Expand Down
13 changes: 13 additions & 0 deletions docs/manual/src/udl/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,16 @@ fun helloName(name: String = "world" ): String {
// ...
}
```

## Async

Async functions can be exposed using the `[Async]` attribute:

```idl
namespace Example {
[Async]
string async_hello();
}
```

See the [Async/Future support section](../futures.md) for details.
4 changes: 4 additions & 0 deletions fixtures/coverall/src/coverall.udl
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ interface Coveralls {

/// Reverses the bytes.
bytes reverse(bytes value);

EmptyStruct set_and_get_empty_struct(EmptyStruct empty_struct);
};

// coveralls keep track of their repairs (an interface in a dict)
Expand Down Expand Up @@ -245,3 +247,5 @@ interface ISecond {
// Default only
boolean compare(IFirst? other);
};

dictionary EmptyStruct {};
Loading

0 comments on commit 2e22cb2

Please sign in to comment.