Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support 128 bit integers u128 and i128 #293

Open
chinedufn opened this issue Sep 17, 2024 · 1 comment
Open

Support 128 bit integers u128 and i128 #293

chinedufn opened this issue Sep 17, 2024 · 1 comment
Labels
good first issue Good for newcomers

Comments

@chinedufn
Copy link
Owner

Swift 6 introduced support for 128 bit integers https://github.com/swiftlang/swift-evolution/blob/main/proposals/0425-int128.md

We should begin supporting them in swift-bridge.

For instance, after completing this issue the following should compile:

#[swift_bridge::bridge]
mod ffi {
    extern "Rust" {
        fn rust_unsigned_128(num: u128) -> u128;
        fn rust_signed_128(num: i128) -> i128;
    }

    extern "Swift" {
        fn swift_unsigned_128(num: u128) -> u128;
        fn swift_signed_128(num: i128) -> i128;
    }
}
@chinedufn chinedufn added the good first issue Good for newcomers label Sep 17, 2024
@chinedufn
Copy link
Owner Author

chinedufn commented Sep 17, 2024

Guide

Here's how to add support for u128 and i128:

Add primitive integration tests

Add new integration test functions for u128 and i128:

#[swift_bridge::bridge]
mod ffi {
extern "Rust" {
fn test_rust_calls_swift_primitives();
fn rust_double_u8(arg: u8) -> u8;
fn rust_double_i8(arg: i8) -> i8;
fn rust_double_u16(arg: u16) -> u16;
fn rust_double_i16(arg: i16) -> i16;
fn rust_double_u32(arg: u32) -> u32;
fn rust_double_i32(arg: i32) -> i32;
fn rust_double_u64(arg: u64) -> u64;
fn rust_double_i64(arg: i64) -> i64;
fn rust_double_f32(arg: f32) -> f32;
fn rust_double_f64(arg: f64) -> f64;
fn rust_negate_bool(arg: bool) -> bool;
}
extern "Swift" {
fn swift_double_u8(arg: u8) -> u8;
fn swift_double_i8(arg: i8) -> i8;
fn swift_double_u16(arg: u16) -> u16;
fn swift_double_i16(arg: i16) -> i16;
fn swift_double_u32(arg: u32) -> u32;
fn swift_double_i32(arg: i32) -> i32;
fn swift_double_u64(arg: u64) -> u64;
fn swift_double_i64(arg: i64) -> i64;
fn swift_double_f32(arg: f32) -> f32;
fn swift_double_f64(arg: f64) -> f64;
fn swift_negate_bool(arg: bool) -> bool;
}
}
fn test_rust_calls_swift_primitives() {
assert_eq!(ffi::swift_double_u8(5), 10);
assert_eq!(ffi::swift_double_i8(5), 10);
assert_eq!(ffi::swift_double_u16(5), 10);
assert_eq!(ffi::swift_double_i16(5), 10);
assert_eq!(ffi::swift_double_u32(5), 10);
assert_eq!(ffi::swift_double_i32(5), 10);
assert_eq!(ffi::swift_double_u64(5), 10);
assert_eq!(ffi::swift_double_i64(5), 10);
assert_eq!(ffi::swift_double_f32(5.), 10.);
assert_eq!(ffi::swift_double_f64(5.), 10.);
assert_eq!(ffi::swift_negate_bool(true), false);
assert_eq!(ffi::swift_negate_bool(false), true);
}
fn rust_double_u8(arg: u8) -> u8 {
arg * 2
}
fn rust_double_i8(arg: i8) -> i8 {
arg * 2
}
fn rust_double_u16(arg: u16) -> u16 {
arg * 2
}
fn rust_double_i16(arg: i16) -> i16 {
arg * 2
}
fn rust_double_u32(arg: u32) -> u32 {
arg * 2
}
fn rust_double_i32(arg: i32) -> i32 {
arg * 2
}
fn rust_double_u64(arg: u64) -> u64 {
arg * 2
}
fn rust_double_i64(arg: i64) -> i64 {
arg * 2
}
fn rust_double_f32(arg: f32) -> f32 {
arg * 2.
}
fn rust_double_f64(arg: f64) -> f64 {
arg * 2.
}
fn rust_negate_bool(arg: bool) -> bool {
!arg
}

//
// Primitive.swift
// SwiftRustIntegrationTestRunner
//
// Created by Frankie Nwafili on 10/3/22.
//
import Foundation
func swift_double_u8(arg: UInt8) -> UInt8 {
arg * 2
}
func swift_double_i8(arg: Int8) -> Int8 {
arg * 2
}
func swift_double_u16(arg: UInt16) -> UInt16 {
arg * 2
}
func swift_double_i16(arg: Int16) -> Int16 {
arg * 2
}
func swift_double_u32(arg: UInt32) -> UInt32 {
arg * 2
}
func swift_double_i32(arg: Int32) -> Int32 {
arg * 2
}
func swift_double_u64(arg: UInt64) -> UInt64 {
arg * 2
}
func swift_double_i64(arg: Int64) -> Int64 {
arg * 2
}
func swift_double_f32(arg: Float) -> Float {
arg * 2.0
}
func swift_double_f64(arg: Double) -> Double {
arg * 2.0
}
func swift_negate_bool(arg: Bool) -> Bool {
!arg
}
func swift_reflect_null(arg: ()) -> () {
arg
}

/// Tests for generic types such as `type SomeType<u32>`
class PrimitiveTests: XCTestCase {
/// Run tests where Rust calls Swift functions that take primitive args.
func testRustCallsSwiftPrimitives() throws {
test_rust_calls_swift_primitives()
}
/// Run tests where Swift calls Rust functions that take primitive args.
func testSwiftCallsRustPrimitives() throws {
XCTAssertEqual(rust_double_u8(10), 20);
XCTAssertEqual(rust_double_i8(10), 20);
XCTAssertEqual(rust_double_u16(10), 20);
XCTAssertEqual(rust_double_i16(10), 20);
XCTAssertEqual(rust_double_u32(10), 20);
XCTAssertEqual(rust_double_i32(10), 20);
XCTAssertEqual(rust_double_u64(10), 20);
XCTAssertEqual(rust_double_i64(10), 20);
XCTAssertEqual(rust_double_f32(10.0), 20.0);
XCTAssertEqual(rust_double_f64(10.0), 20.0);
XCTAssertEqual(rust_negate_bool(true), false);
XCTAssertEqual(rust_negate_bool(false), true);
}
}

Primitive enum variants

Add U128 and I128 variants to the BuiltInPrimitive and StdlibType enums:

/// Primitive types such as `()`, `u8` and `bool`.
pub(crate) enum BuiltInPrimitive {
Null,
U8,
I8,
U16,
I16,
U32,
I32,
U64,
I64,
Usize,
Isize,
F32,
F64,
Bool,
}

Fix compile time errors

Run cargo check -p swift-bridge-ir and fix all compile time errors.

Ensure integration tests pass

Ensure that the PrimitiveTests now pass:

/// Tests for generic types such as `type SomeType<u32>`
class PrimitiveTests: XCTestCase {
/// Run tests where Rust calls Swift functions that take primitive args.
func testRustCallsSwiftPrimitives() throws {
test_rust_calls_swift_primitives()
}
/// Run tests where Swift calls Rust functions that take primitive args.
func testSwiftCallsRustPrimitives() throws {
XCTAssertEqual(rust_double_u8(10), 20);
XCTAssertEqual(rust_double_i8(10), 20);
XCTAssertEqual(rust_double_u16(10), 20);
XCTAssertEqual(rust_double_i16(10), 20);
XCTAssertEqual(rust_double_u32(10), 20);
XCTAssertEqual(rust_double_i32(10), 20);
XCTAssertEqual(rust_double_u64(10), 20);
XCTAssertEqual(rust_double_i64(10), 20);
XCTAssertEqual(rust_double_f32(10.0), 20.0);
XCTAssertEqual(rust_double_f64(10.0), 20.0);
XCTAssertEqual(rust_negate_bool(true), false);
XCTAssertEqual(rust_negate_bool(false), true);
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

1 participant