Skip to content

Commit

Permalink
Support tuples (#195)
Browse files Browse the repository at this point in the history
This commit adds support for tuples. 

related to #188.

Here's an example of using this:

```rust
#[swift_bridge::bridge]
mod ffi {
    extern "Rust" {
        fn reflect_tuple_primitives(tuple: (i16, u32)) -> (i16, u32);
    }
}

fn reflect_tuple_primitives(tuple: (i16, u32)) -> (i16, u32) {
    tuple
}
```

```swift
//...
let tuple = reflect_tuple_primitives((-1, 10))
//...
```
  • Loading branch information
NiwakaDev authored Mar 20, 2023
1 parent d713d36 commit 637c7b3
Show file tree
Hide file tree
Showing 24 changed files with 1,053 additions and 135 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ In addition to allowing you to share your own custom structs, enums and classes
| Option\<T> | Optional\<T> | |
| fn x() -> Result\<T, E> | func x() throws -> T | |
| fn x(arg: Result\<T, E>) | func x(arg: RustResult\<T, E>) | |
| (A, B, C, ...)| (A, B, C, ...)
| Have a Rust standard library type in mind?<br /> Open an issue! | | |
| | Have a Swift standard library type in mind?<br /> Open an issue! | |
<!-- ANCHOR_END: built-in-types-table -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
1745111529BE189B00B96A1A /* TupleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1745111429BE189B00B96A1A /* TupleTests.swift */; };
178F1CD3298E97FB00335AA0 /* ArgumentAttributesTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 178F1CD2298E97FB00335AA0 /* ArgumentAttributesTest.swift */; };
2202BC0827B2DD1700D43CC4 /* SharedEnumTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2202BC0727B2DD1700D43CC4 /* SharedEnumTests.swift */; };
22043293274A8FDF00BAE645 /* VecTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22043292274A8FDF00BAE645 /* VecTests.swift */; };
Expand Down Expand Up @@ -67,6 +68,7 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
1745111429BE189B00B96A1A /* TupleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TupleTests.swift; sourceTree = "<group>"; };
178F1CD2298E97FB00335AA0 /* ArgumentAttributesTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArgumentAttributesTest.swift; sourceTree = "<group>"; };
2202BC0727B2DD1700D43CC4 /* SharedEnumTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedEnumTests.swift; sourceTree = "<group>"; };
22043292274A8FDF00BAE645 /* VecTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VecTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -225,6 +227,7 @@
22C0625428CE6C9A007A6F67 /* CallbackTests.swift */,
C926E4DF294F18C50027E7E2 /* FunctionAttributeTests.swift */,
178F1CD2298E97FB00335AA0 /* ArgumentAttributesTest.swift */,
1745111429BE189B00B96A1A /* TupleTests.swift */,
);
path = SwiftRustIntegrationTestRunnerTests;
sourceTree = "<group>";
Expand Down Expand Up @@ -430,6 +433,7 @@
22FD1C562753CB3F00F64281 /* SwiftFnUsesOpaqueRustTypeTests.swift in Sources */,
228FE61027416C0300805D9E /* OpaqueRustStructTests.swift in Sources */,
22D092A327B7E865009A4C2B /* AsyncTests.swift in Sources */,
1745111529BE189B00B96A1A /* TupleTests.swift in Sources */,
22046383282B4E3F00A09119 /* FunctionAttributeGetTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// TupleTests.swift
// SwiftRustIntegrationTestRunnerTests
//
// Created by Niwaka on 2023/03/12.
//

import Foundation

import XCTest
@testable import SwiftRustIntegrationTestRunner

/// Tests tuples
final class TupleTest: XCTestCase {
/// Verify that we can pass and return Rust tuples.
func testSwiftCallsRustTuples() throws {
XCTContext.runActivity(named: "Verify that we can pass and return a (primitive type, primitive type).") {
_ in
let tuple = rust_reflect_tuple_primitives((-1, 10))
XCTAssertEqual(tuple.0, -1)
XCTAssertEqual(tuple.1, 10)
}
XCTContext.runActivity(named: "Verify that we can pass and return a (OpaqueRustType, String, primitive type).") {
_ in
let tuple = rust_reflect_tuple_opaque_rust_and_string_and_primitive((TupleTestOpaqueRustType(123), "foo", 128))
XCTAssertEqual(tuple.0.val(), 123)
XCTAssertEqual(tuple.1.toString(), "foo")
XCTAssertEqual(tuple.2, 128)
}
}

}
1 change: 1 addition & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
- [Option<T> <---> Optional<T>](./built-in/option/README.md)
- [Result<T, E> <---> RustResult<T, E>](./built-in/result/README.md)
- [Box<dyn FnOnce(A, B) -> C>](./built-in/boxed-functions/README.md)
- [(A, B, C, ...) <---> (A, B, C, ...)](./built-in/tuple/README.md)

- [Safety](./safety/README.md)

Expand Down
67 changes: 67 additions & 0 deletions book/src/built-in/tuple/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# (A, B, C, ...) <---> (A, B, C, ...)

Rust's `(A, B, C, ...)` is seen on the Swift side as a `(A, B, C, ...)`.

## Returning Tuple from Rust -> Swift

```rust
// Rust

mod ffi {
extern "Rust" {
fn get_midpoint(
point1: (f32, f32, f32),
point2: (f32, f32, f32),
) -> (f32, f32, f32);
}

extern "Swift" {
fn make_point() -> (f32, f32, f32);
}
}

fn get_midpoint(
point1: (f32, f32, f32),
point2: (f32, f32, f32)
) -> (f32, f32, f32) {
// ...
}
```

```swift
// Swift

func make_point() -> (Float, Float, Float) {
(1.0, 2.0, 3.0)
}

let midpoint = get_midpoint(
make_point(1.0, 2.0, 3.0),
make_point(4.0, 5.0, 6.0)
)
```

## Taking Tuple from Swift -> Rust

```rust
// Rust

#[swift_bridge::bridge]
mod ffi {
extern "Rust" {
type SomeRustType;
}
extern "Rust" {
fn run(
arg: (SomeRustType, i32)
);
}
}
```

```swift
// Swift

let someType = SomeType()
run((someType, 123))
```
Loading

0 comments on commit 637c7b3

Please sign in to comment.