Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/chinedufn/swift-bridge

swift-bridge facilitates Rust and Swift interop.
https://github.com/chinedufn/swift-bridge

ffi interop ios rust swift

Last synced: about 3 hours ago
JSON representation

swift-bridge facilitates Rust and Swift interop.

Awesome Lists containing this project

README

        

# swift-bridge [![Actions Status](https://github.com/chinedufn/swift-bridge/workflows/test/badge.svg)](https://github.com/chinedufn/swift-bridge/actions) [![docs](https://docs.rs/swift-bridge/badge.svg)](https://docs.rs/swift-bridge) [![crates.io](https://img.shields.io/crates/v/swift-bridge)](https://crates.io/crates/swift-bridge)

> `swift-bridge` facilitates Rust and Swift interop.

`swift-bridge` makes it easy to pass and share high-level types between Rust and Swift,
such as `String`, `Option`, `Result`, `struct`, `class` and more.

It also helps you bridge higher level language features, such as async functions and generics.

Using `swift-bridge` should be safer, more performant and more ergonomic than managing Rust and Swift
FFI by hand.

## Installation

```toml
# In your Cargo.toml

[build-dependencies]
swift-bridge-build = "0.1"

[dependencies]
swift-bridge = "0.1"
```

## Book

You can find information about using Rust and Swift together in [The `swift-bridge` Book](https://chinedufn.github.io/swift-bridge).

## Quick Peek

You use `swift-bridge` by declaring the types and functions that you want to import and export
in a "bridge module", and then annotating that bridge module with the `#[swift_bridge::bridge]`
macro.

Then, at build time, you use either the `swift-bridge-build` API or the `swift-bridge-cli` CLI to
parse your annotated bridge modules and generate the `Swift` and `C` side of the FFI layer.

Here's a quick peek at how you might describe an FFI boundary between Swift and Rust using a bridge module.

```rust
// We use the `swift_bridge::bridge` macro to declare a bridge module.
// Then at build time the `swift-bridge-build` crate is used to generate
// the corresponding Swift and C FFI glue code.
#[swift_bridge::bridge]
mod ffi {
// Create "transparent" structs where both Rust and Swift can directly access the fields.
struct AppConfig {
file_manager: CustomFileManager,
}

// Transparent enums are also supported.
enum UserLookup {
ById(UserId),
ByName(String),
}

// Export opaque Rust types, functions and methods for Swift to use.
extern "Rust" {
type RustApp;

#[swift_bridge(init)]
fn new(config: AppConfig) -> RustApp;

fn get_user(&self, lookup: UserLookup) -> Option<&User>;
}

extern "Rust" {
type User;
type MessageBoard;

#[swift_bridge(get(&nickname))]
fn informal_name(self: &User) -> &str;
}

// Import opaque Swift classes and functions for Rust to use.
extern "Swift" {
type CustomFileManager;
fn save_file(&self, name: &str, contents: &[u8]);
}
}

struct User {
nickname: String
}
```

## Quick Start

The `swift-bridge` repository contains [example applications](examples) that you use to quickly try out the library,
or as a starting point for your own `Swift` + `Rust` based application.

For example, here's how to run the [`codegen-visualizer`](examples/codegen-visualizer) example project locally.

```sh
git clone https://github.com/chinedufn/swift-bridge
cd swift-bridge/examples/codegen-visualizer

open CodegenVisualizer/CodegenVisualizer.xcodeproj
# *** Click the "Run" button at the top left of Xcode ***
```

---

You can find information about using Rust and Swift together in [The `swift-bridge` Book](https://chinedufn.github.io/swift-bridge).

## Built-In Types

In addition to allowing you to share your own custom structs, enums and classes between Rust and Swift,
`swift-bridge` comes with support for a number of Rust and Swift standard library types.

| name in Rust | name in Swift | notes |
| --- | --- | --- |
| u8, i8, u16, i16... etc | UInt8, Int8, UInt16, Int16 ... etc | |
| bool | Bool | |
| String, &String, &mut String | RustString, RustStringRef, RustStringRefMut | |
| &str | RustStr | |
| Vec\ | RustVec\ | |
| SwiftArray\ | Array\ | Not yet implemented |
| &[T] | | Not yet implemented |
| &mut [T] | | Not yet implemented |
| Box\ | | Not yet implemented |
| Box D> | (A, B, C) -> D | Passing from Rust to Swift is supported, but Swift to Rust is not yet implemented. |
| Box D> | (A, B, C) -> D | Not yet implemented |
| Arc\ | | Not yet implemented |
| [T; N] | | Not yet implemented |
| *const T | UnsafePointer\ | |
| *mut T | UnsafeMutablePointer\ | |
| Option\ | Optional\ | |
| fn x() -> Result\ | func x() throws -> T | |
| fn x(arg: Result\) | func x(arg: RustResult\) | |
| (A, B, C, ...)| (A, B, C, ...)
| Have a Rust standard library type in mind?
Open an issue! | | |
| | Have a Swift standard library type in mind?
Open an issue! | |

## Performance

`swift-bridge` aims to be useful in performance critical environments.

None of its generated FFI code uses object serialization, cloning, synchronization or any other form of unnecessary overhead.

## To Test

To run the test suite.

```sh
# Clone the repository
git clone [email protected]:chinedufn/swift-bridge.git
cd swift-bridge

# Run tests
cargo test --all && ./test-swift-rust-integration.sh && ./test-swift-packages.sh
```

## Contributing

If you're interesting in contributing to `swift-bridge`, check out the [contributor's guide](https://chinedufn.github.io/swift-bridge/contributing/index.html).

After getting familiar with the contribution process, try looking at some of the [good first issues](https://github.com/chinedufn/swift-bridge/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)
to see if any peak your interest.

These issues come with step-by-step instructions that should help guide you towards implementing your first patch.

## Acknowledgements

- [cxx](https://github.com/dtolnay/cxx) inspired the idea of using a bridge module to describe the FFI boundary.

---

#### License

_Licensed under [MIT](LICENSE-MIT) or [Apache-2.0](LICENSE-APACHE)._