From 44746b5f3d475c7f2461ab365dc9066041ab02e7 Mon Sep 17 00:00:00 2001
From: EthanShoeDev <13422990+EthanShoeDev@users.noreply.github.com>
Date: Fri, 12 Sep 2025 23:56:08 -0400
Subject: [PATCH] add calc getting started to main app
---
apps/mobile/package.json | 1 +
apps/mobile/src/app/index.tsx | 6 +-
apps/mobile/src/lib/test-uniffi-russh.ts | 32 +
flake.nix | 3 +
packages/react-native-uniffi-russh/.gitignore | 4 +
packages/react-native-uniffi-russh/LICENSE | 20 -
.../android/CMakeLists.txt | 76 +
.../android/build.gradle | 93 +-
.../android/cpp-adapter.cpp | 63 +
.../android/src/main/AndroidManifest.xml | 7 +-
.../java/com/uniffirussh/UniffiRusshModule.kt | 43 +
.../com/uniffirussh/UniffiRusshPackage.kt | 34 +
.../cpp/generated/foobar.cpp | 2965 +++++++++++++++++
.../cpp/generated/foobar.hpp | 85 +
.../cpp/react-native-uniffi-russh.cpp | 16 +
.../cpp/react-native-uniffi-russh.h | 15 +
.../eslint.config.mjs | 2 +-
.../react-native-uniffi-russh/package.json | 40 +-
.../src/NativeUniffiRussh.ts | 10 +
.../src/generated/foobar-ffi.ts | 306 ++
.../src/generated/foobar.ts | 1271 +++++++
.../react-native-uniffi-russh/src/index.tsx | 41 +
.../tsconfig.build.json | 6 +-
.../ubrn.config.yaml | 4 +
pnpm-lock.yaml | 403 +--
25 files changed, 5070 insertions(+), 476 deletions(-)
create mode 100644 apps/mobile/src/lib/test-uniffi-russh.ts
delete mode 100644 packages/react-native-uniffi-russh/LICENSE
create mode 100644 packages/react-native-uniffi-russh/android/CMakeLists.txt
create mode 100644 packages/react-native-uniffi-russh/android/cpp-adapter.cpp
create mode 100644 packages/react-native-uniffi-russh/android/src/main/java/com/uniffirussh/UniffiRusshModule.kt
create mode 100644 packages/react-native-uniffi-russh/android/src/main/java/com/uniffirussh/UniffiRusshPackage.kt
create mode 100644 packages/react-native-uniffi-russh/cpp/generated/foobar.cpp
create mode 100644 packages/react-native-uniffi-russh/cpp/generated/foobar.hpp
create mode 100644 packages/react-native-uniffi-russh/cpp/react-native-uniffi-russh.cpp
create mode 100644 packages/react-native-uniffi-russh/cpp/react-native-uniffi-russh.h
create mode 100644 packages/react-native-uniffi-russh/src/NativeUniffiRussh.ts
create mode 100644 packages/react-native-uniffi-russh/src/generated/foobar-ffi.ts
create mode 100644 packages/react-native-uniffi-russh/src/generated/foobar.ts
create mode 100644 packages/react-native-uniffi-russh/src/index.tsx
diff --git a/apps/mobile/package.json b/apps/mobile/package.json
index 94f7181..c53cb93 100644
--- a/apps/mobile/package.json
+++ b/apps/mobile/package.json
@@ -27,6 +27,7 @@
"@dylankenneally/react-native-ssh-sftp": "^1.5.20",
"@expo/vector-icons": "^15.0.2",
"@fressh/assets": "workspace:*",
+ "@fressh/react-native-uniffi-russh": "workspace:*",
"@react-native-picker/picker": "2.11.1",
"@react-native-segmented-control/segmented-control": "2.5.7",
"@react-navigation/bottom-tabs": "^7.4.0",
diff --git a/apps/mobile/src/app/index.tsx b/apps/mobile/src/app/index.tsx
index 37b0b42..b5bbd4d 100644
--- a/apps/mobile/src/app/index.tsx
+++ b/apps/mobile/src/app/index.tsx
@@ -13,7 +13,7 @@ import {
secretsManager,
} from '../lib/secrets-manager';
import { sshConnectionManager } from '../lib/ssh-connection-manager';
-
+import { result } from '../lib/test-uniffi-russh';
const defaultValues: ConnectionDetails = {
host: 'test.rebex.net',
port: 22,
@@ -119,7 +119,9 @@ export default function Index() {
>
fressh
- A fast, friendly SSH client
+
+ A fast, friendly SSH client {result}
+
Connect to SSH Server
diff --git a/apps/mobile/src/lib/test-uniffi-russh.ts b/apps/mobile/src/lib/test-uniffi-russh.ts
new file mode 100644
index 0000000..7708035
--- /dev/null
+++ b/apps/mobile/src/lib/test-uniffi-russh.ts
@@ -0,0 +1,32 @@
+import {
+ Calculator,
+ type BinaryOperator,
+ SafeAddition,
+ type ComputationResult,
+} from '@fressh/react-native-uniffi-russh';
+
+const calculator = new Calculator();
+
+const addOp = new SafeAddition();
+
+class SafeMultiply implements BinaryOperator {
+ perform(lhs: bigint, rhs: bigint): bigint {
+ return lhs * rhs;
+ }
+}
+
+const multOp = new SafeMultiply();
+
+// bigints
+const three = 3n;
+const seven = 7n;
+
+// Perform the calculation, and to get an object
+// representing the computation result.
+const computation: ComputationResult = calculator
+ .calculate(addOp, three, three)
+ .calculateMore(multOp, seven)
+ .lastResult()!;
+
+// Unpack the bigint value into a string.
+export const result = computation.value.toString();
diff --git a/flake.nix b/flake.nix
index 1b6cb4d..958bade 100644
--- a/flake.nix
+++ b/flake.nix
@@ -35,6 +35,9 @@
build-tools-36-0-0
platforms-android-36
system-images-android-36-0-Baklava-google-apis-playstore-x86-64
+ # Add NDK + CMake for native builds
+ ndk-26-1-10909125
+ cmake-3-22-1
])
else if mode == "remote" then
(with sdk; [
diff --git a/packages/react-native-uniffi-russh/.gitignore b/packages/react-native-uniffi-russh/.gitignore
index 67f3212..a23406b 100644
--- a/packages/react-native-uniffi-russh/.gitignore
+++ b/packages/react-native-uniffi-russh/.gitignore
@@ -84,3 +84,7 @@ android/generated
# React Native Nitro Modules
nitrogen/
+
+# From uniffi-bindgen-react-native
+rust_modules/
+*.a
diff --git a/packages/react-native-uniffi-russh/LICENSE b/packages/react-native-uniffi-russh/LICENSE
deleted file mode 100644
index 39e9838..0000000
--- a/packages/react-native-uniffi-russh/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-MIT License
-
-Copyright (c) 2025 EthanShoeDev
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/packages/react-native-uniffi-russh/android/CMakeLists.txt b/packages/react-native-uniffi-russh/android/CMakeLists.txt
new file mode 100644
index 0000000..25f6b55
--- /dev/null
+++ b/packages/react-native-uniffi-russh/android/CMakeLists.txt
@@ -0,0 +1,76 @@
+# Generated by uniffi-bindgen-react-native
+cmake_minimum_required(VERSION 3.9.0)
+project(UniffiRussh)
+
+set (CMAKE_VERBOSE_MAKEFILE ON)
+set (CMAKE_CXX_STANDARD 17)
+
+# Resolve the path to the uniffi-bindgen-react-native package
+execute_process(
+ COMMAND node -p "require.resolve('uniffi-bindgen-react-native/package.json')"
+ OUTPUT_VARIABLE UNIFFI_BINDGEN_PATH
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+# Get the directory; get_filename_component and cmake_path will normalize
+# paths with Windows path separators.
+get_filename_component(UNIFFI_BINDGEN_PATH "${UNIFFI_BINDGEN_PATH}" DIRECTORY)
+
+# Specifies a path to native header files.
+include_directories(
+ ../cpp
+ ../cpp/generated
+
+ ${UNIFFI_BINDGEN_PATH}/cpp/includes
+)
+
+add_library(react-native-uniffi-russh SHARED
+ ../cpp/react-native-uniffi-russh.cpp
+ ../cpp/generated/foobar.cpp
+ cpp-adapter.cpp
+)
+
+# Set C++ compiler flags
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -frtti")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector-all")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
+
+cmake_path(
+ SET MY_RUST_LIB
+ ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libfoobar.a
+ NORMALIZE
+)
+add_library(my_rust_lib STATIC IMPORTED)
+set_target_properties(my_rust_lib PROPERTIES IMPORTED_LOCATION ${MY_RUST_LIB})
+
+# Add ReactAndroid libraries, being careful to account for different versions.
+find_package(ReactAndroid REQUIRED CONFIG)
+find_library(LOGCAT log)
+
+# REACTNATIVE_MERGED_SO seems to be only be set in a build.gradle.kt file,
+# which we don't use. Thus falling back to version number sniffing.
+if (ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)
+ set(REACTNATIVE_MERGED_SO true)
+endif()
+
+# https://github.com/react-native-community/discussions-and-proposals/discussions/816
+# This if-then-else can be removed once this library does not support version below 0.76
+if (REACTNATIVE_MERGED_SO)
+ target_link_libraries(react-native-uniffi-russh ReactAndroid::reactnative)
+else()
+ target_link_libraries(react-native-uniffi-russh
+ ReactAndroid::turbomodulejsijni
+ ReactAndroid::react_nativemodule_core
+ )
+endif()
+
+find_package(fbjni REQUIRED CONFIG)
+target_link_libraries(
+ react-native-uniffi-russh
+ fbjni::fbjni
+ ReactAndroid::jsi
+ ${LOGCAT}
+ my_rust_lib
+)
diff --git a/packages/react-native-uniffi-russh/android/build.gradle b/packages/react-native-uniffi-russh/android/build.gradle
index dd1076e..17adb3a 100644
--- a/packages/react-native-uniffi-russh/android/build.gradle
+++ b/packages/react-native-uniffi-russh/android/build.gradle
@@ -1,7 +1,8 @@
+// Generated by uniffi-bindgen-react-native
+
buildscript {
- ext.getExtOrDefault = {name ->
- return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['UniffiRussh_' + name]
- }
+ // Buildscript is evaluated before everything else so we can't use getExtOrDefault
+ def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["DummyLibForAndroid_kotlinVersion"]
repositories {
google()
@@ -9,30 +10,83 @@ buildscript {
}
dependencies {
- classpath "com.android.tools.build:gradle:8.7.2"
+ classpath "com.android.tools.build:gradle:7.2.1"
// noinspection DifferentKotlinGradleVersion
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
+def reactNativeArchitectures() {
+ def value = rootProject.getProperties().get("reactNativeArchitectures")
+ return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
+}
+
+def isNewArchitectureEnabled() {
+ return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
+}
apply plugin: "com.android.library"
apply plugin: "kotlin-android"
-apply plugin: "com.facebook.react"
+if (isNewArchitectureEnabled()) {
+ apply plugin: "com.facebook.react"
+}
+
+def getExtOrDefault(name) {
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["UniffiRussh_" + name]
+}
def getExtOrIntegerDefault(name) {
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["UniffiRussh_" + name]).toInteger()
}
-android {
- namespace "com.uniffirussh"
+def supportsNamespace() {
+ def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
+ def major = parsed[0].toInteger()
+ def minor = parsed[1].toInteger()
+ // Namespace support was added in 7.3.0
+ return (major == 7 && minor >= 3) || major >= 8
+}
+
+android {
+ if (supportsNamespace()) {
+ namespace "com.uniffirussh"
+
+ sourceSets {
+ main {
+ manifest.srcFile "src/main/AndroidManifestNew.xml"
+ }
+ }
+ }
+
+ ndkVersion getExtOrDefault("ndkVersion")
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
defaultConfig {
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
+ buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
+ consumerProguardFiles 'proguard-rules.pro'
+
+ buildFeatures {
+ prefab true
+ }
+ externalNativeBuild {
+ cmake {
+ arguments '-DANDROID_STL=c++_shared'
+ abiFilters (*reactNativeArchitectures())
+ }
+ }
+ ndk {
+ abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64"
+ }
+ }
+
+ externalNativeBuild {
+ cmake {
+ path "CMakeLists.txt"
+ }
}
buildFeatures {
@@ -56,10 +110,12 @@ android {
sourceSets {
main {
- java.srcDirs += [
- "generated/java",
- "generated/jni"
- ]
+ if (isNewArchitectureEnabled()) {
+ java.srcDirs += [
+ "generated/java",
+ "generated/jni"
+ ]
+ }
}
}
}
@@ -72,6 +128,17 @@ repositories {
def kotlin_version = getExtOrDefault("kotlinVersion")
dependencies {
- implementation "com.facebook.react:react-android"
+ // For < 0.71, this will be from the local maven repo
+ // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
+ //noinspection GradleDynamicVersion
+ implementation "com.facebook.react:react-native:+"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
+
+if (isNewArchitectureEnabled()) {
+ react {
+ jsRootDir = file("../src/")
+ libraryName = "UniffiRussh"
+ codegenJavaPackageName = "com.uniffirussh"
+ }
+}
diff --git a/packages/react-native-uniffi-russh/android/cpp-adapter.cpp b/packages/react-native-uniffi-russh/android/cpp-adapter.cpp
new file mode 100644
index 0000000..22e0254
--- /dev/null
+++ b/packages/react-native-uniffi-russh/android/cpp-adapter.cpp
@@ -0,0 +1,63 @@
+// Generated by uniffi-bindgen-react-native
+#include
+#include
+#include
+#include "react-native-uniffi-russh.h"
+
+namespace jsi = facebook::jsi;
+namespace react = facebook::react;
+
+// Automated testing checks Java_com_uniffirussh_UniffiRusshModule and uniffirussh
+// by comparing the whole line here.
+/*
+Java_com_uniffirussh_UniffiRusshModule_nativeMultiply(JNIEnv *env, jclass type, jdouble a, jdouble b) {
+ return uniffirussh::multiply(a, b);
+}
+*/
+
+// Installer coming from UniffiRusshModule
+extern "C"
+JNIEXPORT jboolean JNICALL
+Java_com_uniffirussh_UniffiRusshModule_nativeInstallRustCrate(
+ JNIEnv *env,
+ jclass type,
+ jlong rtPtr,
+ jobject callInvokerHolderJavaObj
+) {
+ // https://github.com/realm/realm-js/blob/main/packages/realm/binding/android/src/main/cpp/io_realm_react_RealmReactModule.cpp#L122-L145
+ // React Native uses the fbjni library for handling JNI, which has the concept of "hybrid objects",
+ // which are Java objects containing a pointer to a C++ object. The CallInvokerHolder, which has the
+ // invokeAsync method we want access to, is one such hybrid object.
+ // Rather than reworking our code to use fbjni throughout, this code unpacks the C++ object from the Java
+ // object `callInvokerHolderJavaObj` manually, based on reverse engineering the fbjni code.
+
+ // 1. Get the Java object referred to by the mHybridData field of the Java holder object
+ auto callInvokerHolderClass = env->GetObjectClass(callInvokerHolderJavaObj);
+ auto hybridDataField = env->GetFieldID(callInvokerHolderClass, "mHybridData", "Lcom/facebook/jni/HybridData;");
+ auto hybridDataObj = env->GetObjectField(callInvokerHolderJavaObj, hybridDataField);
+
+ // 2. Get the destructor Java object referred to by the mDestructor field from the myHybridData Java object
+ auto hybridDataClass = env->FindClass("com/facebook/jni/HybridData");
+ auto destructorField =
+ env->GetFieldID(hybridDataClass, "mDestructor", "Lcom/facebook/jni/HybridData$Destructor;");
+ auto destructorObj = env->GetObjectField(hybridDataObj, destructorField);
+
+ // 3. Get the mNativePointer field from the mDestructor Java object
+ auto destructorClass = env->FindClass("com/facebook/jni/HybridData$Destructor");
+ auto nativePointerField = env->GetFieldID(destructorClass, "mNativePointer", "J");
+ auto nativePointerValue = env->GetLongField(destructorObj, nativePointerField);
+
+ // 4. Cast the mNativePointer back to its C++ type
+ auto nativePointer = reinterpret_cast(nativePointerValue);
+ auto jsCallInvoker = nativePointer->getCallInvoker();
+
+ auto runtime = reinterpret_cast(rtPtr);
+ return uniffirussh::installRustCrate(*runtime, jsCallInvoker);
+}
+
+extern "C"
+JNIEXPORT jboolean JNICALL
+Java_com_uniffirussh_UniffiRusshModule_nativeCleanupRustCrate(JNIEnv *env, jclass type, jlong rtPtr) {
+ auto runtime = reinterpret_cast(rtPtr);
+ return uniffirussh::cleanupRustCrate(*runtime);
+}
\ No newline at end of file
diff --git a/packages/react-native-uniffi-russh/android/src/main/AndroidManifest.xml b/packages/react-native-uniffi-russh/android/src/main/AndroidManifest.xml
index a2f47b6..118c2e8 100644
--- a/packages/react-native-uniffi-russh/android/src/main/AndroidManifest.xml
+++ b/packages/react-native-uniffi-russh/android/src/main/AndroidManifest.xml
@@ -1,2 +1,5 @@
-
-
+
+
+
+
\ No newline at end of file
diff --git a/packages/react-native-uniffi-russh/android/src/main/java/com/uniffirussh/UniffiRusshModule.kt b/packages/react-native-uniffi-russh/android/src/main/java/com/uniffirussh/UniffiRusshModule.kt
new file mode 100644
index 0000000..52d9f7d
--- /dev/null
+++ b/packages/react-native-uniffi-russh/android/src/main/java/com/uniffirussh/UniffiRusshModule.kt
@@ -0,0 +1,43 @@
+// Generated by uniffi-bindgen-react-native
+package com.uniffirussh
+
+import com.facebook.react.bridge.ReactApplicationContext
+import com.facebook.react.module.annotations.ReactModule
+import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder
+
+@ReactModule(name = UniffiRusshModule.NAME)
+class UniffiRusshModule(reactContext: ReactApplicationContext) :
+ NativeUniffiRusshSpec(reactContext) {
+
+ override fun getName(): String {
+ return NAME
+ }
+
+ // Two native methods implemented in cpp-adapter.cpp, and ultimately
+ // react-native-uniffi-russh.cpp
+
+ external fun nativeInstallRustCrate(runtimePointer: Long, callInvoker: CallInvokerHolder): Boolean
+ external fun nativeCleanupRustCrate(runtimePointer: Long): Boolean
+
+ override fun installRustCrate(): Boolean {
+ val context = this.reactApplicationContext
+ return nativeInstallRustCrate(
+ context.javaScriptContextHolder!!.get(),
+ context.jsCallInvokerHolder!!
+ )
+ }
+
+ override fun cleanupRustCrate(): Boolean {
+ return nativeCleanupRustCrate(
+ this.reactApplicationContext.javaScriptContextHolder!!.get()
+ )
+ }
+
+ companion object {
+ const val NAME = "UniffiRussh"
+
+ init {
+ System.loadLibrary("react-native-uniffi-russh")
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/react-native-uniffi-russh/android/src/main/java/com/uniffirussh/UniffiRusshPackage.kt b/packages/react-native-uniffi-russh/android/src/main/java/com/uniffirussh/UniffiRusshPackage.kt
new file mode 100644
index 0000000..396e306
--- /dev/null
+++ b/packages/react-native-uniffi-russh/android/src/main/java/com/uniffirussh/UniffiRusshPackage.kt
@@ -0,0 +1,34 @@
+// Generated by uniffi-bindgen-react-native
+package com.uniffirussh
+
+import com.facebook.react.TurboReactPackage
+import com.facebook.react.bridge.NativeModule
+import com.facebook.react.bridge.ReactApplicationContext
+import com.facebook.react.module.model.ReactModuleInfo
+import com.facebook.react.module.model.ReactModuleInfoProvider
+import java.util.HashMap
+
+class UniffiRusshPackage : TurboReactPackage() {
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
+ return if (name == UniffiRusshModule.NAME) {
+ UniffiRusshModule(reactContext)
+ } else {
+ null
+ }
+ }
+
+ override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
+ return ReactModuleInfoProvider {
+ val moduleInfos: MutableMap = HashMap()
+ moduleInfos[UniffiRusshModule.NAME] = ReactModuleInfo(
+ UniffiRusshModule.NAME,
+ UniffiRusshModule.NAME,
+ false, // canOverrideExistingModule
+ false, // needsEagerInit
+ false, // isCxxModule
+ true // isTurboModule
+ )
+ moduleInfos
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/react-native-uniffi-russh/cpp/generated/foobar.cpp b/packages/react-native-uniffi-russh/cpp/generated/foobar.cpp
new file mode 100644
index 0000000..ab608ad
--- /dev/null
+++ b/packages/react-native-uniffi-russh/cpp/generated/foobar.cpp
@@ -0,0 +1,2965 @@
+// This file was autogenerated by some hot garbage in the `uniffi-bindgen-react-native` crate.
+// Trust me, you don't want to mess with it!
+#include "foobar.hpp"
+
+#include "UniffiJsiTypes.h"
+#include
+#include